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 final class ShipDetailViewController: NSViewController {
29 let type: ShipDetailViewType
30 @objc let managedObjectContext = ServerDataStore.default.context
32 init?(type: ShipDetailViewType) {
36 super.init(nibName: nibNameFor(type), bundle: nil)
38 NotificationCenter.default
39 .addObserver(forName: .DidUpdateGuardEscape, object: nil, queue: nil) { [weak self] _ in
41 self?.guardEscaped = self?.ship?.guardEscaped ?? false
45 required init?(coder: NSCoder) {
47 fatalError("not implemented")
52 damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
53 [slot00Field, slot01Field, slot02Field, slot03Field, slot04Field]
54 .forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
57 @IBOutlet private weak var supply: SuppliesView!
58 @IBOutlet private weak var guardEscapedView: GuardEscapedView!
59 @IBOutlet private weak var damageView: DamageView!
60 @IBOutlet private weak var slot00Field: SlotItemLevelView!
61 @IBOutlet private weak var slot01Field: SlotItemLevelView!
62 @IBOutlet private weak var slot02Field: SlotItemLevelView!
63 @IBOutlet private weak var slot03Field: SlotItemLevelView!
64 @IBOutlet private weak var slot04Field: SlotItemLevelView!
66 var observer: ShipSlotObserver?
68 @objc dynamic var guardEscaped: Bool = false {
71 guardEscapedView.isHidden = !guardEscaped
75 @objc dynamic var ship: Ship? {
89 observer = ship.map { ship in
91 let observer = ShipSlotObserver(ship: ship)
92 observer.delegate = self
97 // slot の lv, alv の反映のため
98 let fields = [slot00Field, slot01Field, slot02Field, slot03Field, slot04Field]
99 fields.forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
101 damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
105 zip(fields, [#keyPath(Ship.slot_0), #keyPath(Ship.slot_1), #keyPath(Ship.slot_2), #keyPath(Ship.slot_3), #keyPath(Ship.slot_4)])
106 .forEach { feild, keyPath in
107 feild?.bind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID)), to: ship, withKeyPath: keyPath)
110 damageView.bind(NSBindingName(#keyPath(DamageView.damageType)), to: ship, withKeyPath: #keyPath(Ship.status))
114 fields.forEach { $0?.slotItemID = nil }
116 damageView.damageType = 0
121 override func viewDidLoad() {
125 damageView.setFrameOrigin(.zero)
126 view.addSubview(damageView)
128 guardEscapedView.setFrameOrigin(.zero)
129 view.addSubview(guardEscapedView)
131 case .medium, .minimum:
132 guardEscapedView.controlSize = .mini
140 extension ShipDetailViewController: ShipSlotObserverDelegate {
142 func didChangeSlot0() {
144 notifyChangeValue(forKey: #keyPath(planeString0))
145 notifyChangeValue(forKey: #keyPath(planeString0Color))
148 func didChangeSlot1() {
150 notifyChangeValue(forKey: #keyPath(planeString1))
151 notifyChangeValue(forKey: #keyPath(planeString1Color))
154 func didChangeSlot2() {
156 notifyChangeValue(forKey: #keyPath(planeString2))
157 notifyChangeValue(forKey: #keyPath(planeString2Color))
160 func didChangeSlot3() {
162 notifyChangeValue(forKey: #keyPath(planeString3))
163 notifyChangeValue(forKey: #keyPath(planeString3Color))
166 func didChangeSlot4() {
168 notifyChangeValue(forKey: #keyPath(planeString4))
169 notifyChangeValue(forKey: #keyPath(planeString4Color))
173 private let allPlaneTypes: [EquipmentType] =
174 [.fighter, .bomber, .attacker, .searcher,
175 .airplaneSearcher, .airplaneBomber,
176 .autoGyro, .antiSunmrinerSercher,
177 .largeAirplane, .airplaneFighter,
178 .jetFighter, .jetBomber, .jetAttacker, .jetSearcher
180 extension ShipDetailViewController {
182 // MARK: - Plane count strings
183 private enum PlaneState {
186 case notEquip(Int) // current count
187 case equiped(Int, Int) // current count and max
190 private func planState(_ index: Int) -> PlaneState {
192 guard let ship = ship else { return .cannotEquip }
194 let itemId = ship.slotItemId(index)
195 let maxCount = ship.slotItemMax(index)
197 if maxCount == 0 { return .cannotEquip }
198 if itemId == -1 { return .notEquip(maxCount) }
200 if let item = ship.slotItem(index),
201 let eqType = EquipmentType(rawValue: item.master_slotItem.type_2),
202 allPlaneTypes.contains(eqType) {
204 return .equiped(ship.slotItemCount(index), maxCount)
207 return .notEquip(maxCount)
210 private func planeString(_ index: Int) -> String? {
212 switch planState(index) {
213 case .cannotEquip: return nil
214 case .notEquip(let max): return "\(max)"
215 case .equiped(let count, let max): return "\(count)/\(max)"
219 @objc dynamic var planeString0: String? { return planeString(0) }
220 @objc dynamic var planeString1: String? { return planeString(1) }
221 @objc dynamic var planeString2: String? { return planeString(2) }
222 @objc dynamic var planeString3: String? { return planeString(3) }
223 @objc dynamic var planeString4: String? { return planeString(4) }
225 // MARK: - Plane count string color
226 private func planeStringColor(_ index: Int) -> NSColor {
228 switch planState(index) {
229 case .cannotEquip: return NSColor.controlTextColor
230 case .notEquip: return NSColor.disabledControlTextColor
231 case .equiped: return NSColor.controlTextColor
235 @objc dynamic var planeString0Color: NSColor { return planeStringColor(0) }
236 @objc dynamic var planeString1Color: NSColor { return planeStringColor(1) }
237 @objc dynamic var planeString2Color: NSColor { return planeStringColor(2) }
238 @objc dynamic var planeString3Color: NSColor { return planeStringColor(3) }
239 @objc dynamic var planeString4Color: NSColor { return planeStringColor(4) }
242 extension ShipDetailViewController: NibLoadable {}