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 {
23 /// #keyPath(Ship.master_ship.soku)がkeyであるNSSortDescriptorが含まれるとクラッシュする可能性があるため
24 /// 新設した#keyPath(Ship.soku)をkeyにするように書き換える
25 private func exchangeSortKey(original: [NSSortDescriptor]) -> [NSSortDescriptor] {
28 .map { sortDesc -> NSSortDescriptor in
30 if sortDesc.key == #keyPath(Ship.master_ship.soku) {
32 return NSSortDescriptor(key: #keyPath(Ship.soku), ascending: sortDesc.ascending)
39 final class ShipViewController: MainTabVIewItemViewController {
41 @objc let managedObjectContext = ServerDataStore.default.context
43 @IBOutlet private var shipController: NSArrayController!
44 @IBOutlet private var expTableView: NSScrollView!
45 @IBOutlet private var powerTableView: NSScrollView!
46 @IBOutlet private var power2TableView: NSScrollView!
47 @IBOutlet private var power3TableView: NSScrollView!
48 @IBOutlet private weak var standardDeviationField: NSTextField!
50 private var sortDescriptorsObservation: NSKeyValueObservation?
51 private var arrangedObjectsObservation: NSKeyValueObservation?
53 private var notificationObserver = NotificationObserver()
55 override var nibName: NSNib.Name {
57 return .nibName(instanceOf: self)
60 override var hasShipTypeSelector: Bool { return true }
61 override var selectedShipType: ShipTabType {
65 shipController.filterPredicate = shipTypePredicte(for: selectedShipType)
66 shipController.rearrangeObjects()
70 @objc var standardDeviation: Double {
72 guard let ships = shipController.arrangedObjects as? [Ship], !ships.isEmpty else {
76 guard let avg = shipController.value(forKeyPath: "arrangedObjects.@avg.lv") as? Double else {
81 let total = ships.reduce(0.0) {
83 let delta = Double($1.lv) - avg
85 return $0 + delta * delta
88 return sqrt(total / Double(ships.count))
91 // @objc dynamic var sortDescriptors: [NSSortDescriptor] {
92 // get { return UserDefaults.standard[.shipviewSortDescriptors] }
93 // set { UserDefaults.standard[.shipviewSortDescriptors] = sortDescriptors }
96 private weak var currentTableView: NSView?
98 override func viewDidLoad() {
102 currentTableView = expTableView
106 try shipController.fetch(with: nil, merge: true)
110 fatalError("ShipViewController: can not fetch. \(error)")
114 shipController.sortDescriptors = exchangeSortKey(original: UserDefaults.standard[.shipviewSortDescriptors])
116 sortDescriptorsObservation = shipController.observe(\NSArrayController.sortDescriptors) { [weak self] _, _ in
118 UserDefaults.standard[.shipviewSortDescriptors] = self?.shipController.sortDescriptors ?? []
120 arrangedObjectsObservation = shipController.observe(\NSArrayController.arrangedObjects) { [weak self] _, _ in
122 self?.notifyChangeValue(forKey: #keyPath(standardDeviation))
125 let tableViews = [expTableView, powerTableView, power2TableView, power3TableView]
130 .addObserver(forName: NSScrollView.didEndLiveScrollNotification, object: $0, queue: .main) {
132 guard let target = $0.object as? NSScrollView else {
137 let visibleRect = target.documentVisibleRect
139 .filter { $0 != target }
140 .forEach { $0?.documentView?.scrollToVisible(visibleRect) }
144 standardDeviationField.isHidden = false
148 private func showView(with type: ViewType) {
150 let newSelection: NSView = {
154 case .exp: return expTableView
156 case .power: return powerTableView
158 case .power2: return power2TableView
160 case .power3: return power3TableView
165 if currentTableView == newSelection {
170 guard let tableView = currentTableView else {
175 newSelection.frame = tableView.frame
176 newSelection.autoresizingMask = tableView.autoresizingMask
177 view.replaceSubview(tableView, with: newSelection)
178 view.window?.makeFirstResponder(newSelection)
179 currentTableView = newSelection
182 private func tag(_ sender: AnyObject?) -> Int {
186 case let segmented as NSSegmentedControl:
187 let cell = segmented.cell as? NSSegmentedCell
189 return cell?.tag(forSegment: segmented.selectedSegment) ?? -1
191 case let control as NSControl:
202 @IBAction func changeView(_ sender: AnyObject?) {
204 ViewType(rawValue: tag(sender)).map(showView)
208 extension ShipViewController: NSTableViewDelegate {
210 func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
212 guard let identifier = tableColumn?.identifier else {
217 return tableView.makeView(withIdentifier: identifier, owner: nil)