Class CanvasFollower
- All Implemented Interfaces:
PropertyChangeListener
,EventListener
,Disposable
Listeners
CanvasFollower
listeners need to be registered explicitly by a call to the initialize()
method.
The dispose()
convenience method is provided for unregistering all those listeners.
The listeners registered by this class implement an unidirectional binding:
changes in source are applied on target, but not the converse.
Multi-threading
This class is not thread-safe. All events should be processed in the same thread.- Since:
- 1.3
- Version:
- 1.3
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate boolean
Whether a change is in progress.private boolean
Whether to disable the following of source canvas.private org.opengis.referencing.operation.MathTransform2D
Conversions from source display coordinates to target display coordinates.private byte
Whether an attempt to computedisplayTransform
has already been done.private static final byte
Enumeration values fordisplayTransformStatus
andobjectiveTransformStatus
.private boolean
Whether to follow the source canvas in "real world" coordinates.private boolean
Whether listeners have been registered.private org.opengis.referencing.operation.MathTransform
Conversions from source objective coordinates to target objective coordinates.private byte
Whether an attempt to computeobjectiveTransform
has already been done.private static final byte
Enumeration values fordisplayTransformStatus
andobjectiveTransformStatus
.protected final PlanarCanvas
The canvas which is the source of zoom, translation or rotation events.protected final PlanarCanvas
The canvas on which to apply the change of zoom, translation or rotation.private static final byte
Enumeration values fordisplayTransformStatus
andobjectiveTransformStatus
.private static final byte
Enumeration values fordisplayTransformStatus
andobjectiveTransformStatus
. -
Constructor Summary
ConstructorsConstructorDescriptionCanvasFollower
(PlanarCanvas source, PlanarCanvas target) Creates a new listener for synchronizing "objective to display" transform changes between the specified canvas. -
Method Summary
Modifier and TypeMethodDescriptionprivate static void
canNotCompute
(String caller, Exception e) Invoked when theobjectiveTransform
transform cannot be computed, or when an optional information required for that transform is missing.void
dispose()
Removes all listeners documented in theinitialize()
method.protected boolean
filter
(TransformChangeEvent event) Returnstrue
if this listener should replicate the following changes on the target canvas.private boolean
findObjectiveTransform
(String caller) Optional<org.opengis.referencing.operation.MathTransform2D>
Returns the transform from source display coordinates to target display coordinates.boolean
Returns whether this instance is following changes in "real world" coordinates.Returns the display coordinates of the Point Of Interest (POI) in source canvas.org.opengis.geometry.DirectPosition
Returns the objective coordinates of the Point Of Interest (POI) in source canvas.void
Registers all listeners needed by this object.boolean
Returnstrue
if this object stopped to replicate changes from source canvas to target canvas.void
Invoked when the objective CRS, zoom, translation or rotation changed on a map that we are tracking.void
setDisabled
(boolean stop) Sets whether to stop to replicate changes from source canvas to target canvas.void
setFollowRealWorld
(boolean real) Sets whether this instance should following changes in "real world" coordinates.protected void
transformDisplayCoordinates
(TransformChangeEvent event, AffineTransform after) Invoked bypropertyChange(PropertyChangeEvent)
for updating the transform of the target canvas in display units (typically pixels).protected void
Invoked after the source "objective to display" transform has been updated.protected void
Invoked after the target "objective to display" transform has been updated.protected void
transformObjectiveCoordinates
(TransformChangeEvent event, AffineTransform before) Invoked bypropertyChange(PropertyChangeEvent)
for updating the transform of the target canvas in units of the objective CRS.
-
Field Details
-
source
The canvas which is the source of zoom, translation or rotation events. -
target
The canvas on which to apply the change of zoom, translation or rotation. -
initialized
private boolean initializedWhether listeners have been registered. -
disabled
private boolean disabledWhether to disable the following of source canvas. Other events such as changes of objective CRS are still listened in order to update the fields of this class. -
followRealWorld
private boolean followRealWorldWhether to follow the source canvas in "real world" coordinates. Iffalse
, displacements will be followed in pixel coordinates instead. -
displayTransform
private org.opengis.referencing.operation.MathTransform2D displayTransformConversions from source display coordinates to target display coordinates. Computed when first needed, and recomputed when the objective CRS or the "display to objective" transform change.- See Also:
-
objectiveTransform
private org.opengis.referencing.operation.MathTransform objectiveTransformConversions from source objective coordinates to target objective coordinates. Computed when first needed, and recomputed when the objective CRS changes. Anull
value means that no change is needed or cannot be done.- See Also:
-
displayTransformStatus
private byte displayTransformStatusWhether an attempt to computedisplayTransform
has already been done. ThedisplayTransform
field may still be null if the attempt failed. Value can beVALID
,OUTDATED
,UNKNOWN
orERROR
. -
objectiveTransformStatus
private byte objectiveTransformStatusWhether an attempt to computeobjectiveTransform
has already been done. Note that theobjectiveTransform
field can be up-to-date andnull
. Value can beVALID
,OUTDATED
,UNKNOWN
orERROR
.- See Also:
-
VALID
private static final byte VALIDEnumeration values fordisplayTransformStatus
andobjectiveTransformStatus
.- See Also:
-
OUTDATED
private static final byte OUTDATEDEnumeration values fordisplayTransformStatus
andobjectiveTransformStatus
.- See Also:
-
UNKNOWN
private static final byte UNKNOWNEnumeration values fordisplayTransformStatus
andobjectiveTransformStatus
.- See Also:
-
ERROR
private static final byte ERROREnumeration values fordisplayTransformStatus
andobjectiveTransformStatus
.- See Also:
-
changing
private boolean changingWhether a change is in progress. This is for avoiding never-ending loop if a bidirectional mapping or a cycle exists (A → B → C → A).
-
-
Constructor Details
-
CanvasFollower
Creates a new listener for synchronizing "objective to display" transform changes 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
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
-
initialize
public void initialize()Registers all listeners needed by this object. This method must be invoked at least once after construction, but not necessarily immediately after (it is okay to defer until first needed). The default implementation registers the following listeners: This method is idempotent (it is okay to invoke it twice).- See Also:
-
isDisabled
public boolean isDisabled()Returnstrue
if this object stopped to replicate changes from source canvas to target canvas. Iftrue
, this object continues to listen to changes in order to keep its state consistent, but does not replicate those changes on the target canvas.A non-initialized object is considered disabled.
- Returns:
- whether this object stopped to replicate changes from source canvas to target canvas.
-
setDisabled
public void setDisabled(boolean stop) Sets whether to stop to replicate changes from source canvas to target canvas. It does not stop this object to listen to events, because it is necessary for keeping its state consistent.- Parameters:
stop
-true
for stopping to replicate changes from source canvas to target canvas.
-
getFollowRealWorld
public boolean getFollowRealWorld()Returns whether this instance is following changes in "real world" coordinates. Iftrue
(the default value), then changes applied on the source canvas and converted into changes to apply on thetarget
canvas in such a way that the two canvas got the same translations in real world units. It may result in a different amount of pixels is the two canvas have different zoom level, or a different direction if a canvas is rotated relatively to the other canvas.- Returns:
- whether this instance is following changes in "real world" coordinates.
-
setFollowRealWorld
public void setFollowRealWorld(boolean real) Sets whether this instance should following changes in "real world" coordinates. The default value istrue
. If this is set tofalse
, then the same changes in pixel coordinates will be applied on canvas regardless the difference in rotation or zoom level.- Parameters:
real
- whether this instance should following changes in "real world" coordinates.
-
getSourceObjectivePOI
public org.opengis.geometry.DirectPosition getSourceObjectivePOI()Returns the objective coordinates of the Point Of Interest (POI) in source canvas. This information is used when the source and target canvases do not use the same CRS. Changes in "real world" coordinates on the target canvas are guaranteed to reflect the changes in "real world" coordinates of the source canvas at that location only. At all other locations, the "real world" coordinate changes may differ because of map projection deformations.The default implementation computes the value from
getSourceDisplayPOI()
if present, or fallback onsource.getPointOfInterest(true)
otherwise. Subclasses can override this method for using a different point of interest.The CRS associated to the position shall be
Canvas.getObjectiveCRS()
. For performance reason, this is not verified by thisCanvasFollower
class.- Returns:
- objective coordinates in source canvas where displacements, zooms and rotations applied on the source canvas should be mirrored exactly on the target canvas.
- See Also:
-
getSourceDisplayPOI
Returns the display coordinates of the Point Of Interest (POI) in source canvas. This method provides the same information thangetSourceObjectivePOI()
, but in units that are more convenient for expressing the location of mouse cursor for example.The default implementation returns an empty value.
- Returns:
- display coordinates in source canvas where displacements, zooms and rotations applied on the source canvas should be mirrored exactly on the target canvas.
-
getDisplayTransform
Returns the transform from source display coordinates to target display coordinates. This transform may change every time that a zoom; translation or rotation is applied on at least one canvas. The transform may be absent if an error prevent to compute it, for example is no coordinate operation has been found between the objective CRS of the source and target canvases.- Returns:
- transform from source display coordinates to target display coordinates.
-
propertyChange
Invoked when the objective CRS, zoom, translation or rotation changed on a map that we are tracking. If the event is an instance ofTransformChangeEvent
, then this method applies the same change on the target canvas.This method delegates part of its work to the following methods, which can be overridden for altering the changes:
transformObjectiveCoordinates(TransformChangeEvent, AffineTransform)
if following real world coordinates.transformDisplayCoordinates(TransformChangeEvent, AffineTransform)
if following pixel coordinates instead of real world.transformedSource(TransformChangeEvent)
after the change has been applied on source.transformedTarget(TransformChangeEvent)
after the change has been applied on target.
- Specified by:
propertyChange
in interfacePropertyChangeListener
- Parameters:
event
- a change in the canvas that this listener is tracking.
-
filter
Returnstrue
if this listener should replicate the following changes on the target canvas. The default implementation returnstrue
if the transform reason isTransformChangeEvent.Reason.OBJECTIVE_NAVIGATION
orTransformChangeEvent.Reason.DISPLAY_NAVIGATION
. -
transformObjectiveCoordinates
Invoked bypropertyChange(PropertyChangeEvent)
for updating the transform of the target canvas in units of the objective CRS. The target canvas is updated by this method as if the given transform was applied before its current objective to display transform.The default implementation delegates to
PlanarCanvas.transformObjectiveCoordinates(AffineTransform)
. Subclasses can override if they need to transform additional data. -
transformDisplayCoordinates
Invoked bypropertyChange(PropertyChangeEvent)
for updating the transform of the target canvas in display units (typically pixels). The target canvas is updated by this method as if the given transform was applied after its current objective to display transform.The default implementation delegates to
PlanarCanvas.transformDisplayCoordinates(AffineTransform)
. Subclasses can override if they need to transform additional data. -
transformedSource
Invoked after the source "objective to display" transform has been updated. This method is invoked automatically bypropertyChange(PropertyChangeEvent)
. The default implementation does nothing. Subclasses can override if they need to transform additional data.- Parameters:
event
- the change which has been applied on the source canvas.
-
transformedTarget
Invoked after the target "objective to display" transform has been updated. This method is invoked automatically bypropertyChange(PropertyChangeEvent)
. The default implementation does nothing. Subclasses can override if they need to transform additional data.- Parameters:
event
- the change which has been applied on the target canvas.
-
findObjectiveTransform
Finds the transform to use for converting changes from source canvas to target canvas. This method should be invoked only ifobjectiveTransformStatus
is notVALID
. After this method returned,objectiveTransform
contains the transform to use, which may benull
if none.- Parameters:
caller
- the public method which is invoked this private method. Used only for logging purposes.- Returns:
- whether a transform has been computed.
-
canNotCompute
Invoked when theobjectiveTransform
transform cannot be computed, or when an optional information required for that transform is missing. This method assumes that the public caller (possibly indirectly) ispropertyChange(PropertyChangeEvent)
.- Parameters:
caller
- the public method which is invoked this private method. Used only for logging purposes.e
- the exception that occurred.
-
dispose
public void dispose()Removes all listeners documented in theinitialize()
method. This method should be invoked whenCanvasFollower
is no longer needed, in order to avoid memory leak.- Specified by:
dispose
in interfaceDisposable
- See Also:
-