Skip to content

Commit cb2a368

Browse files
committed
updated
1 parent 19df643 commit cb2a368

File tree

35 files changed

+2089
-108
lines changed

35 files changed

+2089
-108
lines changed

Example/Example.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// AppDelegate.swift
3+
// CollectionViewTemplate
4+
//
5+
// Created by Florian Zand on 19.01.23.
6+
//
7+
8+
import Cocoa
9+
10+
@main
11+
class AppDelegate: NSObject, NSApplicationDelegate {
12+
func applicationDidFinishLaunching(_: Notification) {
13+
// Insert code here to initialize your application
14+
}
15+
16+
func applicationWillTerminate(_: Notification) {
17+
// Insert code here to tear down your application
18+
}
19+
20+
func applicationSupportsSecureRestorableState(_: NSApplication) -> Bool {
21+
true
22+
}
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"colors" : [
3+
{
4+
"idiom" : "universal"
5+
}
6+
],
7+
"info" : {
8+
"author" : "xcode",
9+
"version" : 1
10+
}
11+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "mac",
5+
"scale" : "1x",
6+
"size" : "16x16"
7+
},
8+
{
9+
"idiom" : "mac",
10+
"scale" : "2x",
11+
"size" : "16x16"
12+
},
13+
{
14+
"idiom" : "mac",
15+
"scale" : "1x",
16+
"size" : "32x32"
17+
},
18+
{
19+
"idiom" : "mac",
20+
"scale" : "2x",
21+
"size" : "32x32"
22+
},
23+
{
24+
"idiom" : "mac",
25+
"scale" : "1x",
26+
"size" : "128x128"
27+
},
28+
{
29+
"idiom" : "mac",
30+
"scale" : "2x",
31+
"size" : "128x128"
32+
},
33+
{
34+
"idiom" : "mac",
35+
"scale" : "1x",
36+
"size" : "256x256"
37+
},
38+
{
39+
"idiom" : "mac",
40+
"scale" : "2x",
41+
"size" : "256x256"
42+
},
43+
{
44+
"idiom" : "mac",
45+
"scale" : "1x",
46+
"size" : "512x512"
47+
},
48+
{
49+
"idiom" : "mac",
50+
"scale" : "2x",
51+
"size" : "512x512"
52+
}
53+
],
54+
"info" : {
55+
"author" : "xcode",
56+
"version" : 1
57+
}
58+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}

OutlineViewDiffableDatasource Example/Example/Base.lproj/Main.storyboard

Lines changed: 885 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict/>
5+
</plist>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//
2+
// ViewController.swift
3+
//
4+
//
5+
// Created by Florian Zand on 19.01.23.
6+
//
7+
8+
import AppKit
9+
import AdvancedCollectionTableView
10+
11+
class MainViewController: NSViewController {
12+
typealias DataSource = CollectionViewDiffableDataSource<Section, GalleryItem>
13+
typealias ItemRegistration = NSCollectionView.ItemRegistration<NSCollectionViewItem, GalleryItem>
14+
15+
@IBOutlet var collectionView: NSCollectionView!
16+
17+
var galleryItems = GalleryItem.sampleItems
18+
19+
lazy var dataSource = DataSource(collectionView: collectionView, itemRegistration: itemRegistration)
20+
21+
let itemRegistration = ItemRegistration() { collectionViewItem, _, galleryItem in
22+
/// Configurate the item
23+
var configuration = NSItemContentConfiguration()
24+
configuration.text = galleryItem.title
25+
configuration.secondaryText = galleryItem.detail
26+
configuration.image = NSImage(named: galleryItem.title)
27+
configuration.contentProperties.shadow = .black(opacity: 0.5, radius: 5.0)
28+
if let badgeText = galleryItem.badgeText {
29+
configuration.badges = [.text(badgeText, color: galleryItem.badgeColor, type: .attachment)]
30+
}
31+
32+
if galleryItem.isFavorite {
33+
configuration.badges = [.text("􀋃", color: .systemRed, shape: .circle, type: .attachment)]
34+
}
35+
36+
/// Apply the configuration
37+
collectionViewItem.contentConfiguration = configuration
38+
39+
/// Gets called when the item state changes (on selection, mouse hover, etc.)
40+
collectionViewItem.configurationUpdateHandler = { item, state in
41+
/// Updates the configuration based on whether the mouse is hovering the item
42+
configuration.contentProperties.scaleTransform = state.isHovered ? 1.03 : 1.0
43+
configuration.overlayView = state.isHovered ? NSView(color: .white, opacity: 0.25) : nil
44+
45+
/// Apply the updated configuration animated.
46+
item.contentConfiguration = configuration
47+
}
48+
}
49+
50+
override func viewDidLoad() {
51+
super.viewDidLoad()
52+
53+
collectionView.collectionViewLayout = .grid(columns: 3)
54+
collectionView.dataSource = dataSource
55+
56+
/// Enables deleting selected items via backspace key.
57+
dataSource.deletingHandlers.canDelete = { selectedItems in return selectedItems }
58+
dataSource.deletingHandlers.didDelete = { deletedItems, _ in
59+
self.galleryItems.remove(deletedItems)
60+
}
61+
62+
/// Enables reordering selected items by dragging them.
63+
dataSource.reorderingHandlers.canReorder = { selectedItems in return true }
64+
dataSource.reorderingHandlers.didReorder = { transaction in
65+
self.galleryItems = self.galleryItems.applying(transaction.difference)!
66+
}
67+
68+
dataSource.rightClickHandler = { selectedItems in
69+
selectedItems.forEach({ item in
70+
item.isFavorite = !item.isFavorite
71+
})
72+
/// Reconfigurates items without reloading them by calling the item registration handler.
73+
self.dataSource.reconfigureElements(selectedItems)
74+
}
75+
76+
applySnapshot(using: galleryItems)
77+
78+
dataSource.selectElements([galleryItems.first!], scrollPosition: .top)
79+
collectionView.makeFirstResponder()
80+
}
81+
82+
func applySnapshot(using items: [GalleryItem]) {
83+
var snapshot = dataSource.emptySnapshot()
84+
snapshot.appendSections([.main])
85+
snapshot.appendItems(items, toSection: .main)
86+
dataSource.apply(snapshot, .withoutAnimation)
87+
}
88+
}
89+
90+
private extension NSView {
91+
/// Creates a colored view.
92+
convenience init(color: NSColor, opacity: CGFloat) {
93+
self.init(frame: .zero)
94+
backgroundColor = color
95+
alphaValue = opacity
96+
}
97+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//
2+
// CollectionItem.swift
3+
//
4+
//
5+
// Created by Florian Zand on 24.01.23.
6+
//
7+
8+
import AppKit
9+
import FZQuicklook
10+
11+
public class GalleryItem: NSObject, Identifiable {
12+
13+
public let title: String
14+
public let detail: String
15+
public let badgeText: String?
16+
public let badgeColor: NSColor
17+
public var isFavorite: Bool
18+
19+
public init(_ title: String, detail: String, badgeText: String? = nil, badgeColor: NSColor = .controlAccentColor, isFavorite: Bool = false) {
20+
self.title = title
21+
self.detail = detail
22+
self.badgeText = badgeText
23+
self.badgeColor = badgeColor
24+
self.isFavorite = isFavorite
25+
}
26+
27+
static let sampleItems = [GalleryItem("Neil Catstrong", detail: "Liquid Ink"),
28+
GalleryItem("Majestic Mouser", detail: "Painted by Vermeer"),
29+
GalleryItem("Vapor Cat", detail: "Vaporwave", badgeText: "new"),
30+
GalleryItem("Cosmojelly", detail: "Oil on Canvas"),
31+
GalleryItem("Plasmawhale", detail: "Science Fiction", badgeText: "favorite", badgeColor: .systemPurple),
32+
GalleryItem("Berghain", detail: "Surrealist Painting"),
33+
GalleryItem("About Blank", detail: "Oil Painting"),
34+
GalleryItem("Fireworker Monkey", detail: "Japanese Manga"),
35+
GalleryItem("Dystopian City", detail: "Oil Painting", isFavorite: true),
36+
GalleryItem("Underground", detail: "Oil on Canvas"),
37+
GalleryItem("Tresor", detail: "Painting", isFavorite: true),
38+
GalleryItem("Oxi", detail: "Oil on Canvas")]
39+
}
40+
41+
/// By conforming to `QuicklookPreviewable` and providing `previewItemURL` the items can be previewed by pressing spacebar which opens a Quicklook panel (simliar to Finder).
42+
extension GalleryItem: QuicklookPreviewable {
43+
public var previewItemURL: URL? {
44+
Bundle.main.urlForImageResource(title)
45+
}
46+
47+
public var previewItemTitle: String? {
48+
title
49+
}
50+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// OutlineItem.swift
3+
//
4+
//
5+
// Created by Florian Zand on 22.06.23.
6+
//
7+
8+
import Foundation
9+
10+
struct OutlineItem: Hashable, ExpressibleByStringLiteral, CustomStringConvertible {
11+
let title: String
12+
13+
var description: String {
14+
title
15+
}
16+
17+
init(_ title: String) {
18+
self.title = title
19+
}
20+
21+
init(stringLiteral value: String) {
22+
self.title = value
23+
}
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//
2+
// Section.swift
3+
//
4+
//
5+
// Created by Florian Zand on 22.06.23.
6+
//
7+
8+
import Foundation
9+
10+
public enum Section: String, Hashable, Identifiable {
11+
case main = "Main"
12+
case section2 = "Section 2"
13+
case section3 = "Section 3"
14+
15+
public var title: String {
16+
rawValue
17+
}
18+
19+
public var id: String {
20+
rawValue
21+
}
22+
}
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
//
2+
// SidebarViewController.swift
3+
//
4+
//
5+
// Created by Florian Zand on 19.01.23.
6+
//
7+
8+
import AppKit
9+
import AdvancedCollectionTableView
10+
11+
class SidebarViewController: NSViewController {
12+
typealias DataSource = OutlineViewDiffableDataSource<OutlineItem>
13+
typealias CellRegistration = NSTableView.CellRegistration<NSTableCellView, OutlineItem>
14+
15+
@IBOutlet var outlineView: NSOutlineView!
16+
17+
lazy var dataSource = DataSource(outlineView: outlineView, cellRegistration: cellRegistration)
18+
19+
let cellRegistration = CellRegistration { tableCell, _, _, outlineItem in
20+
/// `defaultContentConfiguration` returns a table cell content configuration with default styling based on the table view it's displayed at (in this case a sidebar table).
21+
var configuration = tableCell.defaultContentConfiguration()
22+
configuration.text = outlineItem.title
23+
tableCell.contentConfiguration = configuration
24+
}
25+
26+
override func viewDidLoad() {
27+
super.viewDidLoad()
28+
29+
outlineView.dataSource = dataSource
30+
dataSource.reorderingHandlers.canReorder = { _, _ in return true }
31+
applySnapshot()
32+
}
33+
34+
func applySnapshot() {
35+
var snapshot = dataSource.emptySnapshot()
36+
let rootItems: [OutlineItem] = ["Root 1", "Root 2", "Root 3", "Root 4", "Root 5"]
37+
snapshot.append(rootItems)
38+
for item in rootItems {
39+
var children: [OutlineItem] = []
40+
for i in 0..<5 {
41+
children.append(.init("\(item.title).\(i+1)"))
42+
}
43+
snapshot.append(children, to: item)
44+
for child in children {
45+
var childs: [OutlineItem] = []
46+
for a in 0..<5 {
47+
childs.append(.init("\(child.title).\(a+1)"))
48+
}
49+
snapshot.append(childs, to: child)
50+
}
51+
}
52+
dataSource.apply(snapshot, .withoutAnimation)
53+
}
54+
}

0 commit comments

Comments
 (0)