diff --git a/Timer/AppDelegate.swift b/Timer/AppDelegate.swift index 9cb5a4d..3c4e027 100644 --- a/Timer/AppDelegate.swift +++ b/Timer/AppDelegate.swift @@ -20,6 +20,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele func applicationDidFinishLaunching(_ aNotification: Notification) { let controller = MVTimerController() + controller.isMainController = true controllers.append(controller) self.addBadgeToDock(controller: controller) @@ -81,6 +82,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele @objc func newDocument(_ sender: AnyObject?) { let controller = MVTimerController(closeToWindow: NSApplication.shared.keyWindow) controller.window?.level = self.windowLevel() + controller.isMainController = controllers.isEmpty controllers.append(controller) } @@ -109,6 +111,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele } private func registerDefaults() { - UserDefaults.standard.register(defaults: [MVUserDefaultsKeys.staysOnTop: false]) + UserDefaults.standard.register(defaults: [ + MVUserDefaultsKeys.staysOnTop: false, + MVUserDefaultsKeys.typicalTimeSuffixes: false + ]) } } diff --git a/Timer/MVClockView.swift b/Timer/MVClockView.swift index 1f27d8e..fa01fc4 100644 --- a/Timer/MVClockView.swift +++ b/Timer/MVClockView.swift @@ -69,6 +69,11 @@ class MVClockView: NSControl { } } } + var typicalSuffixes = false { + didSet { + self.updateLabels() + } + } // MARK: - @@ -342,28 +347,36 @@ class MVClockView: NSControl { private func updateLabels() { var suffixWidth: CGFloat = 0 + let minutesSuffixFormat: NSString = typicalSuffixes ? "%im" : "%i'" + let secondsSuffixFormat: NSString = typicalSuffixes ? "%is" : "%i\"" if self.seconds < 60 { - minutesLabel.string = NSString(format: "%i\"", Int(self.seconds)) as String + minutesLabel.string = NSString(format: secondsSuffixFormat, Int(self.seconds)) as String suffixWidth = minutesLabelSecondsSuffixWidth } else { - minutesLabel.string = NSString(format: "%i'", Int(self.minutes)) as String + minutesLabel.string = NSString(format: minutesSuffixFormat, Int(self.minutes)) as String suffixWidth = minutesLabelSuffixWidth } minutesLabel.sizeToFit() - var frame = minutesLabel.frame - frame.origin.x = round((self.bounds.width - (frame.size.width - suffixWidth)) / 2) - minutesLabel.frame = frame + // typical suffixes look better without frame adjustments + if !typicalSuffixes { + var frame = minutesLabel.frame + frame.origin.x = round((self.bounds.width - (frame.size.width - suffixWidth)) / 2) + minutesLabel.frame = frame + } if self.seconds < 60 { secondsLabel.string = "" } else { - secondsLabel.string = NSString(format: "%i\"", Int(self.seconds.truncatingRemainder(dividingBy: 60))) as String + secondsLabel.string = NSString(format: secondsSuffixFormat, Int(self.seconds.truncatingRemainder(dividingBy: 60))) as String secondsLabel.sizeToFit() - frame = secondsLabel.frame - frame.origin.x = round((self.bounds.width - (frame.size.width - secondsSuffixWidth)) / 2) - secondsLabel.frame = frame + // typical suffixes look better without frame adjustments + if !typicalSuffixes { + var frame = secondsLabel.frame + frame.origin.x = round((self.bounds.width - (frame.size.width - secondsSuffixWidth)) / 2) + secondsLabel.frame = frame + } } } diff --git a/Timer/MVMainView.swift b/Timer/MVMainView.swift index 1f59288..3301819 100644 --- a/Timer/MVMainView.swift +++ b/Timer/MVMainView.swift @@ -16,6 +16,7 @@ class MVMainView: NSView { private var contextMenu: NSMenu? public var menuItem: NSMenuItem? private var soundMenuItems: [NSMenuItem] = [] + var typicalTimeSuffixMenuItem: NSMenuItem? // swiftlint:disable unused_setter_value override var menu: NSMenu? { @@ -52,9 +53,27 @@ class MVMainView: NSView { submenu.addItem(soundItem) } self.soundMenuItems.first?.state = .on + + let menuItemViewConfig = NSMenuItem( + title: "View", + action: nil, + keyEquivalent: "" + ) + let submenuViewConfig = NSMenu() + submenuViewConfig.autoenablesItems = false + + typicalTimeSuffixMenuItem = NSMenuItem( + title: "Use typical minutes and seconds suffixes", + action: #selector(self.toggleViewItemState), + keyEquivalent: "" + ) + submenuViewConfig.addItem(typicalTimeSuffixMenuItem!) + self.contextMenu?.addItem(menuItem!) self.contextMenu?.addItem(menuItemSoundChoice) self.contextMenu?.setSubmenu(submenu, for: menuItemSoundChoice) + self.contextMenu?.addItem(menuItemViewConfig) + self.contextMenu?.setSubmenu(submenuViewConfig, for: menuItemViewConfig) let notificationCenter = NotificationCenter.default @@ -102,6 +121,17 @@ class MVMainView: NSView { } } + @objc func toggleViewItemState(_ sender: NSMenuItem) { + var value = sender.state == .on ? true : false + value.toggle() + switch sender { + case typicalTimeSuffixMenuItem: + self.controller?.setViewState(value, forKey: MVUserDefaultsKeys.typicalTimeSuffixes) + default: + break + } + } + deinit { NotificationCenter.default.removeObserver(self) } diff --git a/Timer/MVTimerController.swift b/Timer/MVTimerController.swift index ecebb3a..adedea2 100644 --- a/Timer/MVTimerController.swift +++ b/Timer/MVTimerController.swift @@ -8,6 +8,8 @@ class MVTimerController: NSWindowController { private var audioPlayer: AVAudioPlayer? // player must be kept in memory private var soundURL = Bundle.main.url(forResource: "alert-sound", withExtension: "caf") + var isMainController: Bool = false + convenience init() { let mainView = MVMainView(frame: NSRect.zero) @@ -25,6 +27,8 @@ class MVTimerController: NSWindowController { self.windowFrameAutosaveName = "TimerWindowAutosaveFrame" window.makeKeyAndOrderFront(self) + + loadViewStateFromUserDefaults() } convenience init(closeToWindow: NSWindow?) { @@ -105,4 +109,32 @@ class MVTimerController: NSWindowController { self.soundURL = nil } } + + func setViewState(_ value: Bool, forKey viewConfigKey: String) { + setViewState(value, forKey: viewConfigKey, save: isMainController) + } + + private func setViewState(_ value: Bool, forKey viewConfigKey: String, save: Bool) { + let state: NSControl.StateValue = value ? .on : .off + switch viewConfigKey { + case MVUserDefaultsKeys.typicalTimeSuffixes: + mainView.typicalTimeSuffixMenuItem?.state = state + clockView.typicalSuffixes = value + default: + break + } + if save { + UserDefaults.standard.set(value, forKey: viewConfigKey) + } + } + + private func loadViewStateFromUserDefaults() { + let keys: [String] = [ + MVUserDefaultsKeys.typicalTimeSuffixes + ] + for key in keys { + let value = UserDefaults.standard.bool(forKey: key) + setViewState(value, forKey: key, save: false) + } + } } diff --git a/Timer/MVUserDefaultsKeys.swift b/Timer/MVUserDefaultsKeys.swift index d400c83..c1ae6af 100644 --- a/Timer/MVUserDefaultsKeys.swift +++ b/Timer/MVUserDefaultsKeys.swift @@ -1,3 +1,4 @@ struct MVUserDefaultsKeys { static let staysOnTop = "staysOnTop" + static let typicalTimeSuffixes = "typicalTimeSuffixes" }