NSCollectionView как NSCollectionViewItem - PullRequest
1 голос
/ 09 июля 2019

Вот окно, которое я хочу достичь: window to achieve Это NSViewController (RedViewController) с NSCollectionView (RedCollectionView) в качестве представления.
Это элемент (BlueItem) имеет NSCollectionView (BlueCollectionView) в качестве представления.
Это элемент элемента (GreenItem), имеет NSImageView (GreenImageView) в качестве представления.
RedCollectionView будет прокручиваться вертикально, и его элементы будут доступны для выбора. Однако BlueCollectionView предназначен только для отображения, он не прокручивается сам по себе и не может быть выбран.
Вот код для AppDelegate:

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
  lazy var redViewController: RedViewController = {
    let redViewController = RedViewController.init()
    return redViewController
  }()

  lazy var window: NSWindow = {
    let window = NSWindow.init(contentViewController: self.redViewController)
    return window
  }()

  lazy var windowController: NSWindowController = {
    let windowController = NSWindowController.init(window: self.window)
    return windowController
  }()

  func applicationDidFinishLaunching(_ aNotification: Notification) {
    self.windowController.showWindow(nil)
  }
}

Вот код для RedViewController:

class RedViewController: NSViewController, NSCollectionViewDataSource, NSCollectionViewDelegate {
  lazy var collectionViewLayout: NSCollectionViewFlowLayout = {
    let collectionViewLayout = NSCollectionViewFlowLayout.init()
    collectionViewLayout.itemSize = NSSize(width: 100.0, height: 100.0)
    collectionViewLayout.minimumLineSpacing = 10.0
    collectionViewLayout.minimumInteritemSpacing = 10.0
    collectionViewLayout.sectionInset = NSEdgeInsetsMake(10.0, 10.0, 10.0, 10.0)
    return collectionViewLayout
  }()

  class RedCollectionView: NSCollectionView { /* nothing here for now */ }

  lazy var redCollectionView: RedCollectionView = {
    let redCollectionView = RedCollectionView.init(frame: NSRect(x: 0.0, y: 0.0, width: 500.0, height: 500.0))
    redCollectionView.collectionViewLayout = self.collectionViewLayout
    redCollectionView.dataSource = self
    redCollectionView.delegate = self
    redCollectionView.isSelectable = true
    redCollectionView.backgroundColors = [NSColor.red]
    return redCollectionView
  }()

  override func loadView() {
    let clipView = NSClipView.init()
    clipView.documentView = self.redCollectionView
    let scrollView = NSScrollView.init(frame: NSRect(x: 0.0, y: 0.0, width: 500.0, height: 500.0))
    scrollView.contentView = clipView
    self.view = scrollView
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    self.redCollectionView.register(BlueItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier("BlueItemID"))
  }

  func numberOfSections(in collectionView: NSCollectionView) -> Int {
    return 1
  }

  func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
    return 50
  }

  func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
    let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "BlueItemID"), for: indexPath)
    guard let blueItem = item as? BlueItem else { return item }
    return blueItem
  }

  func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
    indexPaths.forEach({ print($0) })
    collectionView.deselectItems(at: indexPaths)
  }
}

Вот код для BlueItem:

class BlueItem: NSCollectionViewItem, NSCollectionViewDataSource {
  lazy var collectionViewLayout: NSCollectionViewFlowLayout = {
    let collectionViewLayout = NSCollectionViewFlowLayout.init()
    collectionViewLayout.itemSize = NSSize(width: 27.0, height: 27.0)
    collectionViewLayout.minimumLineSpacing = 3.0
    collectionViewLayout.minimumInteritemSpacing = 3.0
    collectionViewLayout.sectionInset = NSEdgeInsetsMake(3.0, 3.0, 3.0, 3.0)
    return collectionViewLayout
  }()

  class BlueCollectionView: NSCollectionView {
    override func mouseDown(with event: NSEvent) {
      super.mouseDown(with: event)
      self.nextResponder?.mouseDown(with: event)
    }

    override func mouseUp(with event: NSEvent) {
      super.mouseUp(with: event)
      self.nextResponder?.mouseUp(with: event)
    }
  }

  lazy var blueCollectionView: BlueCollectionView = {
    let blueCollectionView = BlueCollectionView.init(frame: NSRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
    blueCollectionView.collectionViewLayout = self.collectionViewLayout
    blueCollectionView.dataSource = self
    blueCollectionView.isSelectable = false
    blueCollectionView.backgroundColors = [NSColor.blue]
    return blueCollectionView
  }()

  override func loadView() {
    self.view = self.blueCollectionView
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    self.blueCollectionView.register(GreenItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier("GreenItemID"))
  }

  func numberOfSections(in collectionView: NSCollectionView) -> Int {
    return 1
  }

  func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
    return 7
  }

  func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
    let item = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "GreenItemID"), for: indexPath)
    guard let greenItem = item as? GreenItem else { return item }
    return greenItem
  }
}

И, наконец, вот код для GreenItem:

class GreenItem: NSCollectionViewItem {
  class GreenImageView: NSImageView { /* nothing here for now */ }

  lazy var greenImageView: GreenImageView = {
    let image: NSImage = NSImage.init(imageLiteralResourceName: "greenImage")
    let greenImageView = GreenImageView.init(image: image)
    return greenImageView
  }()

  override func loadView() {
    self.view = self.greenImageView
  }
}

Когда я запускаю приложение, я получаю такой результат: app screenshot

Итак, у меня есть 3 вопроса:
1. BlueItem с его BlueCollectionView не получает ожидаемый синий фон.
2. Макет потока BlueCollectionView пытается отобразить все элементы в первой строке. Похоже, он не знает размер представления коллекции.
3. Когда я пытаюсь выбрать BlueItem: если я щелкаю пустое пространство внутри BlueItem, делегат RedCollectionView запускается, как и ожидалось, но если я щелкаю зеленую часть внутри BlueItem, делегат RedCollectionView не запускается.

...