From e7c949209d988856b5df8fb0712f0e1bb0779a6f Mon Sep 17 00:00:00 2001 From: ad Date: Thu, 17 May 2018 13:47:53 +0300 Subject: [PATCH] + Groups --- MTMR.xcodeproj/project.pbxproj | 4 ++ MTMR/ItemsParsing.swift | 17 ++++++ MTMR/TouchBarController.swift | 30 ++++++++-- MTMR/Widgets/GroupBarItem.swift | 103 ++++++++++++++++++++++++++++++++ 4 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 MTMR/Widgets/GroupBarItem.swift diff --git a/MTMR.xcodeproj/project.pbxproj b/MTMR.xcodeproj/project.pbxproj index d4e619f..192353d 100644 --- a/MTMR.xcodeproj/project.pbxproj +++ b/MTMR.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 6027D1BA2080E52A004FFDC7 /* VolumeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6027D1B82080E52A004FFDC7 /* VolumeViewController.swift */; }; 6042B6A72083E03A00C525C8 /* AppScrubberTouchBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */; }; 6042B6AA2083E27000C525C8 /* DeprecatedCarbonAPI.c in Sources */ = {isa = PBXBuildFile; fileRef = 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */; }; + 60669B4320AD8FA80074E817 /* GroupBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60669B4220AD8FA80074E817 /* GroupBarItem.swift */; }; 607EEA4B2087835F009DA5F0 /* WeatherBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */; }; 607EEA4D2087A8DA009DA5F0 /* CurrencyBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */; }; 60C44AFD20A373A100C0EC91 /* MusicBarItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */; }; @@ -69,6 +70,7 @@ 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppScrubberTouchBarItem.swift; sourceTree = ""; }; 6042B6A82083E1F500C525C8 /* DeprecatedCarbonAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DeprecatedCarbonAPI.h; sourceTree = ""; }; 6042B6A92083E27000C525C8 /* DeprecatedCarbonAPI.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = DeprecatedCarbonAPI.c; sourceTree = ""; }; + 60669B4220AD8FA80074E817 /* GroupBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupBarItem.swift; sourceTree = ""; }; 607EEA4A2087835F009DA5F0 /* WeatherBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeatherBarItem.swift; sourceTree = ""; }; 607EEA4C2087A8DA009DA5F0 /* CurrencyBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrencyBarItem.swift; sourceTree = ""; }; 60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MusicBarItem.swift; sourceTree = ""; }; @@ -236,6 +238,7 @@ 6042B6A62083E03A00C525C8 /* AppScrubberTouchBarItem.swift */, 60F7D453208CC31400ABF5D2 /* InputSourceBarItem.swift */, 60C44AFC20A373A100C0EC91 /* MusicBarItem.swift */, + 60669B4220AD8FA80074E817 /* GroupBarItem.swift */, ); path = Widgets; sourceTree = ""; @@ -370,6 +373,7 @@ B09EB1E4207C082000D5C1E0 /* HapticFeedback.swift in Sources */, 60F7D454208CC31400ABF5D2 /* InputSourceBarItem.swift in Sources */, 36A778BE20A6C27100B38714 /* GeneralExtensions.swift in Sources */, + 60669B4320AD8FA80074E817 /* GroupBarItem.swift in Sources */, 36C2ECDB207C3FE7003CDA33 /* ItemsParsing.swift in Sources */, B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */, 36C2ECD7207B6DAE003CDA33 /* TimeTouchBarItem.swift in Sources */, diff --git a/MTMR/ItemsParsing.swift b/MTMR/ItemsParsing.swift index 6980fa3..86ca580 100644 --- a/MTMR/ItemsParsing.swift +++ b/MTMR/ItemsParsing.swift @@ -136,6 +136,17 @@ class SupportedTypesHolder { parameters: [:] ) }, + "group": { decoder in + enum CodingKeys: CodingKey { case items } + let container = try decoder.container(keyedBy: CodingKeys.self) + let items = try container.decode([BarItemDefinition].self, forKey: .items) + return ( + item: .groupBar(items: items), + action: .none, + longAction: .none, + parameters: [:] + ) + }, ] static let sharedInstance = SupportedTypesHolder() @@ -169,6 +180,7 @@ enum ItemType: Decodable { case currency(interval: Double, from: String, to: String) case inputsource() case music(interval: Double) + case groupBar(items: [BarItemDefinition]) private enum CodingKeys: String, CodingKey { case type @@ -184,6 +196,7 @@ enum ItemType: Decodable { case image case url case longUrl + case items } enum ItemTypeRaw: String, Decodable { @@ -198,6 +211,7 @@ enum ItemType: Decodable { case currency case inputsource case music + case groupBar } init(from decoder: Decoder) throws { @@ -239,6 +253,9 @@ enum ItemType: Decodable { case .music: let interval = try container.decodeIfPresent(Double.self, forKey: .refreshInterval) ?? 1800.0 self = .music(interval: interval) + case .groupBar: + let items = try container.decodeIfPresent([BarItemDefinition].self, forKey: .items) + self = .groupBar(items: items!) } } } diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift index 41bdd2c..08f2b89 100644 --- a/MTMR/TouchBarController.swift +++ b/MTMR/TouchBarController.swift @@ -39,6 +39,8 @@ extension ItemType { return "com.toxblh.mtmr.inputsource." case .music(interval: _): return "com.toxblh.mtmr.music." + case .groupBar(items: _): + return "com.toxblh.mtmr.groupBar." } } @@ -73,6 +75,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate { } } + var touchbarHidden: Bool = true + var blacklistAppIdentifiers: [String] = [] var frontmostApplicationIdentifier: String? { get { @@ -84,6 +88,10 @@ class TouchBarController: NSObject, NSTouchBarDelegate { private override init() { super.init() SupportedTypesHolder.sharedInstance.register(typename: "exitTouchbar", item: .staticButton(title: "exit"), action: .custom(closure: { [weak self] in self?.dismissTouchBar()}), longAction: .none) + + SupportedTypesHolder.sharedInstance.register(typename: "close") { _ in + return (item: .staticButton(title: ""), action: .custom(closure: { [weak self] in self?.touchbarHidden = true; self?.createAndUpdatePreset() }), longAction: .none, parameters: [.width: .width(30), .image: .image(source: (NSImage(named: .stopProgressFreestandingTemplate))!)]) + } if let blackListed = UserDefaults.standard.stringArray(forKey: "com.toxblh.mtmr.blackListedApps") { self.blacklistAppIdentifiers = blackListed @@ -138,8 +146,10 @@ class TouchBarController: NSObject, NSTouchBarDelegate { func updateActiveApp() { if self.blacklistAppIdentifiers.index(of: self.frontmostApplicationIdentifier!) != nil { DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, false) + self.touchbarHidden = true } else { presentTouchBar() + self.touchbarHidden = false } } @@ -196,10 +206,12 @@ class TouchBarController: NSObject, NSTouchBarDelegate { } @objc private func presentTouchBar() { - if self.controlStripState { - NSTouchBar.presentSystemModalFunctionBar(touchBar, systemTrayItemIdentifier: .controlStripItem) - } else { - NSTouchBar.presentSystemModalFunctionBar(touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem) + if touchbarHidden { + if self.controlStripState { + NSTouchBar.presentSystemModalFunctionBar(touchBar, systemTrayItemIdentifier: .controlStripItem) + } else { + NSTouchBar.presentSystemModalFunctionBar(touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem) + } } } @@ -259,6 +271,8 @@ class TouchBarController: NSObject, NSTouchBarDelegate { barItem = InputSourceBarItem(identifier: identifier) case .music(interval: let interval): barItem = MusicBarItem(identifier: identifier, interval: interval) + case .groupBar(items: let items): + barItem = GroupBarItem(identifier: identifier, items: items) } if let action = self.action(forItem: item), let item = barItem as? CustomButtonTouchBarItem { @@ -279,8 +293,12 @@ class TouchBarController: NSObject, NSTouchBarDelegate { if case .image(let source)? = item.additionalParameters[.image], let item = barItem as? CustomButtonTouchBarItem { item.image = source.image } - if case .title(let value)? = item.additionalParameters[.title], let item = barItem as? CustomButtonTouchBarItem { - item.title = value + if case .title(let value)? = item.additionalParameters[.title] { + if let item = barItem as? GroupBarItem { + item.collapsedRepresentationLabel = value + } else if let item = barItem as? CustomButtonTouchBarItem { + item.title = value + } } return barItem } diff --git a/MTMR/Widgets/GroupBarItem.swift b/MTMR/Widgets/GroupBarItem.swift new file mode 100644 index 0000000..aa10e9a --- /dev/null +++ b/MTMR/Widgets/GroupBarItem.swift @@ -0,0 +1,103 @@ +// +// GroupBarItem.swift +// MTMR +// +// Created by Daniel Apatin on 11.05.2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// +import Cocoa + +class GroupBarItem: NSPopoverTouchBarItem, NSTouchBarDelegate { + + var jsonItems: [BarItemDefinition] + + var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:] + var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:] + var leftIdentifiers: [NSTouchBarItem.Identifier] = [] + var centerIdentifiers: [NSTouchBarItem.Identifier] = [] + var centerItems: [NSTouchBarItem] = [] + var rightIdentifiers: [NSTouchBarItem.Identifier] = [] + var scrollArea: NSCustomTouchBarItem? + var centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString)) + + init(identifier: NSTouchBarItem.Identifier, items: [BarItemDefinition]) { + jsonItems = items + super.init(identifier: identifier) + self.popoverTouchBar.delegate = self + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + + } + + @objc override func showPopover(_ sender: Any?) { + self.itemDefinitions = [:] + self.items = [:] + self.leftIdentifiers = [] + self.centerItems = [] + self.rightIdentifiers = [] + + self.loadItemDefinitions(jsonItems: jsonItems) + self.createItems() + + centerItems = centerIdentifiers.compactMap({ (identifier) -> NSTouchBarItem? in + return items[identifier] + }) + + self.centerScrollArea = NSTouchBarItem.Identifier("com.toxblh.mtmr.scrollArea.".appending(UUID().uuidString)) + self.scrollArea = ScrollViewItem(identifier: centerScrollArea, items: centerItems) + + TouchBarController.shared.touchBar.delegate = self + TouchBarController.shared.touchBar.defaultItemIdentifiers = [] + TouchBarController.shared.touchBar.defaultItemIdentifiers = self.leftIdentifiers + [centerScrollArea] + self.rightIdentifiers + + if TouchBarController.shared.controlStripState { + NSTouchBar.presentSystemModalFunctionBar(TouchBarController.shared.touchBar, systemTrayItemIdentifier: .controlStripItem) + } else { + NSTouchBar.presentSystemModalFunctionBar(TouchBarController.shared.touchBar, placement: 1, systemTrayItemIdentifier: .controlStripItem) + } + } + + func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? { + if identifier == centerScrollArea { + return self.scrollArea + } + + guard let item = self.items[identifier], + let definition = self.itemDefinitions[identifier], + definition.align != .center else { + return nil + } + return item + } + + func loadItemDefinitions(jsonItems: [BarItemDefinition]) { + let dateFormatter = DateFormatter() + dateFormatter.dateFormat = "HH-mm-ss" + let time = dateFormatter.string(from: Date()) + for item in jsonItems { + let identifierString = item.type.identifierBase.appending(time + "--" + UUID().uuidString) + let identifier = NSTouchBarItem.Identifier(identifierString) + itemDefinitions[identifier] = item + if item.align == .left { + leftIdentifiers.append(identifier) + } + if item.align == .right { + rightIdentifiers.append(identifier) + } + if item.align == .center { + centerIdentifiers.append(identifier) + } + } + } + + func createItems() { + for (identifier, definition) in self.itemDefinitions { + self.items[identifier] = TouchBarController.shared.createItem(forIdentifier: identifier, definition: definition) + } + } +}