Class Decorator

All Implemented Interfaces:
PropertyNameSource, PropertySource, GamePiece, PropertyExporter, StateMergeable, PersistentPropertyContainer, ImageSearchTarget, SearchTarget
Direct Known Subclasses:
ActionButton, AreaOfEffect, CalculatedProperty, Clone, CounterGlobalKeyCommand, Delete, Deselect, DynamicProperty, Embellishment, Embellishment0, FreeRotator, GlobalHotKey, Hideable, Immobilized, Labeler, Marker, MenuSeparator, MovementMarkable, NonRectangular, Obscurable, Pivot, PlaceMarker, PlaySound, PropertySheet, ReportState, RestrictCommands, Restricted, ReturnToDeck, SendToLocation, SubMenu, TableInfo, TranslatableMessage, Translate, TriggerAction, UsePrototype

The abstract class describing a generic 'Trait' of a full GamePiece. Follows the Decorator design pattern of wrapping around another instance of GamePiece (the 'inner' piece) and delegating some of the GamePiece methods to it. The "innermost" piece of a Trait/Decorator stack will be a BasicPiece -- but note that although BasicPiece does implement GamePiece, it is NOT a Decorator like traits are, and must be handled differently. Since Traits (Decorators) implement the GamePiece interface, they are "given a look at" any method call to GamePiece, and may act on it and/or pass it "inward" toward the next Decorator in the stack, eventually arriving at the BasicPiece. This is the reason for the VASSAL situation wherein only traits lower (more outward) in the list of traits are able to affect/control/hide/restrict/etc traits that are higher (more inward, nearer the BasicPiece) in the list -- because the outer traits receive the GamePiece method calls first, and thus have the opportunity to intercept or modify them if appropriate before passing them inward. So a full logical GamePiece (the thing you see on the board), may consist of many Decorator instances (one for each trait) wrapped around the BasicPiece.
  • Field Details

  • Constructor Details

    • Decorator

      public Decorator()
  • Method Details

    • setInner

      public void setInner(GamePiece p)
      Parameters:
      p - Set the inner GamePiece -- usually the next Trait (Decorator) inward, or the BasicPiece itself.
    • setMap

      public void setMap(Map m)
      Specified by:
      setMap in interface GamePiece
      Parameters:
      m - Each GamePiece belongs to a single Map. Default behavior for a trait is to pass the new map inward toward the BasicPiece.
    • getMap

      public Map getMap()
      Specified by:
      getMap in interface GamePiece
      Returns:
      the map for this piece. Each GamePiece belongs to a single Map. Default behavior ask the next member inward which map it is on - the BasicPiece normally hold the map information, so the request will eventually reach it.
    • getInner

      public GamePiece getInner()
      Returns:
      the next member "inward" (toward the BasicPiece) of the full GamePiece. Follows the Decorator design pattern of wrapping around another instance of GamePiece (the 'inner' piece) and delegating some of the GamePiece methods to it. The "innermost" piece of a Trait/Decorator stack will be a BasicPiece. Since Traits (Decorators) implement the GamePiece interface, they are "given a look at" any method call to GamePiece, and may act on it and/or pass it "inward" toward the next Decorator in the stack, eventually arriving at the BasicPiece. This is the reason for the VASSAL situation wherein only traits lower (more outward) in the list of traits are able to affect/control/hide/restrict/etc traits that are higher (more inward, nearer the BasicPiece) in the list -- because the outer traits receive the GamePiece method calls first, and thus have the opportunity to intercept or modify them if appropriate before passing them inward. So a full logical GamePiece (the thing you see on the board), may consist of many Decorator instances (one for each trait) wrapped around the BasicPiece.
    • setParent

      public void setParent(Stack s)
      Specified by:
      setParent in interface GamePiece
      Parameters:
      s - sets the Stack to which this piece belongs. Default behavior for a trait is to send the request to set the Stack inward (toward the BasicPiece)
    • getParent

      public Stack getParent()
      Specified by:
      getParent in interface GamePiece
      Returns:
      the Stack to which this piece belongs, if any. Default behavior for a trait is to ask the next member inward.
    • getProperty

      public Object getProperty(Object key)
      Properties can be associated with a piece -- many may be game-specific, but others are standard, such as the LocationName property exposed by BasicPiece -- and can be read through this interface. The properties may or may not need to be encoded in the piece's getState() method. Properties include the value of e.g. Marker Traits, DynamicProperty Traits, and so forth. Furthermore they include the values of any visible "Global Property" in a Vassal module, whether at the module level, map level, or zone level -- but these "higher level" properties, coming from "outside the piece", CANNOT be written to by the setProperty(java.lang.Object, java.lang.Object) method even though they can be read by this method -- in this sense the two methods are NOT perfect mirrors.

      Within a Trait/Decorator, default behavior is to process some requests directly (e.g. requests for our "inner" or "outer" link), process our *part* of certain other requests (e.g. request for our game state information we supply state information for this trait and then append any information obtained from passing the same request inward), and then for any other requests that we cannot process we simply pass the request to the next trait/member inward.

      When using this interface a piece's own properties are preferred to those of "Global Properties", and those in turn are searched Zone-first then Map, then Module.

      This method implements the PropertySource interface, which allows Global Properties to be read by other types of object than GamePieces.
      Specified by:
      getProperty in interface GamePiece
      Specified by:
      getProperty in interface PropertySource
      Parameters:
      key - String key of property to be returned
      Returns:
      Object containing new value of the specified property
    • getLocalizedProperty

      public Object getLocalizedProperty(Object key)
      Returns a localized translation of the specified property value, if available. Otherwise returns the non-localized version. See getProperty(java.lang.Object).
      Specified by:
      getLocalizedProperty in interface PropertySource
      Parameters:
      key - String key of property to be returned
      Returns:
      Object containing localized text of the specified property, if available, otherwise non-localized value
    • setProperty

      public void setProperty(Object key, Object val)
      Within a Trait/Decorator, the default behavior when setting a property is to handle changing our own inner/outer links directly, to cache the selection state (while also passing it inward), and to simply pass every other property change request inward. A Trait with its own properties to maintain would intercept and process those requests, while sending the rest inward to the next member of the piece.

      Properties can be associated with a piece -- many may be game-specific, but others are standard, such as the LocationName property exposed by BasicPiece -- and can be set through this interface. The properties may or may not need to be encoded in the piece's getState() method. Properties include the value of e.g. Marker Traits, DynamicProperty Traits, and so forth.

      NOTE: Not all properties maintained by traits can be "set" by setProperty, even though they can be read by getProperty -- they may be "read only" for instance. You will need to check the code for individual traits to see what they support in this regard.

      NOTE: Properties outside the piece CANNOT be set by this method (e.g. Global Properties), even though they can be read by getProperty(java.lang.Object) -- in this the two methods are not perfect mirrors.
      Specified by:
      setProperty in interface GamePiece
      Parameters:
      key - String key of property to be changed
      val - Object containing new value of the property
    • setPersistentProperty

      public Command setPersistentProperty(Object key, Object val)
      Default behavior for a Trait/Decorator is to pass requests to set persistent properties inward to the next member of the piece. Setting a persistent property writes a property value into the piece (creating a new entry in the piece's persistent property table if the specified key does not yet exist in it). Persistent properties are game-state-robust: they are saved/restored with saved games, and are passed via Command to other players' clients in a multiplayer game. The persistent property value can then be read from the piece via e.g. #getProperty. When reading back properties out of a piece, the piece's built-in properties are checked first, then scratchpad properties (see #setProperty), then external properties such as Global Properties. If only persistentProperties are to be searched, use getPersistentProperty(java.lang.Object) instead.

      In practical terms, setPersistentProperty is used mainly to implement the "Old" properties of BasicPiece (e.g. "OldLocationName", "OldZone", "OldMap", "OldBoard", "OldX", "OldY"). A Persistent Property is indeed nearly identical with DynamicProperty in storage/retrieval characteristics, and simply lacks the in-module interface for setting values, etc. Module Designers are thus recommended to stick with Dynamic Property traits for these functions.
      Specified by:
      setPersistentProperty in interface PersistentPropertyContainer
      Parameters:
      key - String key naming the persistent property to be set. If a corresponding persistent property does not exist it will be created.
      val - New value for the persistent property
      Returns:
      a Command object which, when passed to another player's client via logfile, server, or saved game, will allow the result of the "set" operation to be replicated.
    • getPersistentProperty

      public Object getPersistentProperty(Object key)
      Specified by:
      getPersistentProperty in interface PersistentPropertyContainer
      Parameters:
      key - String key naming the persistent property whose value is to be returned.
      Returns:
      the current value of a persistent property, or null if it doesn't exist.
    • getOuter

      public Decorator getOuter()
      Returns:
      next piece "outward" (away from BasicPiece) in the trait list. This method is required by Obscurable to handle masking of getProperty calls.
    • setPosition

      public void setPosition(Point p)
      Specified by:
      setPosition in interface GamePiece
      Parameters:
      p - Sets the location of this piece on its Map Default behavior by a Trait/Decorator is to pass the position request inward to the next member of the piece.
    • getPosition

      public Point getPosition()
      Specified by:
      getPosition in interface GamePiece
      Returns:
      The location of this piece on its Map. Default behavior by a Trait/Decorator is to request the information from the next inward member of the piece.
    • mySetState

      public abstract void mySetState(String newState)
      Sets the state of this-trait-only (inverse of myGetState()). The "state information" is information that can change during the course of a game. State information is saved when the game is saved and is transferred between players on the server. For example, the relative order of pieces in a stack is state information, but whether the stack is expanded is not.
      Parameters:
      newState - New state information serialized in string form, ready to be passed to a SequenceEncoder#decode.
    • setState

      public void setState(String newState)
      Extract the string describing this trait's state and forward the remaining string to the inner piece. The "state information" is "game state" information that can change during the course of a game. State information is saved when the game is saved and is transferred between players on the server. For example, the relative order of pieces in a stack is state information, but whether the stack is expanded is not.
      Specified by:
      setState in interface GamePiece
      Parameters:
      newState - the new state of this trait and all inner members of the piece
    • mergeState

      public void mergeState(String newState, String oldState)
      Compute the difference between newState and oldState and apply that difference to the current state. Default behavior for a Trait/Decorator is to do the same for all inward members of the piece.

      The "state information" is "game state" information that can change during the course of a game. State information is saved when the game is saved and is transferred between players on the server. For example, the relative order of pieces in a stack is state information, but whether the stack is expanded is not.
      Specified by:
      mergeState in interface StateMergeable
      Parameters:
      newState - the new state of this trait and all inner members of the piece
      oldState - the old state of this trait and all inner members of the piece
    • myGetState

      public abstract String myGetState()
      The "state information" is "game state" information that can change during the course of a game. State information is saved when the game is saved and is transferred between players on the server. For example, the relative order of pieces in a stack is state information, but whether the stack is expanded is not.
      Returns:
      the game state information of this trait alone
      See Also:
      which returns state information for all inward piece members as well
    • getState

      public String getState()
      Specified by:
      getState in interface GamePiece
      Returns:
      the state of a Trait/Decorator is a composition of myGetState() and the inner piece members' states

      The "state information" is game state information that can change during the course of a game. State information is saved when the game is saved and is transferred between players on the server. For example, the relative order of pieces in a stack is state information, but whether the stack is expanded is not.
    • myGetType

      public abstract String myGetType()
      The "type information" of a piece or trait is information that does not change during the course of a game. Image file names, context menu strings, etc., all should be reflected in the type. The type information is returned serialized string form, ready to be decoded by a SequenceEncoder#decode.
      Returns:
      the type information of this trait alone
      See Also:
      BasicCommandEncoder, which returns type information for all inward piece members as well
    • getType

      public String getType()
      The type of a Decorator/Trait is a composition of myGetType() and the type information of its inner piece member(s).

      The "type information" of a piece or trait is information that does not change during the course of a game. Image file names, context menu strings, etc., all should be reflected in the type. The type information is returned serialized string form, ready to be decoded by a SequenceEncoder#decode.
      Specified by:
      getType in interface GamePiece
      Returns:
      the combined type of this trait (from myGetType()) plus all inner piece members
      See Also:
      BasicCommandEncoder
    • myGetKeyCommands

      protected abstract KeyCommand[] myGetKeyCommands()
      Returns:
      the key commands for this trait alone
      See Also:
      which returns the key commands for this trait AND all inner piece members
    • getKeyCommands

      protected KeyCommand[] getKeyCommands()
      Returns:
      The set of key commands that will populate the piece's right-click menu. The key commands are accessible through the Properties.KEY_COMMANDS property. The commands for a Trait/Decorator are a composite of myGetKeyCommands() and the commands of its inner piece member(s), so requesting this information of the "outermost" Trait/Decorator of a piece will produce the complete set of Key Commands for the entire logical game piece. See also: myGetKeyCommands(), which returns the commands for this Trait/Decorator only.
    • myKeyEvent

      public abstract Command myKeyEvent(KeyStroke stroke)
      The response of this trait alone to the given KeyStroke or the virtual keystroke of a NamedKeyStroke. NamedKeyStrokes are allocated a unique internal KeyStroke when they are first used in a module, and that KeyStroke is passed up and down the decorator stack to represent them (see NamedKeyStroke.getKeyStroke()).
      Parameters:
      stroke - KeyStroke to apply (to apply a Named Keystroke send NamedKeyStroke.getKeyStroke()
      Returns:
      Generated Command to reproduce any changes just made to to the game state, or null if no effect
      See Also:
      keyEvent(javax.swing.KeyStroke)
    • keyEvent

      public Command keyEvent(KeyStroke stroke)
      The primary way for the piece or trait to receive events. Appends the command returned by myKeyEvent(javax.swing.KeyStroke) with the command returned by the inner piece member's GamePiece.keyEvent(javax.swing.KeyStroke) method. KeyStroke events are forwarded to this method if they are received while the piece is selected (or as the result of e.g. a Global Key Command being sent to the piece). The class implementing GamePiece can respond in any way it likes. Actual key presses by the player, selected items from the right-click Context Menu, keystrokes "applied on move" by a Map that the piece has just moved on, and Global Key Commands all send KeyStrokes (and NamedKeyStrokes) which are passed to pieces and traits through this interface.
      Specified by:
      keyEvent in interface GamePiece
      Parameters:
      stroke - KeyStroke to apply (note that although they are passed as KeyStroke objects, they may be NamedKeyStroke objects)
      Returns:
      a Command that, when executed, will make all changes to the game state (maps, pieces, other pieces, etc) to duplicate what the Trait/Decorator plus any inner piece members did in response to this event, on another machine. Often a ChangePiece command, but for example if this keystroke caused the piece/trait to decide to fire off a Global Key Command, then the Command returned would include the entire results of that, appended as subcommands. Returns null if the keystroke did not produce an effect.
      See Also:
      ForwardToKeyBuffer
    • getId

      public String getId()
      Each GamePiece must have a unique String identifier
      Specified by:
      getId in interface GamePiece
      Returns:
      unique ID for this piece
      See Also:
      GameState.getNewPieceId()
    • setId

      public void setId(String id)
      Each GamePiece must have a unique String identifier
      Specified by:
      setId in interface GamePiece
      Parameters:
      id - sets unique ID for this piece
      See Also:
      GameState.getNewPieceId()
    • getOutermost

      public static GamePiece getOutermost(GamePiece p)
      Parameters:
      p - Trait to find the outermost trait of.
      Returns:
      the outermost Decorator/Trait of this piece, i.e. the entire logical Game Piece with all traits
    • getInnermost

      public static GamePiece getInnermost(GamePiece p)
      Parameters:
      p - Trait to find the Innermost trait of
      Returns:
      the innermost GamePiece member of this piece. In most cases, an instance of BasicPiece.
    • getDecorator

      public static GamePiece getDecorator(GamePiece p, Class<?> type)
      Returns:
      Working inward from this Trait/Decorator, finds and returns the first Trait/Decorator within the given GamePiece that is an instance of the given Class.
    • getExpressionList

      public List<String> getExpressionList()
      Specified by:
      getExpressionList in interface SearchTarget
      Returns:
      a list of the Decorator's string/expression fields if any (for search)
    • getFormattedStringList

      public List<String> getFormattedStringList()
      Specified by:
      getFormattedStringList in interface SearchTarget
      Returns:
      a list of any Message Format strings referenced in the Decorator, if any (for search)
    • getMenuTextList

      public List<String> getMenuTextList()
      Specified by:
      getMenuTextList in interface SearchTarget
      Returns:
      a list of any Menu/Button/Tooltip Text strings referenced in the Decorator, if any (for search)
    • getNamedKeyStrokeList

      public List<NamedKeyStroke> getNamedKeyStrokeList()
      Specified by:
      getNamedKeyStrokeList in interface SearchTarget
      Returns:
      a list of any Named KeyStrokes referenced in the Decorator, if any (for search)
    • getPropertyList

      public List<String> getPropertyList()
      Specified by:
      getPropertyList in interface SearchTarget
      Returns:
      a list of any Property Names referenced in the Decorator, if any (for search)
    • getEditor

      public PieceEditor getEditor()
      Returns:
      the configurer for this trait - the dialog which allows the editing the piece's type information. Default configurer is a SimplePieceEditor, but many traits will want to provide custom versions.
    • toString

      public String toString()
      Overrides:
      toString in class Object
      Returns:
      string information on trait, for debugging purposes
    • getLocalizedName

      public String getLocalizedName()
      Description copied from interface: GamePiece
      And the translated name for this piece
      Specified by:
      getLocalizedName in interface GamePiece
      Returns:
      the translated name for this piece. Most pieces do not have translatable elements, so just return the standard name
    • getI18nData

      public PieceI18nData getI18nData()
      Return Internationalization (I18n) data for this piece
      Returns:
      I18n data, used to hold translations of strings
    • getI18nData

      protected PieceI18nData getI18nData(String command, String description)
    • getI18nData

      protected PieceI18nData getI18nData(String[] commands, String[] descriptions)
    • getCommandDescription

      protected String getCommandDescription(String description, String command)
    • getTranslation

      protected String getTranslation(String key)
    • reportDataError

      protected static void reportDataError(EditablePiece piece, String message, String data, Throwable e)
      Report a Data Error detected by a trait
      Parameters:
      piece - Our GamePiece for the error message
      message - Main error message
      data - additional data string
      e - throwable error associated with the problem
    • reportDataError

      protected static void reportDataError(EditablePiece piece, String message, String data)
      Report a Data Error detected by a trait
      Parameters:
      piece - Our GamePiece for the error message
      message - Main error message
      data - additional data string
    • reportDataError

      protected static void reportDataError(EditablePiece piece, String message)
      Report a Data Error detected by a trait
      Parameters:
      piece - Our GamePiece for the error message
      message - Main error message
    • getPropertyNames

      public List<String> getPropertyNames()
      Specified by:
      getPropertyNames in interface PropertyNameSource
      Returns:
      List of property names "exposed" by this piece -- that are available to other Traits and components to read. Default behavior for a Trait is not to expose any properties, but Traits which should expose some (e.g. DynamicProperty or Marker) would provide an array of the property names here.
    • setOldProperties

      @Deprecated(since="20200906", forRemoval=true) public static void setOldProperties(GamePiece p)
      Deprecated, for removal: This API element is subject to removal in a future version.
      Set the Oldxxxx properties related to movement This call has been replaced by putOldProperties(GamePiece) Any changes to Oldxxxx properties MUST be recorded in Commands.
      Parameters:
      p - Piece to set properties on
    • putOldProperties

      public static Command putOldProperties(GamePiece p)
      * Set the Oldxxxx properties related to movement (e.g. OldLocationName, OldZone, OldBoard, OldMap, OldX, OldY)
      Parameters:
      p - Piece to set properties on
      Returns:
      Command encoding the property values
    • setOldProperties

      @Deprecated(since="2020-08-06", forRemoval=true) public void setOldProperties()
      Deprecated, for removal: This API element is subject to removal in a future version.
    • repack

      public static void repack(Component c)
      Utility methods to allow Decorator Editors to repack themselves. Ensure the resulting dialog fits and is fully visible on the screen
      Parameters:
      c - must be one of the Swing components that make up the Decorator's controls.
    • repack

      public static void repack(Configurer c)
      Utility methods to allow Decorator Editors to repack themselves. Ensure the resulting dialog fits and is fully visible on the screen
      Parameters:
      c - must be one of the Decoarator's Configurers
    • setSelected

      protected void setSelected(boolean b)
      Support caching Selection status locally
      Parameters:
      b - current selected status of our piece
    • isSelected

      protected boolean isSelected()
      Support caching Selection status locally
      Returns:
      true if our piece is selected
    • addImageNamesRecursively

      public void addImageNamesRecursively(Collection<String> s)
      ImageSearchTarget Adds all images used by this component AND any children to the collection
      Specified by:
      addImageNamesRecursively in interface ImageSearchTarget
      Overrides:
      addImageNamesRecursively in class AbstractImageFinder
      Parameters:
      s - Collection to add image names to
    • testEquals

      public boolean testEquals(Object o)
      Test if this Decorator's Class, Type and State are equal to another trait. Implementations of this method should compare the individual values of the fields that make up the Decorators Type and State. Implementations should NOT compare the values returned by myGetType() or myGetState(). This method is intended to be used by Unit Tests to verify that a trait is unchanged after going through a process such as serialization/deserialization.
      Parameters:
      o - Object to compare this Decorator to
      Returns:
      true if the Class, type and state all match
    • buildDescription

      protected String buildDescription(String i18nKey, String description)
      Build a description of a trait of the form Type - Description Where Type is the translated trait type description and Description is a supplied additional description
      Parameters:
      i18nKey - Translation key for trait type description
      description - Optional additional description
      Returns:
      Combined description
    • buildDescription

      protected String buildDescription(String i18nKey)
    • buildDescription

      protected String buildDescription(String i18nKey, String value, String description)
      Build a description of a trait of the form Type - value - Description
      Parameters:
      i18nKey - Translation key for trait type description
      value - Optional value to include in the description
      description - Optional additional description
      Returns:
      Combined description
    • getProperties

      public Map<String,​Object> getProperties(Map<String,​Object> result)
      Implement PropertyExporter.getProperties at the Decorator level. Add the properties from this Decorator to the supplied Map, then call the next innermost piece to do the same. Do not overwrite values if an outer trait has a property with the same name.
      Specified by:
      getProperties in interface PropertyExporter
      Parameters:
      result - Map of property values
      Returns:
      Updated Map of property values