2 // ShipDetailViewController.swift
5 // Created by Hori,Masaki on 2016/12/25.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
11 enum ShipDetailViewType {
20 private func nibNameFor(_ type: ShipDetailViewType) -> NSNib.Name {
24 case .full: return ShipDetailViewController.nibName
26 case .medium: return NSNib.Name("MediumShipViewController")
28 case .minimum: return NSNib.Name("MediumShipViewController")
33 final class ShipDetailViewController: NSViewController {
35 let type: ShipDetailViewType
36 @objc let managedObjectContext = ServerDataStore.default.context
38 init?(type: ShipDetailViewType) {
42 super.init(nibName: nibNameFor(type), bundle: nil)
44 NotificationCenter.default
45 .addObserver(forName: .DidUpdateGuardEscape, object: nil, queue: nil) { [weak self] _ in
47 self?.guardEscaped = self?.ship?.guardEscaped ?? false
51 required init?(coder: NSCoder) {
53 fatalError("not implemented")
58 damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
59 [slot00Field, slot01Field, slot02Field, slot03Field, slot04Field]
60 .forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
63 @IBOutlet private weak var supply: SuppliesView!
64 @IBOutlet private weak var guardEscapedView: GuardEscapedView!
65 @IBOutlet private weak var damageView: DamageView!
66 @IBOutlet private weak var slot00Field: SlotItemLevelView!
67 @IBOutlet private weak var slot01Field: SlotItemLevelView!
68 @IBOutlet private weak var slot02Field: SlotItemLevelView!
69 @IBOutlet private weak var slot03Field: SlotItemLevelView!
70 @IBOutlet private weak var slot04Field: SlotItemLevelView!
72 var observer: ShipSlotObserver?
74 @objc dynamic var guardEscaped: Bool = false {
78 guardEscapedView.isHidden = !guardEscaped
82 @objc dynamic var ship: Ship? {
97 observer = ship.map { ship in
99 let observer = ShipSlotObserver(ship: ship)
100 observer.delegate = self
105 // slot の lv, alv の反映のため
106 let fields = [slot00Field, slot01Field, slot02Field, slot03Field, slot04Field]
107 fields.forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
109 damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
113 zip(fields, [#keyPath(Ship.slot_0), #keyPath(Ship.slot_1), #keyPath(Ship.slot_2), #keyPath(Ship.slot_3), #keyPath(Ship.slot_4)])
114 .forEach { feild, keyPath in
116 feild?.bind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID)), to: ship, withKeyPath: keyPath)
119 damageView.bind(NSBindingName(#keyPath(DamageView.damageType)), to: ship, withKeyPath: #keyPath(Ship.status))
123 fields.forEach { $0?.slotItemID = nil }
125 damageView.damageType = 0
130 override func viewDidLoad() {
134 damageView.setFrameOrigin(.zero)
135 view.addSubview(damageView)
137 guardEscapedView.setFrameOrigin(.zero)
138 view.addSubview(guardEscapedView)
141 case .medium, .minimum:
142 guardEscapedView.controlSize = .mini
151 extension ShipDetailViewController: ShipSlotObserverDelegate {
153 func didChangeSlot0() {
155 notifyChangeValue(forKey: #keyPath(planeString0))
156 notifyChangeValue(forKey: #keyPath(planeString0Color))
159 func didChangeSlot1() {
161 notifyChangeValue(forKey: #keyPath(planeString1))
162 notifyChangeValue(forKey: #keyPath(planeString1Color))
165 func didChangeSlot2() {
167 notifyChangeValue(forKey: #keyPath(planeString2))
168 notifyChangeValue(forKey: #keyPath(planeString2Color))
171 func didChangeSlot3() {
173 notifyChangeValue(forKey: #keyPath(planeString3))
174 notifyChangeValue(forKey: #keyPath(planeString3Color))
177 func didChangeSlot4() {
179 notifyChangeValue(forKey: #keyPath(planeString4))
180 notifyChangeValue(forKey: #keyPath(planeString4Color))
184 private let allPlaneTypes: [EquipmentType] =
185 [.fighter, .bomber, .attacker, .searcher,
186 .airplaneSearcher, .airplaneBomber,
187 .autoGyro, .antiSunmrinerSercher,
188 .largeAirplane, .airplaneFighter,
189 .jetFighter, .jetBomber, .jetAttacker, .jetSearcher
191 extension ShipDetailViewController {
193 // MARK: - Plane count strings
194 private enum PlaneState {
198 case notEquip(Int) // current count
200 case equiped(Int, Int) // current count and max
203 private func planState(_ index: Int) -> PlaneState {
205 guard let ship = ship else {
210 let itemId = ship.slotItemId(index)
211 let maxCount = ship.slotItemMax(index)
219 return .notEquip(maxCount)
222 if let item = ship.slotItem(index),
223 let eqType = EquipmentType(rawValue: item.master_slotItem.type_2),
224 allPlaneTypes.contains(eqType) {
226 return .equiped(ship.slotItemCount(index), maxCount)
229 return .notEquip(maxCount)
232 private func planeString(_ index: Int) -> String? {
234 switch planState(index) {
236 case .cannotEquip: return nil
238 case .notEquip(let max): return "\(max)"
240 case .equiped(let count, let max): return "\(count)/\(max)"
245 @objc dynamic var planeString0: String? { return planeString(0) }
246 @objc dynamic var planeString1: String? { return planeString(1) }
247 @objc dynamic var planeString2: String? { return planeString(2) }
248 @objc dynamic var planeString3: String? { return planeString(3) }
249 @objc dynamic var planeString4: String? { return planeString(4) }
251 // MARK: - Plane count string color
252 private func planeStringColor(_ index: Int) -> NSColor {
254 switch planState(index) {
256 case .cannotEquip: return NSColor.controlTextColor
258 case .notEquip: return NSColor.disabledControlTextColor
260 case .equiped: return NSColor.controlTextColor
265 @objc dynamic var planeString0Color: NSColor { return planeStringColor(0) }
266 @objc dynamic var planeString1Color: NSColor { return planeStringColor(1) }
267 @objc dynamic var planeString2Color: NSColor { return planeStringColor(2) }
268 @objc dynamic var planeString3Color: NSColor { return planeStringColor(3) }
269 @objc dynamic var planeString4Color: NSColor { return planeStringColor(4) }
272 extension ShipDetailViewController: NibLoadable {}