Class FigureLayer
- java.lang.Object
-
- diva.canvas.CanvasLayer
-
- diva.canvas.FigureLayer
-
- All Implemented Interfaces:
CanvasComponent
,EventAcceptor
,FigureContainer
,FigureSet
,VisibleComponent
public class FigureLayer extends CanvasLayer implements FigureContainer, EventAcceptor
A figure layer is a layer on which Figures can be drawn. It contains a z-list in which all the contained figures are held, and implements wrappers for most of the z-list methods to provide flexible access to the contained figures. Figures are also stored at contiguous integer indexes, with index zero being the "topmost" figure and the highest index being the "lowest" figure.FigureLayer responds to events on figures themselves by forwarding the events to interactors attached to a hit figure. It does not support events on the layer itself (see EventLayer for that).
- Version:
- $Id$
- Author:
- John Reekie
- Pt.AcceptedRating:
- Yellow
-
-
Constructor Summary
Constructors Constructor Description FigureLayer()
Create a new figure layer that is not in a pane.FigureLayer(CanvasPane pane)
Create a new figure layer within the given pane.FigureLayer(CanvasPane pane, ZList zlist)
Create a new figure layer within the given pane and with the given ZList to hold the figures it contains.FigureLayer(ZList zlist)
Create a new figure layer with the given ZList to hold its figures.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
add(int index, Figure f)
Insert a figure into the layer at the given position.void
add(Figure f)
Add a figure to the layer.void
clear()
Removes all of the figures from this layer.boolean
contains(Figure f)
Test if the layer contains the given figure.void
decorate(Figure child, FigureDecorator decorator)
Decorate a child figure, replacing the child figure with the decorator.void
dispatchEvent(java.awt.AWTEvent event)
Dispatch an AWT event on this layer.java.util.Iterator
figures()
Return an iteration of the figures in this container.java.util.Iterator
figuresFromBack()
Return an iteration of the figures in this container, from back to front.java.util.Iterator
figuresFromFront()
Return an iteration of the figures in this container, from front to back.Figure
get(int index)
Get the figure at the given index.Figure
getCurrentFigure()
Return the figure that the mouse pointer is currently over, or null if none.protected Figure
getFigure(LayerEvent e)
Return the figure pointed to by the given LayerEvent.int
getFigureCount()
Return the number of figures in this layer.ZList
getFigures()
Get the internal z-list.java.awt.geom.Rectangle2D
getLayerBounds()
Get the bounds of the shapes draw in this layer.double
getPickHalo()
Get the "pick halo".java.lang.String
getToolTipText(LayerEvent e)
Get the toolTipText for the point in the given LayerEvent.void
grabPointer(LayerEvent e, Figure f)
"Grab" the pointer.int
indexOf(Figure f)
Return the index of the given figure.boolean
isEnabled()
Test the enabled flag of this layer.boolean
isVisible()
Test the visibility flag of this layer.void
paint(java.awt.Graphics2D g)
Paint this layer onto a 2D graphics object.void
paint(java.awt.Graphics2D g, java.awt.geom.Rectangle2D region)
Paint this layer onto a 2D graphics object, within the given region.Figure
pick(java.awt.geom.Rectangle2D region)
Get the picked figure.Figure
pick(java.awt.geom.Rectangle2D region, Filter filter)
Get the picked figure.protected void
processLayerEvent(LayerEvent e)
Process a layer event.protected void
processLayerMotionEvent(LayerEvent e)
Process a layer motion event.void
remove(int index)
Remove the figure at the given position in the list.void
remove(Figure f)
Remove the given figure from this layer.void
repaint(java.awt.geom.Rectangle2D region)
Repaint all figures that intersect the given rectangle.void
setEnabled(boolean flag)
Set the enabled flag of this layer.void
setIndex(int index, Figure f)
Set the index of the given figure.void
setPickHalo(double halo)
Set the "pick halo".void
setVisible(boolean flag)
Set the visibility flag of this layer.void
undecorate(FigureDecorator decorator)
Remove a figure from the given decorator and add it back into this container.-
Methods inherited from class diva.canvas.CanvasLayer
getCanvasPane, getParent, getTransformContext, repaint, repaint, setParent
-
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
-
Methods inherited from interface diva.canvas.CanvasComponent
getParent, getTransformContext, repaint, repaint
-
-
-
-
Constructor Detail
-
FigureLayer
public FigureLayer()
Create a new figure layer that is not in a pane. The layer will not be displayed, and its coordinate transformation will be as though it were a one-to-one mapping. Use of this constructor is strongly discouraged, as many of the geometry-related methods expect to see a pane.
-
FigureLayer
public FigureLayer(CanvasPane pane)
Create a new figure layer within the given pane.- Parameters:
pane
- The given pane.
-
FigureLayer
public FigureLayer(CanvasPane pane, ZList zlist)
Create a new figure layer within the given pane and with the given ZList to hold the figures it contains.- Parameters:
pane
- The given pane.zlist
- The given zlist.
-
FigureLayer
public FigureLayer(ZList zlist)
Create a new figure layer with the given ZList to hold its figures. This can be used to create a more efficient z-list than the default, which is an instance of BasicZList.- Parameters:
zlist
- The given zlist.
-
-
Method Detail
-
add
public void add(Figure f)
Add a figure to the layer. The figure is added to the ZList, and the figure's layer and parent fields set appropriately. The figure will be painted over the top of all existing figures. It does not check whether the figure is already in the layer -- clients clients are therefore responsible for being bug-free.- Specified by:
add
in interfaceFigureContainer
- Parameters:
f
- The figure to be added
-
add
public void add(int index, Figure f)
Insert a figure into the layer at the given position. To insert the figure just in front of some other figure, use getIndex() to get the other figure's index, and pass index as the first argument. To insert the figure just behind some other figure, pass index+1 as the first argument. To insert so the figure displays over the top of other figures, insert at zero.Clients should assume that an implementation of this method does not check if the figure is already contained -- clients are therefore responsible for being bug-free.
- Parameters:
index
- The indexf
- The figure to be added.
-
clear
public void clear()
Removes all of the figures from this layer.
-
contains
public boolean contains(Figure f)
Test if the layer contains the given figure. Note that, in general, a much better way of making this same test is to check if the parent of the figure is the same object as this layer.- Specified by:
contains
in interfaceFigureContainer
- Specified by:
contains
in interfaceFigureSet
- Parameters:
f
- The figure to be checked.- Returns:
- true if the figure is contained.
-
decorate
public void decorate(Figure child, FigureDecorator decorator)
Decorate a child figure, replacing the child figure with the decorator.- Specified by:
decorate
in interfaceFigureContainer
- Parameters:
child
- The child figure.decorator
- The decorator.
-
dispatchEvent
public void dispatchEvent(java.awt.AWTEvent event)
Dispatch an AWT event on this layer. If the layer is not enabled, return immediately. Otherwise process the event according to its type. If the event represents a mouse click, drag, or release, call the protected method processLayerEvent; if it represents a mouse movement, call the protected method processLayerMotionEvent. Currently other events types are not handled.- Specified by:
dispatchEvent
in interfaceEventAcceptor
- Parameters:
event
- the event.
-
figures
public java.util.Iterator figures()
Return an iteration of the figures in this container. The order in which figures are iterated is undefined.
-
figuresFromBack
public java.util.Iterator figuresFromBack()
Return an iteration of the figures in this container, from back to front. This is the order in which figures should normally be painted.- Specified by:
figuresFromBack
in interfaceFigureSet
- Returns:
- The iterator
-
figuresFromFront
public java.util.Iterator figuresFromFront()
Return an iteration of the figures in this container, from front to back. This is the order in which events should normally be intercepted.- Specified by:
figuresFromFront
in interfaceFigureSet
- Returns:
- The iterator
-
get
public Figure get(int index)
Get the figure at the given index. Indexes are contiguous from zero to getFigureCount()-1, with figures at lower indexes being displayed "on top of" figures with higher indexes.- Parameters:
index
- The given index- Returns:
- The figure at the given index
-
getFigureCount
public int getFigureCount()
Return the number of figures in this layer.- Specified by:
getFigureCount
in interfaceFigureContainer
- Returns:
- The number of figures.
-
getCurrentFigure
public Figure getCurrentFigure()
Return the figure that the mouse pointer is currently over, or null if none.- Returns:
- The figure the mouse is currently over.
-
getFigures
public ZList getFigures()
Get the internal z-list. Clients must not modify the z-list, but can use it for making queries on its contents.- Returns:
- The internal z-list.
-
getLayerBounds
public java.awt.geom.Rectangle2D getLayerBounds()
Get the bounds of the shapes draw in this layer. In this class, we return the bounds of all the figures in the z-list.- Overrides:
getLayerBounds
in classCanvasLayer
- Returns:
- The bounds of this layer.
-
getPickHalo
public final double getPickHalo()
Get the "pick halo". This is the distance in either axis that an object can be from the mouse to be considered hit.- Returns:
- the pick halo.
- See Also:
setPickHalo(double)
-
grabPointer
public void grabPointer(LayerEvent e, Figure f)
"Grab" the pointer. Typically, this method will be called from an Interactor class in response to a mousePressed() event. The effect of calling this method is to make the series of mouse events up to and including the mouseReleased() event appear to be originating from the figure f rather than the actual figure that was clicked on. For example, if clicking and dragging on a graph node creates and the drags a new edge, this method will be called after constructing the edge to make the edge itself handle the mouse drag events instead of the node.- Parameters:
e
- The LayerEventf
- The figure
-
getToolTipText
public java.lang.String getToolTipText(LayerEvent e)
Get the toolTipText for the point in the given LayerEvent. This method starts with the figure that is set by the mouse motion events when the pointer moves over a figure. Starting with that figure, it walks up the tree until it finds a figure that returns a tool tip, or until it reaches a root figure. If it finds a tool tip, it returns it, otherwise it returns null.- Overrides:
getToolTipText
in classCanvasLayer
- Parameters:
e
- The layer event, ignored in this class.- Returns:
- This method always returns null.
-
indexOf
public int indexOf(Figure f)
Return the index of the given figure. Figures with a higher index are drawn behind figures with a lower index.- Parameters:
f
- The figure- Returns:
- The index of the given figure
-
isEnabled
public final boolean isEnabled()
Test the enabled flag of this layer. Note that this flag does not indicate whether the layer is actually enabled, as its pane or one if its ancestors may not be enabled.- Specified by:
isEnabled
in interfaceEventAcceptor
- Returns:
- true if the object is prepared to handle events with processEvent()
-
isVisible
public final boolean isVisible()
Test the visibility flag of this layer. Note that this flag does not indicate whether the layer is actually visible on the screen, as its pane or one if its ancestors may not be visible.- Specified by:
isVisible
in interfaceVisibleComponent
- Returns:
- true if the object is visible.
-
paint
public void paint(java.awt.Graphics2D g)
Paint this layer onto a 2D graphics object. If the layer is not visible, return immediately. Otherwise paint all figures from back to front.- Specified by:
paint
in interfaceVisibleComponent
- Parameters:
g
- The 2D graphics object that this object it to be painted upon.
-
paint
public void paint(java.awt.Graphics2D g, java.awt.geom.Rectangle2D region)
Paint this layer onto a 2D graphics object, within the given region. If the layer is not visible, return immediately. Otherwise paint all figures that overlap the given region, from back to front.- Specified by:
paint
in interfaceVisibleComponent
- Parameters:
g
- The 2D graphics object that this object it to be painted upon.region
- The region.
-
pick
public Figure pick(java.awt.geom.Rectangle2D region)
Get the picked figure. This method recursively traverses the tree until it finds a figure that is "hit" by the region. Note that a region is given instead of a point so that "hysteresis" can be implemented. If no figure is picked, return null. The region should not have zero size, or no figure will be hit.- Specified by:
pick
in interfaceFigureContainer
- Parameters:
region
- The rectangle- Returns:
- The figure
-
pick
public Figure pick(java.awt.geom.Rectangle2D region, Filter filter)
Get the picked figure. This method recursively traverses the tree until it finds a figure that is "hit" by the region. Note that a region is given instead of a point so that "hysteresis" can be implemented. If no figure is picked, return null. The region should not have zero size, or no figure will be hit.- Specified by:
pick
in interfaceFigureContainer
- Parameters:
region
- The rectanglefilter
- The filter- Returns:
- the Figure or null.
-
remove
public void remove(Figure f)
Remove the given figure from this layer. The figure's layer is set to null.- Specified by:
remove
in interfaceFigureContainer
- Parameters:
f
- The figure to be removed
-
remove
public void remove(int index)
Remove the figure at the given position in the list. The figure's layer is set to null.- Parameters:
index
- The given position.
-
repaint
public void repaint(java.awt.geom.Rectangle2D region)
Repaint all figures that intersect the given rectangle.- Parameters:
region
- The given rectangle
-
setEnabled
public final void setEnabled(boolean flag)
Set the enabled flag of this layer. If the flag is false, then the layer will not respond to user input events.- Specified by:
setEnabled
in interfaceEventAcceptor
- Parameters:
flag
- True if the object is prepared to handle events with processEvent();
-
setPickHalo
public final void setPickHalo(double halo)
Set the "pick halo". This is the distance a figure can be from the mouse in either axis to be considered hit by the mouse. By default, it it set to 0.5, meaning that the hit detection rectangle is 1.0 along each side.- Parameters:
halo
- The pick halo- See Also:
getPickHalo()
-
setIndex
public void setIndex(int index, Figure f)
Set the index of the given figure. That is, move it in the display list to the given position. To move the figure to just in front of some other figure, use getIndex() to get the other figure's index, and pass index as the first argument. To move the figure to just behind some other figure, pass index+1 as the first argument. (Other figures will have their indexes changed accordingly.)Note that this method does not check if the figure is already contained -- clients are therefore responsible for being bug-free.
- Parameters:
index
- The index to be setf
- The figure- Throws:
java.lang.IndexOutOfBoundsException
- The new index is out of range.
-
setVisible
public final void setVisible(boolean flag)
Set the visibility flag of this layer. If the flag is false, then the layer will not be drawn on the screen.- Specified by:
setVisible
in interfaceVisibleComponent
- Parameters:
flag
- True if this object is to be visible.
-
undecorate
public void undecorate(FigureDecorator decorator)
Remove a figure from the given decorator and add it back into this container.- Specified by:
undecorate
in interfaceFigureContainer
- Parameters:
decorator
- The decorator
-
getFigure
protected final Figure getFigure(LayerEvent e)
Return the figure pointed to by the given LayerEvent. If there is no figure, then return null.- Parameters:
e
- The given LayerEvent- Returns:
- The figure or null
-
processLayerEvent
protected void processLayerEvent(LayerEvent e)
Process a layer event. The behaviour of this method depends on the action type. If it is MOUSE_PRESSED, then it recurses down the figure tree searching for the top-most figure under the cursor. (If a figure has been hit on its transparent part, then it will not be considered to be above another figure -- the method Figure.hits() determines whether a figure gets the event.) When it finds it, it remembers it, and then proceeds back up the tree, passing the event to the event dispatcher of any figures that have one. After each such call, if the event has been consumed, then the upwards-traversal stops. Finally, if this layer is reached, and the event has not been consumed, then any registered LayerListeners are called. (Or should they be notified in any case?)If the event type is MOUSE_DRAGGED or MOUSE_RELEASED, then the downwards recursion is skipped, and the upwards propagation is begun from the figure remembered from the MOUSE_PRESSED processing. Again, the propagation stops when the event is consumed.
Note: the above strategy will not work with more than one input device. Is there anything in MouseEvent that allows us to identify the input device?
- Parameters:
e
- The LayerEvent
-
processLayerMotionEvent
protected void processLayerMotionEvent(LayerEvent e)
Process a layer motion event. The behavior of this method depends on the action type. If the action is MOUSE_ENTERED. then the figure tree is scanned to find if the mouse is now over a figure, and the event is dispatched to that figure if so. If the action is MOUSE_MOVED, then the tree is scanned again to find the figure currently under the mouse; if it is different, then leave and enter events are generated on the previous and current figures (either may not exist); otherwise a motion event is generated on the current figure. If the action is MOUSE_EXITED, then the current figure, if there is one, has an exit event sent to it. In all of these cases the event is propagated from the current figure up the hierarchy until consumed.- Parameters:
e
- The LayerEvent
-
-