Skip to content

Commit

Permalink
maintain live view scroll positon in every playing
Browse files Browse the repository at this point in the history
  • Loading branch information
novi committed Apr 16, 2017
1 parent 9658960 commit bfd9225
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 8 deletions.
9 changes: 5 additions & 4 deletions Playgrounds/NumswPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@ import CoreGraphics
public class NumswPlayground {
internal init() {
#if os(iOS)
viewController = RenderTableViewController()
viewController = RenderTableViewController(state: viewState)
#endif
}

#if os(iOS)
public let viewController: RenderTableViewController
internal let viewState = RenderTableViewController.State()
#endif

public func append(renderer: ChartRenderer) {
renderers.append(renderer)
viewController.append(renderer: renderer)
}

public func plot(_ x: [Double], _ y: [Double]) {
Expand Down Expand Up @@ -69,13 +70,13 @@ public class NumswPlayground {
return _shared!
}

private var renderers: [ChartRenderer] = [] {
/*private var renderers: [ChartRenderer] = [] {
didSet {
#if os(iOS)
viewController.replace(renderers: renderers.map { $0 as Renderer })
#endif
}
}
}*/

private var chartBuilder: ChartBuilder?

Expand Down
134 changes: 131 additions & 3 deletions Playgrounds/RenderTableViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,60 @@
import UIKit
import QuartzCore


#if SANDBOX_APP
// sandbox app
internal enum PlaygroundValue {
case array([PlaygroundValue])
case boolean(Bool)
case data(Data)
case date(Date)
case dictionary([String: PlaygroundValue])
case floatingPoint(Double)
case integer(Int)
case string(String)
}
internal class PlaygroundKeyValueStore {
static let current = PlaygroundKeyValueStore()
private init() {

}
subscript(key: String) -> PlaygroundValue? {
set {
print("KeyValueStore setting \(newValue as Any) for \(key)")
if let value = newValue {
switch value {
case .floatingPoint(let double):
UserDefaults.standard.set(double, forKey: key)
case .integer(let integer):
UserDefaults.standard.set(integer, forKey: key)
default:
fatalError("Not implemented")
}
} else {
UserDefaults.standard.removeObject(forKey: key)
}
}
get {
print("KeyValueStore getting for \(key)")
guard let object = UserDefaults.standard.object(forKey: key) else {
return nil
}
if let integer = object as? Int {
return .integer(integer)
} else if let double = object as? Double {
return .floatingPoint(double)
} else {
fatalError("Not implemented")
}
}
}
}
#else
// playground
import PlaygroundSupport
#endif

private class RenderTableViewCell: UITableViewCell {

private static let renderQueue = DispatchQueue(label: "Renderer-Queue")
Expand Down Expand Up @@ -88,7 +142,41 @@ public class RenderTableViewController: UITableViewController {

private var renderers: [Renderer] = []

public init() {
internal class State {
private enum Key: String {
case tableViewScrollOffsetX = "table_view_scrolloffset_x"
case tableViewScrollOffsetY = "table_view_scrolloffset_y"
case rendererCount = "renderer_count"
}

var tableViewScrollOffset: CGPoint = .zero
init() {
let kvs = PlaygroundKeyValueStore.current
if let xValue = kvs[Key.tableViewScrollOffsetX.rawValue],
case .floatingPoint(let x) = xValue,
let yValue = kvs[Key.tableViewScrollOffsetY.rawValue],
case .floatingPoint(let y) = yValue {
tableViewScrollOffset = CGPoint(x: x, y: y)
} else {
tableViewScrollOffset = .zero
}
}

func reset() {
tableViewScrollOffset = .zero
}

func sync() {
let kvs = PlaygroundKeyValueStore.current
kvs[Key.tableViewScrollOffsetX.rawValue] = .floatingPoint(Double(tableViewScrollOffset.x))
kvs[Key.tableViewScrollOffsetY.rawValue] = .floatingPoint(Double(tableViewScrollOffset.y))
}
}

private var state: State

internal init(state: State) {
self.state = state
super.init(style: .plain)
}

Expand All @@ -106,15 +194,29 @@ public class RenderTableViewController: UITableViewController {

}

public func replace(renderers: [Renderer]) {
// not in use?
/*public func replace(renderers: [Renderer]) {
self.renderers = renderers
self.tableView.reloadData()
}*/

public func removeAllRenderers() {
self.renderers = []
self.tableView.reloadData()
}

public func append(renderer: Renderer) {
// partial update
self.renderers.append(renderer)
self.tableView.insertRows(at: [IndexPath(row: renderers.count, section: 0)], with: .automatic)
//self.tableView.insertRows(at: [IndexPath(row: renderers.count-1, section: 0)], with: .none)
tableView.reloadData()

// scroll to previous content position
let lastRowOffset = tableView.rectForRow(at: IndexPath(row: renderers.count-1, section: 0))

let maxYOffset = max(lastRowOffset.origin.y + lastRowOffset.size.height - view.bounds.size.height, 0) // 0 ~
let offset = CGPoint(x: state.tableViewScrollOffset.x, y: min(maxYOffset, state.tableViewScrollOffset.y))
tableView.setContentOffset(offset, animated: false)
}

// some times not invoked?? on iPad playground
Expand Down Expand Up @@ -148,6 +250,7 @@ public class RenderTableViewController: UITableViewController {
// temporary, we use this deprecated method until the solution is found
public override func willAnimateRotation(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
super.willAnimateRotation(to: toInterfaceOrientation, duration: duration)
state.reset()
updateVisibleCellImagesIfNeeded()
}

Expand All @@ -173,5 +276,30 @@ public class RenderTableViewController: UITableViewController {
cell.updateImageViewIfNeeded()
}
}

#if SANDBOX_APP
// Tap to dismiss any table view cell
public override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.dismiss(animated: true, completion: nil)
}
#endif

public override func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
storeTableViewScrollOffset()
}

public override func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
storeTableViewScrollOffset()
}

public override func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
storeTableViewScrollOffset()
}

private func storeTableViewScrollOffset() {
// store tableview scroll offset
state.tableViewScrollOffset = tableView.contentOffset
state.sync()
}
}
#endif
3 changes: 2 additions & 1 deletion Playgrounds/sandbox/sandbox/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ class ViewController: UIViewController {
return ChartRenderer(chart: chart)
}

let vc = RenderTableViewController()
let vc = NumswPlayground.shared.viewController
vc.removeAllRenderers()

for _ in 0...10 {
vc.append(renderer: makeRenderer())
Expand Down

0 comments on commit bfd9225

Please sign in to comment.