diff --git a/Gray.xcodeproj/project.pbxproj b/Gray.xcodeproj/project.pbxproj index 056c98f..230c41f 100644 --- a/Gray.xcodeproj/project.pbxproj +++ b/Gray.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 2AECAC775C01910CCBFAD88E /* libPods-Gray.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C02BDE925690A5BBA8E6D44 /* libPods-Gray.a */; }; BD111046215CEB240002D537 /* Shell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD111045215CEB240002D537 /* Shell.swift */; }; + BD1BA9BE215E68840052633B /* IconController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1BA9BD215E68840052633B /* IconController.swift */; }; BD1D9545215E435F003ABBCF /* VersionController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD1D9544215E435F003ABBCF /* VersionController.swift */; }; BD30844A215C198D002A9349 /* ApplicationsLogicController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD308449215C198D002A9349 /* ApplicationsLogicController.swift */; }; BD67CE0E215BF15F00216FDB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD67CE0D215BF15F00216FDB /* AppDelegate.swift */; }; @@ -17,7 +18,7 @@ BD67CE1C215BF4FE00216FDB /* ApplicationsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD67CE1B215BF4FE00216FDB /* ApplicationsViewController.swift */; }; BD750FDC215C1AC60024E70A /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD750FDB215C1AC60024E70A /* Application.swift */; }; BD9D3D7B215C2D5C00233333 /* ApplicationsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD9D3D7A215C2D5C00233333 /* ApplicationsDataSource.swift */; }; - BD9D3D7D215C2D7100233333 /* ApplicationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD9D3D7C215C2D7100233333 /* ApplicationView.swift */; }; + BD9D3D7D215C2D7100233333 /* ApplicationListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD9D3D7C215C2D7100233333 /* ApplicationListView.swift */; }; BD9D3D7F215C30B000233333 /* ApplicationCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD9D3D7E215C30B000233333 /* ApplicationCollectionViewController.swift */; }; /* End PBXBuildFile section */ @@ -26,6 +27,7 @@ 8925482688825713455FEF24 /* Pods-Gray.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Gray.release.xcconfig"; path = "Target Support Files/Pods-Gray/Pods-Gray.release.xcconfig"; sourceTree = ""; }; 9C02BDE925690A5BBA8E6D44 /* libPods-Gray.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Gray.a"; sourceTree = BUILT_PRODUCTS_DIR; }; BD111045215CEB240002D537 /* Shell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Shell.swift; sourceTree = ""; }; + BD1BA9BD215E68840052633B /* IconController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconController.swift; sourceTree = ""; }; BD1D9544215E435F003ABBCF /* VersionController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VersionController.swift; sourceTree = ""; }; BD308449215C198D002A9349 /* ApplicationsLogicController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationsLogicController.swift; sourceTree = ""; }; BD67CE0A215BF15F00216FDB /* Gray.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Gray.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -37,7 +39,7 @@ BD67CE1B215BF4FE00216FDB /* ApplicationsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationsViewController.swift; sourceTree = ""; }; BD750FDB215C1AC60024E70A /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; BD9D3D7A215C2D5C00233333 /* ApplicationsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationsDataSource.swift; sourceTree = ""; }; - BD9D3D7C215C2D7100233333 /* ApplicationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationView.swift; sourceTree = ""; }; + BD9D3D7C215C2D7100233333 /* ApplicationListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationListView.swift; sourceTree = ""; }; BD9D3D7E215C30B000233333 /* ApplicationCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationCollectionViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -77,6 +79,7 @@ BD67CE0D215BF15F00216FDB /* AppDelegate.swift */, BD111045215CEB240002D537 /* Shell.swift */, BD1D9544215E435F003ABBCF /* VersionController.swift */, + BD1BA9BD215E68840052633B /* IconController.swift */, ); path = Sources; sourceTree = ""; @@ -119,7 +122,7 @@ BD9D3D7A215C2D5C00233333 /* ApplicationsDataSource.swift */, BD308449215C198D002A9349 /* ApplicationsLogicController.swift */, BD67CE1B215BF4FE00216FDB /* ApplicationsViewController.swift */, - BD9D3D7C215C2D7100233333 /* ApplicationView.swift */, + BD9D3D7C215C2D7100233333 /* ApplicationListView.swift */, ); path = Applications; sourceTree = ""; @@ -227,11 +230,12 @@ files = ( BD750FDC215C1AC60024E70A /* Application.swift in Sources */, BD9D3D7B215C2D5C00233333 /* ApplicationsDataSource.swift in Sources */, + BD1BA9BE215E68840052633B /* IconController.swift in Sources */, BD67CE1C215BF4FE00216FDB /* ApplicationsViewController.swift in Sources */, BD67CE0E215BF15F00216FDB /* AppDelegate.swift in Sources */, BD30844A215C198D002A9349 /* ApplicationsLogicController.swift in Sources */, BD1D9545215E435F003ABBCF /* VersionController.swift in Sources */, - BD9D3D7D215C2D7100233333 /* ApplicationView.swift in Sources */, + BD9D3D7D215C2D7100233333 /* ApplicationListView.swift in Sources */, BD111046215CEB240002D537 /* Shell.swift in Sources */, BD9D3D7F215C30B000233333 /* ApplicationCollectionViewController.swift in Sources */, ); diff --git a/Resources/Info.plist b/Resources/Info.plist index e4ff79b..fc5b1f0 100644 --- a/Resources/Info.plist +++ b/Resources/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.0.5 + 0.1.0 CFBundleVersion 1 LSMinimumSystemVersion diff --git a/Sources/Applications/ApplicationCollectionViewController.swift b/Sources/Applications/ApplicationCollectionViewController.swift index 267bfef..867cee8 100644 --- a/Sources/Applications/ApplicationCollectionViewController.swift +++ b/Sources/Applications/ApplicationCollectionViewController.swift @@ -16,7 +16,7 @@ class ApplicationCollectionViewController: NSViewController, ApplicationViewDele itemSize: .init(width: 100, height: 70), minimumLineSpacing: 0) lazy var collectionView = NSCollectionView(layout: layout, - register: ApplicationView.self) + register: ApplicationListView.self) init(models: [Application] = []) { self.dataSource = ApplicationsDataSource(models: models) @@ -44,12 +44,12 @@ class ApplicationCollectionViewController: NSViewController, ApplicationViewDele func collectionView(_ collectionView: NSCollectionView, willDisplay item: NSCollectionViewItem, forRepresentedObjectAt indexPath: IndexPath) { - (item as? ApplicationView)?.delegate = self + (item as? ApplicationListView)?.delegate = self } // MARK: - ApplicationViewDelegate - func applicationView(_ view: ApplicationView, didClickSegmentedControl segmentedControl: NSSegmentedControl) { + func applicationView(_ view: ApplicationListView, didClickSegmentedControl segmentedControl: NSSegmentedControl) { guard let indexPath = collectionView.indexPath(for: view), let appearance = segmentedControl.label(forSegment: segmentedControl.selectedSegment), let newAppearance = Application.Appearance.init(rawValue: appearance) else { return } diff --git a/Sources/Applications/ApplicationView.swift b/Sources/Applications/ApplicationListView.swift similarity index 76% rename from Sources/Applications/ApplicationView.swift rename to Sources/Applications/ApplicationListView.swift index 6310bf9..49c2a76 100644 --- a/Sources/Applications/ApplicationView.swift +++ b/Sources/Applications/ApplicationListView.swift @@ -2,11 +2,13 @@ import Cocoa import UserInterface protocol ApplicationViewDelegate: class { - func applicationView(_ view: ApplicationView, didClickSegmentedControl segmentedControl: NSSegmentedControl) + func applicationView(_ view: ApplicationListView, didClickSegmentedControl segmentedControl: NSSegmentedControl) } -class ApplicationView: NSCollectionViewItem { +class ApplicationListView: NSCollectionViewItem { weak var delegate: ApplicationViewDelegate? + + lazy var iconView: NSImageView = .init() lazy var label: NSTextField = .init() lazy var toggle = NSSegmentedControl(labels: Application.Appearance.allCases.compactMap({ $0.rawValue }), trackingMode: .selectOne, @@ -34,11 +36,15 @@ class ApplicationView: NSCollectionViewItem { label.isBezeled = false label.isEditable = false label.maximumNumberOfLines = 3 - view.addSubviews(line, label, toggle) + view.addSubviews(line, iconView, label, toggle) let margin: CGFloat = 16 NSLayoutConstraint.constrain( - label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: margin), + iconView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: margin), + iconView.centerYAnchor.constraint(equalTo: view.centerYAnchor), + iconView.widthAnchor.constraint(equalToConstant: 36), + iconView.heightAnchor.constraint(equalToConstant: 36), + label.leadingAnchor.constraint(equalTo: iconView.trailingAnchor, constant: margin), label.trailingAnchor.constraint(equalTo: toggle.leadingAnchor, constant: -margin), label.centerYAnchor.constraint(equalTo: view.centerYAnchor), toggle.centerYAnchor.constraint(equalTo: view.centerYAnchor), diff --git a/Sources/Applications/ApplicationsDataSource.swift b/Sources/Applications/ApplicationsDataSource.swift index ca9e8e4..5ef7263 100644 --- a/Sources/Applications/ApplicationsDataSource.swift +++ b/Sources/Applications/ApplicationsDataSource.swift @@ -4,6 +4,7 @@ import UserInterface class ApplicationsDataSource: NSObject, NSCollectionViewDataSource { private(set) var models: [Application] + let iconController = IconController() // MARK: - Initializer @@ -40,8 +41,9 @@ class ApplicationsDataSource: NSObject, NSCollectionViewDataSource { func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem { - return collectionView.dequeue(ApplicationView.self, with: model(at: indexPath), for: indexPath) { + return collectionView.dequeue(ApplicationListView.self, with: model(at: indexPath), for: indexPath) { view, model in + view.iconView.image = self.iconController.icon(for: model) view.label.stringValue = model.name view.toggle.setSelected(model.appearance == .light, forSegment: 0) view.toggle.setSelected(model.appearance == .dark, forSegment: 1) diff --git a/Sources/IconController.swift b/Sources/IconController.swift new file mode 100644 index 0000000..c8553bc --- /dev/null +++ b/Sources/IconController.swift @@ -0,0 +1,15 @@ +import Cocoa + +class IconController { + let cache = NSCache() + + func icon(for application: Application) -> NSImage { + if let image = cache.object(forKey: application.url.path as NSString) { + return image + } + + let image = NSWorkspace.shared.icon(forFile: application.url.path) + cache.setObject(image, forKey: application.url.path as NSString) + return image + } +}