OSDN Git Service

#keyPathが使用できない部分も#keyPathにしていたため修正
[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             notifyChangeValue(forKey: "standardDeviation")
97             return
98         }
99         
100         super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
101     }
102     
103     fileprivate func showView(with type: ViewType) {
104         let newSelection: NSView = {
105             switch type {
106             case .exp: return expTableView
107             case .power: return powerTableView
108             case .power2: return power2TableView
109             case .power3: return power3TableView
110             }
111         }()
112         if currentTableView == newSelection { return }
113         guard let tableView = currentTableView
114             else { return }
115         newSelection.frame = tableView.frame
116         newSelection.autoresizingMask = tableView.autoresizingMask
117         view.replaceSubview(tableView, with: newSelection)
118         view.window?.makeFirstResponder(newSelection)
119         currentTableView = newSelection
120     }
121     
122     private func tag(_ sender: AnyObject?) -> Int {
123         guard let sender = sender
124             else { return -1 }
125         if let control = sender as? NSSegmentedControl,
126             let cell = sender.cell as? NSSegmentedCell {
127             return cell.tag(forSegment: control.selectedSegment)
128         }
129         if let control = sender as? NSControl {
130             return control.tag
131         }
132         return -1
133     }
134     @IBAction func changeView(_ sender: AnyObject?) {
135         ViewType(rawValue: tag(sender)).map { showView(with: $0) }
136     }
137 }
138
139 extension ShipViewController: NSTableViewDelegate {
140     func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
141         guard let identifier = tableColumn?.identifier else { return nil }
142         return tableView.make(withIdentifier: identifier, owner: nil)
143     }
144 }