Module org.apache.sis.gui
Package org.apache.sis.gui.map

# Class GestureFollower

Object
CanvasFollower
GestureFollower

All Implemented Interfaces:
  `PropertyChangeListener`, `EventListener`, `EventHandler<MouseEvent>`, `Disposable`

public class GestureFollower extends CanvasFollower implements EventHandler<MouseEvent>
A listener of mouse or keyboard events in a source canvas which can be reproduced in a target canvas. This listener can reproduce the "real world" displacements documented in parent class. In addition, this class can also follow mouse movements in source canvas and move a cursor in the target canvas at the same "real world" position.

## Listeners

`GestureFollower` listeners need to be registered explicitly by a call to the `CanvasFollower​.initialize()` method. The `dispose()` convenience method is provided for unregistering all those listeners.

## Multi-threading

This class is not thread-safe. All events should be processed in the JavaFX thread.

Since:
  1.3

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `final BooleanProperty`
  `cursorEnabled`
  Whether mouse position in source canvas should be shown by a cursor in the target canvas.
  `final BooleanProperty`
  `transformEnabled`
  Whether changes in the "objective to display" transforms should be propagated from source to target canvas.

  ### Fields inherited from class CanvasFollower

  `source, target`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `GestureFollower(MapCanvas source, MapCanvas target)`
  Creates a new listener for synchronizing "objective to display" transform changes and cursor position between the specified canvas.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `void`
  `dispose()`
  Removes all listeners registered by this `GestureFollower` instance.
  `protected boolean`
  `filter(TransformChangeEvent event)`
  Returns `true` if this listener should replicate the following changes on the target canvas.
  `Optional<Point2D>`
  `getSourceDisplayPOI()`
  Returns the position for the mouse cursor in the source canvas if that position is known.
  `void`
  `handle(MouseEvent event)`
  Invoked when the mouse position changed.
  `protected void`
  `transformedSource(TransformChangeEvent event)`
  Invoked after the source "objective to display" transform has been updated.

  ### Methods inherited from class CanvasFollower

  `getDisplayTransform, getFollowRealWorld, getSourceObjectivePOI, initialize, isDisabled, propertyChange, setDisabled, setFollowRealWorld, transformDisplayCoordinates, transformedTarget, transformObjectiveCoordinates`

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### transformEnabled

    public final BooleanProperty transformEnabled
    Whether changes in the "objective to display" transforms should be propagated from source to target canvas. The default value is `false`; this property needs to be enabled explicitly by caller if desired.

  - ### cursorEnabled

    public final BooleanProperty cursorEnabled
    Whether mouse position in source canvas should be shown by a cursor in the target canvas. The default value is `false`; this property needs to be enabled explicitly by caller if desired.

- ## Constructor Details

  - ### GestureFollower

    public GestureFollower(MapCanvas source, MapCanvas target)
    Creates a new listener for synchronizing "objective to display" transform changes and cursor position between the specified canvas. This is a unidirectional binding: changes in source are applied on target, but not the converse.

    Caller needs to register listeners by a call to the `CanvasFollower​.initialize()` method. This is not done automatically by this constructor for allowing users to control when to start listening to changes.

    Parameters:
      `source` - the canvas which is the source of zoom, pan or rotation events.
      `target` - the canvas on which to apply the changes of zoom, pan or rotation.

- ## Method Details

  - ### getSourceDisplayPOI

    public Optional<Point2D> getSourceDisplayPOI()
    Returns the position for the mouse cursor in the source canvas if that position is known. This information is used when the source and target canvases do not use the same CRS. `GestureFollower` tries to transform the canvas views in such a way that the "real world" change is the same for both canvas at that location.

    The returned value is "live"; it may change with mouse and gesture events. Callers should not modify that value, and copy it if they need to keep it.

    Overrides:
      `getSourceDisplayPOI` in class `CanvasFollower`
    Returns:
      mouse position in source canvas where displacements, zooms and rotations applied on the source canvas should be mirrored exactly on the target canvas.

  - ### handle

    public void handle(MouseEvent event)
    Invoked when the mouse position changed. This method should be invoked only if `cursorEnabled` is `true` (this is not verified by this method).
    Specified by:
      `handle` in interface `EventHandler<MouseEvent>`
    Parameters:
      `event` - the enter, exit or move event.

  - ### filter

    protected boolean filter(TransformChangeEvent event)
    Returns `true` if this listener should replicate the following changes on the target canvas. This implementation returns `true` if the transform reason is `TransformChangeEvent​.Reason​.INTERIM`. It allows immediate feedback to users without waiting for the background thread to complete rendering.
    Overrides:
      `filter` in class `CanvasFollower`
    Parameters:
      `event` - a transform change event that occurred on the source canvas.
    Returns:
      whether to replicate that change on the target canvas.

  - ### transformedSource

    protected void transformedSource(TransformChangeEvent event)
    Invoked after the source "objective to display" transform has been updated. This implementation adjusts the cursor position for compensating the relative change in mouse position.

    #### Details

    If the map moved in the source canvas without a change of mouse cursor position (for example if the user navigates using the keyboard), then the mouse position changed relatively to the map, so the cursor position on the target canvas needs to be updated accordingly. This is a temporary change applied until the next `MouseEvent` gives us new mouse coordinates relative to the map.
    Overrides:
      `transformedSource` in class `CanvasFollower`
    Parameters:
      `event` - the change which has been applied on the CanvasFollower.source canvas.

  - ### dispose

    public void dispose()
    Removes all listeners registered by this `GestureFollower` instance. This method should be invoked when `GestureFollower` is no longer needed, in order to avoid memory leak.
    Specified by:
      `dispose` in interface `Disposable`
    Overrides:
      `dispose` in class `CanvasFollower`
    See Also:
      - `CanvasFollower​.initialize()`