OSDN Git Service

省略できる記法があればそれを用いるようにした
[kcd/KCD.git] / KCD / AppDelegate.swift
1 //
2 //  AppDelegate.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/02/03.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 fileprivate extension Selector {
12     static let fireInAppDelegate = #selector(AppDelegate.fire(_:))
13     
14     static let showHideHistory = #selector(AppDelegate.showHideHistory(_:))
15     static let showHideSlotItemWindow = #selector(AppDelegate.showHideSlotItemWindow(_:))
16     static let showHideUpgradableShipWindow = #selector(AppDelegate.showHideUpgradableShipWindow(_:))
17     static let showHideScreenshotListWindow = #selector(AppDelegate.showHideScreenshotListWindow(_:))
18     static let showHideAirBaseInfoWindow = #selector(AppDelegate.showHideAirBaseInfoWindow(_:))
19     static let saveLocalData = #selector(AppDelegate.saveLocalData(_:))
20     static let loadLocalData = #selector(AppDelegate.loadLocalData(_:))
21     static let showHidePreferencePanle = #selector(AppDelegate.showHidePreferencePanle(_:))
22     static let openNewBrowser = #selector(AppDelegate.openNewBrowser(_:))
23     static let selectBookmark = #selector(AppDelegate.selectBookmark(_:))
24     static let showWindowAduster = #selector(AppDelegate.showWindowAduster(_:))
25     
26     static let saveDocument = #selector(AppDelegate.saveDocument(_:))
27     static let openDocument = #selector(AppDelegate.openDocument(_:))
28     static let removeDatabaseFile = #selector(AppDelegate.removeDatabaseFile(_:))
29     static let showShipWindow = #selector(AppDelegate.showShipWindow(_:))
30     static let showEquipmentWindow = #selector(AppDelegate.showEquipmentWindow(_:))
31     static let showMapWindow = #selector(AppDelegate.showMapWindow(_:))
32     static let showOwnershipShipWindow = #selector(AppDelegate.showOwnershipShipWindow(_:))
33 }
34
35 @NSApplicationMain
36 class AppDelegate: NSObject {
37     static var shared: AppDelegate {
38         // swiftlint:disable force_cast
39         return NSApplication.shared().delegate as! AppDelegate
40     }
41     let appNameForUserAgent: String = "Version/9.1.2 Safari/601.7.7"
42     let fleetManager: FleetManager = FleetManager()
43     
44     private let historyCleanNotifer = PeriodicNotifier(hour: 0, minutes: 7)
45     private let jsonTracker = JSONTracker()
46     private let timeSignalNotifier = TimeSignalNotifier()
47     private let resourceHistory = ResourceHistoryManager()
48     
49     fileprivate let browserWindowController = BroserWindowController()
50     
51     #if ENABLE_JSON_LOG
52     let jsonViewWindowController: JSONViewWindowController? = {
53         let vc = JSONViewWindowController()
54         vc.showWindow(nil)
55         return vc
56     }()
57     #else
58     private let jsonViewWindowController: JSONViewWindowController? = nil
59     #endif
60     
61     #if UI_TEST
62     private let uiTestWindowController: UITestWindowController? = {
63         let vc = UITestWindowController()
64         vc.showWindow(nil)
65         return vc
66     }()
67     #else
68     private let uiTestWindowController: UITestWindowController? = nil
69     #endif
70     
71     
72     // MARK: - Variable
73     @IBOutlet var debugMenuItem: NSMenuItem!
74     @IBOutlet var billingWindowMenuItem: NSMenuItem!
75     
76     fileprivate lazy var historyWindowController: HistoryWindowController = {
77         HistoryWindowController()
78     }()
79     fileprivate lazy var slotItemWindowController: SlotItemWindowController = {
80         SlotItemWindowController()
81     }()
82     fileprivate lazy var preferencePanelController: PreferencePanelController = {
83         PreferencePanelController()
84     }()
85     fileprivate lazy var upgradableShipWindowController: UpgradableShipsWindowController = {
86         UpgradableShipsWindowController()
87     }()
88     fileprivate lazy var airBaseWindowController: AirBaseWindowController = {
89         AirBaseWindowController()
90     }()
91     fileprivate lazy var browserContentAdjuster: BrowserContentAdjuster = {
92         BrowserContentAdjuster()
93     }()
94     fileprivate(set) lazy var screenshotListWindowController: ScreenshotListWindowController = {
95         let wc = ScreenshotListWindowController()
96         let _ = wc.window
97         return wc
98     }()
99     
100     fileprivate lazy var shipWindowController: ShipWindowController = {
101         ShipWindowController()
102     }()
103     fileprivate lazy var shipMDWindowController: ShipMasterDetailWindowController = {
104         ShipMasterDetailWindowController()
105     } ()
106     fileprivate lazy var equipmentWindowController: EquipmentWindowController = {
107         EquipmentWindowController()
108     }()
109     fileprivate lazy var mapWindowController: MapWindowController = {
110         MapWindowController()
111     }()
112     
113     private var browserWindowControllers: [ExternalBrowserWindowController] = []
114     private var updaters: [() -> Void] = []
115     fileprivate var logedJSONViewWindowController: JSONViewWindowController?
116     private var isLoadedMainMenu = false
117     
118     var screenShotSaveDirectory: String {
119         get {
120             return UserDefaults.standard.screenShotSaveDirectory ?? ApplicationDirecrories.pictures.path
121         }
122         set {
123             UserDefaults.standard.screenShotSaveDirectory = newValue
124         }
125     }
126     var screenShotSaveDirectoryURL: URL {
127         return URL(fileURLWithPath: screenShotSaveDirectory)
128     }
129     dynamic var monospaceSystemFont11: NSFont {
130         return NSFont.monospacedDigitSystemFont(ofSize: 11, weight: NSFontWeightRegular)
131     }
132     dynamic var monospaceSystemFont12: NSFont {
133         return NSFont.monospacedDigitSystemFont(ofSize: 12, weight: NSFontWeightRegular)
134     }
135     dynamic var monospaceSystemFont13: NSFont {
136         return NSFont.monospacedDigitSystemFont(ofSize: 13, weight: NSFontWeightRegular)
137     }
138     
139     // MARK: - Function
140     override func awakeFromNib() {
141         if isLoadedMainMenu { return }
142         isLoadedMainMenu = true
143         
144         ValueTransformerRegister.registerAll()
145         UserDefaults.registerAllDefaults()
146         CustomHTTPProtocol.start()
147         CommandRegister.register()
148         
149         let _ = BookmarkManager.shared()
150         let _ = screenshotListWindowController
151         browserWindowController.showWindow(nil)
152         if !UserDefaults.standard.showsDebugMenu { debugMenuItem.isHidden = true }
153         NotificationCenter.default
154         .addObserver(forName: .Periodic, object: historyCleanNotifer, queue: nil) { _ in
155             HistoryItemCleaner().cleanOldHistoryItems()
156         }
157     }
158     
159     func addCounterUpdate(_ updater: @escaping () -> Void) {
160         updaters.append(updater)
161     }
162     func clearCache() {
163         CustomHTTPProtocol.clearCache()
164     }
165     func createNewBrowser() -> ExternalBrowserWindowController {
166         let browser = ExternalBrowserWindowController()
167         browserWindowControllers.append(browser)
168         browser.window?.makeKeyAndOrderFront(nil)
169         var token: NSObjectProtocol! = nil
170         token = NotificationCenter.default
171             .addObserver(forName: .NSWindowWillClose,
172                          object: browser.window,
173                          queue: nil) { [unowned self] notification in
174                             NotificationCenter.default.removeObserver(token)
175                             if let obj = notification.object as? NSWindow,
176                                 let index = self.browserWindowControllers.index(where: { $0.window == obj }) {
177                                 self.browserWindowControllers.remove(at: index)
178                             }
179         }
180         return browser
181     }
182     
183     func fire(_ timer: Timer) {
184         updaters.forEach { $0() }
185     }
186 }
187 // MARK: - IBActions
188 extension AppDelegate {
189     private func isFrontMostWindow(_ window: NSWindow) -> Bool {
190         return window.isVisible && window.isMainWindow
191     }
192     private func makeFrontOrOrderOut(_ window: NSWindow?) {
193         guard let window = window else { return }
194         isFrontMostWindow(window) ? window.orderOut(nil) : window.makeKeyAndOrderFront(nil)
195     }
196     @IBAction func showHideHistory(_ sender: AnyObject?) {
197         makeFrontOrOrderOut(historyWindowController.window)
198     }
199     @IBAction func showHideSlotItemWindow(_ sender: AnyObject?) {
200         makeFrontOrOrderOut(slotItemWindowController.window)
201     }
202     @IBAction func showHideUpgradableShipWindow(_ sender: AnyObject?) {
203         makeFrontOrOrderOut(upgradableShipWindowController.window)
204     }
205     @IBAction func showHideScreenshotListWindow(_ sender: AnyObject?) {
206         makeFrontOrOrderOut(screenshotListWindowController.window)
207     }
208     @IBAction func showHideAirBaseInfoWindow(_ sender: AnyObject?) {
209         makeFrontOrOrderOut(airBaseWindowController.window)
210     }
211     @IBAction func showHidePreferencePanle(_ sender: AnyObject?) {
212         makeFrontOrOrderOut(preferencePanelController.window)
213     }
214     @IBAction func showWindowAduster(_ sender: AnyObject?) {
215         browserContentAdjuster.showWindow(nil)
216     }
217     @IBAction func openNewBrowser(_ sender: AnyObject?) {
218         let _ = createNewBrowser()
219     }
220     @IBAction func selectBookmark(_ sender: AnyObject?) {
221         let b = createNewBrowser()
222         b.selectBookmark(sender)
223     }
224     @IBAction func removeDatabaseFile(_ sender: AnyObject?) {
225         guard let path = Bundle.main.path(forResource: "RemoveDatabaseFileAndRestart", ofType: "app")
226             else { return print("Can not find RemoveDatabaseFileAndRestart.app") }
227         let process = Process()
228         process.launchPath = "/usr/bin/open"
229         process.arguments = [path]
230         process.launch()
231     }
232     @IBAction func showMainBrowser(_ sender: AnyObject?) {
233         browserWindowController.showWindow(nil)
234     }
235     
236     @IBAction func showShipWindow(_ sender: AnyObject?) {
237         shipWindowController.showWindow(nil)
238     }
239     @IBAction func showEquipmentWindow(_ sender: AnyObject?) {
240         equipmentWindowController.showWindow(nil)
241     }
242     @IBAction func showMapWindow(_ sender: AnyObject?) {
243         mapWindowController.showWindow(nil)
244     }
245     @IBAction func showOwnershipShipWindow(_ sender: AnyObject?) {
246         shipMDWindowController.showWindow(nil)
247     }
248     
249     @IBAction func saveLocalData(_ sender: AnyObject?) {
250         TSVSupport().save()
251     }
252     @IBAction func loadLocalData(_ sender: AnyObject?) {
253         TSVSupport().load()
254     }
255     
256     @IBAction func saveDocument(_ sender: AnyObject?) {
257         let panel = NSSavePanel()
258         panel.allowedFileTypes = ["plist"]
259         panel.prompt = "Save Panel"
260         panel.title = "Save Panel"
261         panel.begin {
262             guard $0 == NSModalResponseOK,
263                 let url = panel.url,
264                 let array = self.jsonViewWindowController?.commands
265                 else { return }
266             let data = NSKeyedArchiver.archivedData(withRootObject: array)
267             do {
268                 try data.write(to: url)
269             } catch { print("Can not write to \(url)") }
270         }
271     }
272     @IBAction func openDocument(_ sender: AnyObject?) {
273         let panel = NSOpenPanel()
274         panel.allowedFileTypes = ["plist"]
275         panel.allowsMultipleSelection = false
276         panel.prompt = "Open log"
277         panel.title = "Open log"
278         panel.begin {
279             guard $0 == NSModalResponseOK,
280             let url = panel.url
281             else { return }
282             do {
283                 let data = try Data(contentsOf: url)
284                 let array = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data as NSData)
285                 guard let commands = array as? [[String: Any]]
286                     else { return }
287                 
288                 self.logedJSONViewWindowController = JSONViewWindowController()
289                 self.logedJSONViewWindowController?.commands = commands
290                 self.logedJSONViewWindowController?.window?.title = "SAVED LOG FILE VIEWER"
291                 self.logedJSONViewWindowController?.showWindow(nil)
292             } catch { print("Can not load \(url)") }
293         }
294     }
295     
296     private func setTitle(_ menuItem: NSMenuItem,
297                           _ window: NSWindow?,
298                           _ showLabel: String,
299                           _ hideLabel: String) {
300         guard let window = window else { return }
301         if isFrontMostWindow(window) {
302             menuItem.title = hideLabel
303         } else {
304             menuItem.title = showLabel
305         }
306     }
307     // swiftlint:disable function_body_length
308     override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
309         guard let action = menuItem.action else { return false }
310         switch action {
311         case Selector.showHideHistory:
312             setTitle(menuItem,
313                      historyWindowController.window,
314                      NSLocalizedString("Show History", comment: "Show History"),
315                      NSLocalizedString("Hide History", comment: "Hide History"))
316             return true
317         case Selector.showHideSlotItemWindow:
318             setTitle(menuItem,
319                      slotItemWindowController.window,
320                      NSLocalizedString("Show Slot Item", comment: "Show Slot Item"),
321                      NSLocalizedString("Hide Slot Item", comment: "Hide Slot Item"))
322             return true
323         case Selector.showHideUpgradableShipWindow:
324             setTitle(menuItem,
325                      upgradableShipWindowController.window,
326                      NSLocalizedString("Show Upgradable Ships", comment: "Show Upgradable Ships"),
327                      NSLocalizedString("Hide Upgradable Ships", comment: "Hide Upgradable Ships"))
328             return true
329         case Selector.showHideScreenshotListWindow:
330             setTitle(menuItem,
331                      screenshotListWindowController.window,
332                      NSLocalizedString("Show Screenshot List", comment: "Show Screenshot List"),
333                      NSLocalizedString("Hide Screenshot List", comment: "Hide Screenshot List"))
334             return true
335         case Selector.showHideAirBaseInfoWindow:
336             setTitle(menuItem,
337                      airBaseWindowController.window,
338                      NSLocalizedString("Show Air Base Info", comment: "Show Air Base Info"),
339                      NSLocalizedString("Hide Air Base Info", comment: "Hide Air Base Info"))
340             return true
341         case Selector.saveLocalData, Selector.loadLocalData:
342             return true
343         case Selector.showHidePreferencePanle:
344             return true
345         case Selector.openNewBrowser:
346             return true
347         case Selector.selectBookmark:
348             return true
349         case Selector.showWindowAduster:
350             return true
351         case Selector.saveDocument, Selector.openDocument:
352             return jsonViewWindowController != nil
353         case Selector.removeDatabaseFile:
354             return true
355         case Selector.showShipWindow, Selector.showEquipmentWindow,
356              Selector.showMapWindow, Selector.showOwnershipShipWindow:
357             return true
358         default:
359             return false
360         }
361     }
362 }
363
364 extension AppDelegate: NSApplicationDelegate {
365     func applicationWillFinishLaunching(_ notification: Notification) {
366         NSUserNotificationCenter.default.delegate = self
367         Timer.scheduledTimer(timeInterval: 0.33,
368                              target: self,
369                              selector: .fireInAppDelegate,
370                              userInfo: nil,
371                              repeats: true)
372     }
373     func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
374         return true
375     }
376 }
377
378 extension AppDelegate: NSUserNotificationCenterDelegate {
379     func userNotificationCenter(_ center: NSUserNotificationCenter,
380                                 shouldPresent notification: NSUserNotification) -> Bool {
381         return true
382     }
383 }
384
385 @available(OSX 10.12.2, *)
386 fileprivate var objectForTouchBar: [Int: NSTouchBar] = [:]
387
388 @available(OSX 10.12.2, *)
389 extension AppDelegate: NSTouchBarProvider {
390     @IBOutlet var mainTouchBar: NSTouchBar? {
391         get {
392             return objectForTouchBar[hash]
393         }
394         set {
395             objectForTouchBar[hash] = newValue
396         }
397     }
398     
399     var touchBar: NSTouchBar? {
400         get {
401             let mainWindow = NSApplication.shared().mainWindow
402             if mainWindow == self.browserWindowController.window { return nil }
403             if let _ = mainTouchBar {
404                 return mainTouchBar
405             }
406             var topLevel: NSArray = []
407             Bundle.main.loadNibNamed("MainTouchBar",
408                                      owner: self,
409                                      topLevelObjects: &topLevel)
410             return mainTouchBar
411         }
412         set {}
413     }
414 }