diff --git a/PHP Monitor.xcodeproj/project.pbxproj b/PHP Monitor.xcodeproj/project.pbxproj index 11c1351..3e02353 100644 --- a/PHP Monitor.xcodeproj/project.pbxproj +++ b/PHP Monitor.xcodeproj/project.pbxproj @@ -25,6 +25,10 @@ C476FF9822B0DD830098105B /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = C476FF9722B0DD830098105B /* Alert.swift */; }; C4811D2422D70A4700B5F6B3 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2322D70A4700B5F6B3 /* App.swift */; }; C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */; }; + C48D0C9025CC7FD000CC7490 /* StatsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C48D0C8F25CC7FD000CC7490 /* StatsView.xib */; }; + C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C48D0C9225CC804200CC7490 /* XibLoadable.swift */; }; + C48D0C9625CC80B100CC7490 /* XibViews.swift in Sources */ = {isa = PBXBuildFile; fileRef = C48D0C9525CC80B100CC7490 /* XibViews.swift */; }; + C48D0C9A25CC888B00CC7490 /* HeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C48D0C9925CC888B00CC7490 /* HeaderView.xib */; }; C49EAB46259FC305007F6C3B /* Paths.swift in Sources */ = {isa = PBXBuildFile; fileRef = C49EAB45259FC305007F6C3B /* Paths.swift */; }; C4ACA38F25C754C100060C66 /* PhpExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4ACA38E25C754C100060C66 /* PhpExtension.swift */; }; C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; }; @@ -54,6 +58,10 @@ C476FF9722B0DD830098105B /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = ""; }; C4811D2322D70A4700B5F6B3 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = ""; }; C4811D2922D70F9A00B5F6B3 /* MainMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainMenu.swift; sourceTree = ""; }; + C48D0C8F25CC7FD000CC7490 /* StatsView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatsView.xib; sourceTree = ""; }; + C48D0C9225CC804200CC7490 /* XibLoadable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XibLoadable.swift; sourceTree = ""; }; + C48D0C9525CC80B100CC7490 /* XibViews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XibViews.swift; sourceTree = ""; }; + C48D0C9925CC888B00CC7490 /* HeaderView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = HeaderView.xib; sourceTree = ""; }; C49EAB45259FC305007F6C3B /* Paths.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Paths.swift; sourceTree = ""; }; C4ACA38E25C754C100060C66 /* PhpExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhpExtension.swift; sourceTree = ""; }; C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = ""; }; @@ -144,6 +152,9 @@ isa = PBXGroup; children = ( C47331A1247093B7009A0597 /* StatusMenu.swift */, + C48D0C9925CC888B00CC7490 /* HeaderView.xib */, + C48D0C8F25CC7FD000CC7490 /* StatsView.xib */, + C48D0C9525CC80B100CC7490 /* XibViews.swift */, ); path = Menu; sourceTree = ""; @@ -194,6 +205,7 @@ children = ( C4F8C0A322D4F12C002EFE61 /* DateExtension.swift */, C46FA23E246C358E00944F05 /* StringExtension.swift */, + C48D0C9225CC804200CC7490 /* XibLoadable.swift */, ); path = Extensions; sourceTree = ""; @@ -258,9 +270,11 @@ files = ( C41C1B3B22B0098000E7CF16 /* Assets.xcassets in Resources */, C41C1B3E22B0098000E7CF16 /* Main.storyboard in Resources */, + C48D0C9025CC7FD000CC7490 /* StatsView.xib in Resources */, C405A4D124B9B9140062FAFA /* InternetAccessPolicy.plist in Resources */, C473319F2470923A009A0597 /* Localizable.strings in Resources */, C405A4D024B9B9140062FAFA /* InternetAccessPolicy.strings in Resources */, + C48D0C9A25CC888B00CC7490 /* HeaderView.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -279,6 +293,7 @@ C42295DD2358D02000E263B2 /* Command.swift in Sources */, C4811D2422D70A4700B5F6B3 /* App.swift in Sources */, C41C1B4922B00A9800E7CF16 /* MenuBarImageGenerator.swift in Sources */, + C48D0C9325CC804200CC7490 /* XibLoadable.swift in Sources */, C4811D2A22D70F9A00B5F6B3 /* MainMenu.swift in Sources */, C412E5FC25700D5300A1FB67 /* HomebrewPackage.swift in Sources */, C41C1B3722B0097F00E7CF16 /* AppDelegate.swift in Sources */, @@ -286,6 +301,7 @@ C49EAB46259FC305007F6C3B /* Paths.swift in Sources */, C476FF9822B0DD830098105B /* Alert.swift in Sources */, C474B00624C0E98C00066A22 /* LocalNotification.swift in Sources */, + C48D0C9625CC80B100CC7490 /* XibViews.swift in Sources */, C47331A2247093B7009A0597 /* StatusMenu.swift in Sources */, C46FA23F246C358E00944F05 /* StringExtension.swift in Sources */, C4EE188422D3386B00E126E5 /* Constants.swift in Sources */, diff --git a/phpmon/Classes/Menu/HeaderView.xib b/phpmon/Classes/Menu/HeaderView.xib new file mode 100644 index 0000000..e04af43 --- /dev/null +++ b/phpmon/Classes/Menu/HeaderView.xib @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpmon/Classes/Menu/StatsView.xib b/phpmon/Classes/Menu/StatsView.xib new file mode 100644 index 0000000..e28f11f --- /dev/null +++ b/phpmon/Classes/Menu/StatsView.xib @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/phpmon/Classes/Menu/StatusMenu.swift b/phpmon/Classes/Menu/StatusMenu.swift index 71b7cf4..ea0ea51 100644 --- a/phpmon/Classes/Menu/StatusMenu.swift +++ b/phpmon/Classes/Menu/StatusMenu.swift @@ -19,9 +19,9 @@ class StatusMenu : NSMenu { } return } - - let string = "\("mi_php_version".localized) \(App.phpInstall!.version.long)" - self.addItem(NSMenuItem(title: string, action: nil, keyEquivalent: "")) + + let phpVersionText = "\("mi_php_version".localized) \(App.phpInstall!.version.long)" + self.addItem(HeaderView.asMenuItem(text: phpVersionText)) } public func addPhpActionMenuItems() { @@ -56,7 +56,7 @@ class StatusMenu : NSMenu { } private func addServicesMenuItems() { - self.addItem(NSMenuItem(title: "mi_active_services".localized, action: nil, keyEquivalent: "")) + self.addItem(HeaderView.asMenuItem(text: "mi_active_services".localized)) let services = NSMenuItem(title: "mi_restart_specific".localized, action: nil, keyEquivalent: "") let servicesMenu = NSMenu() @@ -79,21 +79,18 @@ class StatusMenu : NSMenu { } // Configuration - self.addItem(NSMenuItem(title: "mi_configuration".localized, action: nil, keyEquivalent: "")) + self.addItem(HeaderView.asMenuItem(text: "mi_configuration".localized)) self.addItem(NSMenuItem(title: "mi_valet_config".localized, action: #selector(MainMenu.openValetConfigFolder), keyEquivalent: "v")) self.addItem(NSMenuItem(title: "mi_php_config".localized, action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "c")) self.addItem(NSMenuItem(title: "mi_phpinfo".localized, action: #selector(MainMenu.openPhpInfo), keyEquivalent: "i")) - // Limits + // Stats self.addItem(NSMenuItem.separator()) - self.addItem(NSMenuItem(title: "mi_limits".localized, action: nil, keyEquivalent: "")) - self.addItem(NSMenuItem(title: "\("mi_memory_limit".localized): \(App.phpInstall!.configuration.memory_limit)", action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "")) - self.addItem(NSMenuItem(title: "\("mi_post_max_size".localized): \(App.phpInstall!.configuration.post_max_size)", action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "")) - self.addItem(NSMenuItem(title: "\("mi_upload_max_filesize".localized): \(App.phpInstall!.configuration.upload_max_filesize)", action: #selector(MainMenu.openActiveConfigFolder), keyEquivalent: "")) + self.addItem(StatsView.asMenuItem()) // Extensions self.addItem(NSMenuItem.separator()) - self.addItem(NSMenuItem(title: "mi_detected_extensions".localized, action: nil, keyEquivalent: "")) + self.addItem(HeaderView.asMenuItem(text: "mi_detected_extensions".localized)) if (App.phpInstall!.extensions.count == 0) { self.addItem(NSMenuItem(title: "mi_no_extensions_detected".localized, action: nil, keyEquivalent: "")) diff --git a/phpmon/Classes/Menu/XibViews.swift b/phpmon/Classes/Menu/XibViews.swift new file mode 100644 index 0000000..060f345 --- /dev/null +++ b/phpmon/Classes/Menu/XibViews.swift @@ -0,0 +1,31 @@ +// +// StatsView.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 04/02/2021. +// Copyright © 2021 Nico Verbruggen. All rights reserved. +// + +import Foundation +import Cocoa + +class StatsView: NSView, XibLoadable { + static func asMenuItem() -> NSMenuItem { + let item = NSMenuItem() + item.view = Self.createFromXib() + item.target = self + return item + } +} +class HeaderView: NSView, XibLoadable { + @IBOutlet weak var textField: NSTextField! + + static func asMenuItem(text: String) -> NSMenuItem { + let view = Self.createFromXib() + view?.textField.stringValue = text.uppercased() + let item = NSMenuItem() + item.view = view + item.target = self + return item + } +} diff --git a/phpmon/Extensions/XibLoadable.swift b/phpmon/Extensions/XibLoadable.swift new file mode 100644 index 0000000..b5a2bc8 --- /dev/null +++ b/phpmon/Extensions/XibLoadable.swift @@ -0,0 +1,33 @@ +// +// NibLoadable.swift +// PHP Monitor +// +// Created by Nico Verbruggen on 04/02/2021. +// Copyright © 2021 Nico Verbruggen. All rights reserved. +// + +import Foundation + +import Cocoa + +// Adapted from: https://stackoverflow.com/a/46268778 + +protocol XibLoadable { + static var xibName: String? { get } + static func createFromXib(in bundle: Bundle) -> Self? +} + +extension XibLoadable where Self: NSView { + static var xibName: String? { + return String(describing: Self.self) + } + + static func createFromXib(in bundle: Bundle = Bundle.main) -> Self? { + guard let xibName = xibName else { return nil } + var topLevelArray: NSArray? = nil + bundle.loadNibNamed(NSNib.Name(xibName), owner: self, topLevelObjects: &topLevelArray) + guard let results = topLevelArray else { return nil } + let views = Array(results).filter { $0 is Self } + return views.last as? Self + } +}