-------------------------------------------------------------------------------- --! @title TemporaryDisplay --! @brief Flash Knob Values on Labels with Auto-Revert --! @category UIHelpers --! --! Shows a reusable pattern for temporarily displaying a knob's value on a --! label, then reverting to the default name after a delay. Uses spawn + wait --! since widget callbacks are not coroutines and cannot call wait() directly. --! A counter ensures only the last update reverts, handling rapid knob turns. --! --! @demonstrates Label, Knob, Panel, Mapper, Unit, spawn, wait -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -- Reusable helper: flash a value on a label, revert after delay -------------------------------------------------------------------------------- local flashCounters = {} function flashLabel(label, text, defaultText, ms) label.text = text flashCounters[label] = (flashCounters[label] or 0) + 1 local myId = flashCounters[label] spawn(function() wait(ms or 1000) if flashCounters[label] == myId then label.text = defaultText end end) end -------------------------------------------------------------------------------- -- Layout -------------------------------------------------------------------------------- setBackgroundColour("1a1a1a") local panel = Panel{"controls"} panel.bounds = {10, 10, 340, 90} panel.backgroundColour = "2a2a2a" local margin = 10 local knobSize = 60 local labelH = 16 local function makeKnobWithLabel(parent, name, default, min, max, x, opts) local label = parent:Label{name, bounds = {x, margin + knobSize + 2, knobSize, labelH}, align = "centred", fontSize = 11, textColour = "888888", backgroundColour = "#00000000" } local knob = parent:Knob{name .. "_k", default, min, max, bounds = {x, margin, knobSize, knobSize}, showLabel = false, showValue = false, showPopupDisplay = false, fillColour = opts.colour or "555555", outlineColour = opts.colour or "888888" } if opts.mapper then knob.mapper = opts.mapper end if opts.unit then knob.unit = opts.unit end return knob, label, name end local volKnob, volLabel, volName = makeKnobWithLabel(panel, "VOL", 0.8, 0, 1, margin, {mapper = Mapper.Cubic, unit = Unit.LinearGain, colour = "FF8800"}) local cutKnob, cutLabel, cutName = makeKnobWithLabel(panel, "CUTOFF", 20000, 20, 20000, margin + 70 + margin, {mapper = Mapper.Exponential, unit = Unit.Hertz, colour = "FFCC00"}) local resKnob, resLabel, resName = makeKnobWithLabel(panel, "RES", 0, 0, 1, margin + 2 * (70 + margin), {unit = Unit.PercentNormalized, colour = "FFCC00"}) -------------------------------------------------------------------------------- -- Wire up temporary display -------------------------------------------------------------------------------- volKnob.changed = function(self) local dB = self.value > 0 and string.format("%.1f dB", 20 * math.log10(self.value)) or "-inf" flashLabel(volLabel, dB, volName, 800) end cutKnob.changed = function(self) local text = self.value < 1000 and string.format("%.0f Hz", self.value) or string.format("%.1f kHz", self.value / 1000) flashLabel(cutLabel, text, cutName, 800) end resKnob.changed = function(self) flashLabel(resLabel, string.format("%.0f%%", self.value * 100), resName, 800) end setSize(360, 110) makePerformanceView()