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")
- resetAllBtn.title = KMLocalizedString("Reset All")
- 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?"), 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."), label)
- alert.addButton(withTitle: KMLocalizedString("Reset"))
- alert.addButton(withTitle: KMLocalizedString("Cancel"))
- 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?")
- alert.informativeText = KMLocalizedString("Choosing Reset will restore all settings to the state they were in when PDF Reader Pro Edition was first installed.")
- alert.addButton(withTitle: KMLocalizedString("Reset"))
- alert.addButton(withTitle: KMLocalizedString("Cancel"))
-
- 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()
- }
- }
|