Class MapCanvas

All Implemented Interfaces:
Localized
Direct Known Subclasses:
Map­Canvas­AWT

public abstract class MapCanvas extends PlanarCanvas
A canvas for maps to be rendered on screen in a JavaFX application. The map may be an arbitrary JavaFX node, typically an Image­View or Canvas, which must be supplied by subclasses. This base class provides handlers for keyboard, mouse, track pad or touch screen events such as pans, zooms and rotations. The keyboard actions are:
Keyboard actions
Key Action
Move view to the right
Move view to the left
Move view to the top
Move view to the bottom
⎇ + ⇨ Rotate clockwise
⎇ + ⇦ Rotate anticlockwise
Page down Zoom in
Page up Zoom out
Home Reset
Ctrl + above Above actions as a smaller translation, zoom or rotation

Subclassing

Implementations need to add at least one JavaFX node in the floating­Pane list of children. Map rendering involves the following steps:
  1. create­Renderer() is invoked in the JavaFX thread. That method shall take a snapshot of every information needed for performing the rendering in background.
  2. Map­Canvas​.Renderer​.render() is invoked in a background thread. That method creates or updates the nodes to show in this Map­Canvas but without interacting with the canvas yet.
  3. Map­Canvas​.Renderer​.commit(Map­Canvas) is invoked in the JavaFX thread. The nodes prepared by render() can be transferred to floating­Pane in that method.
Since:
1.1
  • Property Details

    • rendering

      public final ReadOnlyBooleanProperty renderingProperty
      Returns a property telling whether a rendering is in progress. This property become true when this Map­Canvas is about to start a background thread for performing a rendering, and is reset to false after this Map­Canvas has been updated with new rendering result.
      See Also:
    • error

      public final ReadOnlyObjectProperty<Throwable> errorProperty
      Returns a property giving the exception or error that occurred during last rendering operation. The property value is reset to null when a rendering operation completed successfully.
      See Also:
  • Field Details

    • floatingPane

      protected final Pane floatingPane
      The pane showing the map and any other JavaFX nodes to scale and translate together with the map. This pane is initially empty; subclasses should add nodes (canvas, images, shapes, texts, etc.) into the Pane​.get­Children() list. All children must specify their coordinates in units relative to the pane (absolute layout). Those coordinates can be computed from real world coordinates by Planar­Canvas​.objective­To­Display.

      This pane contains an Affine transform which is updated by user gestures such as pans, zooms or rotations. Visual positions of all children move together in response to user's gesture, thus giving an appearance of pane floating around. Changes in floating­Pane affine transform are temporary; they are applied for producing immediate visual feedback while the map is recomputed in a background thread. Once calculation is completed and the content of this pane has been updated, the floating­Pane Affine transform is reset to identity.

    • fixedPane

      protected final StackPane fixedPane
      The pane showing the map and other JavaFX nodes to keep at fixed position regardless pans, zooms or rotations applied on the map. This pane contains at least the floatingPane (which itself contains the map), but more children (shapes, texts, controls, etc.) can be added by subclasses into the Pane​.get­Children() list.
  • Constructor Details

    • MapCanvas

      public MapCanvas(Locale locale)
      Creates a new canvas for JavaFX application.
      Parameters:
      locale - the locale to use for labels and some messages, or null for default.
  • Method Details

    • initialize

      protected void initialize(GridGeometry visibleArea)
      Sets the objective bounds and/or the zoom level and objective CRS to use for the initial view of data. The visible­Area CRS defines the initial objective CRS of this canvas. The visible­Area envelope defines the (usually constant) objective bounds of this canvas. In addition if visible­Area contains a grid to CRS transform, its inverse will define the initial objective to display transform (which in turn defines the initial viewed area and zoom level).

      This method should be invoked only when new data have been loaded, or when the caller wants to discard any zoom or translation and reset the view to the given bounds. This method does not cause new repaint event; request­Repaint() must be invoked by the caller if desired.

      Parameters:
      visible­Area - bounding box, objective CRS and or initial zoom level, or null if unknown (in which case an identity transform will be set).
      Throws:
      Mismatched­Dimension­Exception - if the given grid geometry is not two-dimensional.
      Since:
      1.3
      See Also:
    • reset

      public void reset()
      Resets the map view to its default zoom level and default position with no rotation. Contrarily to clear(), this method does not remove the map content.
    • getObjectiveBounds

      public Envelope getObjectiveBounds()
      Returns the data bounds to use for computing the initial "objective to display" transform. This is the value specified by the last call to set­Objective­Bounds(Envelope). The coordinate reference system of the returned envelope defines also the CRS which is restored when the reset() method is invoked.
      Returns:
      the data bounds to use for computing the initial "objective to display" transform, or null if unspecified.
      Since:
      1.3
    • setObjectiveBounds

      public void setObjectiveBounds(Envelope visibleArea)
      Sets the data bounds to use for computing the initial value of Planar­Canvas​.objective­To­Display. Invoking this method also sets the initial objective CRS of this canvas to the CRS of given envelope.

      This method should be invoked only when new data have been loaded, or when the caller wants to discard any zoom or translation and reset the view to the given bounds. This method does not cause new repaint event; request­Repaint() must be invoked by the caller if desired.

      Parameters:
      visible­Area - bounding box in (new) objective CRS of the initial area to show, or null if unknown (in which case an identity transform will be set).
      Throws:
      Mismatched­Dimension­Exception - if the given envelope is not two-dimensional.
      See Also:
    • setObjectiveToDisplay

      public void setObjectiveToDisplay(LinearTransform newValue) throws RenderException
      Sets the conversion from objective CRS to display coordinate system. Invoking this method has the effect of changing the viewed area, the zoom level or the rotation of the map. Caller needs to invoke request­Repaint() after this method call (this is not done automatically).
      Overrides:
      set­Objective­To­Display in class Canvas
      Parameters:
      new­Value - the new objective to display conversion.
      Throws:
      Illegal­Argument­Exception - if given the transform does not have the expected number of dimensions or is not affine.
      Render­Exception - if the objective to display transform cannot be set to the given value for another reason.
    • transformObjectiveCoordinates

      public void transformObjectiveCoordinates(AffineTransform before)
      Updates the objective to display transform with the given transform in objective coordinates. This method must be invoked in the JavaFX thread. The visual is updated immediately by transforming the current image, then a more accurate image is prepared in a background thread.

      Transform events

      This method fires immediately an "objectiveToDisplay" event with Transform­Change­Event​.Reason​.INTERIM. This event does not yet reflect the state of the objective to display transform. At some arbitrary time in the future, another "objectiveToDisplay" event will occur (still in JavaFX thread) with Transform­Change­Event​.Reason​.DISPLAY_NAVIGATION (really display, not objective). That event will consolidate all INTERIM events that happened since the last non-interim event.
      Overrides:
      transform­Objective­Coordinates in class Planar­Canvas
      Parameters:
      before - coordinate conversion to apply before the current objective to display transform.
      Since:
      1.3
      See Also:
    • transformDisplayCoordinates

      public void transformDisplayCoordinates(AffineTransform after)
      Updates the objective to display transform with the given transform in pixel coordinates. This method must be invoked in the JavaFX thread. The visual is updated immediately by transforming the current image, then a more accurate image is prepared in a background thread.

      Transform events

      This method fires immediately an "objectiveToDisplay" event with Transform­Change­Event​.Reason​.INTERIM. This event does not yet reflect the state of the objective to display transform. At some arbitrary time in the future, another "objectiveToDisplay" event will occur (still in JavaFX thread) with Transform­Change­Event​.Reason​.DISPLAY_NAVIGATION. That event will consolidate all INTERIM events that happened since the last non-interim event.
      Overrides:
      transform­Display­Coordinates in class Planar­Canvas
      Parameters:
      after - coordinate conversion to apply after the current objective to display transform.
      Since:
      1.3
      See Also:
    • createRenderer

      protected abstract MapCanvas.Renderer createRenderer()
      Invoked in JavaFX thread for creating a renderer to be executed in a background thread. Subclasses shall copy in this method all Map­Canvas properties that the background thread will need for performing the rendering process.
      Returns:
      rendering process to be executed in background thread, or null if there is nothing to paint.
    • requestRepaint

      public final void requestRepaint()
      Requests the map to be rendered again, possibly with new data. Invoking this method does not necessarily causes the repaint process to start immediately. The request will be queued and executed at an arbitrary (short) time later.
    • renderingProperty

      public final ReadOnlyBooleanProperty renderingProperty()
      Returns a property telling whether a rendering is in progress. This property become true when this Map­Canvas is about to start a background thread for performing a rendering, and is reset to false after this Map­Canvas has been updated with new rendering result.
      Returns:
      a property telling whether a rendering is in progress.
    • errorProperty

      public final ReadOnlyObjectProperty<Throwable> errorProperty()
      Returns a property giving the exception or error that occurred during last rendering operation. The property value is reset to null when a rendering operation completed successfully.
      Returns:
      a property giving the exception or error that occurred during last rendering operation.
    • clearError

      protected final void clearError()
      Clears the error message in status bar.
    • errorOccurred

      protected void errorOccurred(Throwable ex)
      Sets the error property to the given value. This method is provided for subclasses that perform processing outside the Map­Canvas​.Renderer. It does not need to be invoked if the error occurred during the rendering process.

      If the error property already has a value, then the new error will be to the current error as a suppressed exception. The error property is cleared when a rendering operation completed successfully.

      Parameters:
      ex - the exception that occurred (cannot be null).
    • runAfterRendering

      protected boolean runAfterRendering(Runnable task)
      Registers a task to execute after the background thread finished its current rendering task. This method shall be invoked in JavaFX thread. If there is a rendering in progress at the time this method is invoked, then the given task is queued for execution in JavaFX thread after the rendering finished. Otherwise the given task is executed immediately.

      Exceptions are propagated if the given task has been executed immediately, or logged if execution has been deferred.

      This method is useful for subclasses when modifying the Map­Canvas state during a rendering process may cause inconsistent state.

      Parameters:
      task - the task to execute.
      Returns:
      true if the task has been executed immediately, or false if it has been queued for later execution.
      Since:
      1.2
      See Also:
    • clear

      protected void clear()
      Removes map content and clears all properties of this canvas.

      Usage

      Overriding methods in subclasses should invoke super​.clear(). Other methods should generally not invoke this method directly, and use the following code instead:
      runAfterRendering(this::clear);
      
      See Also:
    • toString

      public String toString()
      Returns a string representation of this canvas for debugging purposes. This string spans multiple lines.
      Overrides:
      to­String in class Object
      Returns:
      debug string (may change in any future version).
      Since:
      1.3
    • addPropertyChangeListener

      public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener)
      Registers a listener for the property of the given name. The listener will be notified every time that the property of the given name got a new value. If the same listener is registered twice for the same property, then it will be notified twice (this method does not perform duplication checks).
      Parameters:
      property­Name - name of the property to listen (should be one of the *_PROPERTY constants).
      listener - property listener to register.
    • removePropertyChangeListener

      public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener)
      Unregisters a property listener. The given property­Name should be the name used during listener registration. If the specified listener is not registered for the named property, then nothing happen. If the listener has been registered twice, then only one registration is removed (one registration will remain).
      Parameters:
      property­Name - name of the listened property.
      listener - property listener to unregister.
    • hasPropertyChangeListener

      protected final boolean hasPropertyChangeListener(String propertyName)
      Returns true if the given property has at least one listener.
      Parameters:
      property­Name - name of the property to test.
      Returns:
      true if the given property has at least one listener.
    • firePropertyChange

      protected void firePropertyChange(String propertyName, Object oldValue, Object newValue)
      Notifies all registered listeners that a property of the given name changed its value. The change event source will be this. It is caller responsibility to verify that the old and new values are different (this method does not check for equality).
      Parameters:
      property­Name - name of the property that changed its value.
      old­Value - the old property value (may be null).
      new­Value - the new property value (may be null).
      See Also:
    • firePropertyChange

      protected void firePropertyChange(PropertyChangeEvent event)
      Notifies all registered listeners that a property changed its value. It is caller responsibility to verify that the event source and property name are valid.
      Parameters:
      event - the event to forward. Cannot be null.
      See Also: