Class AbstractGameComponent
- java.lang.Object
-
- ca.cgjennings.apps.arkham.component.AbstractGameComponent
-
- All Implemented Interfaces:
GameComponent
,java.io.Serializable
,java.lang.Cloneable
public abstract class AbstractGameComponent extends java.lang.Object implements GameComponent
Provides default implementations for theGameComponent
interface.- Author:
- Chris Jennings
- See Also:
- Serialized Form
-
-
Field Summary
Fields Modifier and Type Field Description protected java.lang.String
comments
protected boolean
hasUndrawnChanges
protected Settings
privateSettings
protected Sheet[]
sheets
-
Constructor Summary
Constructors Constructor Description AbstractGameComponent()
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods Modifier and Type Method Description void
clearAll()
Set all game component data to a neutral, blank state.AbstractGameComponent
clone()
Returns a deep copy of this game component.double
computeIdealScaleForImage(java.awt.image.BufferedImage image, java.lang.String imageKey)
double
computeMinimumScaleForImage(java.awt.image.BufferedImage image, java.lang.String imageKey)
void
coreCheck()
Checks if all required libraries and extensions are installed.abstract Sheet[]
createDefaultSheets()
Creates a set of default sheets that are compatible with this component and associates them with the component as if by callingGameComponent.setSheets(ca.cgjennings.apps.arkham.sheet.Sheet[])
.static java.lang.String
filterComponentText(java.lang.String source)
Given a string from a game component that may contain markup or other special coding, return a copy of the string containing plain text with all coding removed and newlines converted to spaces.java.lang.String
getComment()
Returns the design rationale comments associated with this component.java.awt.image.BufferedImage
getDefaultPortrait(java.lang.String portraitKey)
Given a portrait image key name (without the "-portrait-template"), return the appropriate portrait image.java.lang.String
getFullName()
Returns the "full name" of this component.java.lang.String
getName()
Returns the name of this component.Settings
getSettings()
Returns aSettings
instance that will return this component's private settings.Sheet[]
getSheets()
Returns the sheets attached to this component to draw its faces, ornull
if no sheets are attached.java.lang.String[]
getSheetTitles()
Returns human-readable names for the sheets used by this component.boolean
hasChanged()
Returnstrue
if this component has been modified since the last call tohasChanged()
.boolean
hasUnsavedChanges()
Returns the value of this component's unsaved changes flag.static double
idealScaleForImage(double idealWidth, double idealHeight, double imageWidth, double imageHeight)
static java.awt.image.BufferedImage
imagePathToImage(java.lang.String path)
Deprecated.UseStrangeImage.get(java.lang.String)
to load user-supplied images.boolean
isDeckLayoutSupported()
Returnstrue
if components of this type can be placed in a deck.protected void
markChanged()
A convenience method that can be used to mark a default sheet or group of sheets as having changed.void
markChanged(int sheetIndex)
Called to signal that changes have been made that require thei
the sheet to be redrawn.void
markSaved()
This method is called by the component's editor when the the component is saved to clear the component's unsaved changes flag.void
markUnsavedChanges()
This method sets the component's unsaved changes flag.protected void
read(java.io.ObjectInputStream in)
Provides default code to read this object's values from a subclass.void
setComment(java.lang.String comment)
Sets the design rationale comment associated with this component.void
setName(java.lang.String name)
Sets the name of the component.protected void
setNameImpl(java.lang.String name)
Sets the component name without marking any sheets as changed or marking the component as having unsaved changes.void
setSheets(Sheet[] sheets)
Sets the sheets that are attached to this component to draw its faces.protected void
write(java.io.ObjectOutputStream out)
Provides default code to write this object's values from a subclass.-
Methods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface ca.cgjennings.apps.arkham.component.GameComponent
convertFrom, convertTo, createDefaultEditor, createUpgradeConversionTrigger, getClassName
-
-
-
-
Method Detail
-
getName
public java.lang.String getName()
Description copied from interface:GameComponent
Returns the name of this component. This is not the name of the component type, but the name of the specific component. For example, a component that represents a game item would return the name of the item.- Specified by:
getName
in interfaceGameComponent
- Returns:
- the component's name; possibly a shortened version of the full name
- See Also:
GameComponent.getFullName()
-
setName
public void setName(java.lang.String name)
Sets the name of the component. If the new name is different from the existing name, and there are sheets installed, then any sheets which are not subclasses ofUndecoratedCardBack
will be marked as changed. In addition, the component is marked as having unsaved changes. To change this behaviour, you can override this method; seesetNameImpl(java.lang.String)
.- Parameters:
name
- the new name of the component- Throws:
java.lang.NullPointerException
- if the name isnull
-
setNameImpl
protected final void setNameImpl(java.lang.String name)
Sets the component name without marking any sheets as changed or marking the component as having unsaved changes. Subclasses may call this from within an overriddensetName(java.lang.String)
method to change the default behaviour for marking sheets.- Parameters:
name
- the new name of the component- Throws:
java.lang.NullPointerException
- if the name isnull
-
clone
public AbstractGameComponent clone()
Description copied from interface:GameComponent
Returns a deep copy of this game component. The default clone implementation provided bysuper.clone()
will return a shallow copy of the object. This will correctly clone all of this instance's fields that have primitive types. It is then up to you to clone any object fields where the field is not of an immutable type. Images used to store portraits, although not technically immutable, are treated as immutable by Strange Eons. So long as you also follow this convention, you can save memory by sharing the shallow copy of the image.Debugging tip: One operation that makes use of the
clone()
method is the Spin Off command. If you apply this command, make changes to the copied component, redraw the original component, and notice that changes in the copy have carried over to the original, then you are using a shallow copy rather than a deep copy. (That is, you are sharing a reference to the same mutable object rather than making a copy of the mutable object during the cloning.)- Specified by:
clone
in interfaceGameComponent
- Overrides:
clone
in classjava.lang.Object
- Returns:
- a deep copy of this component
-
getFullName
public java.lang.String getFullName()
Returns the "full name" of this component. Typically this is the same asGameComponent.getName()
, butGameComponent.getName()
may optionally return a shorter name. For example, a component that represents a human character might return the character's first name fromGameComponent.getName()
and their full name from this method.This base class implementation returns
getName()
.- Specified by:
getFullName
in interfaceGameComponent
- Returns:
- the full name of the component
- See Also:
GameComponent.getName()
-
getComment
public java.lang.String getComment()
Description copied from interface:GameComponent
Returns the design rationale comments associated with this component. If there are no comments, it should return an empty string.- Specified by:
getComment
in interfaceGameComponent
- Returns:
- design comments supplied by the user of the component
-
setComment
public void setComment(java.lang.String comment)
Sets the design rationale comment associated with this component. If the comment is different from the existing comment, thenmarkUnsavedChanges()
.- Parameters:
comment
- the new design comment- Throws:
java.lang.NullPointerException
- if the comment isnull
-
clearAll
public void clearAll()
Set all game component data to a neutral, blank state. Marks all sheets as changed, as well as marking the component unsaved. Sets this component's content to an empty state. Typically, this is called from an editor when the user wishes to erase their work and start over.The base class implementation will clear the name and comments, mark the sheets changed, clear any set expansion, and mark the component unsaved.
- Specified by:
clearAll
in interfaceGameComponent
-
setSheets
public void setSheets(Sheet[] sheets)
Description copied from interface:GameComponent
Sets the sheets that are attached to this component to draw its faces. Once set, the array is owned by the component and must not be modified.- Specified by:
setSheets
in interfaceGameComponent
- Parameters:
sheets
- the sheets to associate with the component, ornull
to clear the associated sheets- See Also:
GameComponent.getSheets()
,GameComponent.createDefaultSheets()
-
getSheets
public Sheet[] getSheets()
Description copied from interface:GameComponent
Returns the sheets attached to this component to draw its faces, ornull
if no sheets are attached. The returned array is owned by the game component and must not be modified.- Specified by:
getSheets
in interfaceGameComponent
- Returns:
- the sheets that will be updated by calls to
GameComponent.markChanged(int)
. - See Also:
GameComponent.getSheets()
-
createDefaultSheets
public abstract Sheet[] createDefaultSheets()
Description copied from interface:GameComponent
Creates a set of default sheets that are compatible with this component and associates them with the component as if by callingGameComponent.setSheets(ca.cgjennings.apps.arkham.sheet.Sheet[])
. As withGameComponent.getSheets()
, the returned sheets are owned by the component and must not be modified.- Specified by:
createDefaultSheets
in interfaceGameComponent
- Returns:
- the newly created sheets
-
getSheetTitles
public java.lang.String[] getSheetTitles()
Returns human-readable names for the sheets used by this component. A typical result would be something like["Front Face", "Back Face"]
, localized for the user interface language.Implementations should assume that the titles are for the same kinds and number of sheets that are returned by
GameComponent.createDefaultSheets()
. (In other words, if a user of this class decides to use their own sheet implementations, you are not responsible for ensuring the sheet titles are accurate.)Note: The returned sheet name may be shared with any number of callers. The values must be considered read-only unless otherwise stated by the subclass documentation.
The base class implementation will provide suitable localized titles for most cases. It is designed to handle any number of alternating front and back faces, with one exception. If there are exactly three sheets, then it assumes that the third sheet is a token related to the first two.
- Specified by:
getSheetTitles
in interfaceGameComponent
- Returns:
- an array of sheet titles matching the assigned sheets, or
null
if there are no sheets attached - See Also:
GameComponent.createDefaultSheets()
-
markChanged
public void markChanged(int sheetIndex)
Description copied from interface:GameComponent
Called to signal that changes have been made that require thei
the sheet to be redrawn. This is typically not called directly. Instead, calling a method like "setName
" should check if the name being set is actually different, and if so then call this method for each sheet that may have changed as a result. Plug-ins that customize an existing component may also call this method as needed to reflect new features that they have added.Implementations of this method will typically call the
Sheet.markChanged()
method of the relevant sheet (unless the sheet set isnull
), set a flag for use byGameComponent.hasChanged()
, and then callGameComponent.markUnsavedChanges()
.- Specified by:
markChanged
in interfaceGameComponent
- Parameters:
sheetIndex
- the index of the sheet that needs to be redrawn
-
markChanged
protected void markChanged()
A convenience method that can be used to mark a default sheet or group of sheets as having changed. The base class will callmarkChanged(int)
for every sheet.
-
hasChanged
public boolean hasChanged()
Description copied from interface:GameComponent
Returnstrue
if this component has been modified since the last call tohasChanged()
.- Specified by:
hasChanged
in interfaceGameComponent
- Returns:
true
if the component has changed since this was last called
-
markUnsavedChanges
public void markUnsavedChanges()
Description copied from interface:GameComponent
This method sets the component's unsaved changes flag. It is typically called fromGameComponent.markChanged(int)
.- Specified by:
markUnsavedChanges
in interfaceGameComponent
-
hasUnsavedChanges
public boolean hasUnsavedChanges()
Description copied from interface:GameComponent
Returns the value of this component's unsaved changes flag.- Specified by:
hasUnsavedChanges
in interfaceGameComponent
- Returns:
true
if this component has unsaved changes
-
markSaved
public void markSaved()
Description copied from interface:GameComponent
This method is called by the component's editor when the the component is saved to clear the component's unsaved changes flag.- Specified by:
markSaved
in interfaceGameComponent
-
getSettings
public Settings getSettings()
Description copied from interface:GameComponent
Returns aSettings
instance that will return this component's private settings. A component's private settings are saved along with the component when it is written to a file. This can be used to override the default settings for component (which are determined by the the shared game settings for the game associated with the component) as a way to "hack" existing component designs. It can also be used by the component itself to store arbitrary information.DIY components
generally use the component's private settings to store the current user-configurable state of the component.Note that setting the key with the name
Game.GAME_SETTING_KEY
("game") will change the parent scope of the private settings to therelevant game's settings
for that game whose code matches the new value. (The initial value of this key is normally set on the component's half using the game code specified in the component's class map entry.)- Specified by:
getSettings
in interfaceGameComponent
- Returns:
- the private settings that can be used to override settings for this component
-
isDeckLayoutSupported
public boolean isDeckLayoutSupported()
Description copied from interface:GameComponent
Returnstrue
if components of this type can be placed in a deck. Typically, only components that don't have faces returnfalse
. (Decks themselves, for example, cannot be placed inside other decks.)- Specified by:
isDeckLayoutSupported
in interfaceGameComponent
- Returns:
true
if and only if this component can be added to a deck- See Also:
GameComponent.createDefaultSheets()
,Deck.isDeckLayoutSupported(java.io.File)
-
coreCheck
public void coreCheck()
Description copied from interface:GameComponent
Checks if all required libraries and extensions are installed. If a required library is not install This method is called when the component is read from a file, and possibly at other timesThis can safely be implemented as an empty method. However, implementing it correctly improves the user experience since they can be notified of which plug-ins they need to install to correctly use the component. In the case of a required but not installed library, the library can actually be downloaded and installed on demand and the component can then be successfully opened.
- Specified by:
coreCheck
in interfaceGameComponent
- See Also:
CoreComponents
-
filterComponentText
public static java.lang.String filterComponentText(java.lang.String source)
Given a string from a game component that may contain markup or other special coding, return a copy of the string containing plain text with all coding removed and newlines converted to spaces. Useful for printing a display name.- Parameters:
source
- the string to filter- Throws:
java.lang.NullPointerException
- if the source string isnull
-
getDefaultPortrait
public java.awt.image.BufferedImage getDefaultPortrait(java.lang.String portraitKey)
Given a portrait image key name (without the "-portrait-template"), return the appropriate portrait image.
-
idealScaleForImage
@Deprecated public static double idealScaleForImage(double idealWidth, double idealHeight, double imageWidth, double imageHeight)
Returns the largest scaling factor that, when multiplied by the given image size, ensures that the image will match the ideal size in at least one dimension. The image will either match the ideal size in the other dimension, or else be larger than the other ideal dimension. If the image is opaque, the result is the scaling factor to obtain the smallest image with the same aspect ratio that would completely cover the ideal image area.- Parameters:
idealWidth
- the width of the area the image must coveridealHeight
- the height of the area the image must coverimageWidth
- the current width of the image to be fittedimageHeight
- the current height of the image to be fitted- Returns:
- the scale that would ensure that the image would just cover the specified area
-
computeMinimumScaleForImage
public double computeMinimumScaleForImage(java.awt.image.BufferedImage image, java.lang.String imageKey)
-
computeIdealScaleForImage
public double computeIdealScaleForImage(java.awt.image.BufferedImage image, java.lang.String imageKey)
-
imagePathToImage
@Deprecated public static java.awt.image.BufferedImage imagePathToImage(java.lang.String path)
Deprecated.UseStrangeImage.get(java.lang.String)
to load user-supplied images.Returns a bitmap image for a user-supplied path. The path may name a local file or be any of the special URL paths supported byStrangeImage
. If the path points to a vector image (and vector support is installed), then the image will be converted to a bitmap automatically, at a size and resolution based on- Parameters:
path
- the path to locate an image for- Returns:
- a bitmap image for the path; if the path does not point to a valid image, a stand-in "missing image" image will be returned
-
write
protected final void write(java.io.ObjectOutputStream out) throws java.io.IOException
Provides default code to write this object's values from a subclass. For historical reasons, nothing is written by this class's default serialization mechanism. Subclasses therefore have to read and set the name, comment, and settings instances themselves. This method can be called from a subclasswriteObject
method to do this on behalf of the subclass.- Parameters:
out
- the stream to write to- Throws:
java.io.IOException
- if an I/O exception occurs
-
read
protected final void read(java.io.ObjectInputStream in) throws java.io.IOException, java.lang.ClassNotFoundException
Provides default code to read this object's values from a subclass. For historical reasons, nothing is written by this class's default serialization mechanism. Subclasses therefore have to read and write the name, comment, and settings instances themselves. This method can be called from a subclassreadObject
method to restore serialized data written withwrite(java.io.ObjectOutputStream)
.- Parameters:
in
- the stream to read from- Throws:
java.io.IOException
- if an I/O exception occursjava.lang.ClassNotFoundException
-
-