OSDN Git Service

洋上補給の補強増設用のショートネームをつけた
[kcd/KCD.git] / KCD / ShipDetailViewController.swift
1 //
2 //  ShipDetailViewController.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2016/12/25.
6 //  Copyright © 2016年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 enum ShipDetailViewType {
12     
13     case full
14     case medium
15     case minimum
16 }
17
18 private func nibNameFor(_ type: ShipDetailViewType) -> NSNib.Name {
19     
20     switch type {
21     case .full: return ShipDetailViewController.nibName
22     case .medium: return NSNib.Name("MediumShipViewController")
23     case .minimum: return NSNib.Name("MediumShipViewController")
24     }
25 }
26
27 final class ShipDetailViewController: NSViewController {
28     
29     let type: ShipDetailViewType
30     @objc let managedObjectContext = ServerDataStore.default.context
31     
32     init?(type: ShipDetailViewType) {
33         
34         self.type = type
35         
36         super.init(nibName: nibNameFor(type), bundle: nil)
37         
38         NotificationCenter.default
39             .addObserver(forName: .DidUpdateGuardEscape, object: nil, queue: nil) { [weak self] _ in
40                 
41                 self?.guardEscaped = self?.ship?.guardEscaped ?? false
42         }
43     }
44     
45     required init?(coder: NSCoder) {
46         
47         fatalError("not implemented")
48     }
49     
50     deinit {
51         
52         damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
53         [slot00Field, slot01Field, slot02Field, slot03Field, slot04Field]
54             .forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
55     }
56     
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!
65     
66     var observer: ShipSlotObserver?
67     
68     @objc dynamic var guardEscaped: Bool = false {
69         
70         didSet {
71             guardEscapedView.isHidden = !guardEscaped
72         }
73     }
74     
75     @objc dynamic var ship: Ship? {
76         
77         didSet {
78             
79             defer {
80                 didChangeSlot0()
81                 didChangeSlot1()
82                 didChangeSlot2()
83                 didChangeSlot3()
84                 didChangeSlot4()
85             }
86             
87             supply.ship = ship
88             
89             observer = ship.map { ship in
90                 
91                 let observer  = ShipSlotObserver(ship: ship)
92                 observer.delegate = self
93                 
94                 return observer
95             }
96             
97             // slot の lv, alv の反映のため
98             let fields = [slot00Field, slot01Field, slot02Field, slot03Field, slot04Field]
99             fields.forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
100             
101             damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
102             
103             if let ship = ship {
104                 
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)
108                 }
109                 
110                 damageView.bind(NSBindingName(#keyPath(DamageView.damageType)), to: ship, withKeyPath: #keyPath(Ship.status))
111                 
112             } else {
113                 
114                 fields.forEach { $0?.slotItemID = nil }
115                 
116                 damageView.damageType = 0
117             }
118         }
119     }
120     
121     override func viewDidLoad() {
122         
123         super.viewDidLoad()
124         
125         damageView.setFrameOrigin(.zero)
126         view.addSubview(damageView)
127         
128         guardEscapedView.setFrameOrigin(.zero)
129         view.addSubview(guardEscapedView)
130         switch type {
131         case .medium, .minimum:
132             guardEscapedView.controlSize = .mini
133             
134         default: break
135         }
136         
137     }
138 }
139
140 extension ShipDetailViewController: ShipSlotObserverDelegate {
141     
142     func didChangeSlot0() {
143         
144         notifyChangeValue(forKey: #keyPath(planeString0))
145         notifyChangeValue(forKey: #keyPath(planeString0Color))
146     }
147     
148     func didChangeSlot1() {
149         
150         notifyChangeValue(forKey: #keyPath(planeString1))
151         notifyChangeValue(forKey: #keyPath(planeString1Color))
152     }
153     
154     func didChangeSlot2() {
155         
156         notifyChangeValue(forKey: #keyPath(planeString2))
157         notifyChangeValue(forKey: #keyPath(planeString2Color))
158     }
159     
160     func didChangeSlot3() {
161         
162         notifyChangeValue(forKey: #keyPath(planeString3))
163         notifyChangeValue(forKey: #keyPath(planeString3Color))
164     }
165     
166     func didChangeSlot4() {
167         
168         notifyChangeValue(forKey: #keyPath(planeString4))
169         notifyChangeValue(forKey: #keyPath(planeString4Color))
170     }
171 }
172
173 private let allPlaneTypes: [EquipmentType] =
174     [.fighter, .bomber, .attacker, .searcher,
175      .airplaneSearcher, .airplaneBomber,
176      .autoGyro, .antiSunmrinerSercher,
177      .largeAirplane, .airplaneFighter,
178      .jetFighter, .jetBomber, .jetAttacker, .jetSearcher
179 ]
180 extension ShipDetailViewController {
181     
182     // MARK: - Plane count strings
183     private enum PlaneState {
184         
185         case cannotEquip
186         case notEquip(Int)  // current count
187         case equiped(Int, Int)  // current count and max
188     }
189     
190     private func planState(_ index: Int) -> PlaneState {
191         
192         guard let ship = ship else { return .cannotEquip }
193         
194         let itemId = ship.slotItemId(index)
195         let maxCount = ship.slotItemMax(index)
196         
197         if maxCount == 0 { return .cannotEquip }
198         if itemId == -1 { return .notEquip(maxCount) }
199         
200         if let item = ship.slotItem(index),
201             let eqType = EquipmentType(rawValue: item.master_slotItem.type_2),
202             allPlaneTypes.contains(eqType) {
203             
204             return .equiped(ship.slotItemCount(index), maxCount)
205         }
206         
207         return .notEquip(maxCount)
208     }
209     
210     private func planeString(_ index: Int) -> String? {
211         
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)"
216         }
217     }
218     
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) }
224     
225     // MARK: - Plane count string color
226     private func planeStringColor(_ index: Int) -> NSColor {
227         
228         switch planState(index) {
229         case .cannotEquip: return NSColor.controlTextColor
230         case .notEquip: return NSColor.disabledControlTextColor
231         case .equiped: return NSColor.controlTextColor
232         }
233     }
234     
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) }
240 }
241
242 extension ShipDetailViewController: NibLoadable {}