1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-07-10 12:29:01 +00:00

Adds negative feedback to ROM installation process.

As an ugly kludge, code wise.
This commit is contained in:
Thomas Harte 2019-07-23 16:24:23 -04:00
parent 4d361b1952
commit 374cac0107
2 changed files with 69 additions and 7 deletions

View File

@ -336,13 +336,15 @@ class MachineDocument:
// MARK: User ROM provision. // MARK: User ROM provision.
@IBOutlet var romRequesterPanel: NSWindow? @IBOutlet var romRequesterPanel: NSWindow?
@IBOutlet var romRequesterText: NSTextField? @IBOutlet var romRequesterText: NSTextField?
@IBOutlet var romReceiverErrorField: NSTextField?
@IBOutlet var romReceiverView: CSROMReceiverView? @IBOutlet var romReceiverView: CSROMReceiverView?
var romRequestBaseText = "" private var romRequestBaseText = ""
func requestRoms() { func requestRoms() {
// Load the ROM requester dialogue. // Load the ROM requester dialogue.
Bundle.main.loadNibNamed("ROMRequester", owner: self, topLevelObjects: nil) Bundle.main.loadNibNamed("ROMRequester", owner: self, topLevelObjects: nil)
self.romReceiverView!.delegate = self self.romReceiverView!.delegate = self
self.romRequestBaseText = romRequesterText!.stringValue self.romRequestBaseText = romRequesterText!.stringValue
romReceiverErrorField?.alphaValue = 0.0
// Populate the current absentee list. // Populate the current absentee list.
populateMissingRomList() populateMissingRomList()
@ -388,6 +390,7 @@ class MachineDocument:
// If no ROMs are still missing, start the machine. // If no ROMs are still missing, start the machine.
do { do {
let fileData = try Data(contentsOf: URL) let fileData = try Data(contentsOf: URL)
var didInstallRom = false
// Try to match by size first, CRC second. Accept that some ROMs may have // Try to match by size first, CRC second. Accept that some ROMs may have
// some additional appended data. Arbitrarily allow them to be up to 10kb // some additional appended data. Arbitrarily allow them to be up to 10kb
@ -414,10 +417,11 @@ class MachineDocument:
try fileManager.createDirectory(atPath: targetPath.path, withIntermediateDirectories: true, attributes: nil) try fileManager.createDirectory(atPath: targetPath.path, withIntermediateDirectories: true, attributes: nil)
try trimmedData.write(to: targetFile) try trimmedData.write(to: targetFile)
} catch let error { } catch let error {
Swift.print("Some sort of error \(error)") showRomReceiverError(error: "Couldn't write to application support directory: \(error)")
} }
self.missingROMs.remove(at: index) self.missingROMs.remove(at: index)
didInstallRom = true
break break
} }
} }
@ -425,14 +429,60 @@ class MachineDocument:
index = index + 1 index = index + 1
} }
if self.missingROMs.count == 0 { if didInstallRom {
self.windowControllers[0].window?.endSheet(self.romRequesterPanel!) if self.missingROMs.count == 0 {
configureAs(self.selectedMachine!) self.windowControllers[0].window?.endSheet(self.romRequesterPanel!)
configureAs(self.selectedMachine!)
} else {
populateMissingRomList()
}
} else { } else {
populateMissingRomList() showRomReceiverError(error: "Didn't recognise contents of \(URL.lastPathComponent)")
} }
} catch let error { } catch let error {
Swift.print("TODO: couldn't open \(URL.absoluteString); \(error)") showRomReceiverError(error: "Couldn't read file at \(URL.absoluteString): \(error)")
}
}
// Yucky ugliness follows; my experience as an iOS developer intersects poorly with
// NSAnimationContext hence the various stateful diplications below. isShowingError
// should be essentially a duplicate of the current alphaValue, and animationCount
// is to resolve my inability to figure out how to cancel scheduled animations.
private var errorText = ""
private var isShowingError = false
private var animationCount = 0
private func showRomReceiverError(error: String) {
// Set or append the new error.
if self.errorText.count > 0 {
self.errorText = self.errorText + "\n" + error
} else {
self.errorText = error
}
// Apply the new complete text.
romReceiverErrorField!.stringValue = self.errorText
if !isShowingError {
// Schedule the box's appearance.
NSAnimationContext.beginGrouping()
NSAnimationContext.current.duration = 0.1
romReceiverErrorField?.animator().alphaValue = 1.0
NSAnimationContext.endGrouping()
isShowingError = true
}
// Schedule the box to disappear.
self.animationCount = self.animationCount + 1
let capturedAnimationCount = animationCount
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(2)) {
if self.animationCount == capturedAnimationCount {
NSAnimationContext.beginGrouping()
NSAnimationContext.current.duration = 1.0
self.romReceiverErrorField?.animator().alphaValue = 0.0
NSAnimationContext.endGrouping()
self.isShowingError = false
self.errorText = ""
}
} }
} }

View File

@ -8,6 +8,7 @@
<objects> <objects>
<customObject id="-2" userLabel="File's Owner" customClass="MachineDocument" customModule="Clock_Signal" customModuleProvider="target"> <customObject id="-2" userLabel="File's Owner" customClass="MachineDocument" customModule="Clock_Signal" customModuleProvider="target">
<connections> <connections>
<outlet property="romReceiverErrorField" destination="Bia-0m-GxK" id="wnH-Kz-uXD"/>
<outlet property="romReceiverView" destination="EiT-Mj-1SZ" id="Y2M-Qd-i7y"/> <outlet property="romReceiverView" destination="EiT-Mj-1SZ" id="Y2M-Qd-i7y"/>
<outlet property="romRequesterPanel" destination="QvC-M9-y7g" id="saI-YH-9NP"/> <outlet property="romRequesterPanel" destination="QvC-M9-y7g" id="saI-YH-9NP"/>
<outlet property="romRequesterText" destination="5qG-I3-Qav" id="J9M-T8-Xyy"/> <outlet property="romRequesterText" destination="5qG-I3-Qav" id="J9M-T8-Xyy"/>
@ -48,10 +49,21 @@ DQ
<action selector="cancelRequestROMs:" target="-2" id="58q-yi-dlv"/> <action selector="cancelRequestROMs:" target="-2" id="58q-yi-dlv"/>
</connections> </connections>
</button> </button>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bia-0m-GxK">
<rect key="frame" x="20" y="61" width="442" height="17"/>
<textFieldCell key="cell" allowsUndo="NO" alignment="center" title="Multiline Label" drawsBackground="YES" id="8jl-xs-LjP">
<font key="font" metaFont="message"/>
<color key="textColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="tertiaryLabelColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstItem="Bia-0m-GxK" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" constant="20" id="9Lj-3p-7Vr"/>
<constraint firstAttribute="trailing" secondItem="5qG-I3-Qav" secondAttribute="trailing" constant="20" id="AwT-WO-Nyf"/> <constraint firstAttribute="trailing" secondItem="5qG-I3-Qav" secondAttribute="trailing" constant="20" id="AwT-WO-Nyf"/>
<constraint firstAttribute="bottom" secondItem="nvl-dm-8bK" secondAttribute="bottom" constant="20" id="BU0-5T-YRH"/> <constraint firstAttribute="bottom" secondItem="nvl-dm-8bK" secondAttribute="bottom" constant="20" id="BU0-5T-YRH"/>
<constraint firstAttribute="bottom" secondItem="Bia-0m-GxK" secondAttribute="bottom" constant="61" id="ENn-7a-NGa"/>
<constraint firstAttribute="trailing" secondItem="Bia-0m-GxK" secondAttribute="trailing" constant="18" id="UUy-bf-87w"/>
<constraint firstItem="5qG-I3-Qav" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" constant="20" id="bRM-z1-cRf"/> <constraint firstItem="5qG-I3-Qav" firstAttribute="leading" secondItem="EiT-Mj-1SZ" secondAttribute="leading" constant="20" id="bRM-z1-cRf"/>
<constraint firstAttribute="trailing" secondItem="nvl-dm-8bK" secondAttribute="trailing" constant="20" id="eQI-Nj-ane"/> <constraint firstAttribute="trailing" secondItem="nvl-dm-8bK" secondAttribute="trailing" constant="20" id="eQI-Nj-ane"/>
<constraint firstItem="nvl-dm-8bK" firstAttribute="top" relation="greaterThanOrEqual" secondItem="5qG-I3-Qav" secondAttribute="bottom" constant="17" id="plB-x4-He5"/> <constraint firstItem="nvl-dm-8bK" firstAttribute="top" relation="greaterThanOrEqual" secondItem="5qG-I3-Qav" secondAttribute="bottom" constant="17" id="plB-x4-He5"/>