Class ALspSwingLabelStyler

All Implemented Interfaces:
ILspStyler

public abstract class ALspSwingLabelStyler extends ALspLabelStyler

Styler that can use Swing components as label content.

Use getComponentStyle in the implementation of your style method.

This styler makes sure that the used Swing components are painted on the Event Dispatch Thread. Because of this, the styler can only be used for awt views.

Implement getComponent to specify the component to use. You can re-use the same component instance for different domain objects, similar to Swing cell renderers.

Call componentChanged whenever the component for a domain object has become invalid and needs to be updated.

The following code shows how this class can be implemented:


 private static class ComponentStyler extends ALspSwingLabelStyler {

   private SwingComponent fSwingComponent = ...;

   @Override
   public void style( Collection<?> aObjects, ALspLabelStyleCollector aStyleCollector, TLspContext aContext ) {
     for ( Object object : aObjects ) {
       // Retrieve the style that represents the Swing component and use it
       ALspStyle componentStyle = getComponentStyle( object, SUBLABEL_ID, aContext );
       // The returned style can be null initially, until the component been rendered to in icon. A style change event
       // will be fired automatically when this happens. In subsequent calls, the style will not be null anymore.
       if ( componentStyle != null ) {
         aStyleCollector.object( object ).label( SUBLABEL_ID ).styles( styles ).submit();
       }
     }
   }

   @Override
   protected JComponent getComponent( Object aObject, Object aSublabelId, TLspContext aContext ) {
     // Return the component to use for the given label
     fSwingComponent.adjustForLabel( aObject, aSubLabelId );
     return fSwingComponent;
   }
 }
 
Since:
2012.0
  • Constructor Details

    • ALspSwingLabelStyler

      protected ALspSwingLabelStyler()

      Creates a new ALspSwingLabelStyler that can be used to paint labels using Swing components. When this styler is used, the components are not added to the swing hierarchy. They are painted offscreen instead, and painted using a regular label painter.

      Note that labels are not updated automatically when the content changes. To do this, it is required to call componentChanged. Alternatively, it is possible to use the other constructor with the last argument set to true. In that case, the componentChanged method is called automatically when model changes occur.

    • ALspSwingLabelStyler

      protected ALspSwingLabelStyler(ALspInteractiveLabelProvider aInteractiveLabelProvider, TLspPaintRepresentationState aPaintRepresentationState, boolean aInvalidateOnModelChangeEvent)

      Creates a new ALspSwingLabelStyler that can be used for interactive labels (see TLspInteractiveLabelsController).

      When TLspInteractiveLabelsController makes a label interactive, it adds a Swing label to the Swing hierarchy. When this happens, a problem occurs: the label painter doesn't know anything about the interactive label, so it also paints a label for the same object. Because of this, the label would be painted twice. Once as a Swing component in the Swing hierarchy, and once by the label painter. This constructor solves this problem by making sure that the label painter paints an empty (completely transparent) label when a label becomes interactive. It knows when a label becomes interactive by registering a ILspInteractiveLabelListener to the given ALspInteractiveLabelProvider.

      It is possible to make sure that labels are invalidated on model changes by passing true to this constructor.

      It is possible to make sure that labels are invalidated on model changes by passing true to this constructor. In that case, the shouldInvalidateLabel method is called as well. This method can be used to filter out changes that are not needed, and can thus be used to improve the performance of this styler. When aInvalidateOnModelChangeEvent is false, and the content of the label changes at runtime, the componentChanged method should be called manually.

      Parameters:
      aInteractiveLabelProvider - the interactive label provider. Can be null if no interactive labels are used.
      aPaintRepresentationState - the paint representation and state for which this styler is used. This argument should not be null when aInteractiveLabelProvider is not null, or when aInvalidateOnModelChangeEvent is true.
      aInvalidateOnModelChangeEvent - true to invalidate labels on model changes.
  • Method Details

    • shouldInvalidateLabel

      protected boolean shouldInvalidateLabel(Object aObject, Object aSubLabelID, TLspContext aContext)

      This method indicates if the content of the given label should be invalidated. Note that this method is only called when using the ALspSwingLabelStyler(ALspInteractiveLabelProvider, TLspPaintRepresentationState, boolean) constructor with true as argument. In that case, this method will be called when model changes occur.

      This is useful to improve the performance of ALspSwingLabelStyler when the content of the labels changes at runtime. It allows to filter out changes that don't affect the content of the label. This is useful for moving tracks which for example display their height and their callsign. The callsign doesn't change, but the height might change sometimes. When the track moves, its location changes all the time, resulting in a model change, but the height doesn't necessarily change, so it shouldn't be necessary to calculate the content of the label.

      When this method returns true, this class will invalidate the content of the given label. It will also call ALspInteractiveLabelProvider#updateInteractiveLabel() when the given label is interactive.

      By default, this method always returns true.

      Parameters:
      aObject - the domain object of the label
      aSubLabelID - the sublabel ID
      aContext - the context.
      Returns:
      if the content of the given label should be invalidated.
    • getComponent

      protected abstract JComponent getComponent(Object aObject, Object aSublabelId, TLspContext aContext)
      This method retrieves the component for the given object.

      Similar to the Swing cell renderers, you can re-use a single component instance for different domain objects.

      Parameters:
      aObject - a domain object
      aSublabelId - a sublabel id
      aContext - the context
      Returns:
      a Swing component for the given object.
    • isInteractiveEditedLabel

      protected final boolean isInteractiveEditedLabel(Object aObject, Object aSubLabelID, TLspContext aContext)
      Returns if the given label is interactively edited. This method can for example be used to return different components for regular, and interactive labels in the getComponent method.

      This method can only return true when using the constructor that takes an ALspInteractiveLabelProvider as argument, and when this ALspInteractiveLabelProvider notifies this styler that a label is interactively edited.

      Parameters:
      aObject - the domain object of the label
      aSubLabelID - the sublabel ID
      aContext - the context.
      Returns:
      if the given label is interactively edited.
    • paintImage

      protected BufferedImage paintImage(JComponent aComponent, Dimension aDimension, Object aObject, Object aSublabelID, TLspContext aContext)
      This method paints an image of the given component, for the given label.
      Parameters:
      aComponent - the component to paint as an image.
      aDimension - the dimension of the component (and the resulting image)
      aObject - the domain object of the label.
      aSublabelID - the sublabel ID.
      aContext - the context.
      Returns:
      an image of the given component.
    • componentChanged

      public void componentChanged(Object aObject, Object aSublabelId, TLspContext aContext)

      Notify this styler that the component for the given domain object and sublabel id has changed.

      Calling this method can trigger expensive operations on the Swing Event Dispatch Thread. So for performance reasons, it is advised to call this method only when strictly necessary. For example, an object can change, but when this change doesn't affect the Swing label, it is advised not to call this method.

      Parameters:
      aObject - a domain object
      aSublabelId - a sublabel id
      aContext - the context.
    • allComponentsChanged

      public void allComponentsChanged(TLspContext aContext)
      Notify this styler that the components for all domain objects have changed.
      Parameters:
      aContext - the context
    • getComponentStyle

      protected ALspStyle getComponentStyle(Object aObject, Object aSublabelId, TLspContext aContext)

      Returns the style that contains the representation of the component for the given domain object and sublabel id.

      Note that this call can return null if the representation is not available yet. In that case, this call will make sure the representation is created, and that a style change is fired when that happens. In subsequent calls, the style will not be null anymore.

      Parameters:
      aObject - a domain object
      aSublabelId - a sublabel id
      aContext - the context.
      Returns:
      a style that represents the component, or null if not available