Monorepo for Aesthetic.Computer aesthetic.computer
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add strip footer for instrument and held notes

authored by

Esteban Uribe and committed by
prompt.ac/@jeffrey
efbbac34 b35b575a

+58 -2
+1
slab/menuband/Sources/MenuBand/AppDelegate.swift
··· 148 148 self.updateIcon() 149 149 self.popoverVC?.refreshHeldNotes() 150 150 self.floatingPlayPalette.refresh() 151 + self.waveformStrip.refreshAppearance() 151 152 self.updateWaveformStrip() 152 153 } 153 154 menuBand.onInstrumentVisualChange = { [weak self] in
+57 -2
slab/menuband/Sources/MenuBand/MenuBarWaveformStrip.swift
··· 12 12 private let menuBand: MenuBandController 13 13 private let waveformView = WaveformView() 14 14 private let waveformBezel = NSView() 15 + private let instrumentLabel = NSTextField(labelWithString: "") 16 + private let heldNotesStack = NSStackView() 15 17 private var panel: NSPanel? 16 18 private weak var statusButton: NSStatusBarButton? 17 19 ··· 20 22 private var hideWorkItem: DispatchWorkItem? 21 23 22 24 /// Strip height in points. 23 - private static let stripHeight: CGFloat = 36 25 + private static let stripHeight: CGFloat = 56 24 26 25 27 /// Animation duration in seconds. 26 28 private static let slideDuration: TimeInterval = 0.22 ··· 59 61 waveformBezel.layer?.cornerRadius = 6 60 62 waveformBezel.layer?.backgroundColor = NSColor(white: 0.06, alpha: 1.0).cgColor 61 63 waveformBezel.layer?.borderWidth = 1 64 + heldNotesStack.orientation = .horizontal 65 + heldNotesStack.alignment = .centerY 66 + heldNotesStack.spacing = 4 62 67 } 63 68 64 69 /// Pre-build the panel so the first note doesn't pay construction cost. ··· 107 112 func refreshAppearance() { 108 113 applyAppearanceToVisualizer() 109 114 applyWaveformTint() 115 + refreshReadout() 110 116 } 111 117 112 118 // MARK: - Geometry ··· 150 156 display: true) 151 157 applyAppearanceToVisualizer() 152 158 applyWaveformTint() 159 + refreshReadout() 153 160 waveformView.isLive = true 154 161 panel.orderFrontRegardless() 155 162 ··· 272 279 273 280 waveformView.translatesAutoresizingMaskIntoConstraints = false 274 281 waveformBezel.translatesAutoresizingMaskIntoConstraints = false 282 + instrumentLabel.translatesAutoresizingMaskIntoConstraints = false 283 + heldNotesStack.translatesAutoresizingMaskIntoConstraints = false 275 284 let content = NSView() 276 285 content.wantsLayer = true 277 286 content.layer?.backgroundColor = NSColor.clear.cgColor 278 287 p.contentView = content 279 288 p.contentView!.addSubview(waveformBezel) 289 + p.contentView!.addSubview(instrumentLabel) 290 + p.contentView!.addSubview(heldNotesStack) 280 291 waveformBezel.addSubview(waveformView) 281 292 let bezelInset: CGFloat = 5 282 293 NSLayoutConstraint.activate([ 283 294 waveformBezel.leadingAnchor.constraint(equalTo: p.contentView!.leadingAnchor), 284 295 waveformBezel.trailingAnchor.constraint(equalTo: p.contentView!.trailingAnchor), 285 296 waveformBezel.topAnchor.constraint(equalTo: p.contentView!.topAnchor), 286 - waveformBezel.bottomAnchor.constraint(equalTo: p.contentView!.bottomAnchor), 297 + waveformBezel.heightAnchor.constraint(equalToConstant: 36), 287 298 waveformView.leadingAnchor.constraint(equalTo: waveformBezel.leadingAnchor, constant: bezelInset), 288 299 waveformView.trailingAnchor.constraint(equalTo: waveformBezel.trailingAnchor, constant: -bezelInset), 289 300 waveformView.topAnchor.constraint(equalTo: waveformBezel.topAnchor, constant: bezelInset), 290 301 waveformView.bottomAnchor.constraint(equalTo: waveformBezel.bottomAnchor, constant: -bezelInset), 302 + instrumentLabel.leadingAnchor.constraint(equalTo: p.contentView!.leadingAnchor, constant: 6), 303 + instrumentLabel.bottomAnchor.constraint(equalTo: p.contentView!.bottomAnchor, constant: -4), 304 + heldNotesStack.centerXAnchor.constraint(equalTo: p.contentView!.centerXAnchor), 305 + heldNotesStack.centerYAnchor.constraint(equalTo: instrumentLabel.centerYAnchor), 291 306 ]) 292 307 applyAppearanceToVisualizer() 293 308 applyWaveformTint() 309 + refreshReadout() 294 310 295 311 panel = p 296 312 } ··· 305 321 waveformView.setLightMode(!isDark) 306 322 if isDark { 307 323 waveformBezel.layer?.backgroundColor = NSColor(white: 0.06, alpha: 1.0).cgColor 324 + instrumentLabel.textColor = .white 308 325 } else { 309 326 waveformBezel.layer?.backgroundColor = NSColor(white: 0.82, alpha: 1.0).cgColor 327 + instrumentLabel.textColor = .black 310 328 } 311 329 } 312 330 ··· 324 342 waveformBezel.layer?.borderColor = familyColor 325 343 .withAlphaComponent(0.55).cgColor 326 344 } 345 + } 346 + 347 + private func refreshReadout() { 348 + let safe = max(0, min(127, Int(menuBand.effectiveMelodicProgram))) 349 + let familyColor = menuBand.midiMode 350 + ? NSColor.controlAccentColor 351 + : InstrumentListView.colorForProgram(safe) 352 + instrumentLabel.stringValue = GeneralMIDI.programNames[safe] 353 + instrumentLabel.font = NSFont.systemFont(ofSize: 10, weight: .black) 354 + for view in heldNotesStack.arrangedSubviews { 355 + heldNotesStack.removeArrangedSubview(view) 356 + view.removeFromSuperview() 357 + } 358 + for name in menuBand.heldNoteNames() { 359 + heldNotesStack.addArrangedSubview(makeHeldNoteBox(name: name, color: familyColor)) 360 + } 361 + } 362 + 363 + private func makeHeldNoteBox(name: String, color: NSColor) -> NSView { 364 + let box = NSView() 365 + box.wantsLayer = true 366 + box.layer?.cornerRadius = 4 367 + box.layer?.backgroundColor = color.withAlphaComponent(0.85).cgColor 368 + box.translatesAutoresizingMaskIntoConstraints = false 369 + let label = NSTextField(labelWithString: name) 370 + label.font = NSFont.monospacedSystemFont(ofSize: 9, weight: .heavy) 371 + label.textColor = .black 372 + label.drawsBackground = false 373 + label.translatesAutoresizingMaskIntoConstraints = false 374 + box.addSubview(label) 375 + NSLayoutConstraint.activate([ 376 + label.leadingAnchor.constraint(equalTo: box.leadingAnchor, constant: 5), 377 + label.trailingAnchor.constraint(equalTo: box.trailingAnchor, constant: -5), 378 + label.topAnchor.constraint(equalTo: box.topAnchor, constant: 1), 379 + label.bottomAnchor.constraint(equalTo: box.bottomAnchor, constant: -1), 380 + ]) 381 + return box 327 382 } 328 383 }