diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 863eeedcb..2b21d153e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -115,6 +115,7 @@ 4B07835B1FC11D42001D12BB /* Configurable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0783591FC11D10001D12BB /* Configurable.cpp */; }; 4B08A2751EE35D56008B7065 /* Z80InterruptTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2741EE35D56008B7065 /* Z80InterruptTests.swift */; }; 4B08A2781EE39306008B7065 /* TestMachine.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B08A2771EE39306008B7065 /* TestMachine.mm */; }; + 4B08A56920D72BEF0016CE5A /* Activity.xib in Resources */ = {isa = PBXBuildFile; fileRef = 4B08A56720D72BEF0016CE5A /* Activity.xib */; }; 4B0CCC451C62D0B3001CAC5F /* CRT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */; }; 4B0E04EA1FC9E5DA00F43484 /* CAS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E04E81FC9E5DA00F43484 /* CAS.cpp */; }; 4B0E04EB1FC9E78800F43484 /* CAS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B0E04E81FC9E5DA00F43484 /* CAS.cpp */; }; @@ -705,6 +706,7 @@ 4B08A2761EE39306008B7065 /* TestMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestMachine.h; sourceTree = ""; }; 4B08A2771EE39306008B7065 /* TestMachine.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine.mm; sourceTree = ""; }; 4B08A2791EE3957B008B7065 /* TestMachine+ForSubclassEyesOnly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "TestMachine+ForSubclassEyesOnly.h"; sourceTree = ""; }; + 4B08A56820D72BEF0016CE5A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = "Clock Signal/Base.lproj/Activity.xib"; sourceTree = SOURCE_ROOT; }; 4B0B6E121C9DBD5D00FFB60D /* CRTConstants.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = CRTConstants.hpp; sourceTree = ""; }; 4B0CCC421C62D0B3001CAC5F /* CRT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CRT.cpp; sourceTree = ""; }; 4B0CCC431C62D0B3001CAC5F /* CRT.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CRT.hpp; sourceTree = ""; }; @@ -1988,6 +1990,7 @@ 4B55CE5E1C3B7D960093A61B /* MachineDocument.swift */, 4B8FE2211DA19FB20090D3CE /* MachinePanel.swift */, 4B95FA9C1F11893B0008E395 /* ZX8081OptionsPanel.swift */, + 4B08A56720D72BEF0016CE5A /* Activity.xib */, 4BC5FC2E20CDDDEE00410AA0 /* AppleIIOptions.xib */, 4B8FE2131DA19D5F0090D3CE /* Atari2600Options.xib */, 4B8FE2151DA19D5F0090D3CE /* MachineDocument.xib */, @@ -3284,6 +3287,7 @@ 4BA141BD2072E8A500A31EC9 /* MachinePicker.xib in Resources */, 4B1EDB451E39A0AC009D6819 /* chip.png in Resources */, 4B2A332D1DB86821002876E3 /* OricOptions.xib in Resources */, + 4B08A56920D72BEF0016CE5A /* Activity.xib in Resources */, 4BD61664206B2AC800236112 /* QuickLoadOptions.xib in Resources */, 4B8FE21B1DA19D5F0090D3CE /* Atari2600Options.xib in Resources */, 4B8FE21C1DA19D5F0090D3CE /* MachineDocument.xib in Resources */, @@ -3984,6 +3988,14 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 4B08A56720D72BEF0016CE5A /* Activity.xib */ = { + isa = PBXVariantGroup; + children = ( + 4B08A56820D72BEF0016CE5A /* Base */, + ); + name = Activity.xib; + sourceTree = ""; + }; 4B1497961EE4B97F00CE2596 /* ZX8081Options.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/Activity.xib b/OSBindings/Mac/Clock Signal/Base.lproj/Activity.xib new file mode 100644 index 000000000..2f3e6e302 --- /dev/null +++ b/OSBindings/Mac/Clock Signal/Base.lproj/Activity.xib @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/OSBindings/Mac/Clock Signal/Base.lproj/MainMenu.xib b/OSBindings/Mac/Clock Signal/Base.lproj/MainMenu.xib index ccd7fca32..ff476331c 100644 --- a/OSBindings/Mac/Clock Signal/Base.lproj/MainMenu.xib +++ b/OSBindings/Mac/Clock Signal/Base.lproj/MainMenu.xib @@ -146,10 +146,16 @@ - + - + + + + + + + diff --git a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift index 6ae182abc..b3b6330c6 100644 --- a/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift +++ b/OSBindings/Mac/Clock Signal/Documents/MachineDocument.swift @@ -40,6 +40,11 @@ class MachineDocument: optionsPanel?.setIsVisible(true) } + @IBOutlet var activityPanel: NSPanel! + @IBAction func showActivity(_ sender: AnyObject!) { + activityPanel.setIsVisible(true) + } + fileprivate var audioQueue: CSAudioQueue! = nil fileprivate var bestEffortUpdater: CSBestEffortUpdater? @@ -119,6 +124,9 @@ class MachineDocument: } override func close() { + activityPanel?.setIsVisible(false) + activityPanel = nil + optionsPanel?.setIsVisible(false) optionsPanel = nil @@ -286,6 +294,9 @@ class MachineDocument: menuItem.state = machine.inputMode == .joystick ? .on : .off return true + case #selector(self.showActivity(_:)): + return self.activityPanel != nil + default: break } } @@ -293,40 +304,42 @@ class MachineDocument: } // MARK: Activity display. + fileprivate var activityLevelIndicators: [String: NSLevelIndicator] = [:] func setupActivityDisplay() { - return + var leds = machine.leds + if leds.count > 0 { + Bundle.main.loadNibNamed(NSNib.Name(rawValue: "Activity"), owner: self, topLevelObjects: nil) + showActivity(nil) - if machine.leds.count > 0 { - let panel = NSPanel() - panel.title = "Activity" - panel.styleMask = .hudWindow - panel.setIsVisible(true) + // Inspect the activity panel for indicators. + var activityIndicators: [NSLevelIndicator] = [] + var textFields: [NSTextField] = [] + if let contentView = self.activityPanel.contentView { + for view in contentView.subviews { + if let levelIndicator = view as? NSLevelIndicator { + activityIndicators.append(levelIndicator) + } - for name in machine.leds { - let button = NSButton() - button.title = name - button.setButtonType(.radio) - button.translatesAutoresizingMaskIntoConstraints = false - button.isEnabled = false -// button.color - panel.contentView?.addSubview(button) + if let textField = view as? NSTextField { + textFields.append(textField) + } + } + } - let views = ["button": button] - let horizontalConstraints = - NSLayoutConstraint.constraints( - withVisualFormat: "H:|-[button]-|", - options: NSLayoutConstraint.FormatOptions(rawValue: 0), - metrics: nil, - views: views) - let verticalConstraints = - NSLayoutConstraint.constraints( - withVisualFormat: "V:|-[button]-|", - options: NSLayoutConstraint.FormatOptions(rawValue: 0), - metrics: nil, - views: views) + // If there are fewer level indicators than LEDs, trim that list. + if activityIndicators.count < leds.count { + leds.removeSubrange(activityIndicators.count ..< leds.count) + } - panel.contentView?.addConstraints(horizontalConstraints) - panel.contentView?.addConstraints(verticalConstraints) + // Remove unused views. + for c in leds.count ..< activityIndicators.count { + textFields[c].removeFromSuperview() + activityIndicators[c].removeFromSuperview() + } + + // Apply labels. + for c in 0 ..< leds.count { + textFields[c].stringValue = leds[c] } } }