diff --git a/AMD Power Gadget/AppDelegate.swift b/AMD Power Gadget/AppDelegate.swift index e3bd786..a40fd30 100644 --- a/AMD Power Gadget/AppDelegate.swift +++ b/AMD Power Gadget/AppDelegate.swift @@ -37,7 +37,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { } static func haveActiveWindows() -> Bool { - if !UserDefaults.standard.bool(forKey: "statusbarenabled") {return true} + guard UserDefaults.statusbarenabled else { return true } return ViewController.activeSelf != nil || PowerToolViewController.activeSelf != nil @@ -65,23 +65,13 @@ class AppDelegate: NSObject, NSApplicationDelegate { } func applicationDidFinishLaunching(_ aNotification: Notification) { + let useTran = UserDefaults.usetranslucency + let sb = UserDefaults.statusbarenabled + let sl = UserDefaults.startAtLogin - let keyDefaults = [ - "usetranslucency" : false, - "statusbarenabled": true, - "startAtLogin": false, - "startAtLoginAsked": false - ] - - UserDefaults.standard.register(defaults: keyDefaults) - - let useTran = UserDefaults.standard.bool(forKey: "usetranslucency") - let sb = UserDefaults.standard.bool(forKey: "statusbarenabled") - let sl = UserDefaults.standard.bool(forKey: "startAtLogin") - - if !UserDefaults.standard.bool(forKey: "startAtLoginAsked") { + if !UserDefaults.startAtLoginAsked { askStartup() - UserDefaults.standard.set(true, forKey: "startAtLoginAsked") + UserDefaults.startAtLoginAsked = true } else { applyStartAtLogin(enabled: sl) } applyStatusBarSwitch(enabled: sb) @@ -122,7 +112,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { ViewController.activeSelf?.toggleTranslucency(enabled: translucency) PowerToolViewController.activeSelf?.toggleTranslucency(enabled: translucency) - UserDefaults.standard.set(translucency, forKey: "usetranslucency") + UserDefaults.usetranslucency = translucency } func applyStatusBarSwitch(enabled: Bool) { @@ -137,13 +127,28 @@ class AppDelegate: NSObject, NSApplicationDelegate { mbController = nil } - UserDefaults.standard.set(enabled, forKey: "statusbarenabled") + UserDefaults.statusbarenabled = enabled } func applyStartAtLogin(enabled: Bool) { startAtLoginToggle.state = enabled ? .on : .off - UserDefaults.standard.set(enabled, forKey: "startAtLogin") + UserDefaults.startAtLogin = enabled SMLoginItemSetEnabled("wtf.spinach.APGLaunchHelper" as CFString, enabled) } } +import UserDefaultValue + +extension UserDefaults { + @UserDefaultValue(key: "usetranslucency") + static var usetranslucency = false + + @UserDefaultValue(key: "statusbarenabled") + static var statusbarenabled = false + + @UserDefaultValue(key: "startAtLogin") + static var startAtLogin = false + + @UserDefaultValue(key: "startAtLoginAsked") + static var startAtLoginAsked = false +} diff --git a/AMD Power Gadget/Power Tool/PowerToolViewController.swift b/AMD Power Gadget/Power Tool/PowerToolViewController.swift index 16086ee..a7ee00b 100644 --- a/AMD Power Gadget/Power Tool/PowerToolViewController.swift +++ b/AMD Power Gadget/Power Tool/PowerToolViewController.swift @@ -122,7 +122,7 @@ class PowerToolViewController: NSViewController, NSWindowDelegate { topLabel1.font = NSFont(name: "SF Pro Rounded", size: 32) topLabel2.font = NSFont(name: "SF Pro Rounded", size: 32) - toggleTranslucency(enabled: UserDefaults.standard.bool(forKey: "usetranslucency")) + toggleTranslucency(enabled: UserDefaults.usetranslucency) PowerToolViewController.activeSelf = self AppDelegate.updateDockIcon() diff --git a/AMD Power Gadget/StatusbarController.swift b/AMD Power Gadget/StatusbarController.swift index 778bd99..1866a91 100644 --- a/AMD Power Gadget/StatusbarController.swift +++ b/AMD Power Gadget/StatusbarController.swift @@ -7,8 +7,9 @@ // import Cocoa +import MenuBuilder -fileprivate class StatusbarView: NSView{ +fileprivate class StatusbarView: NSView { var meanFreq: Float = 0 var maxFreq: Float = 0 @@ -20,15 +21,13 @@ fileprivate class StatusbarView: NSView{ var normalValue: [NSAttributedString.Key : NSObject]? var compactValue: [NSAttributedString.Key : NSObject]? - - func setup(){ + func setup() { let compactLH: CGFloat = 6 let p = NSMutableParagraphStyle() p.minimumLineHeight = compactLH p.maximumLineHeight = compactLH compactLabel = [ - NSAttributedString.Key.font: NSFont.init(name: "Monaco", size: 7.2)!, NSAttributedString.Key.foregroundColor: NSColor.labelColor, NSAttributedString.Key.paragraphStyle: p @@ -51,20 +50,26 @@ fileprivate class StatusbarView: NSView{ } override func draw(_ dirtyRect: NSRect) { - guard let context = NSGraphicsContext.current?.cgContext else { return } - - let fr = String(format: "%.1f", meanFreq * 0.001) -// drawCompactSingle(label: "AVG", value: "\(fr) Ghz", x: 0) - - let mfr = String(format: "%.1f", maxFreq * 0.001) - - - drawDoubleCompactValue(label: "CPU", up: "\(mfr) Ghz", down: "\(fr) Ghz", x: 0) - drawCompactSingle(label: "TEM", value: "\(Int(round(temp)))º", x: 80) - drawCompactSingle(label: "PWR", value: "\(Int(round(pwr)))W", x: 122) + var width: CGFloat = 0 + if UserDefaults.showCPUUsage { + let fr = String(format: "%.1f", meanFreq * 0.001) +// drawCompactSingle(label: "AVG", value: "\(fr) Ghz", x: 0) + let mfr = String(format: "%.1f", maxFreq * 0.001) + drawDoubleCompactValue(label: "CPU", up: "\(mfr) Ghz", down: "\(fr) Ghz", x: &width) + } + if UserDefaults.showTemperatureUsage { + drawCompactSingle(label: "TEM", value: "\(Int(round(temp)))º", x: &width) + } + if UserDefaults.showPowerUsage { + drawCompactSingle(label: "PWR", value: "\(Int(round(pwr)))W", x: &width) + } + + if width != frame.width { + frame = NSRect(origin: frame.origin, size: CGSize(width: width, height: frame.height)) + } } - func drawDoubleCompactValue(label: String, up: String, down: String, x: CGFloat) { + func drawDoubleCompactValue(label: String, up: String, down: String, x: inout CGFloat) { let attributedString = NSAttributedString(string: label, attributes: normalLabel) attributedString.draw(at: NSPoint(x: x, y: 2.5)) @@ -73,14 +78,18 @@ fileprivate class StatusbarView: NSView{ let down = NSAttributedString(string: down, attributes: compactValue) down.draw(at: NSPoint(x: x + 33, y: 0)) + + x += 80 } - func drawCompactSingle(label: String, value: String, x: CGFloat) { + func drawCompactSingle(label: String, value: String, x: inout CGFloat) { let attributedString = NSAttributedString(string: label, attributes: compactLabel) attributedString.draw(in: NSRect(x: x, y: -4.5, width: 7, height: frame.height)) let value = NSAttributedString(string: value, attributes: normalValue) value.draw(at: NSPoint(x: x + 10, y: 2.5)) + + x += 42 } } @@ -106,10 +115,9 @@ class StatusbarController { statusItem.button?.action = #selector(itemClicked) statusItem.button?.sendAction(on: [.leftMouseUp, .rightMouseUp]) - statusItem.length = 170 view.frame = statusItem.button!.bounds - addMenuItems() + rebuildMenuItems() updateTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { _ in self.update() @@ -141,7 +149,9 @@ class StatusbarController { view?.temp = temperature view?.pwr = power view.setNeedsDisplay(view.frame) - + if statusItem.length != view.frame.width { + statusItem.length = view.frame.width + } } @objc func itemClicked(){ @@ -176,24 +186,63 @@ class StatusbarController { exit(0) } - private func addMenuItems() { - menu = NSMenu() - guard let m = menu else {return} - var item = NSMenuItem(title: "AMD Power Gadget", action: #selector(gadget), keyEquivalent: ""); item.target = self - m.addItem(item) - item = NSMenuItem(title: "AMD Power Tool", action: #selector(tool), keyEquivalent: ""); item.target = self - m.addItem(item) - item = NSMenuItem(title: "SMC Fans", action: #selector(fans), keyEquivalent: ""); item.target = self - m.addItem(item) - - - m.addItem(NSMenuItem.separator()) - - item = NSMenuItem(title: "Exit", action: #selector(exitApp), keyEquivalent: ""); item.target = self - m.addItem(item) - -// statusItem.menu = menu + private func rebuildMenuItems() { + menu = NSMenu { + MenuItem("AMD Power Gadget") + .onSelect { [unowned self] in + gadget() + } + MenuItem("AMD Power Tool") + .onSelect { [unowned self] in + tool() + } + MenuItem("SMC Fans") + .onSelect { [unowned self] in + fans() + } + SeparatorItem() + createMenuItem("Show CPU Usage", defaults: UserDefaults.$showCPUUsage) + createMenuItem("Show Temperature Usage", defaults: UserDefaults.$showTemperatureUsage) + createMenuItem("Show Power Usage", defaults: UserDefaults.$showPowerUsage) + SeparatorItem() + MenuItem("Exit") + .shortcut("q") + .onSelect { [unowned self] in + exitApp() + } + } } + + private func createMenuItem(_ text: String, defaults: UserDefaultValue) -> MenuItem { + if !defaults.wrappedValue || canHideMenuItem() { + return MenuItem(text) + .state(defaults.wrappedValue ? .on : .off) + .onSelect { [unowned self] in + defaults.wrappedValue.toggle() + rebuildMenuItems() + } + } else { + return MenuItem(text) + .state(defaults.wrappedValue ? .on : .off) + .toolTip("Do Not Allow to Hide All MenuBarItem") + } + } + + private func canHideMenuItem() -> Bool { + // Do Not Allow to Hide All MenuBarItem + [UserDefaults.showCPUUsage, UserDefaults.showTemperatureUsage, UserDefaults.showPowerUsage].filter { $0 }.count > 1 + } } +import UserDefaultValue +private extension UserDefaults { + @UserDefaultValue(key: "showCPUUsage") + static var showCPUUsage = true + + @UserDefaultValue(key: "showTemperatureUsage") + static var showTemperatureUsage = true + + @UserDefaultValue(key: "showPowerUsage") + static var showPowerUsage = true +} diff --git a/AMD Power Gadget/ViewController.swift b/AMD Power Gadget/ViewController.swift index b3fba89..990ebe4 100644 --- a/AMD Power Gadget/ViewController.swift +++ b/AMD Power Gadget/ViewController.swift @@ -74,7 +74,7 @@ class ViewController: NSViewController, NSWindowDelegate { timeStart = Date.timeIntervalSinceReferenceDate - toggleTranslucency(enabled: UserDefaults.standard.bool(forKey: "usetranslucency")) + toggleTranslucency(enabled: UserDefaults.usetranslucency) sampleData(forced: true) sampleData(forced: true) diff --git a/SMCAMDProcessor.xcodeproj/project.pbxproj b/SMCAMDProcessor.xcodeproj/project.pbxproj index ef32302..87afedb 100644 --- a/SMCAMDProcessor.xcodeproj/project.pbxproj +++ b/SMCAMDProcessor.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ @@ -49,6 +49,8 @@ B5F46D7F240E593D009F2961 /* CPUPowerStepView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F46D7E240E593D009F2961 /* CPUPowerStepView.swift */; }; B5F46D81240E6F19009F2961 /* ProcessorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F46D80240E6F19009F2961 /* ProcessorModel.swift */; }; B5F46D83240E76D9009F2961 /* PowerToolViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5F46D82240E76D9009F2961 /* PowerToolViewController.swift */; }; + F7B467B828A0FA6900C5A338 /* UserDefaultValue in Frameworks */ = {isa = PBXBuildFile; productRef = F7B467B728A0FA6900C5A338 /* UserDefaultValue */; }; + F7B467BE28A10A7300C5A338 /* MenuBuilder in Frameworks */ = {isa = PBXBuildFile; productRef = F7B467BD28A10A7300C5A338 /* MenuBuilder */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -132,6 +134,8 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + F7B467B828A0FA6900C5A338 /* UserDefaultValue in Frameworks */, + F7B467BE28A10A7300C5A338 /* MenuBuilder in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -395,6 +399,10 @@ dependencies = ( ); name = "AMD Power Gadget"; + packageProductDependencies = ( + F7B467B728A0FA6900C5A338 /* UserDefaultValue */, + F7B467BD28A10A7300C5A338 /* MenuBuilder */, + ); productName = "AMD Power Gadget"; productReference = B56162C42400EF770006A7D8 /* AMD Power Gadget.app */; productType = "com.apple.product-type.application"; @@ -467,6 +475,10 @@ Base, ); mainGroup = B57D27EA23F66AE7002BC699; + packageReferences = ( + F7B467B628A0FA6900C5A338 /* XCRemoteSwiftPackageReference "UserDefaultValue" */, + F7B467BC28A10A7300C5A338 /* XCRemoteSwiftPackageReference "MenuBuilder" */, + ); productRefGroup = B57D27F523F66AE7002BC699 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -976,6 +988,38 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + F7B467B628A0FA6900C5A338 /* XCRemoteSwiftPackageReference "UserDefaultValue" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/mlch911/UserDefaultValue"; + requirement = { + branch = master; + kind = branch; + }; + }; + F7B467BC28A10A7300C5A338 /* XCRemoteSwiftPackageReference "MenuBuilder" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/mlch911/MenuBuilder"; + requirement = { + branch = main; + kind = branch; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + F7B467B728A0FA6900C5A338 /* UserDefaultValue */ = { + isa = XCSwiftPackageProductDependency; + package = F7B467B628A0FA6900C5A338 /* XCRemoteSwiftPackageReference "UserDefaultValue" */; + productName = UserDefaultValue; + }; + F7B467BD28A10A7300C5A338 /* MenuBuilder */ = { + isa = XCSwiftPackageProductDependency; + package = F7B467BC28A10A7300C5A338 /* XCRemoteSwiftPackageReference "MenuBuilder" */; + productName = MenuBuilder; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = B57D27EB23F66AE7002BC699 /* Project object */; } diff --git a/SMCAMDProcessor.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/SMCAMDProcessor.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 5e70afb..919434a 100644 --- a/SMCAMDProcessor.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/SMCAMDProcessor.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:">