A CompositeGroup is a specialization of the
Composite interface. Therefore, it is recommended that you read
the documentation of the Composite interface first to acquire a
basic understanding of this interfaces inherited responsibility.
As seen there a Composite contains and manages child
Primitive objects. A CompositeGroup, on the other
hand, is capable of containing other Composite and
CompositeLine objects.
The CoordinateSystem of a CompositeGroup is always
mutable and thus does not get pooled.
As you can see in the diagram above, the interface BaseCompositeContainer
is the root of all composite groups - CompositeGroup and CompositeView
are both subtypes of interface BaseCompositeContainer. This chapter focuses
on the various subtypes of interface CompositeGroup.
The BaseCompositeContainer interface is a collection container
specification for objects which implement the BaseComposite
interface. Such objects can be added to and removed from any instance of a
class which implements this interface.
The following methods define the important interface aspects:
void addComposite(BaseComposite)
Adds the given BaseComposite to this
BaseCompositeContainer.
void addComposites(List)
Adds the BaseComposites contained in the given list to this
BaseCompositeContainer.
int getCompositeCount()
Returns the number of BaseComposite actually added to the
BaseCompositeContainer.
BaseCompositeIterator getCompositeIterator()
Returns a BaseCompositeIterator that can be used to iterate
over the BaseCompositeContainers list of
BaseComposites.
void setComposites(List)
Add the BaseComposites contained in the given
List to this BaseCompositeContainer.
All the BaseComposites that are part of the list of
BaseComposite of the BaseCompositeContainer but
not part of the List given by bcomposites will
be removed from the list of BaseComposite of the
BaseCompositeContainer.
void removeAllComposites()
Removes all BaseComposites from the list of
BaseComposite of the BaseCompositeContainer.
void removeComposite(BaseComposite)
Removes the given BaseComposite from this
BaseCompositeContainer.
void removeComposites(List)
Removes the BaseComposites contained in the given list from
this BaseCompositeContainer.
A CompositeGroup has the ability to manage
BaseComposite objects. The methods to do so are derived from
class BaseCompositeContainer.
A CompositeGroup may be folded, which means that the
BaseComposite objects added to the CompositeGroup
are not drawn to the screen.
A CompositeGroup supports two folded states. These states
are defined by the following constants:
FOLDSTATE_FOLDED
FOLDSTATE_UNFOLDED
The following methods can be used to affect the foldable state and appearance.
int getFoldState()
Returns the state of folding of the CompositeGroup. If the
CompositeGroup is not foldable FOLDSTATE_UNFOLDED
is returned.
void setFoldState(int)
Sets the CompositeGroup to the state of folding given by
state. The supported states of folding are defined through
constants defined in this interface. If the CompositeGroup
is not foldable nothing happens. If the CompositeGroup is
actually in the given state also nothing will happen.
Size getFoldStateButtonSize()
Returns a Size instance that describes the extensions for
the FoldStateButton. The values of the extensions should be given
in inner coordinate system of the CompositeGroup.
Notice that the FoldStateButton is the button that is used to
toggle between the different folding states.
void setFoldStateButtonSize(Size)
Sets the extensions of the FoldStateButton to the extensions of
the Size instance given by size. The values of
the extensions should be given in the inner coordinate system of
the CompositeGroup.
Notice that the FoldStateButton is the button that is used to
toggle between the different folding states.
Size getFoldStateSize(int)
Returns a Size instance that describes the extensions of a
CompositeGroup when it is in a folded state defined by the
constant given by foldstate. These extensions may vary for
different states of folding. The values of the extensions are given in
the coordinate system of the context the CompositeGroup
lies within.
Notice that at the actual state of development only the
FOLDSTATE_FOLDED constant is supported.
void setFoldStateSize(int, Size)
Sets the extensions of a CompositeGroup for the fold state
defined by the constant given by foldstate to the extensions
of the Size instance given by size. The values
of the extensions should be given in the coordinate system of the context
the CompositeGroup lies within.
When setting the extensions for the defined fold state and the
CompositeGroup is actually in that state creates a
ResizeEvent if one of the new extensions is different from
the current extensions for that state.
Notice that at the actual state of development only the
FOLDSTATE_FOLDED and FOLDSTATE_UNFOLDED constants are
supported.
void setFoldable(boolean)
Sets the state of foldability for this CompositeGroup to the
value given by foldable. If the CompositeGroup
is no longer foldable and it is in a fold state different from
FOLDSTATE_UNFOLDED the fold state will be changed to
FOLDSTATE_UNFOLDED.
boolean isFoldable()
Returns a boolean that indicates whether this
CompositeGroup is foldable or not.
void toggleFoldState()
Toggles between the different folding states.
A CompositeGroup object creates additional events above and
beyond a Composite. To be notified about the occurrence of
these events, one has to register an object that implements the
CompositeGroupListener interface.
Some of the events generated by a CompositeGroup are vetoable,
which means that the processing of an event can be programmatically stopped.
In order to veto an event, you have to register a
VetoableCompositeGroupListener.
For more information about this interface, please take a closer look
at the documentation for
VetoableCompositeGroupListener.
For more information about the CompositeGroupListener, please
see interface CompositeGroupListener.
The methods a CompositeGroup provides to support
the event mechanism are:
void addCompositeGroupListener(CompositeGroupListener)
Adds the given CompositeGroupListener to the
CompositeGroups internal structure, such that the listener
is informed about every event that occurs.
void addVetoableCompositeGroupListener(VetoableCompositeGroupListener)
Adds the given VetoableCompositeGroupListener to the
CompositeGroups internal structure, such that the listener
is informed about every event that occurs.
void removeCompositeGroupListener(CompositeGroupListener)
Removes the given CompositeGroupListener from the
CompositeGroups internal structure, such that the listener
is no longer informed about occuring events.
void removeVetoableCompositeGroupListener(VetoableCompositeGroupListener)
Removes the given VetoableCompositeGroupListener from the
CompositeGroups internal structure, such that the listener
is no longer informed about occuring events.
This interface represents the definition of a CompositeGroup that
behaves like a 2-dimensional table, complete with rows and columns. This table
allows a Composite object to be placed inside any cell which may
span multiple columns and rows. The indices of the columns and rows are 1-based,
such that the upper-left cell has the position [1,1]. Columns and rows can be
resized, moved, added, removed and uniquely identified by their headers.
A CompositeTable is made up of a View and a Model.
Embedded Composite objects and properties, such as row and column
count, are part of the model. The view holds visual data, such as widths and
selections. The following lists show to which group the different classes belong:
View
CompositeTable
CompositeTableGrid
SelectionItems
AbstractTableHeaderVisualizer
DefaultTableHeaderVisualizer
CompositeTableSelectionEvent
CompositeTableSelectionListener
Model
CompositeTableModel
DefaultCompositeTableModel
The following figure shows a CompositeTable containing 4 labels positioned
in cells [2,2] (with horizontal spanning), [2,6], [4,2] and cell [4,4] (with a horizontal spanning).
Package table
contains classes that build up the base functionality of the
CompositeTable.
There are three types of events and corresponding listeners that are related
to a CompositeTable:
Model events: Fired when changes are made to the model of the table (for example columns are added).
Composite events: Fired when Composite objects
are added to or removed from the model.
Selection events: Fired when a selection change on the table occurs (for example, a column is selected or a cell is deselected).
The following shows all table-related events and listeners and summarizes their purposes.
Table 2.1. Events and Listeners
| Class or Interface | Purpose |
|---|---|
|
This is the listener interface for receiving |
|
All registered |
The events fired by a CompositeTable can be divided into two parts:
events concerning the model (changes to column or row count, composites
added, etc.) and events concerning the view (cells selected, etc.) part
of the table.
To get notified about changes to selected elements (cells, columns, rows, inlying
objects) of a CompositeTable, you must register an instance of type
CompositeTableSelectionListener with the CompositeTable.
This interface defines just one method:
void tableSelectionChanged(CompositeTableSelectionEvent)
Called on all registered listeners whenever a
CompositeTableSelectionEvent occurs on the
CompositeTable.
A CompositeTableSelectionEvent is fired when a cell, column
or row selection in the CompositeTable has occurred.
The following selection types are distinguished:
int CELL_DESELECTED
A cell was deselected.
int CELL_SELECTED
A cell was selected.
int COLUMN_DESELECTED
A column was deselected.
int COLUMN_SELECTED
A column was selected.
int NOTHING_SELECTED
Indicating that nothing is selected.
int ROW_DESELECTED
A row was deselected.
int ROW_SELECTED
A column was selected.
The table provides various resize modes that ordain how the resizing of a column or row via mouse drag is handled. The following modes are provided:
int RESIZE_LAST
The size of the last column or row is adjusted using the same amount of space, but in the opposite direction.
int RESIZE_NEXT
When the size of a column (respectively row) is adjusted, the size of the neighboring column (row) adjusted using the same amount of space, but in the opposite direction.
int RESIZE_NONE
Just set the size without affecting anything. Used by interally method
applyGeomtry and the CompositeTableBuilder.
int RESIZE_SUBSEQUENT
Columns or rows are adjusted proportionally on a size change.
int RESIZE_TABLE
The entire table becomes larger or smaller when a column or row is resize. Hence all non-affected columns and rows remain untouched.
These modes can be manipulated using these methods:
void setCellResizeEnabled(boolean)
Enables / Disables the resizing of column- and rows via mouse interaction.
int getCellResizeMode()
Returns the auto resize mode of the table. The default mode is
RESIZE_SUBSEQUENT.
void setCellResizeMode(int)
Sets the tables resize mode when table columns or rows are resized.
When no mode is set explicitly the default mode
RESIZE_SUBSEQUENT is used.
boolean isCellResizeEnabled()
Determines whether the resizing of cells is allowed.
All data-related information of a CompositeTable is held in a model.
This model is of type CompositeTableModel and specifies the methods a
CompositeTable needs to update tabular data. This means that whenever
table data needs to be updated (in contrast to its presentation) you have to do this
by speaking to the model.
The default implementation for this interface is
DefaultCompositeTableModel.
To get notified about changes in the model a
CompositeTableModelListener
can be registered (respectively removed) using the following methods:
void addTableModelListener(CompositeTableModelListener)
Adds a listener to the list that is notified each time a change to the tables data model occurs.
void removeTableModelListener(CompositeTableModelListener)
Removes the given listener from the list of listeners.
The following methods are provided to invoke inlying Composite objects:
void clear()
Removes all cells from the table-model. All registered
CompositeTableModelCompositeListeners will be informed about
this change.
Composite getCompositeAt(int, int)
Returns the composite corresponding the cell (if any), null
if there is none. If a Composite spans multiple rows /
columns and the given cell lies within this area, the "hit"
Composite is returned.
Composite getCompositeAt(int, int, boolean)
Returns the composite corresponding the cell (if any), null
if there is none. If a Composite spans multiple rows /
columns and the given cell lies within this area, the "hit"
Composite is returned.
void setCompositeAt(int, int, Composite)
Sets the given Composite into the specified cell. A
CompositeTableException is thrown if there is a conflict
with other set composites.
void setCompositeAt(int, int, int, int, Composite)
Sets the given Composite into the specified area of cells.
A CompositeTableException is thrown if there is a conflict
with other set composites.
List getCompositesInRegion(int, int, int, int)
Returns the Composites lying in the given area (if any).
A composite must have at least one point inside the area to be in the
the returned List. The area does include the column
columnStop and the row rowStop.
void removeCompositeAt(int, int)
Removes the composite located at column,row
or lying within the area "hit" by the given column,
row. All registered
CompositeTableModelCompositeListeners will be informed. If
there is no composite at this position, a
CompositeTableException is thrown.
In summary, whenever you wish to
change the column or row count
set column or row spanning manually
set the value of the column or row header
affect the inlying objects of the table
do it using the table model.
If you would like to be informed about model changes, register a
CompositeTableModelListener via method
addTableModelListener() in the model.
The listener interface defines two methods:
void tableModelChanged(CompositeTableModelEvent)
Invoked whenever a change on the properties of the model occurs. At the time of writing this two changes are distinguished and used:
COLUMN_COUNT_CHANGED
ROW_COUNT_CHANGED
The type can be retrieved by calling the method
getType() on the delivered
CompositeTableModelEvent.
The CompositeFactory provides three different
methods to create new CompositeTable instances:
CompositeTable newCompositeTable(CoordinateSystem)
Creates a new CompositeTable using the
CoordinateSystem given by parameter coordSystem.
CompositeTable newCompositeTable(CoordinateSystem, CompositeTableModel)
Creates a new CompositeTable that uses the given
CoordinateSystem and the given
CompositeTableModel.
CompositeTable newCompositeTable(CoordinateSystem, int, int)
Creates a new CompositeTable with the given number of
columns and rows. The CoordinateSystem to be used is given
by parameter coordSystem.
CompositeTable newCompositeTable(CoordinateSystem, Object[], Object[])
Creates a new CompositeTable with the
CoordinateSystem given by parameter coordSystem.
The column headers of the table are specified with parameter
columnHeaders, the row headers with the given array
rowHeaders. The resulting table will have
length() columns and
length() rows.
Here is a code snippet showing how to set up a simple Table:
Example 2.1. Creating a Simple Table
CompositeFactory factory= CompositeFactory.newInstance();
try
{
CoordinateSystem tmpCoords=
CoordinateSystemPool.parse(
"x=Lin[min=0;max=5600],y=Lin[min=0;max=5400]");
Object[] columnNames= { "C1", "C2", "C3"};
Object[] rowNames= { "R1", "R2", "R3", "R4", "R5"};
CompositeTable table= factory.newCompositeTable(tmpCoords,
columnNames, rowNames);
table.setBoundingBox(500, 4500, 500, 4500);
}
catch(CoordinateSystemParseException e)
{
e.printStackTrace();
}
This table has 3 columns (using the Strings C1, C2, C3 as
column headers) and 5 rows (headers R1, R2, R3, R4, R5).
If you use one of the “model-free” constructors (as we did), a default
CompositeTableModel will be created behind the scenes. See section
“Interface CompositeTableModel” of this
chapter for more detailed information.
This section will show you how to set up a custom header for the table. In our domain,
a Composite that is used as a table header is called a “visualizer.”
Class AbstractTableHeaderVisualizer specifies two abstract methods which have to be
implemented by a derived concrete class. These methods are:
AbstractTableHeaderVisualizer deepCopy()
Returns a deep-copy of this visualizer.
Composite getHeaderVisualizer(Object, boolean, int)
Returns a prepared Composite that will get used as a table
header at the given index. Parameter value holds
the value object to be visualized (normally an object of type
String). The given boolean indicates whether
this cell is selected or not.
The abstract class also provides some non-abstract methods to set properties
common to all visualizer objects, such as setSelectedPaintFormat().
Now let us see how to implement a simple custom visualizer component. Our class
has to extend class AbstractTableHeaderVisualizer and contain a Composite that
holds two inlying Primitive objects of type Rect2D:
public class Ch02_TestTableCellVisualizer
extends AbstractTableHeaderVisualizer
{
private Composite composite;
private Rect2D backRect, foreRect;
// default constructor
public Ch02_TestTableCellVisualizer()
{
CompositeFactory factory= CompositeFactory.newInstance();
try
{
composite=
factory.newComposite(
CoordinateSystemPool.parse(
"x=Lin[min=0;max=400],y=Lin[min=0;max=400]"));
composite.addPrimitive(backRect= new Rect2D());
backRect.set(0, 0, 400, 400);
composite.addPrimitive(foreRect= new Rect2D());
}
catch(CoordinateSystemParseException e)
{
if(Debug.DISPLAY_THROWABLES)
Debug.printThrowable(e);
}
}
private Ch02_TestTableCellVisualizer(
Ch02_TestTableCellVisualizer source)
{
this.composite= source.composite.deepCopy();
}
public AbstractTableHeaderVisualizer deepCopy()
{
return new Ch02_TestTableCellVisualizer(this);
}
The only part missing is the implementation of method
getHeaderVisualizer, which we show in this example:
public Composite getHeaderVisualizer(
Object value,
boolean selected,
int index)
{
if(index != 3) return null;
if (selected)
{
backRect.setPaint(selectedPaintFormat);
foreRect.setPaint(unselectedPaintFormat);
foreRect.set(50, 50, 350, 350);
}
else
{
backRect.setPaint(unselectedPaintFormat);
foreRect.setPaint(selectedPaintFormat);
foreRect.set(100, 100, 300, 300);
}
return composite;
}
Now we set the visualizer so that it is used by the CompositeTable:
// assume table was created
table.setColumnHeaderVisualizer(
new Ch02_TestTableCellVisualizer());
This visualizer is very custom, indeed: it draws a mid-sized rectangle when not
selected and a large one when selected. Notice that the Composite is only
returned for column 3. If null is returned (as it is the case for all
leftover columns), the default visualizer is used. This is what the table will
look like:
Selected:

Unselected:

© 2004, 2005 Tensegrity Software GmbH