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. The reset to false happens in all cases: after successful completion, failure or cancellation.
      See Also:
    • positionalAccuracy

      public final ReadOnlyObjectProperty<Length> positionalAccuracyProperty
      Returns a property which gives an estimation of positional accuracy, typically in metres. The positions of pixels or features rendered on the map may have limited accuracy when the positions are computed by a coordinate transformations. The position may also be inaccurate because of approximation applied for faster rendering. The property value may be null if the accuracy is not specified.

      Usage example

      The Status­Bar​.lowest­Accuracy property can bind to this property for reporting the positional accuracy on the status bar. This is done automatically by the Status­Bar​.track(Map­Canvas) method.
      Since:
      1.7
      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.

      See Also:
    • 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 for a default transform showing fully the map.
      Throws:
      Mismatched­Dimension­Exception - if the given grid geometry is not two-dimensional.
      Since:
      1.3
      See Also:
    • getContentIdentifier

      public Optional<Identifier> getContentIdentifier()
      Returns an identifier of the rendered data. The identifier should be unique on a best effort basis, but this is not a strict requirement. It can be, for example, derived from the resource identifier.
      Returns:
      an identifier of the rendered data.
      Since:
      1.7
    • usingFixedTransform

      public MapCanvas.StaticGraphics usingFixedTransform()
      Returns a pane where graphics can be added as if the objective to display transform was static. The returned object takes a snapshot of the transform at the time when this method has been invoked. It allows to show shapes more easily than adding them directly as floating­Pane children, but at the expanse of quality. This compromise is better suited to animation effects such as Fade­Transition and when shapes are removed from the children list after a few seconds.
      Returns:
      a pane where to add shapes without the need to track navigation events after this method call.
      Since:
      1.7
    • reset

      public void reset()
      Resets the map view to its default zoom level and default position with no rotation. Contrary to clear(), this method does not remove the map content.
      See Also:
    • 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 sends immediately a Transform­Change­Event with the "objectiveToDisplay" property name and Reason​.INTERIM. The interim reason means that the change is reflected visually but not yet in the objective to display transform. A short time after this method call, the objective to display transform is effectively updated and another "objectiveToDisplay" event will be sent in the JavaFX thread, but with Reason​.DISPLAY_NAVIGATION. Note that the latter event really expresses the change in display units, not in the objective units of the transform given to this method. 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 sends immediately a Transform­Change­Event with the "objectiveToDisplay" property name and Reason​.INTERIM. The interim reason means that the change is reflected visually but not yet in the objective to display transform. A short time after this method call, the objective to display transform is effectively updated and another "objectiveToDisplay" event will be sent in the JavaFX thread, but with 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:
    • setPositionalAccuracy

      protected void setPositionalAccuracy(Quantity<Length> accuracy)
      Sets an estimation of the positional accuracy of the pixels or features that are rendered on the map. This method sets the value returned by the read-only positional accuracy property. The value should be non-zero when the positions are computed by a coordinate transformations.

      This method may be invoked in the commit() method of the renderer returned by create­Renderer().

      Parameters:
      accuracy - an estimation of positional accuracy, or null if none.
      Since:
      1.7
      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. The reset to false happens in all cases: after successful completion, failure or cancellation.
      Returns:
      a property telling whether a rendering is in progress.
    • positionalAccuracyProperty

      public final ReadOnlyObjectProperty<Length> positionalAccuracyProperty()
      Returns a property which gives an estimation of positional accuracy, typically in metres. The positions of pixels or features rendered on the map may have limited accuracy when the positions are computed by a coordinate transformations. The position may also be inaccurate because of approximation applied for faster rendering. The property value may be null if the accuracy is not specified.

      Usage example

      The Status­Bar​.lowest­Accuracy property can bind to this property for reporting the positional accuracy on the status bar. This is done automatically by the Status­Bar​.track(Map­Canvas) method.
      Returns:
      a property giving an estimation of positional accuracy.
      Since:
      1.7
      See Also:
    • 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 the status bar.
      See Also:
    • 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 the content shown by this canvas while keeping the listeners. This method is invoked for discarding the content currently shown by the canvas, while keeping this Map­Canvas instance for showing new content later. Invoking this method may help to release memory when the map is no longer shown.

      Subclasses should override this method for cleaning their fields. Implementations in subclasses shall invoke super​.clear().

      This method should usually not be invoked directly. Instead, a recommended usage pattern is as below. The call to request­Repaint() can be omitted if this Map­Canvas is removed from the tree of nodes shown by JavaFX.

      runAfterRendering(() -> {
          clear();
          requestRepaint();
      });
      
      Overrides:
      clear in class Canvas
      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