From 7985fb83cc93f7ba84b4685e1ce49559a7e5fa84 Mon Sep 17 00:00:00 2001 From: Selim Mustafaev Date: Mon, 4 Jul 2022 00:37:27 +0300 Subject: [PATCH] Adding sidebar --- AutoCat2.xcodeproj/project.pbxproj | 56 +++++++-- AutoCat2Mac/Base.lproj/Main.storyboard | 111 +++++++++++------- .../Controller/SidebarController.swift | 94 --------------- .../Controllers/MainSplitController.swift | 17 +++ .../Sidebar/SidebarController.swift | 108 +++++++++++++++++ .../Sidebar/SidebarFilterItem.swift | 38 ++++++ .../Controllers/Sidebar/SidebarItem.swift | 15 +++ .../Controllers/Sidebar/SidebarSection.swift | 24 ++++ AutoCat2Mac/Window/MainWindowController.swift | 30 +++++ AutoCatCore/Models/Filter.swift | 23 ++++ 10 files changed, 372 insertions(+), 144 deletions(-) delete mode 100644 AutoCat2Mac/Controller/SidebarController.swift create mode 100644 AutoCat2Mac/Controllers/MainSplitController.swift create mode 100644 AutoCat2Mac/Controllers/Sidebar/SidebarController.swift create mode 100644 AutoCat2Mac/Controllers/Sidebar/SidebarFilterItem.swift create mode 100644 AutoCat2Mac/Controllers/Sidebar/SidebarItem.swift create mode 100644 AutoCat2Mac/Controllers/Sidebar/SidebarSection.swift create mode 100644 AutoCat2Mac/Window/MainWindowController.swift create mode 100644 AutoCatCore/Models/Filter.swift diff --git a/AutoCat2.xcodeproj/project.pbxproj b/AutoCat2.xcodeproj/project.pbxproj index ade8738..871c805 100644 --- a/AutoCat2.xcodeproj/project.pbxproj +++ b/AutoCat2.xcodeproj/project.pbxproj @@ -87,6 +87,12 @@ 7AE32D6927F06536004EF6E0 /* CoreDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE32D6827F06536004EF6E0 /* CoreDataSource.swift */; }; 7AE32D6E27F06D2D004EF6E0 /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 7AE32D6D27F06D2D004EF6E0 /* SwiftDate */; }; 7AE32D7127F06DA4004EF6E0 /* DateSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE32D7027F06DA4004EF6E0 /* DateSection.swift */; }; + 7AFD7AE02871823E00BCCD37 /* SidebarSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD7ADF2871823E00BCCD37 /* SidebarSection.swift */; }; + 7AFD7AE22871826D00BCCD37 /* SidebarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD7AE12871826D00BCCD37 /* SidebarItem.swift */; }; + 7AFD7AE4287182CD00BCCD37 /* SidebarFilterItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD7AE3287182CD00BCCD37 /* SidebarFilterItem.swift */; }; + 7AFD7AE628718BF000BCCD37 /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD7AE528718BF000BCCD37 /* Filter.swift */; }; + 7AFD7AE82871B7DA00BCCD37 /* MainSplitController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD7AE72871B7DA00BCCD37 /* MainSplitController.swift */; }; + 7AFD7AEB2872355000BCCD37 /* MainWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFD7AEA2872355000BCCD37 /* MainWindowController.swift */; }; 929EDE7F27F89C3000E55F65 /* VEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EDE7E27F89C3000E55F65 /* VEngine.swift */; }; 929EDE8127F8A75E00E55F65 /* VPhoto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EDE8027F8A75E00E55F65 /* VPhoto.swift */; }; 929EDE8327F8C6C500E55F65 /* VOwnershipPeriod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 929EDE8227F8C6C500E55F65 /* VOwnershipPeriod.swift */; }; @@ -246,6 +252,12 @@ 7AE32D6527F063A1004EF6E0 /* UIEdgeInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIEdgeInsets.swift; sourceTree = ""; }; 7AE32D6827F06536004EF6E0 /* CoreDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataSource.swift; sourceTree = ""; }; 7AE32D7027F06DA4004EF6E0 /* DateSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateSection.swift; sourceTree = ""; }; + 7AFD7ADF2871823E00BCCD37 /* SidebarSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarSection.swift; sourceTree = ""; }; + 7AFD7AE12871826D00BCCD37 /* SidebarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarItem.swift; sourceTree = ""; }; + 7AFD7AE3287182CD00BCCD37 /* SidebarFilterItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarFilterItem.swift; sourceTree = ""; }; + 7AFD7AE528718BF000BCCD37 /* Filter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Filter.swift; sourceTree = ""; }; + 7AFD7AE72871B7DA00BCCD37 /* MainSplitController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainSplitController.swift; sourceTree = ""; }; + 7AFD7AEA2872355000BCCD37 /* MainWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainWindowController.swift; sourceTree = ""; }; 929EDE7E27F89C3000E55F65 /* VEngine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VEngine.swift; sourceTree = ""; }; 929EDE8027F8A75E00E55F65 /* VPhoto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPhoto.swift; sourceTree = ""; }; 929EDE8227F8C6C500E55F65 /* VOwnershipPeriod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VOwnershipPeriod.swift; sourceTree = ""; }; @@ -361,12 +373,13 @@ path = Components; sourceTree = ""; }; - 7A0391DB28593DAB000EE522 /* Controller */ = { + 7A0391DB28593DAB000EE522 /* Controllers */ = { isa = PBXGroup; children = ( - 7A0391DC28593DBC000EE522 /* SidebarController.swift */, + 7AFD7ADE2871822000BCCD37 /* Sidebar */, + 7AFD7AE72871B7DA00BCCD37 /* MainSplitController.swift */, ); - path = Controller; + path = Controllers; sourceTree = ""; }; 7A24C19427EE212E00049E7F /* Fonts */ = { @@ -539,6 +552,7 @@ 7A49F50827D406CB00AEAAE0 /* Response.swift */, 7A49F50927D406CB00AEAAE0 /* Settings.swift */, 7A49F50A27D406CB00AEAAE0 /* PlateNumber.swift */, + 7AFD7AE528718BF000BCCD37 /* Filter.swift */, ); path = Models; sourceTree = ""; @@ -584,7 +598,8 @@ 7A9FD4052857AF590057ECFA /* AutoCat2Mac */ = { isa = PBXGroup; children = ( - 7A0391DB28593DAB000EE522 /* Controller */, + 7AFD7AE92872353B00BCCD37 /* Window */, + 7A0391DB28593DAB000EE522 /* Controllers */, 7A9FD4062857AF590057ECFA /* AppDelegate.swift */, 7A9FD4082857AF590057ECFA /* ViewController.swift */, 7A9FD40A2857AF5A0057ECFA /* Assets.xcassets */, @@ -625,6 +640,25 @@ path = DataSource; sourceTree = ""; }; + 7AFD7ADE2871822000BCCD37 /* Sidebar */ = { + isa = PBXGroup; + children = ( + 7A0391DC28593DBC000EE522 /* SidebarController.swift */, + 7AFD7ADF2871823E00BCCD37 /* SidebarSection.swift */, + 7AFD7AE12871826D00BCCD37 /* SidebarItem.swift */, + 7AFD7AE3287182CD00BCCD37 /* SidebarFilterItem.swift */, + ); + path = Sidebar; + sourceTree = ""; + }; + 7AFD7AE92872353B00BCCD37 /* Window */ = { + isa = PBXGroup; + children = ( + 7AFD7AEA2872355000BCCD37 /* MainWindowController.swift */, + ); + path = Window; + sourceTree = ""; + }; 929EDE8A27F8E84F00E55F65 /* vmodels */ = { isa = PBXGroup; children = ( @@ -962,6 +996,7 @@ 7A49F50227D406C300AEAAE0 /* StorageService.swift in Sources */, 7A49F4FE27D406BA00AEAAE0 /* AnyEncodable.swift in Sources */, 7ABAB2E627FDF83100553691 /* GenericMethodMock.swift in Sources */, + 7AFD7AE628718BF000BCCD37 /* Filter.swift in Sources */, 7A49F51227D406CB00AEAAE0 /* VName.swift in Sources */, 7A1D80E827F30399007BD64F /* VModel.swift in Sources */, 7A49F51127D406CB00AEAAE0 /* PlateNumber.swift in Sources */, @@ -1005,6 +1040,11 @@ files = ( 7A9FD4092857AF590057ECFA /* ViewController.swift in Sources */, 7A0391DD28593DBC000EE522 /* SidebarController.swift in Sources */, + 7AFD7AE02871823E00BCCD37 /* SidebarSection.swift in Sources */, + 7AFD7AE4287182CD00BCCD37 /* SidebarFilterItem.swift in Sources */, + 7AFD7AE82871B7DA00BCCD37 /* MainSplitController.swift in Sources */, + 7AFD7AE22871826D00BCCD37 /* SidebarItem.swift in Sources */, + 7AFD7AEB2872355000BCCD37 /* MainWindowController.swift in Sources */, 7A9FD4072857AF590057ECFA /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1344,7 +1384,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCore; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -1379,7 +1419,7 @@ "@executable_path/Frameworks", "@loader_path/Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.0; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCore; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -1453,7 +1493,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1486,7 +1526,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MACOSX_DEPLOYMENT_TARGET = 12.3; + MACOSX_DEPLOYMENT_TARGET = 11.0; MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2Mac; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/AutoCat2Mac/Base.lproj/Main.storyboard b/AutoCat2Mac/Base.lproj/Main.storyboard index 4b31aa1..86caf53 100644 --- a/AutoCat2Mac/Base.lproj/Main.storyboard +++ b/AutoCat2Mac/Base.lproj/Main.storyboard @@ -685,7 +685,7 @@ - + @@ -695,15 +695,22 @@ - + + + + + + + + @@ -722,15 +729,15 @@ - + - + - + @@ -747,107 +754,126 @@ - - + + - - - - + + + + - - + + - + - + - - + + - - - - + + + + + + + + + - + - - + + - - - - + + + + + + + - - - - + + + + + + + + + + + + - - + + - - + + - - - - - + + + + + + + @@ -871,5 +897,6 @@ + diff --git a/AutoCat2Mac/Controller/SidebarController.swift b/AutoCat2Mac/Controller/SidebarController.swift deleted file mode 100644 index a861e86..0000000 --- a/AutoCat2Mac/Controller/SidebarController.swift +++ /dev/null @@ -1,94 +0,0 @@ -// -// MainController.swift -// AutoCat2Mac -// -// Created by Selim Mustafaev on 15.06.2022. -// - -import AppKit - -enum SidebarSection: Int, CaseIterable { - - case source - - var name: String { - switch self { - case .source: - return "Vehicles DB" - } - } -} - -enum VehicleSource: Int, CaseIterable { - - case local - case remote - - var name: String { - switch self { - case .local: - return "Local history" - case .remote: - return "Remote DB" - } - } - - var iconName: String { - switch self { - case .local: - return "internaldrive" - case .remote: - return "externaldrive.connected.to.line.below" - } - } -} - -class SidebarController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate { - - override func viewDidLoad() { - super.viewDidLoad() - } - - // MARK: - NSOutlineViewDataSource - - func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { - guard item != nil else { - return SidebarSection.allCases.count - } - - if let section = item as? SidebarSection { - return VehicleSource.allCases.count - } else { - return 0 - } - } - - func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { - guard item != nil else { - return SidebarSection.source - } - - if let section = item as? SidebarSection { - return VehicleSource.allCases[index] - } else { - return SidebarSection.source - } - } - - func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { - return item is SidebarSection - } - - // MARK: - NSOutlineViewDelegate - - func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { - - if let category = item as? SidebarSection { - let cell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "SidebarHeaderCell"), owner: nil) as? NSTableCellView - cell?.textField?.stringValue = category.name - return cell - } - - return nil - } -} diff --git a/AutoCat2Mac/Controllers/MainSplitController.swift b/AutoCat2Mac/Controllers/MainSplitController.swift new file mode 100644 index 0000000..f95a1c5 --- /dev/null +++ b/AutoCat2Mac/Controllers/MainSplitController.swift @@ -0,0 +1,17 @@ +// +// MainSplitController.swift +// AutoCat2Mac +// +// Created by Selim Mustafaev on 03.07.2022. +// + +import AppKit + +class MainSplitController: NSSplitViewController { + + override func viewDidLoad() { + super.viewDidLoad() + + splitView.autosaveName = "MainSplitViewAutosave" + } +} diff --git a/AutoCat2Mac/Controllers/Sidebar/SidebarController.swift b/AutoCat2Mac/Controllers/Sidebar/SidebarController.swift new file mode 100644 index 0000000..aca9af6 --- /dev/null +++ b/AutoCat2Mac/Controllers/Sidebar/SidebarController.swift @@ -0,0 +1,108 @@ +// +// MainController.swift +// AutoCat2Mac +// +// Created by Selim Mustafaev on 15.06.2022. +// + +import AppKit + +class SidebarController: NSViewController, NSOutlineViewDataSource, NSOutlineViewDelegate { + + @IBOutlet weak var outlineView: NSOutlineView! + + var sections: [SidebarSection] = [ + .database(items: [ + SidebarFilterItem.local, + SidebarFilterItem.remote + ]) + ] + + var addItem: NSToolbarItem? + + override func viewDidLoad() { + super.viewDidLoad() + + outlineView.usesAutomaticRowHeights = true + } + + // MARK: - NSOutlineViewDataSource + + func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { + guard item != nil else { + return sections.count + } + + if let section = item as? SidebarSection { + return section.items.count + } else { + return 0 + } + } + + func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { + guard item != nil else { + return sections[index] + } + + if let section = item as? SidebarSection { + return section.items[index] + } else { + return sections[index] + } + } + + func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { + return item is SidebarSection + } + + // MARK: - NSOutlineViewDelegate + + func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { + + if let category = item as? SidebarSection { + let cell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "SidebarHeaderCell"), owner: nil) as? NSTableCellView + cell?.textField?.stringValue = category.name + return cell + } else if let item = item as? SidebarItem { + let cell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "SidebarItemCell"), owner: nil) as? NSTableCellView + cell?.textField?.stringValue = item.title + cell?.imageView?.image = NSImage(systemSymbolName: item.iconName, accessibilityDescription: item.title) + return cell + } + + return nil + } + + func outlineView(_ outlineView: NSOutlineView, isGroupItem item: Any) -> Bool { + item is SidebarSection + } + + func outlineView(_ outlineView: NSOutlineView, shouldSelectItem item: Any) -> Bool { + outlineView.parent(forItem: item) != nil + } + + func outlineView(_ outlineView: NSOutlineView, persistentObjectForItem item: Any?) -> Any? { + guard let section = item as? SidebarSection else { + return nil + } + + return section.name + } + + func outlineView(_ outlineView: NSOutlineView, itemForPersistentObject object: Any) -> Any? { + guard let name = object as? String else { + return nil + } + + return sections.first { $0.name == name } + } + + func outlineViewSelectionDidChange(_ notification: Notification) { + let item = self.outlineView.item(atRow: self.outlineView.selectedRow) + + if let filter = item as? SidebarFilterItem { + print("Selected filter: ", filter.title) + } + } +} diff --git a/AutoCat2Mac/Controllers/Sidebar/SidebarFilterItem.swift b/AutoCat2Mac/Controllers/Sidebar/SidebarFilterItem.swift new file mode 100644 index 0000000..0138413 --- /dev/null +++ b/AutoCat2Mac/Controllers/Sidebar/SidebarFilterItem.swift @@ -0,0 +1,38 @@ +// +// SidebarFilterItem.swift +// AutoCat2Mac +// +// Created by Selim Mustafaev on 03.07.2022. +// + +import AutoCatCore + +class SidebarFilterItem: SidebarItem { + + var iconName: String + var title: String + var badge: Int? + + let filter: Filter + + init(iconName: String, title: String, filter: Filter) { + + self.iconName = iconName + self.title = title + self.filter = filter + } + + static var local: SidebarFilterItem { + + SidebarFilterItem(iconName: "internaldrive", + title: "Local history", + filter: Filter(dataSource: .local)) + } + + static var remote: SidebarFilterItem { + + SidebarFilterItem(iconName: "externaldrive.connected.to.line.below", + title: "Remote DB", + filter: Filter(dataSource: .remote)) + } +} diff --git a/AutoCat2Mac/Controllers/Sidebar/SidebarItem.swift b/AutoCat2Mac/Controllers/Sidebar/SidebarItem.swift new file mode 100644 index 0000000..56242ac --- /dev/null +++ b/AutoCat2Mac/Controllers/Sidebar/SidebarItem.swift @@ -0,0 +1,15 @@ +// +// SidebarItem.swift +// AutoCat2Mac +// +// Created by Selim Mustafaev on 03.07.2022. +// + +import Foundation + +protocol SidebarItem { + + var iconName: String { get } + var title: String { get } + var badge: Int? { get } +} diff --git a/AutoCat2Mac/Controllers/Sidebar/SidebarSection.swift b/AutoCat2Mac/Controllers/Sidebar/SidebarSection.swift new file mode 100644 index 0000000..3989952 --- /dev/null +++ b/AutoCat2Mac/Controllers/Sidebar/SidebarSection.swift @@ -0,0 +1,24 @@ +// +// SidebarSection.swift +// AutoCat2Mac +// +// Created by Selim Mustafaev on 03.07.2022. +// + +import Foundation + +class SidebarSection { + + let name: String + let items: [SidebarItem] + + init(name: String, items: [SidebarItem]) { + self.name = name + self.items = items + } + + static func database(items: [SidebarItem]) -> SidebarSection { + + SidebarSection(name: "Vehicles DB", items: items) + } +} diff --git a/AutoCat2Mac/Window/MainWindowController.swift b/AutoCat2Mac/Window/MainWindowController.swift new file mode 100644 index 0000000..54f9c02 --- /dev/null +++ b/AutoCat2Mac/Window/MainWindowController.swift @@ -0,0 +1,30 @@ +// +// MainWindowController.swift +// AutoCat2Mac +// +// Created by Selim Mustafaev on 03.07.2022. +// + +import AppKit + +class MainWindowController: NSWindowController { + + override func windowDidLoad() { + super.windowDidLoad() + } + + override func awakeFromNib() { + super.awakeFromNib() + + // First - flexible space item + // Second - new number check item + // Third - sidebar separator item + window?.toolbar?.insertItem(withItemIdentifier: .sidebarTrackingSeparator, at: 2) + } + + // MARK: - Toolbar actions + + @IBAction func checkNewNumber(_ sender: NSToolbarItem) { + print("Check new number") + } +} diff --git a/AutoCatCore/Models/Filter.swift b/AutoCatCore/Models/Filter.swift new file mode 100644 index 0000000..bab5de5 --- /dev/null +++ b/AutoCatCore/Models/Filter.swift @@ -0,0 +1,23 @@ +// +// Filter.swift +// AutoCatCore +// +// Created by Selim Mustafaev on 03.07.2022. +// + +import Foundation + +public enum DataSource { + + case local + case remote +} + +public class Filter { + + var dataSource: DataSource = .remote + + public init(dataSource: DataSource) { + self.dataSource = dataSource + } +}