Members

(static, constant) TRACK_DROPDOWN_CHEVRON_GUTTER

Default Value
  • 8

(static, constant) TRACK_DROPDOWN_CHEVRON_SIZE

Chevron is rendered for interactive slots only as the dropdown affordance. Sized 1:1 with the source bitmap (24x24 white-on-transparent). Gutter sits between the label's max right edge and the chevron's left edge so a marquee-truncated label never collides with the icon.

Default Value
  • 24

(static, constant) TRACK_DROPDOWN_INTER_SLOT_GUTTER

Inter-slot gutter from ItemDetails.xml's trackDropdowns layout: slot stride (308) - slot width (278) = 30. Used to cap the auto-sized menu at two slot widths plus this gutter so an open menu never spans more than two columns of horizontal real estate.

Default Value
  • 30

(static, constant) TRACK_DROPDOWN_ROW_H_PADDING

Mirrors TrackDropdownRow's ROW_H_PADDING; kept in sync intentionally so the auto-sized menu width math matches what the row's label actually consumes.

Default Value
  • 12

(static, constant) TRACK_DROPDOWN_TRIGGER_HEIGHT

45 = fontSizeSmaller (25) + 20, matching TrackDropdownRow.onSizeChanged line: m.rowHeight = int(constants.fontSizeSmaller * 1.0) + 20

Default Value
  • 45

(static, constant) TRACK_DROPDOWN_TRIGGER_H_PADDING

Trigger geometry is intentionally IDENTICAL to TrackDropdownRow's row geometry so a closed/unfocused trigger reads pixel-for-pixel like the selected-unfocused row that appears directly below it when the menu opens: same horizontal padding (12px), same font (fontSizeSmaller), same height formula, same label vertical centering. If you change either file's padding/height formula, update both — they are duplicated intentionally for locality. See TrackDropdownRow.onSizeChanged.

The cluster (titles 24 + trigger 45 = 69px) lives inside a 99px vertical budget: description bottom at y=701, buttons top at y=800, with 12px breathing pad above and 18px below the cluster. The 701 description bottom is produced by the itemTracks spacer (62px) inside itemDetails — see ItemDetails.xml. Do NOT shrink the trigger below the row height without re-verifying the trigger↔row visual match.

Default Value
  • 12

Methods

(static) applyBackgroundVisibility() → {void}

Single source of truth for the trigger background's visibility: interactive AND closed -> visible (affordance at rest and when focused/closed) interactive AND open -> hidden (trigger reads as static label above the menu) not interactive -> hidden (static single-option slot)

Returns:
Type: 
void

(static) applyChevronVisibility() → {void}

Chevron tracks the background: only shown for interactive, closed slots. Hidden while the menu is open since the menu being visible already communicates "this is expanded" — leaving the chevron visible would compete with that signal.

Also owns the trigger label's maxWidth: when the chevron is visible the label has to leave room on the right for the icon + gutter; when the chevron is hidden the label reclaims that space so longer values truncate later. This makes the open- menu trigger label match the menu rows' maxWidth (both at slotWidth - 2*hPadding), and gives single-option non-interactive slots their full inner width to display.

Returns:
Type: 
void

(static) applyTheme() → {void}

Returns:
Type: 
void

(static) closeMenu() → {void}

Returns:
Type: 
void

(static) computeMenuWidth(items, slotWidth) → {integer}

Returns the menu width that fits the longest item title, clamped to [slotWidth, slotWidth*2 + interSlotGutter]. The lower clamp keeps the menu anchored under its trigger column; the upper clamp stops an open menu from spanning more than two columns of horizontal real estate.

Measurement is pixel-exact: m.measureLabel is a themed LabelPrimarySmaller, so setting its text and reading boundingRect().width returns the same width the rendered row's ScrollingLabel will use (same font, same fontSizeSmaller, same uiFontFallback scale factor). No fudge multiplier needed. Same render-thread boundingRect technique FontScalingTask uses against the scene's defaultFont / fallbackFont labels.

Parameters:
NameTypeDescription
itemsobject
slotWidthinteger
Returns:
Type: 
integer

(static) findSelectedIndex() → {integer}

Returns the index in m.menuItems whose itemId matches m.top.selectedItemId, or -1 if no row matches. Iterates the rendered rows (not m.top.items) so callers can use the returned value directly as a focusedItemIndex.

Returns:
Type: 
integer

(static) handleClosedKeyEvent(key) → {boolean}

Parameters:
NameTypeDescription
keystring
Returns:
Type: 
boolean

(static) handleMenuKeyEvent(key) → {boolean}

Keys while the menu is open: UP past first -> closeMenu() (stays on trigger). The primary exit gesture for dismissing without committing; BACK also works. DOWN past last -> WRAPS to the first item. The menu never exits on DOWN; the user must either pick an option (OK), press UP from item 0, or press BACK to dismiss. UP / DOWN middle -> move focus + scroll OK -> commit selection, fire selectedAction, closeMenu() LEFT/RIGHT -> closeMenu() + requestFocusExit (horizontal siblings) BACK -> closeMenu()

Parameters:
NameTypeDescription
keystring
Returns:
Type: 
boolean

(static) hideTriggerFocus() → {void}

Returns:
Type: 
void

(static) init() → {void}

Returns:
Type: 
void

(static) layoutTrigger() → {void}

Lays out the trigger surface: scrolling trigger label on a 9-patch bg/border that spans the full slot width.

Returns:
Type: 
void

(static) onDestroy() → {void}

Returns:
Type: 
void

(static) onFocusChanged() → {void}

Returns:
Type: 
void

(static) onIsInteractiveChanged() → {void}

Interactive dropdowns get a persistent filled background + a chevron affordance. Static single-option slots render as plain text with NO background and NO chevron (preserves the app-wide invariant that "backdrop = focusable"). The trigger label itself stays visible across all states, including when the menu is open — it acts as a dim "current value" indicator above the menu while the menu shows alternatives.

Returns:
Type: 
void

(static) onItemsChanged() → {void}

Rebuilds the menu as TrackDropdownRow children inside a clipping viewport. ALL items are rendered — including the currently-selected one — so the menu always has at least 2 rows when interactive (single-option slots are non-interactive and never open a menu). The selected row is rendered with a dim label color that visually echoes the dim trigger label above the menu, making the on-screen duplication read as "your current value, persistent above and inside the menu" rather than competing with the alternatives. See TrackDropdownRow.onFocusStateChanged.

Returns:
Type: 
void

(static) onKeyEvent(key, press) → {boolean}

Parameters:
NameTypeDescription
keystring
pressboolean
Returns:
Type: 
boolean

(static) onSelectedItemChanged() → {void}

Returns:
Type: 
void

(static) onSlotWidthChanged() → {void}

Returns:
Type: 
void

(static) onTriggerTextChanged() → {void}

Returns:
Type: 
void

(static) openMenu() → {void}

Returns:
Type: 
void

(static) scrollToFocused() → {void}

scrollToFocused: Shift the menuItems LayoutGroup vertically inside the clipping viewport so the focused row is always visible. Keeps focus near the top of the viewport once the user scrolls past the first page.

Returns:
Type: 
void

(static) showTriggerFocus() → {void}

Background stays visible in both focused and unfocused states (so the dropdown always affords interactivity). Only the border + label color + chevron tint + marquee flip on focus.

Returns:
Type: 
void

(static) updateFocusedItemVisuals() → {void}

Returns:
Type: 
void