Interface ILcdGXYAsynchronousLayerWrapper
- All Superinterfaces:
ILcdGXYLayer
,ILcdLayer
,ILcdPropertyChangeSource
,ILcdSelection<Object>
,Serializable
- All Known Implementing Classes:
TLcdGXYAsynchronousEditableLabelsLayerTreeNodeWrapper
,TLcdGXYAsynchronousEditableLabelsLayerWrapper
,TLcdGXYAsynchronousLayerTreeNodeWrapper
,TLcdGXYAsynchronousLayerWrapper
,TLcdGXYLspAsynchronousLayerTreeNodeWrapper
,TLcdGXYLspAsynchronousLayerWrapper
ILcdGXYLayer
.
Instead of painting synchronously in the event dispatch thread, this wrapper delegates its paint requests to an
ILcdGXYAsynchronousPaintQueue
. The paint queue has its own asynchronous thread in which it paints
the wrapped layer. This image will then be painted again in the event dispatch thread.
Making a layer paint itself asynchronously
To create the appropriate layer wrapper for your layer you can simply call thecreate(com.luciad.view.gxy.ILcdGXYLayer)
method.
Considerations
When using asynchronous layer painting, please take the following into consideration:
- retrieving painters or editors from this wrapper may cause the current thread to block while
asynchronous painting is ongoing. This includes synchronous view label decluttering algorithms
(see
TLcdGXYAsynchronousViewLabelPainterWrapper
); - the wrapped layer's paint method should take care when waiting for another thread: if that thread in turn waits for asynchronous painting to complete, a deadlock will occur;
- paint queue sharing may affect layer ordering (see ILcdGXYAsynchronousPaintQueue implementations);
- in order to protect its state, the wrapped layer should not be manipulated directly.
Accessing the wrapped layer
This interface offers the following invocation methods to access and manipulate the wrapped layer's state:
invokeAndWaitOnGXYLayer(com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerRunnable)
for safe, blocked access;invokeLaterOnGXYLayer(com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerRunnable)
to safe, asynchronous access;invokeNowOnGXYLayer(com.luciad.view.gxy.asynchronous.ILcdGXYAsynchronousLayerRunnable)
for synchronous access that does not interfere with asynchronous painting.
Synchronizing the layer wrapper and the wrapped layer
If the wrapper itself exposes the wrapped layer's state (i.e. by implementing some interface),
this state must be duplicated and synchronized.
For example, if someone calls ILcdGXYAsynchronousLayerWrapper#setVisible( false )
,
it is expected that the wrapped layer will also change its visibility.
Here, the layer wrapper's responsibility is to duplicate and track state changes (i.e. what to synchronize).
The paint queue determines a safe point in time for synchronizing these changes (i.e. when to synchronize).
The paint queue accesses this functionality through the getSynchronousGXYLayerChangeTracker()
and
getAsynchronousGXYLayerChangeTracker()
methods.
The former method retrieves and applies changes for this wrapper,
the latter retrieves and applies changes for the wrapped layer.
To illustrate the state synchronization mechanism, consider a visibility change in the layer wrapper:
- ILcdGXYAsynchronousLayerWrapper#setVisible(false) is called, e.g. by the user clicking in a layer control
- the layer wrapper fires a property change causing a repaint of the view
- the paint queue is asked to paint the layer
- the paint queue retrieves the layer wrapper's state changes in the EDT
by calling
ILcdGXYAsynchronousLayerWrapper#getSynchronousGXYLayerChangeTracker#getChanges()
. Here, the changed state will consist of the change in visibility. - the paint queue applies the visibility state change to the wrapped layer in the asynchronous paint thread
by calling
ILcdGXYAsynchronousLayerWrapper#getAsynchronousGXYLayerChangeTracker#applyChanges()
. Hence, the wrapped layer will become invisible. - the paint is executed in the asynchronous paint thread, yielding an empty (invisible) result.
- the paint queue retrieves the layer's state changes (if any) in the asynchronous paint thread by calling
ILcdGXYAsynchronousLayerWrapper#getAsynchronousGXYLayerChangeTracker#getChanges()
- the paint queue applies these state changes to the layer wrapper in the EDT by calling
ILcdGXYAsynchronousLayerWrapper#getSynchronousGXYLayerChangeTracker#applyChanges()
- the view is informed of the asynchronous paint and repaints itself to display the results
- Since:
- 7.2
- See Also:
-
Field Summary
-
Method Summary
Modifier and TypeMethodDescriptioncreate
(ILcdGXYLayer aLayer) Utility method to wrapaLayer
with a defaultILcdGXYAsynchronousLayerWrapper
implementation.Returns a state change synchronizer for the wrapped layer.Returns the paint queue handling the asynchronous paints.Returns the layer that contains the actual paint logic.Returns a state change synchronizer for this wrapper.void
invokeAndWaitOnGXYLayer
(ILcdGXYAsynchronousLayerRunnable aInvocation) Executes the given layer runnable so that the invocation does not interfere with the asynchronous painting.void
invokeLaterOnGXYLayer
(ILcdGXYAsynchronousLayerRunnable aInvocation) Executes the given layer runnable so that the invocation does not interfere with the asynchronous painting.void
Executes the given layer runnable so that the invocation does not interfere with the asynchronous painting.void
invokeNowOnGXYLayer
(ILcdGXYAsynchronousLayerRunnable aInvocation) Executes the given layer runnable so that the invocation does not interfere with state synchronization.boolean
Returns whether the wrapped layer is configured to be painted asynchronously.void
setAsynchronous
(boolean aAsynchronous) Disables or enables the asynchronous drawing.void
Sets the paint queue to delegate asynchronous paint requests to.Methods inherited from interface com.luciad.view.gxy.ILcdGXYLayer
applyOnInteract, getBounds, getGXYEditor, getGXYLabelPainter, getGXYPainter, getGXYPen, getLabelMapScaleRange, getLabelScaleRange, getMapScaleRange, getModelXYWorldTransfoClass, getScaleRange, isLabeled, isLabeledSupported, paint, setLabeled, stopPainting
Methods inherited from interface com.luciad.view.ILcdLayer
clearSelection, fireCollectedSelectionChanges, getIcon, getLabel, getModel, isEditable, isEditableSupported, isSelectable, isSelectableSupported, isVisible, selectObject, setEditable, setIcon, setLabel, setSelectable, setVisible
Methods inherited from interface com.luciad.util.ILcdPropertyChangeSource
addPropertyChangeListener, removePropertyChangeListener
Methods inherited from interface com.luciad.util.ILcdSelection
addSelectionListener, getSelectedObjects, getSelectionCount, isSelected, removeSelectionListener, selectedObjects
-
Method Details
-
getGXYAsynchronousPaintQueue
ILcdGXYAsynchronousPaintQueue getGXYAsynchronousPaintQueue()Returns the paint queue handling the asynchronous paints.- Returns:
- a paint queue to which the paint requests are delegated
-
setGXYAsynchronousPaintQueue
Sets the paint queue to delegate asynchronous paint requests to. Paint queues can be shared between multiple layer wrappers. This is even advised, as each paint queue uses memory for buffering the asynchronously generated images.- Parameters:
aQueue
- the asynchronous paint queue responsible for executing the paint calls.
-
getGXYLayer
ILcdGXYLayer getGXYLayer()Returns the layer that contains the actual paint logic. Note that it is generally unsafe to access the layer while it is painting itself, in the painting thread of the paint queue. In addition, the properties of the layer must not yet have been propagated from this layer wrapper. The methodsinvokeAndWaitOnGXYLayer(ILcdGXYAsynchronousLayerRunnable)
andinvokeLaterOnGXYLayer(ILcdGXYAsynchronousLayerRunnable)
provide safe alternatives.- Returns:
- the wrapped layer
-
setAsynchronous
Disables or enables the asynchronous drawing.- Parameters:
aAsynchronous
- if false, paints synchronously, if true, paints asynchronously- Throws:
InterruptedException
- when the thread is interrupted while waiting for the asynchronous paint to complete
-
isAsynchronous
boolean isAsynchronous()Returns whether the wrapped layer is configured to be painted asynchronously.- Returns:
- whether the asynchronous drawing is enabled
-
invokeAndWaitOnGXYLayer
void invokeAndWaitOnGXYLayer(ILcdGXYAsynchronousLayerRunnable aInvocation) throws InterruptedException Executes the given layer runnable so that the invocation does not interfere with the asynchronous painting. The invocation is executed in the view's paint thread (typically the EDT). The method waits until the invocation has stopped.- Parameters:
aInvocation
- the invocation to run. The invocation will pass the original layer.- Throws:
InterruptedException
- when the thread is interrupted while waiting for the asynchronous painting to complete
-
invokeLaterOnGXYLayer
Executes the given layer runnable so that the invocation does not interfere with the asynchronous painting. The invocation is executed in the asynchronous paint thread if the layer is painted asynchronously, and executed in the current thread otherwise. In the former case, the method returns immediately.The invocation should take care when waiting for another thread: if that thread in turn waits for asynchronous painting to complete, a deadlock will occur.
To avoid concurrency problems with property change listeners, layer property changes will be fired on the event dispatch thread, not on the asynchronous paint thread.
- Parameters:
aInvocation
- the invocation to run. The invocation will pass the original layer.
-
invokeLaterOnGXYLayerInEDT
Executes the given layer runnable so that the invocation does not interfere with the asynchronous painting. The invocation is executed in the event dispatch thread. The method always returns immediately.- Parameters:
aInvocation
- the invocation to run. The invocation will pass the original layer.
-
invokeNowOnGXYLayer
Executes the given layer runnable so that the invocation does not interfere with state synchronization. The invocation is executed in the caller's thread. The method waits until the invocation has stopped. During the invocation, asynchronous painting may occur, so care is advised.- Parameters:
aInvocation
- the invocation to run. The invocation will pass the original layer.
-
getSynchronousGXYLayerChangeTracker
ILcdGXYLayerChangeTracker getSynchronousGXYLayerChangeTracker()Returns a state change synchronizer for this wrapper. The wrapper's changes will be applied to the wrapped layer before each asynchronous paint, using the asynchronous wrapper.- Returns:
- a synchronizer tracking changes for this wrapper. To protect this wrapper's state, the tracker should only be used in the synchronous thread, i.e. the event dispatch thread.
-
getAsynchronousGXYLayerChangeTracker
ILcdGXYLayerChangeTracker getAsynchronousGXYLayerChangeTracker()Returns a state change synchronizer for the wrapped layer. The changes will be applied after each asynchronous paint, using the synchronous tracker.- Returns:
- a synchronizer tracking changes for the wrapped layer. To protect the wrapped layer's state, the tracker should only be used in the asynchronous thread, i.e. the paint thread.
-
create
Utility method to wrap
aLayer
with a defaultILcdGXYAsynchronousLayerWrapper
implementation. The used wrapper depends on the interfaces thataLayer
implements.This method supports:
- Single
ILcdGXYLayer
instances. - GXY layer tree structures with
ILcdLayerTreeNode
instances. ILcdGXYEditableLabelsLayer
implementations: the returned asynchronous wrapper will also implement theILcdGXYEditableLabelsLayer
interface.
Any other interfaces the
ILcdGXYLayer
implements will not be exposed by the returned asynchronous wrapper.- Parameters:
aLayer
- The layer (structure) to wrap- Returns:
- A layer (structure) wrapped with asynchronous wrappers.
- Since:
- 2019.0
- Single
-