2 // ShipViewController.swift
5 // Created by Hori,Masaki on 2016/12/25.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
11 private enum ViewType: Int {
20 /// #keyPath(Ship.master_ship.soku)がkeyであるNSSortDescriptorが含まれるとクラッシュする可能性があるため
21 /// 新設した#keyPath(Ship.soku)をkeyにするように書き換える
22 private func exchangeSortKey(original: [NSSortDescriptor]) -> [NSSortDescriptor] {
25 .map { sortDesc -> NSSortDescriptor in
27 if sortDesc.key == #keyPath(Ship.master_ship.soku) {
29 return NSSortDescriptor(key: #keyPath(Ship.soku), ascending: sortDesc.ascending)
36 final class ShipViewController: MainTabVIewItemViewController {
38 @objc let managedObjectContext = ServerDataStore.default.context
40 @IBOutlet private var shipController: NSArrayController!
41 @IBOutlet private var expTableView: NSScrollView!
42 @IBOutlet private var powerTableView: NSScrollView!
43 @IBOutlet private var power2TableView: NSScrollView!
44 @IBOutlet private var power3TableView: NSScrollView!
45 @IBOutlet private weak var standardDeviationField: NSTextField!
47 private var sortDescriptorsObservation: NSKeyValueObservation?
48 private var arrangedObjectsObservation: NSKeyValueObservation?
50 private var notificationObserver = NotificationObserver()
52 override var nibName: NSNib.Name {
54 return .nibName(instanceOf: self)
57 override var hasShipTypeSelector: Bool { return true }
58 override var selectedShipType: ShipTabType {
61 shipController.filterPredicate = shipTypePredicte(for: selectedShipType)
62 shipController.rearrangeObjects()
66 @objc var standardDeviation: Double {
68 guard let ships = shipController.arrangedObjects as? [Ship], !ships.isEmpty else { return 0.0 }
69 guard let avg = shipController.value(forKeyPath: "arrangedObjects.@avg.lv") as? Double else { return 0.0 }
71 let total = ships.reduce(0.0) {
73 let delta = Double($1.lv) - avg
75 return $0 + delta * delta
78 return sqrt(total / Double(ships.count))
81 // @objc dynamic var sortDescriptors: [NSSortDescriptor] {
82 // get { return UserDefaults.standard[.shipviewSortDescriptors] }
83 // set { UserDefaults.standard[.shipviewSortDescriptors] = sortDescriptors }
86 private weak var currentTableView: NSView?
88 override func viewDidLoad() {
92 currentTableView = expTableView
96 try shipController.fetch(with: nil, merge: true)
100 fatalError("ShipViewController: can not fetch. \(error)")
104 shipController.sortDescriptors = exchangeSortKey(original: UserDefaults.standard[.shipviewSortDescriptors])
106 sortDescriptorsObservation = shipController.observe(\NSArrayController.sortDescriptors) { [weak self] _, _ in
108 UserDefaults.standard[.shipviewSortDescriptors] = self?.shipController.sortDescriptors ?? []
110 arrangedObjectsObservation = shipController.observe(\NSArrayController.arrangedObjects) { [weak self] _, _ in
112 self?.notifyChangeValue(forKey: #keyPath(standardDeviation))
115 let tableViews = [expTableView, powerTableView, power2TableView, power3TableView]
120 .addObserver(forName: NSScrollView.didEndLiveScrollNotification, object: $0, queue: .main) {
122 guard let target = $0.object as? NSScrollView else { return }
124 let visibleRect = target.documentVisibleRect
126 .filter { $0 != target }
127 .forEach { $0?.documentView?.scrollToVisible(visibleRect) }
131 standardDeviationField.isHidden = false
135 private func showView(with type: ViewType) {
137 let newSelection: NSView = {
140 case .exp: return expTableView
141 case .power: return powerTableView
142 case .power2: return power2TableView
143 case .power3: return power3TableView
147 if currentTableView == newSelection { return }
149 guard let tableView = currentTableView else { return }
151 newSelection.frame = tableView.frame
152 newSelection.autoresizingMask = tableView.autoresizingMask
153 view.replaceSubview(tableView, with: newSelection)
154 view.window?.makeFirstResponder(newSelection)
155 currentTableView = newSelection
158 private func tag(_ sender: AnyObject?) -> Int {
162 case let segmented as NSSegmentedControl:
163 let cell = segmented.cell as? NSSegmentedCell
165 return cell?.tag(forSegment: segmented.selectedSegment) ?? -1
167 case let control as NSControl:
175 @IBAction func changeView(_ sender: AnyObject?) {
177 ViewType(rawValue: tag(sender)).map(showView)
181 extension ShipViewController: NSTableViewDelegate {
183 func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
185 guard let identifier = tableColumn?.identifier else { return nil }
187 return tableView.makeView(withIdentifier: identifier, owner: nil)