source: launchers/macosx/I2PLauncher/userinterface/preferences/PreferencesViewController.swift @ 56eb11bc

Last change on this file since 56eb11bc was 56eb11bc, checked in by meeh <meeh@…>, 13 months ago

Mac OSX Launcher: Adding Swift 4.2 support to the preferences UI classes.

  • Property mode set to 100644
File size: 9.6 KB
Line 
1//
2//  PreferencesViewController.swift
3//  I2PLauncher
4//
5//  Created by Mikal Villa on 07/11/2018.
6//  Copyright © 2018 The I2P Project. All rights reserved.
7//
8// Table view programming guide from Apple:
9// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TableView/Introduction/Introduction.html
10//
11
12import Cocoa
13import ServiceManagement
14
15
16@objc class PreferencesViewController: NSViewController {
17 
18 
19  var changeDockMenubarIconTimer: Timer?
20 
21  // MARK: - Advanced settings objects
22  @IBOutlet weak var advPrefTableView: NSTableView!
23 
24  // MARK: - Launcher settings objects
25  @IBOutlet var radioDockIcon: NSButton?
26  @IBOutlet var radioMenubarIcon: NSButton?
27  @IBOutlet var radioBothIcon: NSButton?
28  @IBOutlet var checkboxStartWithOSX: NSButton?
29  @IBOutlet var checkboxStartFirefoxAlso: NSButton?
30 
31  // MARK: - Router objects
32  @IBOutlet var checkboxStartWithLauncher: NSButton?
33  @IBOutlet var checkboxStopWithLauncher: NSButton?
34  @IBOutlet var buttonResetRouterConfig: NSButton?
35 
36  @IBAction func onEnterInTextField(_ sender: NSTextField) {
37    let selectedRowNumber = advPrefTableView.selectedRow
38    print("Trying to store preferences")
39    let currentItem = Preferences.shared()[selectedRowNumber]
40    currentItem?.selectedValue = sender.stringValue
41    Preferences.shared()[selectedRowNumber] = currentItem
42    UserDefaults.standard.set(sender.stringValue, forKey: (currentItem?.name)!)
43    Preferences.shared().syncPref()
44  }
45 
46  override func viewDidLoad() {
47    super.viewDidLoad()
48   
49    self.preferredContentSize = NSMakeSize(self.view.frame.size.width, self.view.frame.size.height)
50   
51    if (advPrefTableView != nil) {
52      // For data feeding and view
53      advPrefTableView.delegate = self
54      advPrefTableView.dataSource = self
55     
56      // Responding to Double-Click
57      advPrefTableView.target = self
58      advPrefTableView.doubleAction = #selector(tableViewDoubleClick(_:))
59     
60      // Always redraw preference items which might have changed state since last draw.
61      Preferences.shared().redrawPrefTableItems()
62     
63      // For sorting
64      advPrefTableView.tableColumns[0].sortDescriptorPrototype = NSSortDescriptor(key: "name", ascending: true)
65      advPrefTableView.tableColumns[1].sortDescriptorPrototype = NSSortDescriptor(key: "defaultValue", ascending: true)
66      advPrefTableView.tableColumns[2].sortDescriptorPrototype = NSSortDescriptor(key: "selectedValue", ascending: true)
67     
68      self.advPrefTableView.isEnabled = Preferences.shared().allowAdvancedPreferenceEdit
69    }
70   
71    // Update radio buttons to reflect runtime/stored preferences
72    self.updateRadioButtonEffect(mode: Preferences.shared().showAsIconMode, withSideEffect: false)
73   
74    if (Preferences.shared().stopRouterOnLauncherShutdown) {
75      self.checkboxStopWithLauncher?.state = NSControl.StateValue.on;
76    } else {
77      self.checkboxStopWithLauncher?.state = NSControl.StateValue.off;
78    }
79    if (Preferences.shared().startRouterOnLauncherStart) {
80      self.checkboxStartWithLauncher?.state = NSControl.StateValue.on;
81    } else {
82      self.checkboxStartWithLauncher?.state = NSControl.StateValue.off;
83    }
84   
85   
86  }
87 
88  override func viewDidAppear() {
89    super.viewDidAppear()
90   
91    // Update window title
92    self.parent?.view.window?.title = self.title!
93  }
94 
95  // MARK: - Router settings functions
96 
97  @IBAction func checkboxStartRouterWithLauncherClicked(_ sender: NSButton) {
98    switch sender.state {
99    case NSControl.StateValue.on:
100      print("on")
101      Preferences.shared().startRouterOnLauncherStart = true
102    case NSControl.StateValue.off:
103      print("off")
104      Preferences.shared().startRouterOnLauncherStart = false
105    default: break
106    }
107  }
108 
109  @IBAction func checkboxStopRouterWithLauncherClicked(_ sender: NSButton) {
110    switch sender.state {
111    case NSControl.StateValue.on:
112      print("on")
113      Preferences.shared().stopRouterOnLauncherShutdown = true
114    case NSControl.StateValue.off:
115      print("off")
116      Preferences.shared().stopRouterOnLauncherShutdown = false
117    default: break
118    }
119  }
120 
121  @IBAction func buttonResetRouterConfigClicked(_ sender: Any) {
122    // TODO: Add a modal dialog asking user if they are **really** sure
123  }
124 
125  // MARK: - Launcher settings functions
126 
127  @IBAction func checkboxStartLauncherOnOSXStartupClicked(_ sender: NSButton) {
128    let launcherAppId = "net.i2p.bootstrap.macosx.StartupItemApp"
129    let startupMgr = Startup()
130    switch sender.state {
131    case NSControl.StateValue.on:
132      print("on")
133      Preferences.shared()["I2Pref_startLauncherAtLogin"] = true
134      if (Preferences.shared()["I2Pref_useServiceManagementAsStartupTool"] as! Bool)
135      {
136        let success = SMLoginItemSetEnabled(launcherAppId as CFString, true)
137        print("SMLoginItemSetEnabled returned \(success)....")
138      } else {
139        let _ = startupMgr.addLoginItem(Startup.appPath())
140        print("Shared file for auto-startup added. (viewable via OSX Preferences -> Users -> Login Items)")
141      }
142    case NSControl.StateValue.off:
143      print("off")
144      Preferences.shared()["I2Pref_startLauncherAtLogin"] = false
145      if (Preferences.shared()["I2Pref_useServiceManagementAsStartupTool"] as! Bool)
146      {
147        let success = SMLoginItemSetEnabled(launcherAppId as CFString, false)
148        print("SMLoginItemSetEnabled returned \(success)....")
149      } else {
150        let _ = startupMgr.removeLoginItem(Startup.appPath())
151        print("Shared file for auto-startup removed (if any). (viewable via OSX Preferences -> Users -> Login Items)")
152      }
153    default: break
154    }
155  }
156  @IBAction func checkboxStartFirefoxAlsoAtLaunchClicked(_ sender: NSButton) {
157    switch sender.state {
158    case NSControl.StateValue.on:
159      print("launch firefox: on")
160      Preferences.shared().alsoStartFirefoxOnLaunch = true
161    case NSControl.StateValue.off:
162      print("launch firefox: off")
163      Preferences.shared().alsoStartFirefoxOnLaunch = false
164    default: break
165    }
166  }
167 
168  // MARK: - Radio buttons functions
169 
170  func updateDockMenubarIcons(_ mode: Preferences.ShowAsMode) -> Bool {
171    // Update preferences with latest choise
172    Preferences.shared().showAsIconMode = mode
173    // Update runtime
174    switch mode {
175    case .bothIcon, .dockIcon:
176      // Show dock icon
177      print("Preferences: Update Dock Icon -> Show")
178      if (!getDockIconStateIsShowing()) {
179        return triggerDockIconShowHide(showIcon: true)
180      }
181    case .menubarIcon:
182      // Hide dock icon
183      print("Preferences: Update Dock Icon -> Hide")
184      if (getDockIconStateIsShowing()) {
185        return triggerDockIconShowHide(showIcon: false)
186      }
187    }
188    // Note: In reality, this won't ever happen.
189    // The switch statement above would return before this.
190    return false
191  }
192 
193  func updateRadioButtonEffect(mode: Preferences.ShowAsMode, withSideEffect: Bool = true) {
194    changeDockMenubarIconTimer?.invalidate()
195   
196    radioDockIcon?.state = NSControl.StateValue.off
197    radioMenubarIcon?.state = NSControl.StateValue.off
198    radioBothIcon?.state = NSControl.StateValue.off
199   
200    switch mode {
201    case .bothIcon:
202      radioBothIcon?.state = NSControl.StateValue.on
203    case .dockIcon:
204      radioDockIcon?.state = NSControl.StateValue.on
205    case .menubarIcon:
206      radioMenubarIcon?.state = NSControl.StateValue.on
207    }
208   
209    if (withSideEffect) {
210      if #available(OSX 10.12, *) {
211        changeDockMenubarIconTimer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: false, block: { _ in
212          // If we're on 10.12 or later
213          let _ = self.updateDockMenubarIcons(mode)
214        })
215      } else {
216        // Fallback on earlier versions
217        let _ = self.updateDockMenubarIcons(mode)
218      }
219    }
220  }
221 
222  @IBAction func radioBothIconSelected(_ sender: Any) {
223    updateRadioButtonEffect(mode: Preferences.ShowAsMode.bothIcon)
224  }
225 
226  @IBAction func radioDockIconOnlySelected(_ sender: Any) {
227    updateRadioButtonEffect(mode: Preferences.ShowAsMode.dockIcon)
228  }
229 
230  @IBAction func radioMenubarOnlySelected(_ sender: Any) {
231    updateRadioButtonEffect(mode: Preferences.ShowAsMode.menubarIcon)
232  }
233 
234  // MARK: - Triggers
235 
236  func triggerDockIconHideShow(showIcon state: Bool) -> Bool {
237    // Get transform state.
238    var transformState: ProcessApplicationTransformState
239    if state {
240      transformState = ProcessApplicationTransformState(kProcessTransformToForegroundApplication)
241    } else {
242      transformState = ProcessApplicationTransformState(kProcessTransformToUIElementApplication)
243    }
244   
245    // Show / hide dock icon.
246    var psn = ProcessSerialNumber(highLongOfPSN: 0, lowLongOfPSN: UInt32(kCurrentProcess))
247    let transformStatus: OSStatus = TransformProcessType(&psn, transformState)
248    return transformStatus == 0
249  }
250 
251  func triggerDockIconShowHide(showIcon state: Bool) -> Bool {
252    var result: Bool
253    if state {
254      result = NSApp.setActivationPolicy(NSApplication.ActivationPolicy.regular)
255    } else {
256      result = NSApp.setActivationPolicy(NSApplication.ActivationPolicy.accessory)
257    }
258    return result
259  }
260 
261  func getDockIconStateIsShowing() -> Bool {
262    if NSApp.activationPolicy() == NSApplication.ActivationPolicy.regular {
263      return true
264    } else {
265      return false
266    }
267  }
268 
269 
270  // MARK: - Advanced
271 
272  @IBAction func checkboxEnableAdvancedPreferencesClicked(_ sender: NSButton) {
273    switch sender.state {
274    case NSControl.StateValue.on:
275      print("on")
276      Preferences.shared().allowAdvancedPreferenceEdit = true
277      self.advPrefTableView.isEnabled = true
278    case NSControl.StateValue.off:
279      print("off")
280      Preferences.shared().allowAdvancedPreferenceEdit = false
281      self.advPrefTableView.isEnabled = false
282    default: break
283    }
284  }
285
286 
287  // End of Class
288}
289
290
Note: See TracBrowser for help on using the repository browser.