import Cocoa
enum ShipDetailViewType {
+
case full
case medium
case minimum
}
-private func nibNameFor(_ type: ShipDetailViewType) -> String {
+private func nibNameFor(_ type: ShipDetailViewType) -> NSNib.Name {
+
switch type {
- case .full:
- return "ShipDetailViewController"
- case .medium:
- return "MediumShipViewController"
- case .minimum:
- return "MediumShipViewController"
+ case .full: return ShipDetailViewController.nibName
+ case .medium: return NSNib.Name("MediumShipViewController")
+ case .minimum: return NSNib.Name("MediumShipViewController")
}
}
-class ShipDetailViewController: NSViewController {
+private var shipContext: Int = 0
+private var equippedItem0Context: Int = 0
+private var equippedItem1Context: Int = 0
+private var equippedItem2Context: Int = 0
+private var equippedItem3Context: Int = 0
+private var equippedItem4Context: Int = 0
+
+final class ShipDetailViewController: NSViewController {
+
let type: ShipDetailViewType
- let managedObjectContext = ServerDataStore.default.managedObjectContext
+ @objc let managedObjectContext = ServerDataStore.default.context
init?(type: ShipDetailViewType) {
+
self.type = type
+
super.init(nibName: nibNameFor(type), bundle: nil)
NotificationCenter
.default
- .addObserver(forName: .DidUpdateGuardEscape,
- object: nil,
- queue: nil) { [unowned self] _ in
- self.guardEscaped = self.ship?.guardEscaped ?? false
+ .addObserver(forName: .DidUpdateGuardEscape, object: nil, queue: nil) { [weak self] _ in
+
+ guard let `self` = self else { return }
+
+ self.guardEscaped = self.ship?.guardEscaped ?? false
}
}
+
required init?(coder: NSCoder) {
+
fatalError("not implemented")
}
+
deinit {
+
NotificationCenter.default.removeObserver(self)
- damageView.unbind("damageType")
- supply.unbind("shipStatus")
+ damageView.unbind(NSBindingName(#keyPath(DamageView.damageType)))
+ supply.unbind(NSBindingName(#keyPath(SuppliesView.ship)))
[slot00Field, slot01Field, slot02Field, slot03Field]
- .forEach { $0?.unbind("slotItemID") }
+ .forEach { $0?.unbind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID))) }
+
+ shipController.removeObserver(self, forKeyPath: "selection")
+
+ shipController.removeObserver(self, forKeyPath: "selection.slot_0")
+ shipController.removeObserver(self, forKeyPath: "selection.onslot_0")
+ shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_0")
+
+ shipController.removeObserver(self, forKeyPath: "selection.slot_1")
+ shipController.removeObserver(self, forKeyPath: "selection.onslot_1")
+ shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_1")
+
+ shipController.removeObserver(self, forKeyPath: "selection.slot_2")
+ shipController.removeObserver(self, forKeyPath: "selection.onslot_2")
+ shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_2")
+
+ shipController.removeObserver(self, forKeyPath: "selection.slot_3")
+ shipController.removeObserver(self, forKeyPath: "selection.onslot_3")
+ shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_3")
+
+ shipController.removeObserver(self, forKeyPath: "selection.slot_4")
+ shipController.removeObserver(self, forKeyPath: "selection.onslot_4")
+ shipController.removeObserver(self, forKeyPath: "selection.master_ship.maxeq_4")
+
}
@IBOutlet weak var supply: SuppliesView!
@IBOutlet weak var guardEscapedView: GuardEscapedView!
@IBOutlet weak var damageView: DamageView!
- @IBOutlet weak var slot00Field: NSTextField!
- @IBOutlet weak var slot01Field: NSTextField!
- @IBOutlet weak var slot02Field: NSTextField!
- @IBOutlet weak var slot03Field: NSTextField!
+ @IBOutlet weak var slot00Field: SlotItemLevelView!
+ @IBOutlet weak var slot01Field: SlotItemLevelView!
+ @IBOutlet weak var slot02Field: SlotItemLevelView!
+ @IBOutlet weak var slot03Field: SlotItemLevelView!
@IBOutlet var shipController: NSObjectController!
- dynamic var guardEscaped: Bool = false {
+ @objc dynamic var guardEscaped: Bool = false {
+
didSet {
guardEscapedView.isHidden = !guardEscaped
}
}
- dynamic var ship: KCShipObject? {
- get {
- return shipController.content as? KCShipObject
- }
+
+ @objc dynamic var ship: Ship? {
+
+ get { return shipController.content as? Ship }
set {
- shipController.fetchPredicate = NSPredicate(format: "id = %ld", newValue?.id ?? 0)
+ shipController.fetchPredicate = NSPredicate(#keyPath(Ship.id), equal: newValue?.id ?? 0)
}
}
override func viewDidLoad() {
+
super.viewDidLoad()
damageView.setFrameOrigin(.zero)
view.addSubview(damageView)
- damageView.bind("damageType", to: shipController, withKeyPath: "selection.status", options: nil)
+ damageView.bind(NSBindingName(#keyPath(DamageView.damageType)),
+ to: shipController,
+ withKeyPath: "selection.status", options: nil)
- supply.bind("shipStatus", to: shipController, withKeyPath: "selection.self", options: nil)
+ supply.bind(NSBindingName(#keyPath(SuppliesView.ship)),
+ to: shipController,
+ withKeyPath: "selection.self", options: nil)
guardEscapedView.setFrameOrigin(.zero)
view.addSubview(guardEscapedView)
switch type {
case .medium, .minimum:
guardEscapedView.controlSize = .mini
+
default: break
}
let fields = [slot00Field, slot01Field, slot02Field, slot03Field]
let keypath = ["selection.slot_0", "selection.slot_1", "selection.slot_2", "selection.slot_3"]
zip(fields, keypath).forEach {
- $0.0?.bind("slotItemID", to: shipController, withKeyPath: $0.1, options: nil)
+
+ $0.0?.bind(NSBindingName(#keyPath(SlotItemLevelView.slotItemID)), to: shipController, withKeyPath: $0.1, options: nil)
+ }
+
+ // observe slotitems count
+ shipController.addObserver(self, forKeyPath: "selection", context: &shipContext)
+
+ shipController.addObserver(self, forKeyPath: "selection.slot_0", context: &equippedItem0Context)
+ shipController.addObserver(self, forKeyPath: "selection.onslot_0", context: &equippedItem0Context)
+ shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_0", context: &equippedItem0Context)
+
+ shipController.addObserver(self, forKeyPath: "selection.slot_1", context: &equippedItem1Context)
+ shipController.addObserver(self, forKeyPath: "selection.onslot_1", context: &equippedItem1Context)
+ shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_1", context: &equippedItem1Context)
+
+ shipController.addObserver(self, forKeyPath: "selection.slot_2", context: &equippedItem2Context)
+ shipController.addObserver(self, forKeyPath: "selection.onslot_2", context: &equippedItem2Context)
+ shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_2", context: &equippedItem2Context)
+
+ shipController.addObserver(self, forKeyPath: "selection.slot_3", context: &equippedItem3Context)
+ shipController.addObserver(self, forKeyPath: "selection.onslot_3", context: &equippedItem3Context)
+ shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_3", context: &equippedItem3Context)
+
+ shipController.addObserver(self, forKeyPath: "selection.slot_4", context: &equippedItem4Context)
+ shipController.addObserver(self, forKeyPath: "selection.onslot_4", context: &equippedItem4Context)
+ shipController.addObserver(self, forKeyPath: "selection.master_ship.maxeq_4", context: &equippedItem4Context)
+
+ }
+
+ override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
+
+ if context == &shipContext {
+
+ notifyChangeValue(forKey: #keyPath(planeString0))
+ notifyChangeValue(forKey: #keyPath(planeString0Color))
+ notifyChangeValue(forKey: #keyPath(planeString1))
+ notifyChangeValue(forKey: #keyPath(planeString1Color))
+ notifyChangeValue(forKey: #keyPath(planeString2))
+ notifyChangeValue(forKey: #keyPath(planeString2Color))
+ notifyChangeValue(forKey: #keyPath(planeString3))
+ notifyChangeValue(forKey: #keyPath(planeString3Color))
+ notifyChangeValue(forKey: #keyPath(planeString4))
+ notifyChangeValue(forKey: #keyPath(planeString4Color))
+
+ return
+ }
+ if context == &equippedItem0Context {
+
+ notifyChangeValue(forKey: #keyPath(planeString0))
+ notifyChangeValue(forKey: #keyPath(planeString0Color))
+
+ return
+ }
+ if context == &equippedItem1Context {
+
+ notifyChangeValue(forKey: #keyPath(planeString1))
+ notifyChangeValue(forKey: #keyPath(planeString1Color))
+
+ return
+ }
+ if context == &equippedItem2Context {
+
+ notifyChangeValue(forKey: #keyPath(planeString2))
+ notifyChangeValue(forKey: #keyPath(planeString2Color))
+
+ return
+ }
+ if context == &equippedItem3Context {
+
+ notifyChangeValue(forKey: #keyPath(planeString3))
+ notifyChangeValue(forKey: #keyPath(planeString3Color))
+
+ return
}
+ if context == &equippedItem4Context {
+
+ notifyChangeValue(forKey: #keyPath(planeString4))
+ notifyChangeValue(forKey: #keyPath(planeString4Color))
+
+ return
+ }
+
+ super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
}
}
+
+
+private let allPlaneTypes: [Int] = [6, 7, 8, 9, 10, 11, 25, 26, 41, 45, 56, 57, 58, 59]
+
+
+extension ShipDetailViewController {
+
+ // MARK: - Plane count strings
+ private enum PlaneState {
+
+ case cannotEquip
+ case notEquip(Int)
+ case equiped(Int, Int)
+ }
+
+ private func planState(_ index: Int) -> PlaneState {
+
+ guard let ship = ship else { return .cannotEquip }
+
+ let itemId = ship.slotItemId(index)
+ let maxCount = ship.slotItemMax(index)
+
+ if maxCount == 0 { return .cannotEquip }
+ if itemId == -1 { return .notEquip(maxCount) }
+
+ if let item = ship.slotItem(index),
+ allPlaneTypes.contains(item.master_slotItem.type_2) {
+
+ return .equiped(ship.slotItemCount(index), maxCount)
+ }
+
+ return .notEquip(maxCount)
+ }
+
+ private func planeString(_ index: Int) -> String? {
+
+ switch planState(index) {
+ case .cannotEquip:
+ return nil
+ case .notEquip(let max):
+ return "\(max)"
+ case .equiped(let count, let max):
+ return "\(count)/\(max)"
+ }
+ }
+
+ @objc dynamic var planeString0: String? { return planeString(0) }
+
+ @objc dynamic var planeString1: String? { return planeString(1) }
+
+ @objc dynamic var planeString2: String? { return planeString(2) }
+
+ @objc dynamic var planeString3: String? { return planeString(3) }
+
+ @objc dynamic var planeString4: String? { return planeString(4) }
+
+ // MARK: - Plane count string color
+ private func planeStringColor(_ index: Int) -> NSColor {
+
+ switch planState(index) {
+ case .cannotEquip: return NSColor.controlTextColor
+ case .notEquip: return NSColor.disabledControlTextColor
+ case .equiped: return NSColor.controlTextColor
+ }
+ }
+
+ @objc dynamic var planeString0Color: NSColor { return planeStringColor(0) }
+
+ @objc dynamic var planeString1Color: NSColor { return planeStringColor(1) }
+
+ @objc dynamic var planeString2Color: NSColor { return planeStringColor(2) }
+
+ @objc dynamic var planeString3Color: NSColor { return planeStringColor(3) }
+
+ @objc dynamic var planeString4Color: NSColor { return planeStringColor(4) }
+}
+
+extension ShipDetailViewController: NibLoadable {}