123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- //
- // KMPreferenceController.swift
- // PDF Master
- //
- // 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()
- }
- class KMPreferenceController: NSWindowController {
-
- var preferencePanes: [KMPreferencePane]?
- var history: [NSViewController]?
- var historyIndex: Int = 0
- var currentPane: KMPreferencePane?
- /*
- @class SKIBArray;
- @protocol ;
- @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
-
- @interface SKIBArray : NSArray {
- __strong id object[9];
- unsigned long mutations;
- }
- //@property (nonatomic, retain) id object;
- @property (nonatomic, retain) IBOutlet id object1, object2, object3, object4, object5, object6, object7, object8, object9;
- @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
- }
-
- 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))
- }
- for pane in self.preferencePanes ?? [] {
- let _pane = pane as! NSViewController
- view = _pane.view
- frame = view!.frame
- 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![0]
- 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(&frame, NSHeight(window?.contentView?.frame ?? .zero) - NSMaxY(view!.frame), .minY)
-
- window?.setFrame(frame, display: false)
-
- if let data = view {
- window?.contentView?.addSubview(data)
- }
- }
-
-
-
- /*
- #define INITIALUSERDEFAULTS_KEY @"InitialUserDefaults"
- #define RESETTABLEKEYS_KEY @"ResettableKeys"
- //@synthesize resetButtons;
- - (void)selectPaneWithIdentifier:(NSString *)itemIdentifier {
- [self selectPane:[self preferencePaneForItemIdentifier:itemIdentifier]];
- }
- #pragma mark Actions
- - (void)resetAllSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
- if (returnCode == NSAlertFirstButtonReturn) {
- [[NSUserDefaultsController sharedUserDefaultsController] revertToInitialValues:nil];
- for (NSViewController<SKPreferencePane> *pane in preferencePanes) {
- if ([pane respondsToSelector:@selector(defaultsDidRevert)])
- [pane defaultsDidRevert];
- }
-
- //重置OCR后,记录切换值
- [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"KMStatusPlanPopUpBtnKey"];
- [[NSUserDefaults standardUserDefaults] synchronize];
- }
- }
- - (IBAction)resetAll:(id)sender {
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:NSLocalizedString(@"Reset all preferences to their original values?", @"Message in alert dialog when pressing Reset All button")];
- [alert setInformativeText:NSLocalizedString(@"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 addButtonWithTitle:NSLocalizedString(@"Reset", @"Button title")];
- [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Button title")];
- [alert beginSheetModalForWindow:[self window]
- modalDelegate:self
- didEndSelector:@selector(resetAllSheetDidEnd:returnCode:contextInfo:)
- contextInfo:NULL];
- }
- - (void)resetCurrentSheetDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
- if (returnCode == NSAlertFirstButtonReturn) {
- NSURL *initialUserDefaultsURL = [[NSBundle mainBundle] URLForResource:INITIALUSERDEFAULTS_KEY withExtension:@"plist"];
- NSArray *resettableKeys = [[[NSDictionary dictionaryWithContentsOfURL:initialUserDefaultsURL] objectForKey:RESETTABLEKEYS_KEY] objectForKey:[currentPane nibName]];
- [[NSUserDefaultsController sharedUserDefaultsController] revertToInitialValuesForKeys:resettableKeys];
- if ([currentPane respondsToSelector:@selector(defaultsDidRevert)])
- [currentPane defaultsDidRevert];
- if ([[currentPane title] isEqualToString:@"OCR"]) { //重置OCR后,记录切换值
- [[NSUserDefaults standardUserDefaults] setInteger:0 forKey:@"KMStatusPlanPopUpBtnKey"];
- [[NSUserDefaults standardUserDefaults] synchronize];
- }
- }
- }
- - (IBAction)resetCurrent:(id)sender {
- if (currentPane == nil) {
- NSBeep();
- return;
- }
- NSString *label = [currentPane title];
- NSAlert *alert = [[NSAlert alloc] init];
- [alert setMessageText:[NSString stringWithFormat:NSLocalizedString(@"Reset %@ preferences to their original values?", @"Message in alert dialog when pressing Reset All button"), label]];
- [alert setInformativeText:[NSString stringWithFormat:NSLocalizedString(@"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 addButtonWithTitle:NSLocalizedString(@"Reset", @"Button title")];
- [alert addButtonWithTitle:NSLocalizedString(@"Cancel", @"Button title")];
- [alert beginSheetModalForWindow:[self window]
- modalDelegate:self
- didEndSelector:@selector(resetCurrentSheetDidEnd:returnCode:contextInfo:)
- contextInfo:NULL];
- }
- - (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)changeFont:(id)sender {
- // [[[[self window] contentView] activeFontWell] changeFontFromFontManager:sender];
- }
- - (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
- @implementation SKIBArray
- static void setObjectAtIndex(id __strong *object, id obj, NSUInteger i, unsigned long *mutationsPtr) {
- if (object[i] != obj) {
- // [object[i] release];
- object[i] = obj;
- (*mutationsPtr)++;
- }
- }
- #define SYNTHESIZE_OBJECT_ACCESSORS(i) \
- @dynamic object##i; \
- - (id)object##i { return object[i-1]; } \
- - (void)setObject##i:(id)obj { setObjectAtIndex(object, obj, i-1, &mutations); }
- SYNTHESIZE_OBJECT_ACCESSORS(1)
- SYNTHESIZE_OBJECT_ACCESSORS(2)
- SYNTHESIZE_OBJECT_ACCESSORS(3)
- SYNTHESIZE_OBJECT_ACCESSORS(4)
- SYNTHESIZE_OBJECT_ACCESSORS(5)
- SYNTHESIZE_OBJECT_ACCESSORS(6)
- SYNTHESIZE_OBJECT_ACCESSORS(7)
- SYNTHESIZE_OBJECT_ACCESSORS(8)
- SYNTHESIZE_OBJECT_ACCESSORS(9)
- - (void)dealloc {
- NSUInteger i;
- for (i = 0; i < 9; i++)
- setObjectAtIndex(object, nil, i, &mutations);
- // [super dealloc];
- }
- - (NSUInteger)count {
- NSUInteger i;
- for (i = 0; i < 9; i++)
- if (object[i] == nil) break;
- return i;
- }
- - (id)objectAtIndex:(NSUInteger)anIndex {
- return object[anIndex];
- }
- - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len {
- if (state->state == 0) {
- state->state = 1;
- // state->itemsPtr = object;
- state->mutationsPtr = &mutations;
- return [self count];
- }
- return 0;
- }
- @end
- */
- }
- // 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 (_pane != nil) {
- self.historyIndex += 1
- if self.history!.count > self.historyIndex {
- let range = self.historyIndex ..< self.history!.count-self.historyIndex
- self.history?.removeSubrange(range)
- }
- self.history?.append(_pane!)
- } 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
- frame = KMShrinkRect(&frame, NSHeight(contentView!.frame) - NSMaxY(view.frame), .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) {
- contentView?.replaceSubview(oldView, with: view)
- window?.setFrame(frame, display: true)
- } else {
- let duration = window?.animationResizeTime(frame)
- contentView?.displayIfNeeded()
- NSAnimationContext.runAnimationGroup { context in
- context.duration = duration!
- contentView?.animator().replaceSubview(oldView, with: view)
- window?.animator().setFrame(frame, display: true)
- }
- }
- }
- }
- }
- extension KMPreferenceController: NSToolbarDelegate {
- func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar flag: Bool) -> NSToolbarItem? {
- // NSViewController<SKPreferencePane> * = [self preferencePaneForItemIdentifier:itemIdent];
- let pane = self._preferencePane(forItemIdentifier: itemIdentifier.rawValue) as? NSViewController
- // NSToolbarItem * = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdent];
- 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 ?? [] {
- 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()
- }
- }
|