Kacheln und Fenster sprechen dieselbe Sprache
Alle Kacheln, Popovers und Fenster auf die Designschicht umgestellt: rund hundert gesetzte Schriftgrößen und 159 gesetzte Abstände und Radien sind jetzt Token. Übrig bleibt `spacing: 0` — das ist eine Aussage, keine geratene Zahl. Die Einstellungen bekommen eine Seitenleiste statt sieben Reitern, deren deutsche Beschriftungen zusammen 880 Punkte brauchten. Panel-Token stehen nicht mehr in Fenstern: dort gilt Systemsemantik, damit der Hellmodus nicht schwarz auf schwarz endet. Neu ist ein Schaufenster, das alle Bauteile nebeneinander zeigt — ohne das lässt sich eine Änderung an einem Token nur prüfen, indem man die App bedient, bis jede Kachel einmal zu sehen war. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9b600de9a9
commit
edb327cabe
@@ -0,0 +1,100 @@
|
||||
import AppKit
|
||||
import SwiftUI
|
||||
|
||||
/// Führt das Schaufenster.
|
||||
///
|
||||
/// Aufgebaut wie `SettingsWindowController` — aus demselben Grund: SwiftUIs
|
||||
/// eigene Fensterszenen kommen bei einer App ohne Menüleiste unzuverlässig an.
|
||||
@MainActor
|
||||
final class GalleryWindowController: NSObject, NSWindowDelegate {
|
||||
|
||||
private var window: NSWindow?
|
||||
|
||||
/// Ob Onyx dauerhaft im Dock steht. Bestimmt, wohin nach dem Schließen
|
||||
/// zurückgeschaltet wird.
|
||||
private var keepsDockIcon = false
|
||||
|
||||
/// Ob das Schaufenster überhaupt erreichbar ist.
|
||||
///
|
||||
/// Im Debug immer, im Release nur auf ausdrücklichen Wunsch. Es ist
|
||||
/// Werkzeug, kein Programmteil — und ein Menüeintrag, den niemand braucht,
|
||||
/// ist selbst schon Unordnung.
|
||||
///
|
||||
/// ```
|
||||
/// defaults write com.scarriffleservices.onyx onyx.gallery -bool YES
|
||||
/// ```
|
||||
static var isAvailable: Bool {
|
||||
#if DEBUG
|
||||
true
|
||||
#else
|
||||
UserDefaults.standard.bool(forKey: "onyx.gallery")
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Ob es beim Start gleich aufgehen soll.
|
||||
///
|
||||
/// Der Werkstatt-Kreislauf ist bauen, starten, hinsehen. Ohne das ist der
|
||||
/// dritte Schritt ein Griff zur Maus und zwei Klicks ins Statusmenü — bei
|
||||
/// jedem Durchlauf. `UserDefaults` liest Startargumente von selbst mit:
|
||||
///
|
||||
/// ```
|
||||
/// open Onyx.app --args -onyx.gallery.open YES
|
||||
/// ```
|
||||
static var opensAtLaunch: Bool {
|
||||
isAvailable && UserDefaults.standard.bool(forKey: "onyx.gallery.open")
|
||||
}
|
||||
|
||||
func show(model: AppModel) {
|
||||
keepsDockIcon = model.showsDockIcon
|
||||
|
||||
// Solange ein Fenster offen ist, gehört Onyx in den Dock — sonst ist es
|
||||
// weder über den Dock noch über ⌘-Tab zurückzuholen.
|
||||
NSApp.setActivationPolicy(.regular)
|
||||
|
||||
if window == nil {
|
||||
let hosting = NSHostingController(rootView: GalleryView(model: model))
|
||||
|
||||
let window = NSWindow(contentViewController: hosting)
|
||||
window.title = "Onyx — Schaufenster"
|
||||
window.titlebarAppearsTransparent = true
|
||||
window.titlebarSeparatorStyle = .none
|
||||
window.styleMask = [.titled, .closable, .miniaturizable, .resizable]
|
||||
window.setContentSize(NSSize(width: 1040, height: 720))
|
||||
window.contentMinSize = NSSize(width: 780, height: 540)
|
||||
window.isReleasedWhenClosed = false
|
||||
window.delegate = self
|
||||
OnyxWindowPlacement.center(window)
|
||||
window.setFrameAutosaveName("onyx.gallery")
|
||||
self.window = window
|
||||
}
|
||||
|
||||
NSApp.activate(ignoringOtherApps: true)
|
||||
window?.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
|
||||
/// Der rote Knopf blendet aus, statt zu schließen — wie bei den
|
||||
/// Einstellungen, und aus demselben Grund: Onyx hat kein Hauptfenster, und
|
||||
/// manche Hilfsprogramme beenden eine App, sobald ihr letztes Fenster
|
||||
/// verschwindet.
|
||||
func windowShouldClose(_ sender: NSWindow) -> Bool {
|
||||
hide()
|
||||
return false
|
||||
}
|
||||
|
||||
private func hide() {
|
||||
window?.orderOut(nil)
|
||||
|
||||
// Nur zurück in den Hintergrund, wenn wirklich nichts mehr offen ist.
|
||||
// Das Einstellungsfenster kann noch stehen — es hier mit auszublenden
|
||||
// sähe aus wie ein Absturz.
|
||||
let otherVisible = NSApp.windows.contains {
|
||||
$0 !== window && $0.isVisible && $0.styleMask.contains(.titled)
|
||||
}
|
||||
guard !otherVisible else { return }
|
||||
|
||||
if !keepsDockIcon {
|
||||
NSApp.setActivationPolicy(.accessory)
|
||||
}
|
||||
NSApp.hide(nil)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user