123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431 |
- //
- // KMPreferenceController.swift
- // PDF Reader Pro
- //
- // Created by tangchao on 2023/11/7.
- //
- import Cocoa
- class KMPreferenceWindow: NSWindow {
- // override func responds(to aSelector: Selector!) -> Bool {
- // return aSelector != #selector(toggleToolbarShow) && aSelector != #selector(runToolbarCustomizationPalette) && super.responds(to: aSelector)
- // }
- }
- private let SKPreferencesToolbarIdentifier = "SKPreferencesToolbarIdentifier"
- private let SKPreferenceWindowFrameAutosaveName = "SKPreferenceWindow"
- private let BOTTOM_MARGIN = 27.0
- private let SKLastSelectedPreferencePaneKey = "SKLastSelectedPreferencePane"
- private let NIBNAME_KEY = "nibName"
- @objc protocol KMPreferencePane: NSObjectProtocol {
- @objc optional func defaultsDidRevert()
- @objc optional func reloadData()
- }
- @objcMembers class KMPreferenceController: NSWindowController {
-
- @IBOutlet var resetBtn: NSButton!
- @IBOutlet var resetAllBtn: NSButton!
- var preferencePanes: [KMPreferencePane]?
- var history: [NSViewController]?
- var historyIndex: Int = 0
- var currentPane: KMPreferencePane?
-
- private let INITIALUSERDEFAULTS_KEY = "InitialUserDefaults"
- private let RESETTABLEKEYS_KEY = "ResettableKeys"
- /*
- @interface SKPreferenceController : NSWindowController <NSWindowDelegate, NSTabViewDelegate, NSToolbarDelegate> {
- NSArray *resetButtons;
- }
- @property (nonatomic, retain) IBOutlet NSArray *resetButtons;
- + (id)sharedPrefenceController;
- - (IBAction)resetAll:(id)sender;
- - (IBAction)resetCurrent:(id)sender;
- - (IBAction)doGoToNextPage:(id)sender;
- - (IBAction)doGoToPreviousPage:(id)sender;
- - (IBAction)doGoToFirstPage:(id)sender;
- - (IBAction)doGoToLastPage:(id)sender;
- - (IBAction)doGoBack:(id)sender;
- - (IBAction)doGoForward:(id)sender;
- - (IBAction)changeFont:(id)sender;
- - (IBAction)changeAttributes:(id)sender;
- - (void)selectPaneWithIdentifier:(NSString *)itemIdentifier;
- @end
- */
-
- deinit {
- KMPrint("KMPreferenceController deinit.")
- // currentPane = nil;
- }
-
- static let shared = KMPreferenceController(windowNibName: "PreferenceWindow")
- override func windowDidLoad() {
- super.windowDidLoad()
-
- self.preferencePanes = [KMGeneralPreferences(), KMDisplayPreferences(), KMNotesPreferences(), KMSyncPreferences()]
- self.history = []
- self.historyIndex = 0
-
- if #available(macOS 11.0,*) {
- self.window?.toolbarStyle = .expanded
- }
-
- resetBtn.title = KMLocalizedString("Reset", nil)
- resetAllBtn.title = KMLocalizedString("Reset All", nil)
- let window = self.window
- let toolbar = NSToolbar(identifier: SKPreferencesToolbarIdentifier)
- toolbar.allowsUserCustomization = false
- toolbar.autosavesConfiguration = false
- toolbar.isVisible = true
- toolbar.delegate = self
- window?.toolbar = toolbar
- window?.showsToolbarButton = false
-
- window?.contentView?.wantsLayer = true
-
- // we want to restore the top of the window, while without the force it restores the bottom position without the size
- window?.setFrameUsingName(SKPreferenceWindowFrameAutosaveName, force: true)
- self.windowFrameAutosaveName = SKPreferenceWindowFrameAutosaveName
-
- // [NSGraphicsContext SKAutoSizeButtons:resetButtons rightAlign:false];
-
- var width = 0.0
- var frame: NSRect = .zero
- var pane: NSViewController?
- var view: NSView?
- for pane in self.preferencePanes ?? [] {
- let _pane = pane as? NSViewController
- width = fmax(width, NSWidth(_pane?.view.frame ?? .zero))
- }
- for pane in self.preferencePanes ?? [] {
- let _pane = pane as? NSViewController
- view = _pane?.view
- frame = view?.frame ?? .zero
- if let data = view?.autoresizingMask.contains(.width), data {
- frame.size.width = width
- } else {
- frame.origin.x = floor(0.5 * (width - NSWidth(frame)))
- }
- frame.origin.y = BOTTOM_MARGIN
- view?.frame = frame
- }
-
- self.currentPane = self._preferencePane(forItemIdentifier: UserDefaults.standard.string(forKey: SKLastSelectedPreferencePaneKey) ?? "") ?? self.preferencePanes?.first
- toolbar.selectedItemIdentifier = NSToolbarItem.Identifier((self.currentPane as? NSViewController)?.nibName ?? "")
-
- if let _currentPane = self.currentPane as? NSViewController {
- window?.title = _currentPane.title ?? ""
- self.history?.append(_currentPane)
- }
-
- view = (self.currentPane as? NSViewController)?.view
- frame = window?.frame ?? .zero
- frame.size.width = width
- frame = KMShrinkRect(rect: frame, amount: NSHeight(window?.contentView?.frame ?? .zero) - NSMaxY(view?.frame ?? .zero), edge: .minY)
-
- window?.setFrame(frame, display: false)
-
- if let data = view {
- window?.contentView?.addSubview(data)
- }
-
- NotificationCenter.default.addObserver(self, selector: #selector(preferenceDidChangeNotification), name: KMPreferenceManager.didChangeNotification, object: nil)
-
- self.resetBtn.toolTip = NSLocalizedString("Revert all currently shown preferences to their original values", comment: "")
- self.resetAllBtn.toolTip = NSLocalizedString("Revert all preferences to their original values", comment: "")
- }
-
- @IBAction func changeFont(_ sender: AnyObject?) {
- self.window?.contentView?.activeFontWell()?.changeFontFromFontManager(sender)
- }
-
- /*
- - (void)selectPaneWithIdentifier:(NSString *)itemIdentifier {
- [self selectPane:[self preferencePaneForItemIdentifier:itemIdentifier]];
- }
- #pragma mark Actions
- - (IBAction)doGoToNextPage:(id)sender {
- NSUInteger itemIndex = [preferencePanes indexOfObject:currentPane];
- if (itemIndex != NSNotFound && ++itemIndex < [preferencePanes count])
- [self selectPane:[preferencePanes objectAtIndex:itemIndex]];
- }
- - (IBAction)doGoToPreviousPage:(id)sender {
- NSUInteger itemIndex = [preferencePanes indexOfObject:currentPane];
- if (itemIndex != NSNotFound && itemIndex-- > 0)
- [self selectPane:[preferencePanes objectAtIndex:itemIndex]];
- }
- - (IBAction)doGoToFirstPage:(id)sender {
- [self selectPane:[preferencePanes objectAtIndex:0]];
- }
- - (IBAction)doGoToLastPage:(id)sender {
- [self selectPane:[preferencePanes lastObject]];
- }
- - (IBAction)doGoBack:(id)sender {
- if (historyIndex > 0) {
- historyIndex--;
- [self selectPane:nil];
- }
- }
- - (IBAction)doGoForward:(id)sender {
- if (historyIndex + 1 < [history count]) {
- historyIndex++;
- [self selectPane:nil];
- }
- }
-
- - (IBAction)changeAttributes:(id)sender {
- // [[[[self window] contentView] activeFontWell] changeAttributesFromFontManager:sender];
- }
- - (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
- if ([menuItem action] == @selector(doGoToNextPage:) || [menuItem action] == @selector(doGoToLastPage:))
- return [currentPane isEqual:[preferencePanes lastObject]] == NO;
- else if ([menuItem action] == @selector(doGoToPreviousPage:) || [menuItem action] == @selector(doGoToFirstPage:))
- return [currentPane isEqual:[preferencePanes objectAtIndex:0]] == NO;
- else if ([menuItem action] == @selector(doGoBack:))
- return historyIndex > 0;
- else if ([menuItem action] == @selector(doGoForward:))
- return historyIndex + 1 < [history count];
- return YES;
- }
- #pragma mark Toolbar
- @end
- */
- @IBAction func resetCurrent(_ sender: AnyObject?) {
- if (self.currentPane == nil) {
- return
- }
-
- let label = (self.currentPane as? NSViewController)?.title ?? ""
- let alert = NSAlert()
- alert.messageText = String(format: KMLocalizedString("Reset %@ preferences to their original values?", "Message in alert dialog when pressing Reset All button"), label)
- alert.informativeText = String(format: KMLocalizedString("Choosing Reset will restore all settings in this pane to the state they were in when PDF Reader Pro Edition was first installed.", "Informative text in alert dialog when pressing Reset All button"), label)
- alert.addButton(withTitle: KMLocalizedString("Reset", "Button title"))
- alert.addButton(withTitle: KMLocalizedString("Cancel", "Button title"))
- alert.beginSheetModal(for: self.window!, modalDelegate: self, didEnd: #selector(_resetCurrentSheetDidEnd), contextInfo: nil)
- }
-
- @IBAction func resetAll(_ sender: AnyObject?) {
- let alert = NSAlert()
- alert.messageText = KMLocalizedString("Reset all preferences to their original values?", "Message in alert dialog when pressing Reset All button")
- alert.informativeText = KMLocalizedString("Choosing Reset will restore all settings to the state they were in when PDF Reader Pro Edition was first installed.", "Informative text in alert dialog when pressing Reset All button")
- alert.addButton(withTitle: KMLocalizedString("Reset", "Button title"))
- alert.addButton(withTitle: KMLocalizedString("Cancel", "Button title"))
-
- let response = alert.runModal()
- if (response == .alertFirstButtonReturn) {
- NSUserDefaultsController.shared.revertToInitialValues(forKeys: nil)
- for pane in self.preferencePanes ?? [] {
- pane.defaultsDidRevert?()
- }
-
- KMPreference.shared.resetAllData()
- }
- }
-
- @objc private func preferenceDidChangeNotification(sender: Notification) {
- self.currentPane?.reloadData?()
- }
- }
- // MARK: - Private Methods
- extension KMPreferenceController {
- private func _preferencePane(forItemIdentifier itemIdent: String) -> KMPreferencePane? {
- self._panelControlSelectColor(itemIdent)
- for pane in self.preferencePanes ?? [] {
- let _pane = pane as? NSViewController
- if _pane?.nibName == itemIdent {
- return pane
- }
- }
- return nil
- }
-
- private func _panelControlSelectColor(_ identifier: String) {
- for item in self.window?.toolbar?.items ?? [] {
- if item.itemIdentifier.rawValue == identifier {
- if item.itemIdentifier.rawValue == "GeneralPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsGeneralSel")
- } else if item.itemIdentifier.rawValue == "DisplayPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsViewSel")
- } else if item.itemIdentifier.rawValue == "NotesPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsAnnotationSel")
- } else if item.itemIdentifier.rawValue == "SyncPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsSynchronizeSel")
- } else if item.itemIdentifier.rawValue == "DropboxPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsDropboxSel")
- }
- } else {
- if item.itemIdentifier.rawValue == "GeneralPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsGeneralNor")
- } else if item.itemIdentifier.rawValue == "DisplayPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsViewNor")
- } else if item.itemIdentifier.rawValue == "NotesPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsAnnotationNor")
- } else if item.itemIdentifier.rawValue == "SyncPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsSynchronizeNor")
- } else if item.itemIdentifier.rawValue == "DropboxPreferences" {
- item.image = NSImage(named: "KMImageNameElseSettingsDropboxNor")
- }
- }
- }
- }
-
- @objc private func _selectPaneAction(_ sender: AnyObject?) {
- let _item = sender as? NSToolbarItem
- self._panelControlSelectColor(_item?.itemIdentifier.rawValue ?? "")
-
- if let pane = self._preferencePane(forItemIdentifier: _item?.itemIdentifier.rawValue ?? "") {
- self._selectPane(pane)
- }
- }
-
- private func _selectPane(_ pane: KMPreferencePane) {
- var _pane = pane as? NSViewController
- let _currentPane = self.currentPane as? NSViewController
- if _pane != _currentPane {
- if let data = _pane {
- self.historyIndex += 1
- if let cnt = self.history?.count, cnt > self.historyIndex {
- let range = self.historyIndex ..< cnt-self.historyIndex
- self.history?.removeSubrange(range)
- }
- self.history?.append(data)
- } else {
- _pane = self.history?[self.historyIndex]
- }
-
- let window = self.window
- let contentView = window?.contentView
- let oldView = _currentPane?.view
- let view = _pane?.view
- var frame = window?.frame ?? .zero
- frame = KMShrinkRect(rect: frame, amount: NSHeight(contentView?.frame ?? .zero) - NSMaxY(view?.frame ?? .zero), edge: .minY)
-
- // make sure edits are committed
- _currentPane?.commitEditing()
- NSUserDefaultsController.shared.commitEditing()
-
- self.currentPane = pane
-
- window?.title = (self.currentPane as? NSViewController)?.title ?? ""
- if let data = (self.currentPane as? NSViewController)?.nibName {
- UserDefaults.standard.setValue(data, forKey: SKLastSelectedPreferencePaneKey)
- window?.toolbar?.selectedItemIdentifier = NSToolbarItem.Identifier(data)
- }
-
- if UserDefaults.standard.bool(forKey: SKDisableAnimationsKey) {
- if oldView != nil && view != nil {
- contentView?.replaceSubview(oldView!, with: view!)
- }
- window?.setFrame(frame, display: true)
- } else {
- let duration = window?.animationResizeTime(frame) ?? 0
- contentView?.displayIfNeeded()
- NSAnimationContext.runAnimationGroup { context in
- context.duration = duration
- if oldView != nil && view != nil {
- contentView?.animator().replaceSubview(oldView!, with: view!)
- }
- window?.animator().setFrame(frame, display: true)
- }
- }
- }
- }
-
- @objc private func _resetCurrentSheetDidEnd(_ alert: NSAlert, _ returnCode: Int, _ contextInfo: Any) {
- if (returnCode == NSApplication.ModalResponse.alertFirstButtonReturn.rawValue) {
- if let initialUserDefaultsURL = Bundle.main.url(forResource: INITIALUSERDEFAULTS_KEY, withExtension: "plist") {
- if let _currentPane = self.currentPane as? NSViewController {
- let resettableKeys = (NSDictionary(contentsOf: initialUserDefaultsURL)?.object(forKey: RESETTABLEKEYS_KEY) as? NSDictionary)?.object(forKey: _currentPane.nibName ?? "")
- if let data = resettableKeys as? [String] {
- NSUserDefaultsController.shared.revertToInitialValues(forKeys: data)
- }
- self.currentPane?.defaultsDidRevert?()
-
- if _currentPane is KMGeneralPreferences {
- KMPreference.shared.resetData(.general)
- } else if _currentPane is KMDisplayPreferences {
- KMPreference.shared.resetData(.display)
- } else if _currentPane is KMNotesPreferences {
- KMPreference.shared.resetData(.markup)
- }
- }
- }
- }
- }
- }
- extension KMPreferenceController: NSToolbarDelegate {
- func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
- let pane = self._preferencePane(forItemIdentifier: itemIdentifier.rawValue) as? NSViewController
- let item = NSToolbarItem(itemIdentifier: itemIdentifier)
- item.label = pane?.title ?? ""
- var ima: NSImage?
- if itemIdentifier.rawValue == "GeneralPreferences" {
- ima = NSImage(named: "KMImageNameElseSettingsGeneralNor")
- } else if itemIdentifier.rawValue == "DisplayPreferences" {
- ima = NSImage(named: "KMImageNameElseSettingsViewNor")
- } else if itemIdentifier.rawValue == "NotesPreferences" {
- ima = NSImage(named: "KMImageNameElseSettingsAnnotationNor")
- } else if itemIdentifier.rawValue == "SyncPreferences" {
- ima = NSImage(named: "KMImageNameElseSettingsSynchronizeNor")
- } else if itemIdentifier.rawValue == "DropboxPreferences" {
- ima = NSImage(named: "KMImageNameElseSettingsDropboxNor")
- }
- item.image = ima
- item.target = self
- item.action = #selector(_selectPaneAction)
- return item;
- }
-
- func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
- var items: [NSToolbarItem.Identifier] = []
- for item in self.preferencePanes ?? [] {
- if let name = (item as? NSViewController)?.nibName {
- items.append(NSToolbarItem.Identifier(rawValue: name))
- }
- }
- return items
- }
-
- func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
- return self.toolbarDefaultItemIdentifiers(toolbar)
- }
-
- func toolbarSelectableItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
- return self.toolbarDefaultItemIdentifiers(toolbar)
- }
- }
- extension KMPreferenceController: NSWindowDelegate {
- func windowDidResignMain(_ notification: Notification) {
- self.window?.contentView?.deactivateWellSubcontrols()
- }
-
- func windowWillClose(_ notification: Notification) {
- (self.currentPane as? NSViewController)?.commitEditing()
- NSUserDefaultsController.shared.commitEditing()
- }
- }
|