Class ALcdGXYAsynchronousPaintQueueManager

java.lang.Object
com.luciad.view.gxy.asynchronous.manager.ALcdGXYAsynchronousPaintQueueManager
Direct Known Subclasses:
TLcdGXYAsynchronousPaintQueueManager

public abstract class ALcdGXYAsynchronousPaintQueueManager extends Object

An abstract manager for automatically assigning ILcdGXYAsynchronousPaintQueue instances to asynchronously painted layers which do not yet have a paint queue.

When assigning paint queues to layers, you can choose to share queues, which has the following advantages:

  • buffers can be shared, reducing memory overhead and view compositing overhead. This view compositing overhead is caused by compositing the painted results of the different paint queues into one result suited for the view. (A1)
  • threads can be shared, reducing CPU overhead. On a multi-core system, one should consider having multiple paint queues to optimally use the available CPU resources. (A2)

Sharing also has some limitations:

  • layers cannot share a paint queue if they are not adjacent. This means that two layers separated by a synchronously painted layer can never share a paint queue. (L1)
  • the visual results from shared paint queues are only shown when all layers in the paint queue have been painted. This means that a slow layer will prevent a fast layer from being updated if both share the same paint queue. In such case, it might be better to use separate paint queues for the fast and slow layers. (L2)
  • real-time and background layers cannot share a paint queue (L3)

This manager offers some basic functionality and operations to find an acceptable compromise between resources and requirements. To do this, it divides a view's layers into paint blocks. A paint block is a contiguous set of layers with the same paint queue. This paint queue is only null for synchronously painted layers and asynchronous layers not managed by this manager. The manager provides methods to split, merge and replace paint blocks.

Furthermore, it automatically:

  • splits paint blocks when layers are added/moved/removed to ensure that limitations L1 and L3 are not violated.
  • informs the implementation when layers are added/moved/removed providing it with the possibility to optimize the paint blocks by using the provided paint block operations.
  • handles the possibility to insert the asynchronous layers in multiple views simultaneously.

Implementing classes should implement the following methods:

This manager has some limitations:

  • The manager will only assign paint queues to ILcdGXYAsynchronousLayerWrapper instances which are added to the view with a null queue, and not affect any ILcdGXYAsynchronousLayerWrapper which is added with a non-null queue. Even when the queue of such a wrapper is replaced by a null queue afterwards, it will not be handled by this manager.
  • It is not allowed to manually change the paint queue of ILcdGXYAsynchronousLayerWrapper instances that are managed by an instance of this class.

Warning: all methods of this class must only be called on the Event Dispatch Thread (EDT).

Since:
10.1
See Also:
  • Constructor Details

    • ALcdGXYAsynchronousPaintQueueManager

      protected ALcdGXYAsynchronousPaintQueueManager()

      Creates a new ALcdGXYAsynchronousPaintQueueManager which can manage the ILcdGXYAsynchronousPaintQueues of the ILcdGXYAsynchronousLayerWrapper instances contained in a view.

      Call setGXYView before using this manager.

  • Method Details

    • setGXYView

      public void setGXYView(ILcdGXYView aGXYView)

      Set the view for which this ALcdGXYAsynchronousPaintQueueManager should manage the paint queues.

      For the initialization of this manager, it will create separate paint queues and corresponding PaintBlocks for every asynchronous layer with null queue in the view followed by a call to the evaluateModifiedPaintBlocks method allowing to merge / split the created PaintBlocks. Once this initialization is finished, it will react on the events fired by the view and the layers.

      When this manager is already managing a view, calling this method with a non-null view is equivalent to calling this method successively with null and aGXYView.

      Calling this method with a null view, will remove all attached listeners, and clear the internal state of the manager. It will also reset all the paint queues of the layers this manager is managing to null. Therefore, if this method is called when the layers are still contained in a view, it is necessary to set new paint queues to all asynchronous layers (e.g. by creating a new ALcdGXYAsynchronousPaintQueueManager for the view) before the layers are (re)painted.

      Once this method is called on an ALcdGXYAsynchronousPaintQueueManager that particular manager can no longer be used until a new non-null view is set, since all internal state is cleared. A possible use case of calling this method with a null view is if you want to change the ALcdGXYAsynchronousPaintQueueManager for a certain view.

      Parameters:
      aGXYView - The view to manage, or null to deactivate this manager.
    • getPaintBlocks

      Returns an ordered, unmodifiable List of all PaintBlock instances. The PaintBlock at index 0 will contain the ILcdGXYLayer which has index 0 in the view.

      Returns:
      an ordered, unmodifiable List of all PaintBlock instances
    • getPaintBlock

      Returns the PaintBlock containing aLayer.

      Parameters:
      aLayer - the layer to search the PaintBlock for.
      Returns:
      the PaintBlock containing aLayer.
    • evaluateModifiedPaintBlocks

      public abstract void evaluateModifiedPaintBlocks(List<ALcdGXYAsynchronousPaintQueueManager.PaintBlock> aChangedPaintBlocks, ILcdGXYLayer aLayer)

      Method to inform the implementation that aChangedPaintBlocks should be re-evaluated. This method is called by the manager

      • when a new asynchronous layer is added to the view. For every new asynchronous layer a new paint queue is created, and a corresponding paint block is inserted. This method is then called including that new block and its neighbor blocks.
      • when a synchronous layer is added to the view, causing an existing paint block to split. Both parts of the split paint block will be included in aChangedPaintBlocks.
      • when an asynchronous layer is removed from the view. aChangedPaintBlocks will contain the PaintBlock previously containing the layer. In case the paint block is empty and removed, the adjacent PaintBlock instances will be contained in aChangedPaintBlocks.
      • when a synchronous layer is removed, and the corresponding paint block becomes empty and is removed as well. aChangedPaintBlocks will contain the adjacent PaintBlocks of the removed instance.
      • when a layer is moved from index x to index y, aChangedPaintBlocks will contain the same PaintBlocks as when the layer was removed from index x and added to index y, as described above.
      • when the numberOfCachedBackgroundLayers property of the view changes. The list of changed paint blocks will contain the paint blocks which were split due to the original value of that property, and the paint blocks which are now split due to the new value of that property.
      • when adding, removing and/or moving an ILcdLayerTreeNode with child layers, this method is only called once with the ILcdLayerTreeNode as parameter. The List of changed paint blocks will then include all relevant PaintBlocks, based on the criteria listed above.

      Typically, implementations of this method will call the split and merge methods of the manager to indicate which layers should share a paint queue.

      An example implementation of this method is one which tries to minimize the number of paint queues, by always merging adjacent paint blocks with a non-null queue.

      This method may be called from outside the manager as well, e.g. when the criteria to share a paint queue have been changed.

      Note that this method will not be called when manual changes are applied to the paint blocks. For example, calling the merge, split and/or replace methods will not trigger this method.

      Parameters:
      aChangedPaintBlocks - A List containing all PaintBlocks remaining in this manager which must be re-evaluated. In case a PaintBlock is removed or inserted, this List will also include the neighbor PaintBlock instances. The paint queue of these PaintBlocks will never be null. The PaintBlocks in this List are ordered in the same way as in the getPaintBlocks() List
      aLayer - The ILcdGXYLayer in which the change, triggering the call of this method, occurred, or null when the change was not triggered by a specific layer.
    • createAsynchronousPaintQueue

      protected abstract ILcdGXYAsynchronousPaintQueue createAsynchronousPaintQueue(List<ILcdGXYAsynchronousLayerWrapper> aLayers)

      Factory method to create a new ILcdGXYAsynchronousPaintQueue that will be used by aLayers. The returned ILcdGXYAsynchronousPaintQueue must be a new instance, and must not be in use by any existing PaintBlock.

      This method should always return a non-null paint queue which may be used by all layers in aLayers. Either aLayers will only contain one ILcdGXYAsynchronousLayerWrapper, or a set of ILcdGXYAsynchronousLayerWrappers which were already part of one PaintBlock with a non-null paint queue. Therefore this method should always be able to return a non-null paint queue.

      The manager may wrap paint queues, so it may be that the returned ILcdGXYAsynchronousPaintQueue is not set directly as paint queue on the layers.

      The manager calls this method:

      • Every time an asynchronous layer is added to the view, or moved outside its current paint block. In such cases, the evaluateModifiedPaintBlocks can decided to merge the new paint queue immediately with an existing one. Therefore it is recommended to return ILcdGXYAsynchronousPaintQueue instances which only allocate resources (e.g. a buffer and a separate Thread) when needed, and not on creation.
      • From the merge and split methods when no paint queue was specified for the resulting paint block.
      Parameters:
      aLayers - the ILcdGXYAsynchronousLayerWrappers that will use the returned ILcdGXYAsynchronousPaintQueue
      Returns:
      a new ILcdGXYAsynchronousPaintQueue instance. Must not be null
    • splitPaintBlockSFCT

      public final ALcdGXYAsynchronousPaintQueueManager.PaintBlock splitPaintBlockSFCT(ALcdGXYAsynchronousPaintQueueManager.PaintBlock aPaintBlockToSplitSFCT, int aFirstBlockSize)

      Split aPaintBlockToSplitSFCT in two separate PaintBlock instances: the existing PaintBlock containing the first aFirstBlockSize original ILcdGXYLayers, and a new PaintBlock containing all remaining ILcdGXYLayers.

      The newly created PaintBlock will call the createAsynchronousPaintQueue method to obtain its paint queue..

      Parameters:
      aPaintBlockToSplitSFCT - The PaintBlock that will be split. Must have a non-null paint queue.
      aFirstBlockSize - The size of the first block. Must be greater than 0 and smaller then aPaintBlockToSplit.getLayers().size()
      Returns:
      the newly created PaintBlock instance
    • canMergePaintBlocks

      public boolean canMergePaintBlocks(ALcdGXYAsynchronousPaintQueueManager.PaintBlock aPaintBlock, ALcdGXYAsynchronousPaintQueueManager.PaintBlock aAdjacentPaintBlock)

      Utility method to verify the prerequisites listed in the mergePaintBlocks method. Returns true when the mergePaintBlocks method can be called with the same arguments, false otherwise.

      Parameters:
      aPaintBlock - a PaintBlock
      aAdjacentPaintBlock - an adjacent PaintBlock
      Returns:
      true when aPaintBlock and aAdjacentPaintBlock can be merged, false otherwise
      See Also:
    • mergePaintBlocksSFCT

      public final void mergePaintBlocksSFCT(ALcdGXYAsynchronousPaintQueueManager.PaintBlock aPaintBlockSFCT, ALcdGXYAsynchronousPaintQueueManager.PaintBlock aAdjacentPaintBlock)

      Merge the layers of aPaintBlockSFCT and aAdjacentPaintBlock into aPaintBlockSFCT.

      Merging two paint blocks is only possible if:

      • the two PaintBlock instances are adjacent
      • the two PaintBlock instances have a non-null paint queue.
      • merging the two PaintBlocks will not result in a paint queue which is used by background and non-background layers (see ILcdGXYView#getNumberOfCachedBackgroundLayers()).

      The prerequisites of this method can be verified by using the canMergePaintBlocks method. It is up to the user of this method to verify those prerequisites before calling this method.

      Parameters:
      aPaintBlockSFCT - The PaintBlock to which all layers of aAdjacentPaintBlock will be added.
      aAdjacentPaintBlock - an adjacent PaintBlock
      See Also:
    • replacePaintBlockSFCT

      Replace aPaintBlock by a new PaintBlock with aPaintQueue as paint queue.

      It is not possible to replace a null queue with a non-null queue. When the paint queue of aPaintBlock is not null and aPaintQueue is null, the createAsynchronousPaintQueue method will be used to create a new paint queue.

      This method will have no effect when aPaintQueue is the paint queue of aPaintBlock, and just return aPaintBlock.

      Parameters:
      aPaintBlock - The PaintBlock to replace.
      aPaintQueue - The ILcdGXYAsynchronousPaintQueue for the new PaintBlock. Must not be used by any other PaintBlock, and can only be null if the paint queue of aPaintBlock is null.
      Returns:
      The new PaintBlock, or aPaintBlock in case aPaintQueue is already the paint queue of aPaintBlock
    • getGXYView

      public ILcdGXYView getGXYView()
      Returns the view for which this ALcdGXYAsynchronousPaintQueueManager is created.
      Returns:
      the view for which this ALcdGXYAsynchronousPaintQueueManager is created.