Package limn.components
@NullMarked
package limn.components
Ready-to-use components (Label, Button, TextField, Checkbox/Switch, Dialog)
and the light/dark The discrete-choice widgets answer
Theme.
The discrete-choice widgets answer setSelectedIndex the same way
ListView, TabbedPane,
ComboBox, SegmentedControl and
ButtonGroup spell one operation with one name, and it means one thing
in all five.
- An out-of-range index throws
IndexOutOfBoundsException, exactly asList.getdoes and for the same reason: an index computed from a search that found nothing, a filter that emptied the data, or a value restored from saved state is a caller's bug, and clamping it selects the wrong thing quietly. A caller holding a computed index checks it against the count first. -1is not an argument. Where "nothing is selected" is a real state (a list of records need not have a current record), aclearSelection()names it:ListViewandButtonGrouphave one. ATabbedPaneholding tabs, aComboBoxand aSegmentedControlalways have exactly one selection and so offer none.- A programmatic set reaches the watchers and not the handler.
onSelectis the application's response to the user choosing, and it runs only for a click, a key or an assistive technology's select; asetSelectedIndexfrom code announcesSELECTION/CODEto whoever watches the widget, and to nobody else. A detail pane that must follow the selection wherever it came from watches; a pane that answers the user handles. That is the one rule ofChange.Origin, and it is why two of these controls bound to each other through their handlers cannot recurse at all. - Setting the index that is already selected changes nothing and announces nothing. The guard is on the announcement: a mutator handed the state it already holds says nothing, which is what ends a two-way binding written on the watcher channel on its first echo.
Keyboard traversal is not bound by the first rule: arrowing past either end of a strip lands on the end, because that is what the key means, not what an index means.
-
ClassDescriptionA keyboard shortcut for a
MenuItem: one key plus the modifier mask that must be held with it.A person, drawn as a circle: their picture when there is one, and otherwise their initials over a colour of their own.People drawn as a stack ofAvatars: the approvers of a document, the members of a team.A panel whose background is the content behind it, put through aBackdropEffect: a glass control bar over video, a washed header over a picture, a redacted field.A short status beside or inside something else: "Overdue" in a table's cell, "3" beside an inbox, a dot beside a row's name that says it is unread.Push button with the full state set (normal, hover, pressed, disabled, focused) and anButton.onAction(Runnable)fired by click or by Enter/Space while focused.How much a button asks to be pressed, of the three looks a row of buttons is drawn in.Coordinates a set ofRadioButtons so that exactly one is selected at a time.A card: a surface that holds one record, made of parts that are each optional.How the media is laid out.Where the media goes.How the card is set apart from what is around it.Toggle with two visual variants: the classicBOXwith a check mark, and the mobile-styleSWITCHwhose thumb slides.How the flag is drawn and published: a box that takes a check mark, or a switch whose knob slides.Picks a colour the way a graphics application does: a saturation/value field for the current hue, a hue ramp beside it, a before/after swatch, a hex field, and numeric channels in whichever model the user thinks in: RGB, HSV or CMYK.Which numeric model the channel row is showing.A colour, shown as a chip, that opens aColorPickerin a dialog when clicked: the control an application reaches for when it needs a colour from the user but cannot give up a panel to a whole picker.ComboBox<T>Dropdown selector.Gives any widget a context menu, and answers what a request for one looks like.A modal (or non-modal) dialog that resolves aCompletionStagewith the chosen button's result: never a nested event loop, soshow*returns immediately and the stage completes (on the UI thread) later.One question to a dialog'sDialog.onCancelhandler: may the dialog close with its cancel result? Answered once, withDialog.CancelRequest.allow()orDialog.CancelRequest.refuse(), now or later: a handler that shows a dialog of its own over this one keeps the request and answers from that dialog's result.How the user closed the dialog.Where a surface that floats above the page is actually drawn: in a window of its own, or as an overlay inside the window that owns it.How far a surface is lifted above what is around it.The shadow of oneElevationin a theme: two layers straight down, since the light is above.A section that opens and closes: a header over content that slides out below it.Keeps at most one of severalExpanders open, an accordion: opening one closes the one that was open.A field of a form around one control: a caption above it, a line under it, and the two states a form has, required and invalid.How the picture is sized into the view's box.Single- or multi-line text.Where a line sits in the text region, on two vocabularies that coexist on purpose.What happens to text that does not fit: cut at the box's edge, or ended with an ellipsis.Which typographic token the text is drawn with, orthogonal to the size step, which decides how big that token is.Where the lines sit vertically in the text region.ListView<T>A vertically scrolling list that virtualizes its rows like aJTable/RecyclerView: only the rows in the viewport get a widget, so a list of a million rows costs the same as one of twenty (layout and paint areO(visible)).Something was dropped between two rows of this list.Rows of this list were dragged to another place in it.Playback controls for aVideoView: play/pause, a scrub bar and a position clock — the bar every player lays over its picture.Whether the mute button and volume slider are offered.A horizontal strip of top-level menu titles; the strip itself is drawn in-scene (part of the window chrome).Where a bar is shown.One entry in aMenu: a command, a checkable toggle, a submenu, or a separator.What an item is to the system, beyond its label: one of the three every application has and a system may keep in a menu of its own, or one of the six editing commands.TextFieldthat renders every character as a mask dot, with an optional reveal toggle.A panel of controls that hangs from a widget and closes when it is done with: a filter panel from a tool bar's button, a column chooser, a short form.Which edge of the anchor the panel lines up with.A context menu / dropdown that presents aMenu(with checkable items, separators and cascading submenus) as a real native window: an undecorated, floating, transparent OS window (like a ComboBox popup) that may overflow the owner window exactly like a true OS menu.Simple horizontal progress bar.A single-choice control: a ring that fills with a dot when selected.A horizontal slider of two thumbs that selects a range in[min, max]: a lower value and an upper one over the same track, the span between them filled.What hears the range the user set.The one scrollbar shared by every scrollable component (ListView,TextArea,ScrollView, …), so they look and behave identically.The scroll state the bar reflects and drives.Which axis the bar controls.When the bar is shown.How much of a scrolling widget's box its scrollbars take, and the settling that decides it.How the content is measured for a candidate viewport.Whether a bar floats over the content or takes a strip out of it.Generic scroll container: the child is measured unbounded on the scrolling axes, painted offset by the scroll position and clipped to the viewport on those axes; the wheel scrolls whenever there is overflow, and so does a pointer drag that rests near one of its edges, or goes past one (seeScrollBar).ATextFieldpreset for search: a leading magnifier icon inside the field and a trailing coupled clear button (the ComboBox-caret idiom).A row of connected segments with a single selection, a compact alternative to aRadioButtongroup or tabs.A thin divider line drawn in the theme'sTheme.outlinecolor.Which way the line runs.The numeric size table: one immutable row perControlSizestep.Horizontal slider selecting a value in[min, max].A stepper input for a bounded value, in two modes:Spinner.Mode.NUMERIC:new Spinner(min, max, step)shows a number (decimals inferred from the step);Spinner.Mode.TIME:Spinner.time()showsHH:MM, where the up/down arrows adjust the focused field (hours by 60, minutes by the step) and Left/Right (or a click) move between the two fields.Numeric value vs.Two panes and a divider the user drags to share the space between them.Which axis the two panes are arranged along.Quantities that are pixel-locked: identical at everyControlSizestep.A surface lifted above what is around it: a fill, the shadow itsElevationhas in the theme, and one child inside.Tabbed panel: a horizontal strip of tab headers over a content area that shows the selected tab.Where the strip sits when the headers are narrower than the pane, named for where it lands in an interface that reads left to right.One question toTabbedPane.onTabClose: may this tab close? Answered once, withTabbedPane.TabCloseRequest.allow()orTabbedPane.TabCloseRequest.refuse(), now or later: a handler that shows a dialog keeps the request and answers from its result.What the user moved: a tab from one place in the order to another.Multiline text editor: hard line breaks (Enter), arrow navigation across lines with a sticky column, mouse/Shift+arrow selection spanning lines, clipboard shortcuts, blinking cursor, and both scrollbars: draggable thumbs and wheel-responsive.Single-line text input: blinking cursor (frame-clock ticker), mouse and Shift+arrow selection, Home/End, Ctrl/Cmd+A/C/V/X through the system clipboard, placeholder, and horizontal scrolling that keeps the cursor visible when the text overflows.Central design tokens: colors, corner radii, typography and spacing.Collects the colours of a palette and builds one.Every colour a palette is made of, as values, so that code which has to treat every tone alike (a serializer, an editor, a contrast report) enumerates them instead of naming them all and getting all but one right.A palette as text, and back, so an application can ship a theme its designer built as a file beside the jar instead of as a recompile.ASizedBoxwhose fixed dimensions come from the resolvedControlSizestep instead of from a number baked at construction.One extent, read off a size step.AColumnwhose gap follows the resolvedControlSizestep.APaddingwhose insets follow the resolvedControlSizestep, uniform on all four edges.ARowwhose gap follows the resolvedControlSizestep.Pushes resolvedSizeTokensspacing into the geometry-only containers, which hold plain floats and therefore cannot follow a size step on their own.Which of the three spacing tokens a container follows.Which of the palette's colours a piece of text or a mark is drawn in, said by what it means rather than by the colour: a line that reports a failure isTone.DANGER, whatever red the palette in force calls danger.A horizontal strip of controls (buttons, toggles, segmented controls,Separators…) on a roundedTheme.surfacebackground.What an application has decided about the value a control holds: nothing yet, wrong, doubtful, accepted, or worth a note.Shows the pictures of aVideoStreamSource: each one handed to a device-side picture and composited as one quad in the 2D paint order, so clipping, opacity, overlays and dialogs apply to a video exactly as they apply to a rectangle.How a picture whose aspect ratio differs from the box's is mapped into it.A viewport that renders 3D content into an offscreenRenderTarget(with MSAA) and composites it as a normal 2D layer, proving that GPU-rendered content respects the scene's layering: overlays, dialogs, tooltips and clipping all apply to it because it draws as one quad in the paint order.Draws the 3D scene into a pass each frame;timeSecondsadvances while showing.