Class ALcyDomainObjectCustomizerPanel

All Implemented Interfaces:
ILcdUndoableSource, ILcyCustomizerPanel, ILcdPropertyChangeSource, ImageObserver, MenuContainer, Serializable, Accessible

public abstract class ALcyDomainObjectCustomizerPanel extends ALcyCustomizerPanel

Abstract class that facilitates the implementation of ILcyCustomizerPanel for domain objects. This class can only be used to edit instances of TLcyDomainObjectContext.

This class adds listeners to the model and the layer so that when the set domain object changes or when the editable property of the layer changes, updateCustomizerPanelFromObject(boolean) is called. Furthermore it adds several convenience methods to easily retrieve the domain object and its model, layer and view.

It is however up to the extension of this class to ensure that:

See Also:
  • Constructor Details

    • ALcyDomainObjectCustomizerPanel

      protected ALcyDomainObjectCustomizerPanel(ILcdFilter aDomainObjectContextFilter, String aName)

      Create a new ALcyDomainObjectCustomizerPanel instance

      Parameters:
      aDomainObjectContextFilter - The ILcdFilter that defines which objects are accepted by canSetObject and setObject. When specified, this filter should only accept TLcyDomainObjectContext instances.
      aName - The name for this ALcyCustomizerPanel, see ILcyCustomizerPanel.NAME.
  • Method Details

    • applyChanges

      public boolean applyChanges()
      Updates the set Object according to the current state of the user interface. This means all pending changes are committed.

      If there were any pending changes, so isChangesPending returned true, it should return false after this method has finished, and therefore also a "changesPending" property change event must be fired.

      E.g. consider that a ILcdGXYLayer object is set and a new label text is entered in a text field. When this method is called, the new label text should be set to the ILcdGXYLayer (using ILcdGXYLayer.setLabel).

      This implementation invokes ALcyCustomizerPanel.applyChangesImpl() and sets the "changesPending" property. As a result, the "changesPending" event is fired when needed.

      Note: you should never override this method. Instead, you need to implement the applyChangesImpl() method.

      Specified by:
      applyChanges in interface ILcyCustomizerPanel
      Overrides:
      applyChanges in class ALcyCustomizerPanel
      Returns:
      True if the changes were applied or if there were no changes, false if the changes could not be applied because they are invalid. In that event, isChangesValid returns false.
      See Also:
    • applyChangesImpl

      protected abstract boolean applyChangesImpl()

      Apply any pending changes. This method should do the same as ALcyCustomizerPanel.applyChanges(), except that it should not take care of "changesPending".

      Note that the implementation of this method needs

      A typical implementation of this method would look like

          @Override
          protected boolean applyChangesImpl() {
            Object domainObject = getDomainObject();
            if (domainObject != null) {
              ILcdModel model = getModel();
              try (TLcdLockUtil.Lock autoUnlock = TLcdLockUtil.writeLock(model)) {
                //Thanks to the write lock, it is now safe to update the domain object
                updateDomainObject(domainObject);
                model.elementChanged(domainObject, ILcdModel.FIRE_LATER);
              } finally {
                model.fireCollectedModelChanges();
              }
            }
            return true;
          }
      
      Specified by:
      applyChangesImpl in class ALcyCustomizerPanel
      Returns:
      True if changes could be applied or if there were no changes, false otherwise. Please refer to ALcyCustomizerPanel.applyChanges() for more detailed information.
    • getView

      protected ILcdView getView()
      Convenience method to return the ILcdView that was set by setting a TLcyDomainObjectContext using setObject.
      Returns:
      Null if no TLcyDomainObjectContext is set, the ILcdView related to that context object otherwise.
    • getLayer

      protected ILcdLayer getLayer()
      Convenience method to return the ILcdLayer that was set by setting a TLcyDomainObjectContext using setObject.
      Returns:
      Null if no TLcyDomainObjectContext is set, the ILcdLayer related to that context object otherwise.
    • getModel

      protected ILcdModel getModel()
      Convenience method to return the ILcdModel that was set by setting a TLcyDomainObjectContext using setObject.
      Returns:
      Null if no TLcyDomainObjectContext is set, the ILcdModel related to that context object otherwise.
    • getDomainObject

      protected Object getDomainObject()
      Convenience method to return the domain object (e.g. polyline) that was set by setting a TLcyDomainObjectContext using setObject.
      Returns:
      Null if no TLcyDomainObjectContext object is set, the domain object (e.g., polyline) related to that context object otherwise.
    • canSetObject

      public boolean canSetObject(Object aObject)
      Description copied from class: ALcyCustomizerPanel
      Returns true if and only if setObject would not throw an IllegalArgumentException.

      Only accepts null or objects that pass the object filter. If the filter itself is null, all objects are accepted.

      Specified by:
      canSetObject in interface ILcyCustomizerPanel
      Overrides:
      canSetObject in class ALcyCustomizerPanel
      Parameters:
      aObject - The object to check.
      Returns:
      true if setObject would accept the object, false if it would throw an exception.
    • setObject

      public void setObject(Object aObject)
      Set the object to be edited. This method should be called before the ILcyCustomizerPanel has been added to any parent AWT container. It can be called afterwards as well however. In this case the user interface should update itself to represent the newly set object.

      A value of null is set to inform this ILcyCustomizerPanel to (temporarily) deinitialize itself, it allows to perform cleanup tasks, such as removing listeners. Invokes ALcyCustomizerPanel.updateCustomizerPanelFromObject() to update the user interface.

      Also adds a ILcdModelListener to the model of the set TLcyDomainObjectContext that calls updateCustomizerPanelFromObject whenever the set domain object changes in that model, as well as a PropertyChangeListener to the layer of the set TLcyDomainObjectContext that does the same when the "editable" property of the layer changes.

      Specified by:
      setObject in interface ILcyCustomizerPanel
      Overrides:
      setObject in class ALcyCustomizerPanel
      Parameters:
      aObject - The object to be customized, or null to inform that editing is temporarily disabled.
    • getDomainObjectContext

      protected final TLcyDomainObjectContext getDomainObjectContext()

      Returns the TLcyDomainObjectContext object that was set on this customizer. This context object can be used to retrieve the domain object and the model, layer and view in which it is contained.

      Returns:
      The set TLcyDomainObjectContext. This object can be null when this customizer was deinitialized (with setObject(null)).
    • updateCustomizerPanelFromObject

      protected void updateCustomizerPanelFromObject()

      Calls updateCustomizerPanelFromObject( isPanelEditable() ).

      Updates the user interface state according to the current state of the set Object. This method is called whenever a new object is set using setObject, or when the changes are canceled using cancelChanges.

      It does not need to take care of "changesPending".

      Consider for example that a TLcyLayerContext is set and a new label text is entered in a text field. When this method is called, the new label text should be cleared and the original label of the ILcdLayer (getLabel()) should be put in the text field.

      Note: you should never override this method. Instead, you need to implement the applyChangesImpl() method.

      Specified by:
      updateCustomizerPanelFromObject in class ALcyCustomizerPanel
    • updateCustomizerPanelFromObject

      protected abstract void updateCustomizerPanelFromObject(boolean aPanelEditable)

      This means updating the user interface state according to the current state of the set Object. This method is called whenever a new object is set using setObject, or when the changes are canceled using cancelChanges.

      It does not need to take care of "changesPending".

      Consider for example that a TLcyLayerContext is set and a new label text is entered in a text field. When this method is called, the new label text should be cleared and the original label of the ILcdLayer (getLabel()) should be put in the text field.

      Note that the implementation of this method needs to take a read lock on the model before querying the domain object.

      A typical implementation of this method would look like

      
         @Override
         protected void updateCustomizerPanelFromObject(boolean aPanelEditable){
           updateEditableState( aPanelEditable );
      
           Object domainObject = getDomainObject();
           if ( domainObject != null ){
             ILcdModel model = getModel();
             try( TLcdLockUtil.Lock autoUnlock = TLcdLockUtil.readLock(model) ){
               //thanks to the read lock, the domain object can now safely be queried
               updateUI( domainObject );
             }
           }
         }
       
      Parameters:
      aPanelEditable - true if the panel should be editable, false otherwise. See isPanelEditable() for more information.
    • isPanelEditable

      protected boolean isPanelEditable()
      Returns whether the panel is editable or not. Editable means the values it displays can be modified; for example, the content of a text field can be adapted. Not editable means the values it displays cannot be adapted; for example, a text field should be disabled.

      The default implementation returns

      
         getLayer().isEditableSupported() && getLayer().isEditable()
       
      or true if getLayer() is null.

      Override this method to redefine when the panel is editable or not.

      Returns:
      True if the panel should be editable, false otherwise.