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 }
92 shipController.fetchPredicate = NSPredicate(#keyPath(Ship.id), equal: newValue?.id ?? 0)
96 override func viewDidLoad() {
100 damageView.setFrameOrigin(.zero)
101 view.addSubview(damageView)
102 damageView.bind(NSBindingName(#keyPath(DamageView.damageType)),
104 withKeyPath: "selection.status", options: nil)
106 supply.bind(NSBindingName(#keyPath(SuppliesView.shipStatus)),
108 withKeyPath: "selection.self", options: nil)
110 guardEscapedView.setFrameOrigin(.zero)
111 view.addSubview(guardEscapedView)
113 case .medium, .minimum:
114 guardEscapedView.controlSize = .mini
119 let fields = [slot00Field, slot01Field, slot02Field, slot03Field]
120 let keypath = ["selection.slot_0", "selection.slot_1", "selection.slot_2", "selection.slot_3"]
121 zip(fields, keypath).forEach {
123 $0.0?.bind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID)), to: shipController, withKeyPath: $0.1, options: nil)
126 // observe slotitems count
127 shipController.addObserver(self, forKeyPath: "selection", context: &shipContext)
129 shipController.addObserver(self, forKeyPath: "selection.slot_0", context: &equippedItem0Context)
130 shipController.addObserver(self, forKeyPath: "selection.onslot_0", context: &equippedItem0Context)
131 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_0", context: &equippedItem0Context)
133 shipController.addObserver(self, forKeyPath: "selection.slot_1", context: &equippedItem1Context)
134 shipController.addObserver(self, forKeyPath: "selection.onslot_1", context: &equippedItem1Context)
135 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_1", context: &equippedItem1Context)
137 shipController.addObserver(self, forKeyPath: "selection.slot_2", context: &equippedItem2Context)
138 shipController.addObserver(self, forKeyPath: "selection.onslot_2", context: &equippedItem2Context)
139 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_2", context: &equippedItem2Context)
141 shipController.addObserver(self, forKeyPath: "selection.slot_3", context: &equippedItem3Context)
142 shipController.addObserver(self, forKeyPath: "selection.onslot_3", context: &equippedItem3Context)
143 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_3", context: &equippedItem3Context)
145 shipController.addObserver(self, forKeyPath: "selection.slot_4", context: &equippedItem4Context)
146 shipController.addObserver(self, forKeyPath: "selection.onslot_4", context: &equippedItem4Context)
147 shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_4", context: &equippedItem4Context)
151 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
153 if context == &shipContext {
155 notifyChangeValue(forKey: #keyPath(planeString0))
156 notifyChangeValue(forKey: #keyPath(planeString0Color))
157 notifyChangeValue(forKey: #keyPath(planeString1))
158 notifyChangeValue(forKey: #keyPath(planeString1Color))
159 notifyChangeValue(forKey: #keyPath(planeString2))
160 notifyChangeValue(forKey: #keyPath(planeString2Color))
161 notifyChangeValue(forKey: #keyPath(planeString3))
162 notifyChangeValue(forKey: #keyPath(planeString3Color))
163 notifyChangeValue(forKey: #keyPath(planeString4))
164 notifyChangeValue(forKey: #keyPath(planeString4Color))
168 if context == &equippedItem0Context {
170 notifyChangeValue(forKey: #keyPath(planeString0))
171 notifyChangeValue(forKey: #keyPath(planeString0Color))
175 if context == &equippedItem1Context {
177 notifyChangeValue(forKey: #keyPath(planeString1))
178 notifyChangeValue(forKey: #keyPath(planeString1Color))
182 if context == &equippedItem2Context {
184 notifyChangeValue(forKey: #keyPath(planeString2))
185 notifyChangeValue(forKey: #keyPath(planeString2Color))
189 if context == &equippedItem3Context {
191 notifyChangeValue(forKey: #keyPath(planeString3))
192 notifyChangeValue(forKey: #keyPath(planeString3Color))
196 if context == &equippedItem4Context {
198 notifyChangeValue(forKey: #keyPath(planeString4))
199 notifyChangeValue(forKey: #keyPath(planeString4Color))
204 super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
209 private let allPlaneTypes: [Int] = [6, 7, 8, 9, 10, 11, 25, 26, 41, 45, 56, 57, 58, 59]
212 extension ShipDetailViewController {
214 // MARK: - Plane count strings
215 private enum PlaneState {
219 case equiped(Int, Int)
222 private func planState(_ index: Int) -> PlaneState {
224 guard let ship = ship else { return .cannotEquip }
226 let itemId = ship.slotItemId(index)
227 let maxCount = ship.slotItemMax(index)
229 if maxCount == 0 { return .cannotEquip }
230 if itemId == -1 { return .notEquip(maxCount) }
232 if let item = ship.slotItem(index),
233 allPlaneTypes.contains(item.master_slotItem.type_2) {
235 return .equiped(ship.slotItemCount(index), maxCount)
238 return .notEquip(maxCount)
241 private func planeString(_ index: Int) -> String? {
243 switch planState(index) {
246 case .notEquip(let max):
248 case .equiped(let count, let max):
249 return "\(count)/\(max)"
253 @objc dynamic var planeString0: String? { return planeString(0) }
255 @objc dynamic var planeString1: String? { return planeString(1) }
257 @objc dynamic var planeString2: String? { return planeString(2) }
259 @objc dynamic var planeString3: String? { return planeString(3) }
261 @objc dynamic var planeString4: String? { return planeString(4) }
263 // MARK: - Plane count string color
264 private func planeStringColor(_ index: Int) -> NSColor {
266 switch planState(index) {
267 case .cannotEquip: return NSColor.controlTextColor
268 case .notEquip: return NSColor.disabledControlTextColor
269 case .equiped: return NSColor.controlTextColor
273 @objc dynamic var planeString0Color: NSColor { return planeStringColor(0) }
275 @objc dynamic var planeString1Color: NSColor { return planeStringColor(1) }
277 @objc dynamic var planeString2Color: NSColor { return planeStringColor(2) }
279 @objc dynamic var planeString3Color: NSColor { return planeStringColor(3) }
281 @objc dynamic var planeString4Color: NSColor { return planeStringColor(4) }
284 extension ShipDetailViewController: NibLoadable {}