Class ScrollSurface

java.lang.Object
com.codename1.ui.Component
com.codename1.ui.ScrollSurface
All Implemented Interfaces:
Animation, Editable, StyleListener

public abstract class ScrollSurface extends Component

A painted component that scrolls on two axes, under an optional pinned header row and pinned header column.

A view that draws thousands of items itself -- a calendar, a Gantt chart, a diagram -- cannot afford a component per item, and so cannot use a scrollable Container. This class does for such a view what a scrollable container does for components: panning and the fling after it, the mouse wheel, pinch to zoom, auto scrolling while something is dragged near an edge, and telling a tap from a double tap, a drag and a long press. The view only says how big its content is and paints it.

class Sheet extends ScrollSurface {
    protected void layoutSurface(int width, int height) {
        setHeaderSize(80, 30);
    }
    protected int getContentWidth() { return 5000; }
    protected int getContentHeight() { return 20000; }
    protected void paintContent(Graphics g, int x, int y) {
        // the content's origin is at x, y; only the visible part is clipped in
    }
}
Regions

The component is divided into the content, which scrolls on both axes; the top header, which scrolls only horizontally with it; the left header, which scrolls only vertically; and the corner where the two meet, which does not scroll. Each is painted clipped to its own region. paintOverlay paints last, over all four. A view without headers leaves their size at zero.

Edits

A drag either pans or edits. When a drag or a long press begins, the surface asks editStarted whether it begins an edit, telling it what kind of gesture it is (EditTrigger). From then on the pointer goes to editMoved and, when it lifts, to editEnded. isDragEdits decides whether a plain drag may start an edit anywhere, which is the default where there is a mouse, or only on things made to be dragged (EditTrigger.HANDLE_DRAG), which leaves a finger free to pan.

Bounded and unbounded content

By default the scroll position stays inside the content. A surface whose content has no edges, such as an infinite canvas, turns that off with setBounded(false) and reads the moves through scrollChanged.

  • Field Details

    • HOVER_MS

      protected static final int HOVER_MS
      How long a hover takes to come up and to fade, in milliseconds.
      See Also:
    • LIFT_MS

      protected static final int LIFT_MS
      How long an item that is picked up takes to rise, in milliseconds.
      See Also:
    • SETTLE_MS

      protected static final int SETTLE_MS
      How long a dropped item takes to travel to its place, in milliseconds.
      See Also:
  • Constructor Details

    • ScrollSurface

      protected ScrollSurface()
      A focusable surface that takes every pointer event.
  • Method Details

    • layoutSurface

      protected abstract void layoutSurface(int width, int height)
      Lays the surface out for a size: sets the header sizes and whatever the content's size depends on. Called before every paint and every pointer event, so it has to return at once when nothing has changed.
    • getContentWidth

      protected abstract int getContentWidth()
      The width of what scrolls, in pixels, without the left header.
    • getContentHeight

      protected abstract int getContentHeight()
      The height of what scrolls, in pixels, without the top header.
    • paintContent

      protected abstract void paintContent(Graphics g, int x, int y)
      Paints what scrolls. x and y are where the content's own origin is on screen, which is off screen once it has scrolled. The graphics is clipped to the content region.
    • paintTopHeader

      protected void paintTopHeader(Graphics g, int x, int y)
      Paints the pinned top row. x is where the content's origin is; y is the top of the row.
    • paintLeftHeader

      protected void paintLeftHeader(Graphics g, int x, int y)
      Paints the pinned left column. x is its left; y is where the content's origin is.
    • paintCorner

      protected void paintCorner(Graphics g, int x, int y)
      Paints the corner where the two headers meet, at its top left.
    • paintOverlay

      protected void paintOverlay(Graphics g, int x, int y)
      Paints over everything, in the component's own bounds, whose top left is x, y. Not painted on a printed page: it is for what a gesture in progress shows.
    • setHeaderSize

      protected final void setHeaderSize(int width, int height)
      Sets the width of the pinned left column and the height of the pinned top row, in pixels. Called from layoutSurface.
    • getHeaderWidth

      public final int getHeaderWidth()
      The width of the pinned left column, in pixels.
    • getHeaderHeight

      public final int getHeaderHeight()
      The height of the pinned top row, in pixels.
    • pressStarted

      protected void pressStarted(int x, int y)
      The pointer went down at a point, in the component's coordinates. Whatever it turns into -- a tap, a drag, a long press -- follows.
    • editStarted

      protected boolean editStarted(int x, int y, ScrollSurface.EditTrigger trigger)

      Asked when a drag or a long press begins, at the point where the pointer went down, in the component's coordinates.

      Parameters
      • trigger: what kind of gesture it is
      Returns

      true when an edit has begun and the drag belongs to it; false to pan

    • editMoved

      protected void editMoved(int x, int y)
      The pointer of an edit moved, or the surface scrolled under it.
    • editEnded

      protected void editEnded(boolean committed)
      The edit is over. committed is false when it was cancelled: by cancelEdit, a second finger, or the surface leaving the form.
    • isEditAutoScroll

      protected boolean isEditAutoScroll(int x, int y)
      Whether the surface scrolls under an edit dragged near its edge. Asked on every move of an edit; true by default.
    • tapped

      protected void tapped(int x, int y, boolean doubleTap)
      A tap that was not a drag or a long press.
    • longPressed

      protected void longPressed(int x, int y)
      A long press that started no edit.
    • scrollChanged

      protected void scrollChanged()
      The scroll position changed.
    • zoomBy

      protected boolean zoomBy(float factor, int x, int y)

      Zooms by factor around a point, for a pinch or Control/Command and the wheel.

      Returns

      false when the surface has no zoom, so the gesture is left alone

    • setDragEdits

      public void setDragEdits(boolean dragEdits)
      Whether a plain drag may start an edit anywhere instead of only on handles. On by default where there is a mouse, which has a wheel to scroll with.
    • isDragEdits

      public boolean isDragEdits()
      See setDragEdits.
    • cancelEdit

      public void cancelEdit()
      Cancels an edit in progress, as Escape does; editEnded(false) follows.
    • isEditInProgress

      public boolean isEditInProgress()
      Whether an edit is being dragged.
    • isBounded

      public boolean isBounded()
      Whether the scroll position stays inside the content; true by default.
    • setBounded

      public void setBounded(boolean bounded)
      Lets the scroll position go anywhere, for content without edges. The sizes getContentWidth and getContentHeight report are then not used to limit it.
    • getBodyWidth

      public final int getBodyWidth()
      The width of the content region, in pixels: the component without the left header.
    • getBodyHeight

      public final int getBodyHeight()
      The height of the content region, in pixels: the component without the top header.
    • getMaxOffsetX

      public final int getMaxOffsetX()
      The largest horizontal scroll position of bounded content.
    • getMaxOffsetY

      public final int getMaxOffsetY()
      The largest vertical scroll position of bounded content.
    • getOffsetX

      public final int getOffsetX()
      How far the content has scrolled to the left, in pixels.
    • getOffsetY

      public final int getOffsetY()
      How far the content has scrolled up, in pixels.
    • scrollTo

      public void scrollTo(int x, int y)
      Scrolls to a position, held inside bounded content.
    • setOffsets

      protected final void setOffsets(int x, int y)
      Sets the scroll position without holding it inside the content and without calling scrollChanged, for a view whose content moves under the scroll position (a zoom about a point, a change of date).
    • refreshLayout

      public void refreshLayout()
      Lays out for the current size and holds the scroll position inside bounded content.
    • stopFling

      protected final void stopFling()
      Stops a fling in progress.
    • currentTime

      protected final long currentTime()
      The time the surface animates by: the clock, or the one it was told to stand still at with setAnimationTime.
    • setAnimationTime

      public void setAnimationTime(long millis)
      Stops the clock the surface animates hovers and drops by at a time, so a picture taken in the middle of one is the same every run; a negative time starts the clock again.
    • hoverAt

      protected void hoverAt(int x, int y)
      The pointer rests at a point of the surface without being pressed. A view answers with setHoverTarget, naming what is there and the cursor that says what a press would do.
    • hoverGone

      protected void hoverGone()
      The pointer left, or nothing is known of it any more.
    • setHoverTarget

      protected final void setHoverTarget(Object key, int cursor)
      Names what the pointer is over -- any object with a meaningful equals, or null for nothing -- and the cursor to show.
    • setHoverTooltip

      protected final void setHoverTooltip(String text)
      The tooltip of the thing the pointer is on, for an application that shows tooltips; null for none.
    • getFadingHoverTarget

      public final Object getFadingHoverTarget()
      What the pointer has just left, while its hover fades.
    • getHoverTarget

      public final Object getHoverTarget()
      What the pointer is over, as the view named it.
    • hasHoverFeedback

      public final boolean hasHoverFeedback()
      Whether anything is lit by the pointer or still fading: a view that paints many items asks once before asking getHoverLevel for each.
    • getHoverLevel

      public final float getHoverLevel(Object key)
      How far the hover of key has come up, from 0 to 1.
    • getLiftLevel

      public final float getLiftLevel()
      How far the item being dragged has risen off the surface, from 0 to 1.
    • startSettle

      protected final void startSettle(Object key, int x, int y, int w, int h)
      An item was let go at a rectangle of the content that is not where it belongs: applySettle moves it from there to its place.
    • applySettle

      public final boolean applySettle(Object key, int[] rect)

      Moves the rectangle of an item -- x, y, width, height, in the content -- to where it is on its way from where it was dropped.

      Returns

      true while it travels

    • pointerHover

      public void pointerHover(int[] x, int[] y)
      Description copied from class: Component

      Invoked for devices where the pointer can hover without actually clicking the display. This is true for PC mouse pointer as well as some devices such as the BB storm.

      Parameters
      • x: the pointer x coordinate

      • y: the pointer y coordinate

      Overrides:
      pointerHover in class Component
    • setHovered

      public void setHovered(boolean hovered)
      Description copied from class: Component

      Marks this component as hovered, repainting when the state actually changes AND the theme has a hover style to show for it -- otherwise the repaint would be pure cost, because nothing about the render depends on the flag.

      Parameters
      • hovered: true when the pointer is over this component
      Overrides:
      setHovered in class Component
    • initComponent

      protected void initComponent()
      Description copied from class: Component
      Allows subclasses to bind functionality that relies on fully initialized and "ready for action" component state
      Overrides:
      initComponent in class Component
    • requestAnimation

      protected final void requestAnimation()
      Asks for animateSurface to be called on the next frames, for a view with a motion of its own. Frames stop once nothing moves.
    • animateSurface

      protected boolean animateSurface()

      Advances the view's own motion. Called every frame while the surface animates; call requestAnimation to start the frames.

      Returns

      true while the view still has something moving

    • animate

      public final boolean animate()
      Description copied from class: Component

      Allows the animation to reduce "repaint" calls when it returns false. It is called once for every frame. Frames are defined by the com.codename1.ui.Display class.

      Returns

      true if a repaint is desired or false if no repaint is necessary

      Specified by:
      animate in interface Animation
      Overrides:
      animate in class Component
    • deinitialize

      protected void deinitialize()
      Description copied from class: Component
      Invoked to indicate that the component initialization is being reversed since the component was detached from the container hierarchy. This allows the component to deregister animators and cleanup after itself. This method is the opposite of the initComponent() method.
      Overrides:
      deinitialize in class Component
    • paint

      public void paint(Graphics g)
      Description copied from class: Component

      This method paints the Component on the screen, it should be overriden by subclasses to perform custom drawing or invoke the UI API's to let the PLAF perform the rendering.

      Parameters
      • g: the component graphics
      Specified by:
      paint in interface Animation
      Overrides:
      paint in class Component
    • getPageGrid

      public ScrollSurface.PageGrid getPageGrid(int width, int height)

      How the content divides into pages of width by height pixels, with the headers repeated on each.

      The view is laid out at the page's size for the count, as it is for the painting, and put back as it was.

    • paintPage

      public void paintPage(Graphics g, int x, int y, int width, int height, int contentX, int contentY)

      Paints one page: the content from contentX, contentY on, under the headers that belong to it, at x, y in a page of width by height.

      This is the view's own painting at another size and scroll position, so what prints is what the screen shows. The overlay is left out. The content is clipped to its end, so the last page of a row or column ends where the content does.

    • isPrinting

      protected final boolean isPrinting()
      Whether a page is being painted and not the screen.
    • saveZoomState

      protected Object saveZoomState()
      The zoom a layout at another size may change, as an object the view alone reads: a view that holds its scale inside limits depending on the room it has may move it when laid out for a page, and does not move it back when laid out for the screen again. Null for a view without a zoom.
    • restoreZoomState

      protected void restoreZoomState(Object state)
      Puts back what saveZoomState returned. Called with the view laid out at its own size again.
    • getPageStep

      protected int getPageStep(int bodyHeight)
      How far down a page of content height bodyHeight goes before the next one starts. A view of rows answers a whole number of them, so no page ends in the middle of one.
    • calcPreferredSize

      protected Dimension calcPreferredSize()
      Description copied from class: Component

      Calculates the preferred size based on component content. This method is invoked lazily by getPreferred size.

      Returns

      the calculated preferred size based on component content

      Overrides:
      calcPreferredSize in class Component
    • pointerPressed

      public void pointerPressed(int x, int y)
      Description copied from class: Component

      If this Component is focused, the pointer pressed event will call this method

      Parameters
      • x: the pointer x coordinate

      • y: the pointer y coordinate

      Overrides:
      pointerPressed in class Component
    • pointerDragged

      public void pointerDragged(int x, int y)
      Description copied from class: Component

      If this Component is focused, the pointer dragged event will call this method

      Parameters
      • x: the pointer x coordinate

      • y: the pointer y coordinate

      Overrides:
      pointerDragged in class Component
    • longPointerPress

      public void longPointerPress(int x, int y)
      Description copied from class: Component
      If this Component is focused this method is invoked when the user presses and holds the pointer on the Component
      Overrides:
      longPointerPress in class Component
    • pointerReleased

      public void pointerReleased(int x, int y)
      Description copied from class: Component

      If this Component is focused, the pointer released event will call this method

      Parameters
      • x: the pointer x coordinate

      • y: the pointer y coordinate

      Overrides:
      pointerReleased in class Component
    • mouseWheel

      protected boolean mouseWheel(WheelEvent ev)
      Description copied from class: Component

      Handles a scroll wheel or trackpad scroll over this component, before its listeners and before anything above it in the hierarchy.

      A component that moves its own content -- an editor that scrolls itself, a viewer that pans -- implements this. Everything else leaves it alone and the wheel scrolls the nearest scrollable ancestor, which is what a wheel means.

      This exists because a wheel used to arrive as a synthetic press, drag and release played into the component tree: a component that wanted the wheel got it by handling pointer events, and so did every component that did not want it. The events are gone and this is what replaces them, for the few components that have something of their own to move.

      Parameters
      • ev: the wheel event, carrying the scroll deltas in display pixels
      Returns

      true when this component handled the wheel and nothing else should act on it

      Overrides:
      mouseWheel in class Component
    • pinch

      protected boolean pinch(float scale)
      Description copied from class: Component

      Invoked by subclasses interested in handling pinch to zoom events, if true is returned other drag events will not be broadcast

      Parameters
      • scale: @param scale the scaling of the pinch operation a number larger than 1 means scaling up and smaller than 1 means scaling down. It is recommended that code would threshold the number (so a change between 1.0 and 1.02 shouldn't necessarily trigger zoom). Notice that this number is relevant to current zoom levels and unaware of them so you should also enforce limits of maximum/minimum zoom levels.
      Returns

      false by default

      Overrides:
      pinch in class Component
    • pinchReleased

      protected void pinchReleased(int x, int y)
      Description copied from class: Component

      To be implemented by subclasses interested in being notified when a pinch zoom has ended (i.e the user has removed one of their fingers, but is still dragging).

      Parameters
      • x: The x-coordinate of the remaining finger in the drag. (Absolute)

      • y: The y-coordinate of the remaining finger in the drag. (Absolute)

      Overrides:
      pinchReleased in class Component
    • shouldBlockSideSwipe

      protected boolean shouldBlockSideSwipe()
      Description copied from class: Component
      A component that might need side swipe such as the slider could block it from being used for some other purpose when on top of said component.
      Overrides:
      shouldBlockSideSwipe in class Component