Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for NSTableView sections (aka group rows) #93

Open
2 tasks done
helje5 opened this issue Jan 20, 2020 · 1 comment
Open
2 tasks done

Support for NSTableView sections (aka group rows) #93

helje5 opened this issue Jan 20, 2020 · 1 comment

Comments

@helje5
Copy link

helje5 commented Jan 20, 2020

Checklist

Description

The NSTableView extension doesn't apply section changes and indices assume a single section.

Motivation and Context

Like the UITableView, NSTableView supports sections (called "group rows" in AppKit). It would be great if they would just work in combination w/ ArraySection's.

Proposed Solution

In NSTableView the sections (group rows) are part of the collection feed to the tableview. E.g.

let source = [
    ArraySection(model: "Section 1", elements: ["A", "B", "C"]),
    ArraySection(model: "Section 2", elements: ["D", "E", "F"]),
]

Is presented to NSTableView as:

[0] "Section 1"
[1] "A"
[2] "B"
[3] "C"
[4] "Section 2"
[5] "D"
...

It's not obvious that this isn't supported. Maybe AppKitExtension.swift should have

            assert(changeset.sectionInserted.isEmpty, 
                        "srz, section updates not yet supported on AppKit!")
...

in the reload.

Not quite sure about the best way to implement this. The reload should have all the grouping information necessary. Essentially there would need to be a separate step adjusting the indices to the flat ones, while applying the changes.

Sample TV datasource/delegate on top of ArraySection

extension AppDelegate: NSTableViewDelegate {
  func tableView(_ tv: NSTableView, isGroupRow row: Int) -> Bool {
    switch test.data[flat: row] {
      case .some(.model): return true
      default: return false
    }
  }
  func tableView(_ tv: NSTableView, viewFor tc: NSTableColumn?, row: Int)
       -> NSView?
  {
    let label = NSTextField(labelWithString: test.data[flat: row]?.stringValue ?? "-")
    return label
  }
}
extension AppDelegate: NSTableViewDataSource {
  func numberOfRows(in tableView: NSTableView) -> Int {
    test.data.flatCount
  }
}

final class SectionedTest {
  
  var data = [ ArraySection<String, String> ]()
  
  func applyNewData(_ newValue: [ ArraySection<String, String> ],
                    on tableView: NSTableView)
  {
    let changeset = StagedChangeset(source: data, target: newValue)
    tableView.reload(using: changeset, with: .effectFade) { newValue in
      self.data = newValue
    }
  }
}

enum Row {
  case model(String)
  case element(String)
  var stringValue: String {
    switch self {
      case .model(let s), .element(let s): return s
    }
  }
}
extension Collection where Element == ArraySection<String, String> {
 
  var flatCount : Int {
    reduce(0) { $0 + 1 + $1.elements.count }
  }
  
  subscript(flat index: Int) -> Row? {
    var cursor = 0
    for section in self {
      if cursor == index { return .model(section.model) }
      cursor += 1
      if cursor > index { break }
      
      let offset = index - cursor
      assert(offset >= 0)
      if offset < section.elements.count {
        return .element(section.elements[offset])
      }
      cursor += section.elements.count
    }
    assertionFailure("index out of range \(index) \(count)")
    return nil
  }
}
@ra1028
Copy link
Owner

ra1028 commented Mar 31, 2020

@helje5
The data structure isn't compatible with section and group rows cuz the concepts are different, so I think it won't be able to support NSTableView.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants