Class ScrollView

java.lang.Object
limn.scene.Widget
limn.components.ScrollView
All Implemented Interfaces:
Scrollable

public class ScrollView extends Widget implements Scrollable
Generic scroll container: the child is measured unbounded on the scrolling axes, painted clipped to the viewport and offset by the scroll position; the wheel scrolls whenever there is overflow. The child is physically positioned at (-offsetX, -offsetY), so hit-testing and event coordinates work unchanged.

Scroll indicators are the shared ScrollBar (draggable, themed, policy-driven), the same component every scroller uses.

The bars either float over the content or take a gutter of their own (setBarLayout(limn.components.ScrollGutters.Layout)). Which one is right is a property of what is being scrolled, not a taste: an image, a video or a page of prose wants every point of width and loses nothing to a bar that fades over it, while a table, a form or a tree wants its last column readable at all times, and a bar sitting on it is a defect however briefly it shows.

  • Constructor Details

    • ScrollView

      public ScrollView(Widget child)
      Wraps child, scrolling on both axes as its content overflows.
    • ScrollView

      public ScrollView(Widget child, boolean horizontal, boolean vertical)
      Wraps child, scrolling only on the axes enabled here.
  • Method Details

    • setScrollbarPolicy

      public ScrollView setScrollbarPolicy(ScrollBar.Policy policy)
      Sets the scrollbar visibility policy (default ScrollBar.Policy.AUTO).
    • setBarLayout

      public ScrollView setBarLayout(ScrollGutters.Layout layout)
      Sets whether the bars float over the content or reserve a strip of their own (default ScrollGutters.Layout.OVERLAY).
    • barLayout

      public ScrollGutters.Layout barLayout()
      Whether the scrollbars overlay the content or reserve a gutter.
    • viewportWidth

      public float viewportWidth()
      The width content is actually shown in: the box, less any reserved gutter. Every offset, clamp and reveal is measured against this rather than against Widget.width(), or a reserved bar would hide the last column it exists to keep clear.
    • viewportHeight

      public float viewportHeight()
      Visible height in logical points, excluding anything the content overflows by.
    • offsetX

      public float offsetX()
      Horizontal scroll position in logical points, 0 at the leading edge: the left edge in a left-to-right subtree and the right edge in a right-to-left one. The range is [0, maxOffsetX()] in both, so "scrolled to the start" is 0 either way.
    • offsetY

      public float offsetY()
      Vertical scroll position in logical points, 0 at the top.
    • maxOffsetX

      public float maxOffsetX()
      Largest valid offsetX(); 0 when the content fits.
    • maxOffsetY

      public float maxOffsetY()
      Largest valid offsetY(); 0 when the content fits.
    • scrollBy

      public void scrollBy(float dx, float dy)
      Scrolls by a delta in logical points (clamped).
    • revealRect

      public void revealRect(float x, float y, float rectWidth, float rectHeight)
      Scrolls the minimum so the rect (in viewport coordinates) becomes visible.
      Specified by:
      revealRect in interface Scrollable
    • scrollTo

      public void scrollTo(float newOffsetX, float newOffsetY)
      Scrolls to an absolute offset (clamped to the content). UI thread only.
    • onMeasure

      protected Size onMeasure(Constraints constraints)
      Description copied from class: Widget
      Reports the size this widget wants within constraints. 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 ControlSize and the LayoutDirection once each here and thread them down; never read either in a constructor. The locale needs no threading: it is in scope, and I18n.locale() answers it wherever text is resolved.

      Specified by:
      onMeasure in class Widget
    • onLayout

      protected void onLayout()
      Description copied from class: Widget
      Containers position children here (measure + Widget.layoutBox(float, float, float, float) per child).
      Overrides:
      onLayout in class Widget
    • clipsChildren

      protected boolean clipsChildren()
      Description copied from class: Widget
      Whether Widget.paintChildren(limn.graphics.Canvas) clips its children to this widget's bounds (scroll views, list viewports, tab strips). Partial rendering uses it to clamp a descendant's Widget.invalidate() damage to the visible region; a widget scrolled out of view damages nothing. Any override that clips in paintChildren should also override this.
      Overrides:
      clipsChildren in class Widget
    • paintChildren

      protected void paintChildren(Canvas canvas)
      Description copied from class: Widget
      Children pass; override to clip (e.g. scroll views).
      Overrides:
      paintChildren in class Widget
    • onMouseEvent

      protected void onMouseEvent(MouseEvent event)
      Description copied from class: Widget
      Mouse events (bubbling); call event.consume() when handled.
      Overrides:
      onMouseEvent in class Widget
    • onKeyEvent

      protected void onKeyEvent(KeyEvent event)
      Description copied from class: Widget
      Key events (focused widget first, then ancestors).
      Overrides:
      onKeyEvent in class Widget