OSDN Git Service

コメントを追加
[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 private enum ViewType: Int {
12     
13     case exp
14     case power
15     case power2
16     case power3
17 }
18
19 final class ShipViewController: MainTabVIewItemViewController {
20     
21     @objc let managedObjectContext = ServerDataStore.default.context
22     
23     deinit {
24         
25         NotificationCenter.default.removeObserver(self)
26     }
27     
28     @IBOutlet var shipController: NSArrayController!
29     @IBOutlet var expTableView: NSScrollView!
30     @IBOutlet var powerTableView: NSScrollView!
31     @IBOutlet var power2TableView: NSScrollView!
32     @IBOutlet var power3TableView: NSScrollView!
33     @IBOutlet weak var standardDeviationField: NSTextField!
34     
35     private var sortDescriptorsObservation: NSKeyValueObservation?
36     private var arrangedObjectsObservation: NSKeyValueObservation?
37     
38     override var nibName: NSNib.Name {
39         
40         return .nibName(instanceOf: self)
41     }
42     
43     override var hasShipTypeSelector: Bool { return true }
44     override var selectedShipType: ShipTabType {
45         
46         didSet {
47             shipController.filterPredicate = shipTypePredicte
48             shipController.rearrangeObjects()
49         }
50     }
51     
52     @objc var standardDeviation: Double {
53         
54         guard let ships = shipController.arrangedObjects as? [Ship], !ships.isEmpty else { return 0.0 }
55         guard let avg = shipController.value(forKeyPath: "arrangedObjects.@avg.lv") as? Double else { return 0.0 }
56         
57         let total = ships.reduce(0.0) {
58             
59             let delta = Double($1.lv) - avg
60             
61             return $0 + delta * delta
62         }
63         
64         return sqrt(total / Double(ships.count))
65     }
66     
67     private weak var currentTableView: NSView?
68     
69     override func viewDidLoad() {
70         
71         super.viewDidLoad()
72         
73         currentTableView = expTableView
74         
75         do {
76             
77             try shipController.fetch(with: nil, merge: true)
78             
79         } catch {
80             
81             fatalError("ShipViewController: can not fetch. \(error)")
82             
83         }
84         
85         shipController.sortDescriptors = UserDefaults.standard[.shipviewSortDescriptors]
86         
87         sortDescriptorsObservation = shipController.observe(\NSArrayController.sortDescriptors) { [weak self] _, _ in
88             
89             UserDefaults.standard[.shipviewSortDescriptors] = self?.shipController.sortDescriptors ?? []
90         }
91         arrangedObjectsObservation = shipController.observe(\NSArrayController.arrangedObjects) { [weak self] _, _ in
92             
93             self?.notifyChangeValue(forKey: #keyPath(standardDeviation))
94         }
95         
96         let tableViews = [expTableView, powerTableView, power2TableView, power3TableView]
97         tableViews
98             .forEach {
99                 
100                 NotificationCenter.default
101                     .addObserver(forName: NSScrollView.didEndLiveScrollNotification, object: $0, queue: nil) {
102                         
103                         guard let target = $0.object as? NSScrollView else { return }
104                         
105                         let visibleRect = target.documentVisibleRect
106                         tableViews
107                             .filter { $0 != target }
108                             .forEach { $0?.documentView?.scrollToVisible(visibleRect) }
109                 }
110         }
111         #if DEBUG
112             standardDeviationField.isHidden = false
113         #endif
114     }
115     
116     private func showView(with type: ViewType) {
117         
118         let newSelection: NSView = {
119             
120             switch type {
121             case .exp: return expTableView
122             case .power: return powerTableView
123             case .power2: return power2TableView
124             case .power3: return power3TableView
125             }
126         }()
127         
128         if currentTableView == newSelection { return }
129         
130         guard let tableView = currentTableView else { return }
131         
132         newSelection.frame = tableView.frame
133         newSelection.autoresizingMask = tableView.autoresizingMask
134         view.replaceSubview(tableView, with: newSelection)
135         view.window?.makeFirstResponder(newSelection)
136         currentTableView = newSelection
137     }
138     
139     private func tag(_ sender: AnyObject?) -> Int {
140         
141         switch sender {
142             
143         case let segmented as NSSegmentedControl:
144             let cell = segmented.cell as? NSSegmentedCell
145             
146             return cell?.tag(forSegment: segmented.selectedSegment) ?? -1
147             
148         case let control as NSControl:
149             return control.tag
150             
151         default:
152             return -1
153         }
154     }
155     
156     @IBAction func changeView(_ sender: AnyObject?) {
157         
158         ViewType(rawValue: tag(sender)).map(showView)
159     }
160 }
161
162 extension ShipViewController: NSTableViewDelegate {
163     
164     func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
165         
166         guard let identifier = tableColumn?.identifier else { return nil }
167         
168         return tableView.makeView(withIdentifier: identifier, owner: nil)
169     }
170 }