Class ScrollBar
ListView,
TextArea, ScrollView, …), so they look and behave identically.
It is an overlay widget the host lays out along an edge; it reads/writes
scroll through a ScrollBar.Model and handles its own thumb drag and track paging.
- Themed: the thumb is drawn in
Theme.textMuted, so it is visible on both light and dark surfaces. - Draggable: drag the thumb, or click the track to page.
- Policy (
setPolicy(limn.components.ScrollBar.Policy)):ScrollBar.Policy.HIDDEN,ScrollBar.Policy.ALWAYS,ScrollBar.Policy.ON_SCROLL(fades in on scroll) orScrollBar.Policy.AUTO(also while the pointer is active over the host). - Thin idle / wide on approach: a slim bar that widens when the pointer is over it or dragging, ready to grab.
- Mirrored: a horizontal bar reads with its subtree, so right to left the thumb rests at the right end of the track and walks left as the offset grows. A vertical bar's travel is a y and never mirrors; only the side its thumb hugs does, following the side the host puts the strip on.
- Scrolls under a drag: while something is dragged with the pointer, resting it near an edge of the host's box, or past that edge, scrolls the host along the bar's axis toward that edge, faster the nearer the edge and the farther past it. So a widget of your own that scrolls through a bar scrolls under a drag as the toolkit's do, with no code of its own.
onScrolled() when it scrolls and onHostActivity()
on pointer movement (for AUTO).
The hold is a timer, not an animation. A reveal lasts HOLD_SECONDS past
the last scroll or pointer movement and then fades; the fade in and out are transitions,
which tick only while a value moves. The hold itself used to be a real-time ticker that
returned "still holding" every frame for a second after every pointer move, and a scene
keeps its frame pump running while any ticker is alive: moving the pointer over a form
inside a scroll view rendered at the display's rate with nothing on screen changing, and
resting it over the bar rendered forever. The hold is now a timestamp compared on demand
and one delayed task armed for the moment it expires, so a bar that is showing and still
asks for no frame at all.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceThe scroll state the bar reflects and drives.static enumWhich axis the bar controls.static enumWhen the bar is shown. -
Constructor Summary
ConstructorsConstructorDescriptionScrollBar(ScrollBar.Orientation orientation, ScrollBar.Model model) A bar reading its extent and offset frommodel. -
Method Summary
Modifier and TypeMethodDescriptionprotected voidDescribes the bar as oneSCROLL_BARnode whose value is the host's model in the model's own points, or as nothing at all when there is nothing to scroll.protected booleanonAccessibilityAction(Accessible.Action action, Accessible.Argument arg) Scrolls the host as an assistive technology asked, through the same private path a track press and a thumb drag take, so the host's model is told the same way, the same clamp runs and the bar reveals itself as it does for the wheel.protected @Nullable Widget<?> onHitTest(float localX, float localY) Transparent to events while effectively invisible, so it never blocks the content.voidThe pointer is active over the host: reveal the bar (AUTO).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.voidThe host scrolled: reveal the bar (ON_SCROLL / AUTO).policy()The current visibility policy.voidrefresh()Re-evaluate visibility after the content/overflow changed.setPolicy(ScrollBar.Policy newPolicy) When the bar is shown: always, never, or only while the content overflows.static floatThe strip thickness the host reserves/lays the bar out with.Methods inherited from class limn.scene.Widget
acceptsTextInput, accessibleLabelAccessKey, accessibleLabelTarget, accessibleLabelText, add, add, announceChange, backdropReach, baselineOffset, baselineOffsetOf, caretRect, children, clipboard, clipHeight, clipsChildren, clipWidth, clipX, clipY, controlSize, cursor, declaredControlSize, declaredLayoutDirection, declaredLocale, focusArrivedBackward, focusArrivedByTraversal, handleUserChange, height, hitTest, hitTestChild, id, imageCursor, inheritanceHost, invalidate, invalidate, invalidateAccessible, isEnabled, isFocusable, isFocused, isRightToLeft, isSelfEnabled, isShowing, isVisible, isVisibleByItsOwnFlag, layoutBox, layoutDirection, locale, localToScene, localToSceneBounds, markNeedsContainedLayout, markNeedsLayout, markNeedsLayoutInPlace, maxHeight, maxWidth, measure, minHeight, minWidth, moveChild, moveChild, moveChild, neutralBase, notifyChange, notifyTextEdit, observeChanges, onAccessibilityChild, onAccessibilityChildAction, onAccessibilityChildIdentity, onAttached, onCanEdit, onCharTyped, onDetached, onDragExit, onDragOver, onDragStart, onDrop, onEdit, onFocusGained, onFocusLost, onKeyEvent, onLayout, onPaintOverlay, onPreedit, onSyntheticAction, overlayPassesPointer, paintChildren, paintOutset, paintsDecoration, paintsFromBackdrop, paintWidget, parent, remove, remove, requestFocus, requestFocus, revealInView, revealInView, runHandler, scene, sceneNanos, sceneToLocal, self, setAccessibleDescribedBy, setAccessibleDescription, setAccessibleDescription, setAccessibleIgnored, setAccessibleLabelledBy, setAccessibleName, setAccessibleName, setAccessibleRole, setControlSize, setCursor, setEnabled, setFocusable, setId, setImageCursor, setInheritanceHost, setLayoutDirection, setLocale, setMaxHeight, setMaxWidth, setMinHeight, setMinWidth, setPresentedElsewhere, setTooltip, setTooltip, setVisible, shapeText, textRuler, tooltip, tooltipSource, width, x, y
-
Constructor Details
-
ScrollBar
A bar reading its extent and offset frommodel.
-
-
Method Details
-
setPolicy
When the bar is shown: always, never, or only while the content overflows. -
policy
The current visibility policy. -
thickness
public static float thickness()The strip thickness the host reserves/lays the bar out with. -
onScrolled
public void onScrolled()The host scrolled: reveal the bar (ON_SCROLL / AUTO). -
onHostActivity
public void onHostActivity()The pointer is active over the host: reveal the bar (AUTO). Called for every pointer move over the host, so it must cost nothing while the bar is already showing: a stamp and two comparisons, no invalidation and no frame. -
refresh
public void refresh()Re-evaluate visibility after the content/overflow changed.Content that has just become scrollable reveals the bar for one hold-and-fade, the way an overlay scroller flashes when a pane first has something to scroll. Under
ScrollBar.Policy.AUTO(the default, and what aDialogbody uses) the bar is otherwise invisible until the pointer moves over the host or the wheel turns, so a card that was capped opens with nothing at all saying that anything was cut off. The gutter inset says the card is capped; only the bar says it can be scrolled.It repaints the bar only when something the thumb is drawn from changed since the last refresh: the content's length, the viewport's, the offset, or the bar's own size. A host calls this from its layout, and a layout can run again with nothing in it changed; a refresh that repainted every time turned each such layout into damage, and a host laid out on every frame into a frame that asked for the next one, for ever. The fades and the widening repaint the bar themselves as they run.
-
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. -
onPaint
Description copied from class:WidgetWidget's own background/content, in local coordinates. -
onHitTest
Transparent to events while effectively invisible, so it never blocks the content. -
onMouseEvent
Description copied from class:WidgetMouse events (bubbling); callevent.consume()when handled.- Overrides:
onMouseEventin classWidget<ScrollBar>
-
onAccessibility
Describes the bar as oneSCROLL_BARnode whose value is the host's model in the model's own points, or as nothing at all when there is nothing to scroll.The node exists exactly when the bar is operable by anyone. Under
ScrollBar.Policy.HIDDENthe application asked for no bar, and content that fits its viewport leaves a range with a maximum of zero; in both the bar refuses the pointer at every opacity and paints nothing, and both are structural facts that move only on a policy, content or size change, never on a scroll. The fade is neither: a bar that has faded underScrollBar.Policy.ON_SCROLLorScrollBar.Policy.AUTOis still laid out, still visible and still showing, and an assistive technology's action does not travel through the hit test the fade gates. Its set reachesonScrolled()and reveals the bar exactly as the wheel does, so the node stays through the fade rather than appearing and vanishing in a reader's tree a second after every scroll and every pointer move over the host.No name, deliberately: the widget holds no string, every platform speaks the role and the orientation for a scroll bar, and it is not a tab stop. No value text: the number is the whole of it. The step is one viewport, the only step the bar has, because a track press pages and there is no line step and no keyboard.
INCREMENTandDECREMENTare the two paging directions defined on the value;SET_VALUEis advertised by the facet's presence and is never listed. Nothing here allocates, and nothing here reads the opacity or the widen level, so the frames of a fade damage the bar and publish nothing.- Overrides:
onAccessibilityin classWidget<ScrollBar>- Parameters:
a- the node being described
-
onAccessibilityAction
Scrolls the host as an assistive technology asked, through the same private path a track press and a thumb drag take, so the host's model is told the same way, the same clamp runs and the bar reveals itself as it does for the wheel.INCREMENTandDECREMENTpage by one viewport and grow or shrink the offset in both layout directions: the verbs are defined on the published value, which is a magnitude, and the screen-side flip a mirrored horizontal bar applies to a track press belongs to the pointer alone.SET_VALUEtakes anAccessible.Argument.OfValuein the model's own points and refuses anything else, including a value that is not a finite number, which the clamp would pass through untouched. Every verb is refused while the bar's own enabled flag is off, and while the node would not be in the tree at all — the policy hidden, or the content fitting — because an identifier can arrive after the node left, and the scene's gate re-checks the ancestors and not the bar's own two absences.- Overrides:
onAccessibilityActionin classWidget<ScrollBar>- Parameters:
action- what was askedarg- the value forSET_VALUE; ignored by the two pages- Returns:
- whether the request ran
-