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 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
33
34 final class ShipDetailViewController: NSViewController {
35     
36     let type: ShipDetailViewType
37     @objc let managedObjectContext = ServerDataStore.default.context
38     
39     init?(type: ShipDetailViewType) {
40         
41         self.type = type
42         
43         super.init(nibName: nibNameFor(type), bundle: nil)
44         
45         NotificationCenter
46             .default
47             .addObserver(forName: .DidUpdateGuardEscape, object: nil, queue: nil) { [weak self] _ in
48                 
49                 guard let `self` = self else { return }
50                 
51                 self.guardEscaped = self.ship?.guardEscaped ?? false
52         }
53     }
54     
55     required init?(coder: NSCoder) {
56         
57         fatalError("not implemented")
58     }
59     
60     deinit {
61         
62         NotificationCenter.default.removeObserver(self)
63         damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
64         supply.unbind(NSBindingName(#keyPath(SuppliesView.ship)))
65         [slot00Field, slot01Field, slot02Field, slot03Field]
66             .forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
67         
68         shipController.removeObserver(self, forKeyPath: "selection")
69         
70         shipController.removeObserver(self, forKeyPath: "selection.slot_0")
71         shipController.removeObserver(self, forKeyPath: "selection.onslot_0")
72         shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_0")
73         
74         shipController.removeObserver(self, forKeyPath: "selection.slot_1")
75         shipController.removeObserver(self, forKeyPath: "selection.onslot_1")
76         shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_1")
77
78         shipController.removeObserver(self, forKeyPath: "selection.slot_2")
79         shipController.removeObserver(self, forKeyPath: "selection.onslot_2")
80         shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_2")
81         
82         shipController.removeObserver(self, forKeyPath: "selection.slot_3")
83         shipController.removeObserver(self, forKeyPath: "selection.onslot_3")
84         shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_3")
85         
86         shipController.removeObserver(self, forKeyPath: "selection.slot_4")
87         shipController.removeObserver(self, forKeyPath: "selection.onslot_4")
88         shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_4")
89
90     }
91     
92     
93     @IBOutlet weak var supply: SuppliesView!
94     @IBOutlet weak var guardEscapedView: GuardEscapedView!
95     @IBOutlet weak var damageView: DamageView!
96     @IBOutlet weak var slot00Field: SlotItemLevelView!
97     @IBOutlet weak var slot01Field: SlotItemLevelView!
98     @IBOutlet weak var slot02Field: SlotItemLevelView!
99     @IBOutlet weak var slot03Field: SlotItemLevelView!
100     @IBOutlet var shipController: NSObjectController!
101     
102     @objc dynamic var guardEscaped: Bool = false {
103         
104         didSet {
105             guardEscapedView.isHidden = !guardEscaped
106         }
107     }
108     
109     @objc dynamic var ship: Ship? {
110         
111         get { return shipController.content as? Ship }
112         set {
113             shipController.fetchPredicate = NSPredicate(#keyPath(Ship.id), equal: newValue?.id ?? 0)
114         }
115     }
116     
117     override func viewDidLoad() {
118         
119         super.viewDidLoad()
120         
121         damageView.setFrameOrigin(.zero)
122         view.addSubview(damageView)
123         damageView.bind(NSBindingName(#keyPath(DamageView.damageType)),
124                         to: shipController,
125                         withKeyPath: "selection.status", options: nil)
126         
127         supply.bind(NSBindingName(#keyPath(SuppliesView.ship)),
128                     to: shipController,
129                     withKeyPath: "selection.self", options: nil)
130         
131         guardEscapedView.setFrameOrigin(.zero)
132         view.addSubview(guardEscapedView)
133         switch type {
134         case .medium, .minimum:
135             guardEscapedView.controlSize = .mini
136             
137         default: break
138         }
139         
140         let fields = [slot00Field, slot01Field, slot02Field, slot03Field]
141         let keypath = ["selection.slot_0", "selection.slot_1", "selection.slot_2", "selection.slot_3"]
142         zip(fields, keypath).forEach {
143             
144             $0.0?.bind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID)), to: shipController, withKeyPath: $0.1, options: nil)
145         }
146         
147         // observe slotitems count
148         shipController.addObserver(self, forKeyPath: "selection", context: &shipContext)
149         
150         shipController.addObserver(self, forKeyPath: "selection.slot_0", context: &equippedItem0Context)
151         shipController.addObserver(self, forKeyPath: "selection.onslot_0", context: &equippedItem0Context)
152         shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_0", context: &equippedItem0Context)
153         
154         shipController.addObserver(self, forKeyPath: "selection.slot_1", context: &equippedItem1Context)
155         shipController.addObserver(self, forKeyPath: "selection.onslot_1", context: &equippedItem1Context)
156         shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_1", context: &equippedItem1Context)
157         
158         shipController.addObserver(self, forKeyPath: "selection.slot_2", context: &equippedItem2Context)
159         shipController.addObserver(self, forKeyPath: "selection.onslot_2", context: &equippedItem2Context)
160         shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_2", context: &equippedItem2Context)
161         
162         shipController.addObserver(self, forKeyPath: "selection.slot_3", context: &equippedItem3Context)
163         shipController.addObserver(self, forKeyPath: "selection.onslot_3", context: &equippedItem3Context)
164         shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_3", context: &equippedItem3Context)
165         
166         shipController.addObserver(self, forKeyPath: "selection.slot_4", context: &equippedItem4Context)
167         shipController.addObserver(self, forKeyPath: "selection.onslot_4", context: &equippedItem4Context)
168         shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_4", context: &equippedItem4Context)
169         
170     }
171     
172     override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
173         
174         if context == &shipContext {
175             
176             notifyChangeValue(forKey: #keyPath(planeString0))
177             notifyChangeValue(forKey: #keyPath(planeString0Color))
178             notifyChangeValue(forKey: #keyPath(planeString1))
179             notifyChangeValue(forKey: #keyPath(planeString1Color))
180             notifyChangeValue(forKey: #keyPath(planeString2))
181             notifyChangeValue(forKey: #keyPath(planeString2Color))
182             notifyChangeValue(forKey: #keyPath(planeString3))
183             notifyChangeValue(forKey: #keyPath(planeString3Color))
184             notifyChangeValue(forKey: #keyPath(planeString4))
185             notifyChangeValue(forKey: #keyPath(planeString4Color))
186             
187             return
188         }
189         if context == &equippedItem0Context {
190             
191             notifyChangeValue(forKey: #keyPath(planeString0))
192             notifyChangeValue(forKey: #keyPath(planeString0Color))
193             
194             return
195         }
196         if context == &equippedItem1Context {
197             
198             notifyChangeValue(forKey: #keyPath(planeString1))
199             notifyChangeValue(forKey: #keyPath(planeString1Color))
200             
201             return
202         }
203         if context == &equippedItem2Context {
204             
205             notifyChangeValue(forKey: #keyPath(planeString2))
206             notifyChangeValue(forKey: #keyPath(planeString2Color))
207             
208             return
209         }
210         if context == &equippedItem3Context {
211             
212             notifyChangeValue(forKey: #keyPath(planeString3))
213             notifyChangeValue(forKey: #keyPath(planeString3Color))
214             
215             return
216         }
217         if context == &equippedItem4Context {
218             
219             notifyChangeValue(forKey: #keyPath(planeString4))
220             notifyChangeValue(forKey: #keyPath(planeString4Color))
221             
222             return
223         }
224         
225         super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
226     }
227 }
228
229
230 private let allPlaneTypes: [Int] = [6, 7, 8, 9, 10, 11, 25, 26, 41, 45, 56, 57, 58, 59]
231
232
233 extension ShipDetailViewController {
234     
235     // MARK: - Plane count strings
236     private enum PlaneState {
237         
238         case cannotEquip
239         case notEquip(Int)
240         case equiped(Int, Int)
241     }
242     
243     private func planState(_ index: Int) -> PlaneState {
244         
245         guard let ship = ship else { return .cannotEquip }
246         
247         let itemId = ship.slotItemId(index)
248         let maxCount = ship.slotItemMax(index)
249         
250         if maxCount == 0 { return .cannotEquip }
251         if itemId == -1 { return .notEquip(maxCount) }
252         
253         if let item = ship.slotItem(index),
254             allPlaneTypes.contains(item.master_slotItem.type_2) {
255             
256             return .equiped(ship.slotItemCount(index), maxCount)
257         }
258         
259         return .notEquip(maxCount)
260     }
261     
262     private func planeString(_ index: Int) -> String? {
263         
264         switch planState(index) {
265         case .cannotEquip:
266             return nil
267         case .notEquip(let max):
268             return "\(max)"
269         case .equiped(let count, let max):
270             return "\(count)/\(max)"
271         }
272     }
273     
274     @objc dynamic var planeString0: String? { return planeString(0) }
275     
276     @objc dynamic var planeString1: String? { return planeString(1) }
277     
278     @objc dynamic var planeString2: String? { return planeString(2) }
279     
280     @objc dynamic var planeString3: String? { return planeString(3) }
281     
282     @objc dynamic var planeString4: String? { return planeString(4) }
283     
284     // MARK: - Plane count string color
285     private func planeStringColor(_ index: Int) -> NSColor {
286         
287         switch planState(index) {
288         case .cannotEquip: return NSColor.controlTextColor
289         case .notEquip: return NSColor.disabledControlTextColor
290         case .equiped: return NSColor.controlTextColor
291         }
292     }
293     
294     @objc dynamic var planeString0Color: NSColor { return planeStringColor(0) }
295     
296     @objc dynamic var planeString1Color: NSColor { return planeStringColor(1) }
297     
298     @objc dynamic var planeString2Color: NSColor { return planeStringColor(2) }
299     
300     @objc dynamic var planeString3Color: NSColor { return planeStringColor(3) }
301     
302     @objc dynamic var planeString4Color: NSColor { return planeStringColor(4) }
303 }
304
305 extension ShipDetailViewController: NibLoadable {}