2 // ShipDetailViewController.swift
5 // Created by Hori,Masaki on 2016/12/25.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
11 enum ShipDetailViewType {
18 private func nibNameFor(_ type: ShipDetailViewType) -> NSNib.Name {
21 case .full: return ShipDetailViewController.nibName
22 case .medium: return NSNib.Name("MediumShipViewController")
23 case .minimum: return NSNib.Name("MediumShipViewController")
27 private var shipContext: Int = 0
28 private var equippedItem0Context: Int = 0
29 private var equippedItem1Context: Int = 0
30 private var equippedItem2Context: Int = 0
31 private var equippedItem3Context: Int = 0
32 private var equippedItem4Context: Int = 0
34 final class ShipDetailViewController: NSViewController {
36 let type: ShipDetailViewType
37 @objc let managedObjectContext = ServerDataStore.default.context
39 init?(type: ShipDetailViewType) {
43 super.init(nibName: nibNameFor(type), bundle: nil)
47 .addObserver(forName: .DidUpdateGuardEscape, object: nil, queue: nil) { [weak self] _ in
49 guard let `self` = self else { return }
51 self.guardEscaped = self.ship?.guardEscaped ?? false
55 required init?(coder: NSCoder) {
57 fatalError("not implemented")
62 NotificationCenter.default.removeObserver(self)
63 damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
64 supply.unbind(NSBindingName(#keyPath(SuppliesView.shipStatus)))
65 [slot00Field, slot01Field, slot02Field, slot03Field]
66 .forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
68 shipController.removeObject(self)
72 @IBOutlet weak var supply: SuppliesView!
73 @IBOutlet weak var guardEscapedView: GuardEscapedView!
74 @IBOutlet weak var damageView: DamageView!
75 @IBOutlet weak var slot00Field: SlotItemLevelView!
76 @IBOutlet weak var slot01Field: SlotItemLevelView!
77 @IBOutlet weak var slot02Field: SlotItemLevelView!
78 @IBOutlet weak var slot03Field: SlotItemLevelView!
79 @IBOutlet var shipController: NSObjectController!
81 @objc dynamic var guardEscaped: Bool = false {
84 guardEscapedView.isHidden = !guardEscaped
88 @objc dynamic var ship: Ship? {
90 get { return shipController.content as? Ship }
93 shipController.fetchPredicate = NSPredicate(#keyPath(Ship.id), equal: newValue?.id ?? 0)
97 override func viewDidLoad() {
101 damageView.setFrameOrigin(.zero)
102 view.addSubview(damageView)
103 damageView.bind(NSBindingName(#keyPath(DamageView.damageType)),
105 withKeyPath: "selection.status", options: nil)
107 supply.bind(NSBindingName(#keyPath(SuppliesView.shipStatus)),
109 withKeyPath: "selection.self", options: nil)
111 guardEscapedView.setFrameOrigin(.zero)
112 view.addSubview(guardEscapedView)
114 case .medium, .minimum:
115 guardEscapedView.controlSize = .mini
120 let fields = [slot00Field, slot01Field, slot02Field, slot03Field]
121 let keypath = ["selection.slot_0", "selection.slot_1", "selection.slot_2", "selection.slot_3"]
122 zip(fields, keypath).forEach {
124 $0.0?.bind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID)), to: shipController, withKeyPath: $0.1, options: nil)
127 // observe slotitems count
128 shipController.addObserver(self, forKeyPath: "selection", context: &shipContext)
130 shipController.addObserver(self, forKeyPath: "selection.slot_0", context: &equippedItem0Context)
131 shipController.addObserver(self, forKeyPath: "selection.onslot_0", context: &equippedItem0Context)
132 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_0", context: &equippedItem0Context)
134 shipController.addObserver(self, forKeyPath: "selection.slot_1", context: &equippedItem1Context)
135 shipController.addObserver(self, forKeyPath: "selection.onslot_1", context: &equippedItem1Context)
136 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_1", context: &equippedItem1Context)
138 shipController.addObserver(self, forKeyPath: "selection.slot_2", context: &equippedItem2Context)
139 shipController.addObserver(self, forKeyPath: "selection.onslot_2", context: &equippedItem2Context)
140 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_2", context: &equippedItem2Context)
142 shipController.addObserver(self, forKeyPath: "selection.slot_3", context: &equippedItem3Context)
143 shipController.addObserver(self, forKeyPath: "selection.onslot_3", context: &equippedItem3Context)
144 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_3", context: &equippedItem3Context)
146 shipController.addObserver(self, forKeyPath: "selection.slot_4", context: &equippedItem4Context)
147 shipController.addObserver(self, forKeyPath: "selection.onslot_4", context: &equippedItem4Context)
148 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_4", context: &equippedItem4Context)
152 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
154 if context == &shipContext {
156 notifyChangeValue(forKey: #keyPath(planeString0))
157 notifyChangeValue(forKey: #keyPath(planeString0Color))
158 notifyChangeValue(forKey: #keyPath(planeString1))
159 notifyChangeValue(forKey: #keyPath(planeString1Color))
160 notifyChangeValue(forKey: #keyPath(planeString2))
161 notifyChangeValue(forKey: #keyPath(planeString2Color))
162 notifyChangeValue(forKey: #keyPath(planeString3))
163 notifyChangeValue(forKey: #keyPath(planeString3Color))
164 notifyChangeValue(forKey: #keyPath(planeString4))
165 notifyChangeValue(forKey: #keyPath(planeString4Color))
169 if context == &equippedItem0Context {
171 notifyChangeValue(forKey: #keyPath(planeString0))
172 notifyChangeValue(forKey: #keyPath(planeString0Color))
176 if context == &equippedItem1Context {
178 notifyChangeValue(forKey: #keyPath(planeString1))
179 notifyChangeValue(forKey: #keyPath(planeString1Color))
183 if context == &equippedItem2Context {
185 notifyChangeValue(forKey: #keyPath(planeString2))
186 notifyChangeValue(forKey: #keyPath(planeString2Color))
190 if context == &equippedItem3Context {
192 notifyChangeValue(forKey: #keyPath(planeString3))
193 notifyChangeValue(forKey: #keyPath(planeString3Color))
197 if context == &equippedItem4Context {
199 notifyChangeValue(forKey: #keyPath(planeString4))
200 notifyChangeValue(forKey: #keyPath(planeString4Color))
205 super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
210 private let allPlaneTypes: [Int] = [6, 7, 8, 9, 10, 11, 25, 26, 41, 45, 56, 57, 58, 59]
213 extension ShipDetailViewController {
215 // MARK: - Plane count strings
216 private enum PlaneState {
220 case equiped(Int, Int)
223 private func planState(_ index: Int) -> PlaneState {
225 guard let ship = ship else { return .cannotEquip }
227 let itemId = ship.slotItemId(index)
228 let maxCount = ship.slotItemMax(index)
230 if maxCount == 0 { return .cannotEquip }
231 if itemId == -1 { return .notEquip(maxCount) }
233 if let item = ship.slotItem(index),
234 allPlaneTypes.contains(item.master_slotItem.type_2) {
236 return .equiped(ship.slotItemCount(index), maxCount)
239 return .notEquip(maxCount)
242 private func planeString(_ index: Int) -> String? {
244 switch planState(index) {
247 case .notEquip(let max):
249 case .equiped(let count, let max):
250 return "\(count)/\(max)"
254 @objc dynamic var planeString0: String? { return planeString(0) }
256 @objc dynamic var planeString1: String? { return planeString(1) }
258 @objc dynamic var planeString2: String? { return planeString(2) }
260 @objc dynamic var planeString3: String? { return planeString(3) }
262 @objc dynamic var planeString4: String? { return planeString(4) }
264 // MARK: - Plane count string color
265 private func planeStringColor(_ index: Int) -> NSColor {
267 switch planState(index) {
268 case .cannotEquip: return NSColor.controlTextColor
269 case .notEquip: return NSColor.disabledControlTextColor
270 case .equiped: return NSColor.controlTextColor
274 @objc dynamic var planeString0Color: NSColor { return planeStringColor(0) }
276 @objc dynamic var planeString1Color: NSColor { return planeStringColor(1) }
278 @objc dynamic var planeString2Color: NSColor { return planeStringColor(2) }
280 @objc dynamic var planeString3Color: NSColor { return planeStringColor(3) }
282 @objc dynamic var planeString4Color: NSColor { return planeStringColor(4) }
285 extension ShipDetailViewController: NibLoadable {}