Class ComboBox
Keyboard: Space/Enter/Down opens; Up/Down move the highlight; Enter commits; Esc closes. The popup never takes focus; the combo keeps it, so clicking anywhere else in the parent window closes the popup via focus loss. Headless scenes (tests) keep the same open/highlight/commit state machine without a native window.
In-scene fallback. Where the window reports no
NativeWindow.supportsAbsolutePositioning() (Wayland), a list in a window
of its own would open somewhere other than under the field, so the list is drawn as an overlay
inside the owner window instead. Same rows, same keys, same type-ahead; the difference is that
it is clamped to that window rather than to the display, so a combo near the bottom edge shows
fewer rows and scrolls sooner. Chosen by the platform, not by the application, and
popupWindow() is null throughout.
Field and dropdown share one ControlSize step: the panel is the root
of its own window-bound Scene, so it inherits through
Widget.setInheritanceHost(limn.scene.Widget) rather than through the tree. A dropdown at a different
density from the field that opened it is simply a bug, so there is no setter on the panel.
The LayoutDirection arrives by that same link and for that same reason: a list
whose rows read the other way from the field that opened them is a bug rather than a
configuration. Reading right to left the label sits against the right edge, the chevron takes
the gutter on the left, the list hangs from the field's right edge and the marker column, the
row labels and the scrollbar all move to the other side. The chevron itself does not turn
over: it points up and down.
-
Constructor Summary
ConstructorsConstructorDescriptionA combo over fixed labels; seelocalized(java.util.List<limn.i18n.I18nString>)for items that follow the UI language. -
Method Summary
Modifier and TypeMethodDescriptionprotected floatMixed-step rows align on this, not on the box; seeFlex.CrossAlignment.BASELINE.voidclose()Dismisses the popup without changing the selection.intbooleanisOpen()Whether the popup is showing.static ComboBoxlocalized(List<I18nString> items) A combo whose items follow the UI language: a theme or unit picker, as opposed to a list of file names.protected voidonCharTyped(CharEvent event) Type-ahead: letters typed into an open list jump to what they spell, the way a combo does on Windows and a pop-up button does on GTK and macOS.protected voidA combo removed from the tree must never strand its dropdown on screen: a programmatically-opened popup has no focus to lose, so focus-lost alone does not cover this.protected voidCalled when this widget takes keyboard focus.protected voidCalled when this widget loses keyboard focus.protected voidonKeyEvent(KeyEvent event) Key events (focused widget first, then ancestors).protected SizeonMeasure(Constraints constraints) Reports the size this widget wants withinconstraints.protected voidonMouseEvent(MouseEvent event) Mouse events (bubbling); callevent.consume()when handled.protected voidWidget's own background/content, in local coordinates.Called with the chosen index whenever the selection changes: a pick from the popup and asetSelectedIndex(int)from code both arrive here.voidopen()Opens the popup (native window when bound; pure state when headless).intThe selected item's index; never negative, since a combo refuses an empty item list and so always has exactly one selection.The selected item as it currently reads, in the UI language.setDisplayMode(DisplayMode mode) Asks for a presentation of the drop-down list; seeDisplayMode.setSelectedIndex(int index) Selects an item and firesonSelect; code and a pick from the popup take the same path, so a listener sees every change either way.Methods inherited from class limn.scene.Widget
acceptsTextInput, add, baselineOffsetOf, caretRect, children, clipboard, clipsChildren, controlSize, cursor, declaredControlSize, declaredLayoutDirection, declaredLocale, focusArrivedByTraversal, height, hitTest, imageCursor, invalidate, invalidate, isEnabled, isFocusable, isFocused, isShowing, isVisible, layoutBox, layoutDirection, locale, localToSceneX, localToSceneY, markNeedsContainedLayout, markNeedsLayout, measure, moveChild, neutralBase, onAttached, onFileDrop, onLayout, onPaintOverlay, onPreedit, overlayPassesPointer, paintChildren, paintOutset, paintWidget, parent, remove, requestFocus, revealInView, scene, sceneToLocalX, sceneToLocalY, setControlSize, setCursor, setEnabled, setFocusable, setImageCursor, setInheritanceHost, setLayoutDirection, setLocale, setTooltip, setTooltip, setVisible, shapeText, textRuler, tooltip, width, x, y
-
Constructor Details
-
ComboBox
A combo over fixed labels; seelocalized(java.util.List<limn.i18n.I18nString>)for items that follow the UI language.
-
-
Method Details
-
localized
A combo whose items follow the UI language: a theme or unit picker, as opposed to a list of file names. The items are held as values, so a language change re-measures the popup instead of leaving yesterday's words in it. -
onSelect
Called with the chosen index whenever the selection changes: a pick from the popup and asetSelectedIndex(int)from code both arrive here. -
selectedIndex
public int selectedIndex()The selected item's index; never negative, since a combo refuses an empty item list and so always has exactly one selection. There is nothing to clear to. -
selectedItem
The selected item as it currently reads, in the UI language. -
setSelectedIndex
Selects an item and firesonSelect; code and a pick from the popup take the same path, so a listener sees every change either way. Selecting what is already selected changes nothing and fires nothing; that early return is what keeps two controls bound to each other from recursing, so do not remove it. UI thread only.- Parameters:
index- an item in[0, itemCount)- Throws:
IndexOutOfBoundsException- ifindexis not an item; an index computed from a lookup that missed is a caller's bug here, not a request for the nearest item
-
isOpen
public boolean isOpen()Whether the popup is showing. -
highlightedIndex
public int highlightedIndex()- Returns:
- the highlighted popup row (keyboard navigation state)
-
popupWindow
- Returns:
- the popup's native window while open (screenshots/tests), else
null, which is also the answer while an open popup is drawn in the scene, where there is no window to return
-
open
public void open()Opens the popup (native window when bound; pure state when headless). -
setDisplayMode
Asks for a presentation of the drop-down list; seeDisplayMode. DefaultDisplayMode.NATIVE_WINDOW, so a long list can extend past the window's edge the way a platform combo's does.A preference, not a guarantee. A list asked for
NATIVE_WINDOWis still drawn in scene on a window that cannot be positioned at an anchor (Wayland).IN_SCENEis always honoured, and it is the choice to make when the window has to contain everything it shows: a screenshot, a recording or a screen share of the owner window captures an in-scene list and never a native one.Takes effect on the next open.
-
displayMode
- Returns:
- how the list is presented: while it is open, what it actually chose, including a
platform forcing
IN_SCENE. While it is closed, what was last asked for.
-
close
public void close()Dismisses the popup without changing the selection. No-op when closed. -
onMeasure
Description copied from class:WidgetReports the size this widget wants withinconstraints. Called once per layout pass, and the result is cached against the constraints and the resolved axes (size step, layout direction, locale), so it must be a pure function of them and of this widget's own state.Resolve the
ControlSizeand theLayoutDirectiononce each here and thread them down; never read either in a constructor. The locale needs no threading: it is in scope, andI18n.locale()answers it wherever text is resolved. -
baselineOffset
protected float baselineOffset()Mixed-step rows align on this, not on the box; seeFlex.CrossAlignment.BASELINE.- Overrides:
baselineOffsetin classWidget
-
onPaint
Description copied from class:WidgetWidget's own background/content, in local coordinates. -
onMouseEvent
Description copied from class:WidgetMouse events (bubbling); callevent.consume()when handled.- Overrides:
onMouseEventin classWidget
-
onKeyEvent
Description copied from class:WidgetKey events (focused widget first, then ancestors).- Overrides:
onKeyEventin classWidget
-
onCharTyped
Type-ahead: letters typed into an open list jump to what they spell, the way a combo does on Windows and a pop-up button does on GTK and macOS. Without it the only way through a long clamped list is one arrow press per item.Two behaviours a user expects and neither of which falls out of plain prefix matching. The buffer expires after
TYPE_AHEAD_RESET_NANOS, so "so" typed slowly is two separate jumps rather than a search for "so": a pause means a new word. And repeating one letter cycles through the items starting with it instead of re-finding the first, which is how a list of six things beginning with S is navigated at all.The search wraps and starts after the current highlight, so a match already under the cursor is not what a fresh keystroke finds.
- Overrides:
onCharTypedin classWidget
-
onFocusGained
protected void onFocusGained()Description copied from class:WidgetCalled when this widget takes keyboard focus. Default: nothing.- Overrides:
onFocusGainedin classWidget
-
onFocusLost
protected void onFocusLost()Description copied from class:WidgetCalled when this widget loses keyboard focus. Default: nothing.- Overrides:
onFocusLostin classWidget
-
onDetached
protected void onDetached()A combo removed from the tree must never strand its dropdown on screen: a programmatically-opened popup has no focus to lose, so focus-lost alone does not cover this.- Overrides:
onDetachedin classWidget
-