OSDN Git Service

UAをVersion/10.0.3 Safari/602.4.8に変更
[kcd/KCD.git] / KCD / ShipViewController.swift
1 //
2 //  ShipViewController.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2016/12/25.
6 //  Copyright © 2016年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 fileprivate enum ViewType: Int {
12     case exp
13     case power
14     case power2
15     case power3
16 }
17
18 class ShipViewController: MainTabVIewItemViewController {
19     let managedObjectContext = ServerDataStore.default.context
20     
21     deinit {
22         NotificationCenter.default.removeObserver(self)
23     }
24     
25     @IBOutlet var shipController: NSArrayController!
26     @IBOutlet var expTableView: NSScrollView!
27     @IBOutlet var powerTableView: NSScrollView!
28     @IBOutlet var power2TableView: NSScrollView!
29     @IBOutlet var power3TableView: NSScrollView!
30     @IBOutlet weak var standardDeviationField: NSTextField!
31     
32     override var nibName: String! {
33         return "ShipViewController"
34     }
35     override var hasShipTypeSelector: Bool { return true }
36     override var selectedShipType: ShipType {
37         didSet {
38             shipController.filterPredicate = predicate(for: selectedShipType)
39             shipController.rearrangeObjects()
40         }
41     }
42     
43     var standardDeviation: Double {
44         guard let ships = shipController.arrangedObjects as? [Ship],
45             !ships.isEmpty,
46             let avg = shipController.value(forKeyPath: "arrangedObjects.@avg.lv") as? Double
47             else { return 0.0 }
48         let total = ships.reduce(0.0) {
49             let delta = Double($1.lv) - avg
50             return $0 + delta * delta
51         }
52         return sqrt(total / Double(ships.count))
53     }
54     
55     fileprivate weak var currentTableView: NSView?
56     
57     override func viewDidLoad() {
58         super.viewDidLoad()
59         
60         currentTableView = expTableView
61         
62         do {
63             try shipController.fetch(with: nil, merge: true)
64         } catch {
65             fatalError("ShipViewController: can not fetch. \(error)")
66         }
67         shipController.sortDescriptors = UserDefaults.standard.shipviewSortDescriptors
68         shipController.addObserver(self, forKeyPath: NSSortDescriptorsBinding, context: nil)
69         shipController.addObserver(self, forKeyPath: "arrangedObjects", context: nil)
70         
71         let tableViews = [expTableView, powerTableView, power2TableView, power3TableView]
72         tableViews
73             .forEach {
74                 NotificationCenter.default
75                     .addObserver(forName: .NSScrollViewDidEndLiveScroll, object: $0, queue: nil) {
76                         guard let target = $0.object as? NSScrollView else { return }
77                         let visibleRect = target.documentVisibleRect
78                         tableViews
79                             .filter { $0 != target }
80                             .forEach { $0?.documentView?.scrollToVisible(visibleRect) }
81                 }
82         }
83         #if DEBUG
84             standardDeviationField.isHidden = false
85         #endif
86     }
87     override func observeValue(forKeyPath keyPath: String?,
88                                of object: Any?,
89                                change: [NSKeyValueChangeKey: Any]?,
90                                context: UnsafeMutableRawPointer?) {
91         if keyPath == NSSortDescriptorsBinding {
92             UserDefaults.standard.shipviewSortDescriptors = shipController.sortDescriptors
93             return
94         }
95         if keyPath == "arrangedObjects" {
96             willChangeValue(forKey: "standardDeviation")
97             didChangeValue(forKey: "standardDeviation")
98             return
99         }
100         
101         super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
102     }
103     
104     fileprivate func showView(with type: ViewType) {
105         let newSelection: NSView = {
106             switch type {
107             case .exp: return expTableView
108             case .power: return powerTableView
109             case .power2: return power2TableView
110             case .power3: return power3TableView
111             }
112         }()
113         if currentTableView == newSelection { return }
114         guard let tableView = currentTableView
115             else { return }
116         newSelection.frame = tableView.frame
117         newSelection.autoresizingMask = tableView.autoresizingMask
118         view.replaceSubview(tableView, with: newSelection)
119         view.window?.makeFirstResponder(newSelection)
120         currentTableView = newSelection
121     }
122     
123     private func tag(_ sender: AnyObject?) -> Int {
124         guard let sender = sender
125             else { return -1 }
126         if let control = sender as? NSSegmentedControl,
127             let cell = sender.cell as? NSSegmentedCell {
128             return cell.tag(forSegment: control.selectedSegment)
129         }
130         if let control = sender as? NSControl {
131             return control.tag
132         }
133         return -1
134     }
135     @IBAction func changeView(_ sender: AnyObject?) {
136         ViewType(rawValue: tag(sender)).map { showView(with: $0) }
137     }
138 }
139
140 extension ShipViewController: NSTableViewDelegate {
141     func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
142         guard let identifier = tableColumn?.identifier else { return nil }
143         return tableView.make(withIdentifier: identifier, owner: nil)
144     }
145 }