1
0
mirror of https://github.com/nicoverbruggen/phpmon.git synced 2025-08-07 12:00:09 +02:00

Improve multi-window handling

This commit is contained in:
2021-12-05 03:53:30 +01:00
parent 46867ad25e
commit e0bec333ed
8 changed files with 154 additions and 35 deletions

View File

@ -59,6 +59,8 @@
C4AF9F7A2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F792754499000D44ED0 /* Valet.swift */; };
C4AF9F7D275454A900D44ED0 /* ValetTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4AF9F7C275454A900D44ED0 /* ValetTest.swift */; };
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4CCBA6B275C567B008C7055 /* PMWindowController.swift */; };
C4D8016622B1584700C6DA1B /* Startup.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4D8016522B1584700C6DA1B /* Startup.swift */; };
C4EE188422D3386B00E126E5 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4EE188322D3386B00E126E5 /* Constants.swift */; };
C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */ = {isa = PBXBuildFile; fileRef = C4F2E4362752F0870020E974 /* HomebrewDiagnostics.swift */; };
@ -148,6 +150,7 @@
C4AF9F76275447F100D44ED0 /* ValetConfigParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetConfigParserTest.swift; sourceTree = "<group>"; };
C4AF9F792754499000D44ED0 /* Valet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Valet.swift; sourceTree = "<group>"; };
C4AF9F7C275454A900D44ED0 /* ValetTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValetTest.swift; sourceTree = "<group>"; };
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PMWindowController.swift; sourceTree = "<group>"; };
C4D8016522B1584700C6DA1B /* Startup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Startup.swift; sourceTree = "<group>"; };
C4E713562570150F00007428 /* SECURITY.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = SECURITY.md; sourceTree = "<group>"; };
C4E713572570151400007428 /* docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docs; sourceTree = "<group>"; };
@ -305,6 +308,7 @@
C476FF9722B0DD830098105B /* Alert.swift */,
C41C1B4822B00A9800E7CF16 /* MenuBarImageGenerator.swift */,
C474B00524C0E98C00066A22 /* LocalNotification.swift */,
C4CCBA6B275C567B008C7055 /* PMWindowController.swift */,
);
path = Helpers;
sourceTree = "<group>";
@ -512,6 +516,7 @@
C41C1B4D22B0215A00E7CF16 /* Actions.swift in Sources */,
C48D0CA325CC992000CC7490 /* StatsView.swift in Sources */,
C4F2E4372752F0870020E974 /* HomebrewDiagnostics.swift in Sources */,
C4CCBA6C275C567B008C7055 /* PMWindowController.swift in Sources */,
C41CD0292628D8EE0065BBED /* GlobalKeybindPreference.swift in Sources */,
C42295DD2358D02000E263B2 /* Command.swift in Sources */,
C4811D2422D70A4700B5F6B3 /* App.swift in Sources */,
@ -551,6 +556,7 @@
C4F780CA25D80B75000DBC97 /* HomebrewPackage.swift in Sources */,
C4AF9F7B2754499000D44ED0 /* Valet.swift in Sources */,
C4F780C025D80B6E000DBC97 /* Startup.swift in Sources */,
C4CCBA6D275C567B008C7055 /* PMWindowController.swift in Sources */,
C4F2E4382752F08D0020E974 /* HomebrewDiagnostics.swift in Sources */,
C4F780AE25D80B37000DBC97 /* ExtensionParserTest.swift in Sources */,
C4F780C725D80B75000DBC97 /* StatusMenu.swift in Sources */,

View File

@ -141,4 +141,41 @@ class App {
}
}
// MARK: - Application State
/**
Keep track of open windows.
When this list is updated, the app activation policy is re-evaluated.
The app activation policy dictates how the app runs (as a normal app or as a toolbar app).
*/
var openWindows: [String] = []
/**
Registers a window as currently open.
*/
public func register(window name: String) {
if !openWindows.contains(name) {
openWindows.append(name)
}
updateActivationPolicy()
}
/**
Removes a window, assuming it was closed.
*/
public func remove(window name: String) {
openWindows.removeAll { window in
window == name
}
updateActivationPolicy()
}
/**
If there are any open windows, the app will be a regular app.
If there are no windows open, the app will be an accessory (toolbar) app.
*/
public func updateActivationPolicy() {
NSApp.setActivationPolicy(openWindows.count > 0 ? .regular : .accessory)
}
}

View File

@ -282,9 +282,9 @@
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
</connections>
</application>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="PHP_Monitor" customModuleProvider="target"/>
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="PHP_Monitor" customModuleProvider="target"/>
</objects>
<point key="canvasLocation" x="-444" y="-1"/>
</scene>
@ -578,19 +578,19 @@ Gw
<autoresizingMask key="autoresizingMask"/>
<subviews>
<scrollView autohidesScrollers="YES" horizontalLineScroll="69" horizontalPageScroll="10" verticalLineScroll="69" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="p0j-eB-I2i">
<rect key="frame" x="0.0" y="0.0" width="550" height="344"/>
<rect key="frame" x="0.0" y="0.0" width="550" height="337"/>
<clipView key="contentView" id="6IL-DW-37w">
<rect key="frame" x="1" y="1" width="548" height="342"/>
<rect key="frame" x="1" y="1" width="548" height="335"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="69" rowSizeStyle="automatic" viewBased="YES" id="cp3-34-pQj">
<rect key="frame" x="0.0" y="0.0" width="548" height="342"/>
<rect key="frame" x="0.0" y="0.0" width="548" height="335"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="17" height="0.0"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
<tableColumn width="536" minWidth="40" maxWidth="1000" id="oeH-B2-0rA">
<tableColumn width="536" minWidth="40" maxWidth="10000" id="oeH-B2-0rA">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
@ -656,7 +656,7 @@ Gw
<rect key="frame" x="301" y="27" width="51" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="PHP 8.0" id="d9R-tV-Dlk">
<font key="font" metaFont="system" size="11"/>
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
@ -712,7 +712,7 @@ Gw
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="550" id="iRQ-sz-oyv"/>
</constraints>
<scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="TDE-ff-DQT">
<rect key="frame" x="1" y="356" width="527" height="15"/>
<rect key="frame" x="1" y="328" width="548" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="wFn-93-f10">

View File

@ -0,0 +1,36 @@
//
// PMWindowController.swift
// PHP Monitor
//
// Created by Nico Verbruggen on 05/12/2021.
// Copyright © 2021 Nico Verbruggen. All rights reserved.
//
import Cocoa
/**
This window class keeps track of which windows are currently visible, and reports this info back to the App class.
For more information, check the `windows` property on `App`.
- Note: This class does make a simple assumption: each window controller corresponds to a single view.
*/
class PMWindowController: NSWindowController, NSWindowDelegate {
public var windowName: String {
fatalError("Please specify a window name")
}
override func showWindow(_ sender: Any?) {
super.showWindow(sender)
App.shared.register(window: self.windowName)
}
func windowWillClose(_ notification: Notification) {
App.shared.remove(window: self.windowName)
}
deinit {
print("Window controller '\(windowName)' was deinitialized")
}
}

View File

@ -12,6 +12,8 @@ import Carbon
class PrefsVC: NSViewController {
// MARK: - Window Identifier
// Labels on the left
@IBOutlet weak var leftLabelDynamicIcon: NSTextField!
@IBOutlet weak var leftLabelServices: NSTextField!
@ -39,17 +41,24 @@ class PrefsVC: NSViewController {
// MARK: - Display
public static func create(delegate: NSWindowDelegate?) {
let storyboard = NSStoryboard(name: "Main" , bundle : nil)
let windowController = storyboard.instantiateController(
withIdentifier: "preferencesWindow"
) as! PrefsWC
windowController.window!.title = "prefs.title".localized
windowController.window!.delegate = delegate
windowController.window!.styleMask = [.titled, .closable, .miniaturizable]
windowController.window!.delegate = windowController
App.shared.preferencesWindowController = windowController
}
public static func show(delegate: NSWindowDelegate? = nil) {
if (App.shared.preferencesWindowController == nil) {
let vc = NSStoryboard(name: "Main", bundle: nil)
.instantiateController(withIdentifier: "preferences") as! PrefsVC
let window = NSWindow(contentViewController: vc)
window.title = "prefs.title".localized
window.delegate = delegate
window.styleMask = [.titled, .closable]
App.shared.preferencesWindowController = PrefsWC(window: window)
Self.create(delegate: delegate)
}
App.shared.preferencesWindowController!.showWindow(self)

View File

@ -13,12 +13,22 @@ struct Keys {
static let Space = 49
}
class PrefsWC: NSWindowController {
class PrefsWC: PMWindowController {
// MARK: - Window Identifier
override var windowName: String {
return "Preferences"
}
// MARK: - Window Lifecycle
override func windowDidLoad() {
super.windowDidLoad()
}
// MARK: - Key Interaction
override func keyDown(with event: NSEvent) {
super.keyDown(with: event)

View File

@ -16,27 +16,36 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
@IBOutlet weak var tableView: NSTableView!
public var editorAvailability: [String] = []
public var sites: [Valet.Site] = []
// MARK: - Variables
var sites: [Valet.Site] = []
var editorAvailability: [String] = []
var lastSearchedFor = ""
// MARK: - Display
public static func create(delegate: NSWindowDelegate?) {
let storyboard = NSStoryboard(name: "Main" , bundle : nil)
let windowController = storyboard.instantiateController(
withIdentifier: "siteListWindow"
) as! SiteListWC
windowController.window!.title = "site_list.title".localized
windowController.window!.subtitle = "site_list.subtitle".localized
windowController.window!.delegate = delegate
windowController.window!.styleMask = [
.titled, .closable, .resizable, .miniaturizable
]
windowController.window!.minSize = NSSize(width: 550, height: 200)
windowController.window!.delegate = windowController
App.shared.siteListWindowController = windowController
}
public static func show(delegate: NSWindowDelegate? = nil) {
if (App.shared.siteListWindowController == nil) {
let storyboard = NSStoryboard(name: "Main" , bundle : nil)
let windowController = (storyboard.instantiateController(withIdentifier: "siteListWindow")) as! SiteListWC
windowController.window!.title = "site_list.title".localized
windowController.window!.subtitle = "site_list.subtitle".localized
windowController.window!.delegate = delegate
windowController.window!.styleMask = [.titled, .closable, .resizable]
windowController.window!.minSize = NSSize(width: 550, height: 200)
windowController.window!.maxSize = NSSize(width: 800, height: 10000)
App.shared.siteListWindowController = windowController
Self.create(delegate: delegate)
}
App.shared.siteListWindowController!.showWindow(self)
@ -57,9 +66,7 @@ class SiteListVC: NSViewController, NSTableViewDelegate, NSTableViewDataSource {
self.sites = Valet.shared.sites
}
override func viewWillAppear() {}
override func viewWillDisappear() {}
// MARK: - Site Data Loading

View File

@ -8,16 +8,28 @@
import Cocoa
class SiteListWC: NSWindowController, NSSearchFieldDelegate, NSToolbarDelegate {
class SiteListWC: PMWindowController, NSSearchFieldDelegate, NSToolbarDelegate {
// MARK: - Window Identifier
override var windowName: String {
return "SiteList"
}
// MARK: - Outlets
@IBOutlet weak var searchToolbarItem: NSSearchToolbarItem!
// MARK: - Window Lifecycle
override func windowDidLoad() {
super.windowDidLoad()
self.searchToolbarItem.searchField.delegate = self
self.searchToolbarItem.searchField.becomeFirstResponder()
}
// MARK: - Search functionality
var contentVC: SiteListVC {
return self.contentViewController as! SiteListVC
}
@ -31,6 +43,8 @@ class SiteListWC: NSWindowController, NSSearchFieldDelegate, NSToolbarDelegate {
contentVC.searchedFor(text: searchField.stringValue)
}
// MARK: - Reload functionality
@IBAction func pressedReload(_ sender: Any) {
contentVC.reloadSites()
}