sclass G22SnPSelector > MetaWithChangeListeners is Swingable { settable new SnPSettings settings; // show powers of two in colors selector or all numbers? settableWithVar bool powerOfTwoColors = false; // show powers of two in pixelRows selector or all numbers? settableWithVar bool powerOfTwoPixelRows = true; settable int maxPixelRows = 512; settableWithVar bool allowDecolorizerSelection; settableWithVar bool showDecolorizerSelection; JLabel lblColors; SingleComponentPanel scpDecolorizer = scp(); *() {} *(SnPSettings *settings) {} SnPSettings get() { ret settings; } cachedVisualize { var colors = jListSpinner(colorsList(), settings.colors); main onChange(colors, -> { settings.colors = intFromSpinner(colors); change(); }); varPowerOfTwoColors().onChange(-> spinnerSetNumberList(colors, colorsList()); swing { var menuItem = jLiveValueCheckBoxMenuItem("Only show powers of two", varPowerOfTwoColors()); new JPopupMenu menu; menu.add(menuItem); colors.setComponentPopupMenu(menu); } var pixelRows = jListSpinner(pixelRowsList(), settings.pixelRows); main onChange(pixelRows, -> { settings.pixelRows = intFromSpinner(pixelRows); change(); }); varPowerOfTwoPixelRows().onChange(-> spinnerSetNumberList(pixelRows, pixelRowsList()); swing { var menuItem = jLiveValueCheckBoxMenuItem("Only show powers of two", varPowerOfTwoPixelRows()); new JPopupMenu menu; menu.add(menuItem); pixelRows.setComponentPopupMenu(menu); } lblColors = jSimpleLabel(" colors "); bindChangeListenerToComponent(this, lblColors, -> toolTip(lblColors, makeToolTip())); L controls = ll( colors, lblColors, scpDecolorizer, jSimpleLabel("@ "), pixelRows, jlabel(" p")); if (allowDecolorizerSelection) { varShowDecolorizerSelection().onChangeAndNow(l0 updateDecolorizerView); controls.add(horizontalStrut(3)); controls.add(jPopDownButton_noText( jLiveValueCheckBoxMenuItem("Select channel", varShowDecolorizerSelection()) )); } var vis = hstack(controls); bindChangeListenerToComponent(settings, vis, l0 change); ret vis; } L colorsList() { ret powerOfTwoColors ? powersOfTwoUpTo(2, 256) : virtualCountList_incl(2, 256); } L pixelRowsList() { ret powerOfTwoPixelRows ? powersOfTwoUpTo(maxPixelRows) : virtualCountList_incl(1, maxPixelRows); } S makeToolTip() { long pixels = area(sixteenToNine_p(settings.pixelRows)); int colorBits = numberOfBitsNeededToRepresentNOptions(settings.colors); int bytes = iceil_div(pixels*colorBits, 8); ret "Information per frame: " + nBytes(bytes) +" (assuming a 16:9 aspect ratio)"; } L decolorizerList() { ret ll( new Decolorizer.Simple, new Decolorizer.Red, new Decolorizer.Green, new Decolorizer.Blue ); } void updateDecolorizerView { if (!showDecolorizerSelection) { scpDecolorizer.clear(); settings.decolorizer(null); } else { if (settings.decolorizer == null) settings.decolorizer(new Decolorizer.Simple); scpDecolorizer.set(hstack( jlabel("from channel "), bindComboBoxToVar(settings.varDecolorizer(), jTypedComboBox(decolorizerList())), horizontalStrut(3) )); } } }