public abstract class IlvLabelingModel extends Object
IlvLabelingModel
defines a suitable generic API for labels
that have to be automatically positioned with JViews label layout
algorithms.
The label model is similar to the graph model (or Swing's TreeModel and TableModel). Instead of asking programmers to extend their data objects from a predefined base class, it allows the use of any application object as a label or an obstacle. This makes it much easier to add labeling features to existing applications.
All the labeling algorithms provided in JViews are designed to lay out
a labeling model. This allows any application to benefit from the
JViews label layout algorithms, whether or not it uses the JViews
manager (IlvManager
) or the typical JViews labels
(IlvLabel
). However, to make things very
simple for the common case of applications that use an
IlvManager
, it is not mandatory to work directly with the
labeling model. JViews provides a default implementation of the
labeling model (IlvDefaultLabelingModel
) that can be used to
handle labels in an IlvManager
.
The main goal of the labeling model is to tell the labeling algorithm
which are the labels and how to move them, and which are the obstacles
that the labels should not overlap after the movement. An object is
either a label or an obstacle, or neither (that means it is ignored).
To keep the model very generic, it can work with any arbitrary objects
of class java.lang.Object
.
This class is abstract. Since its purpose is not to provide a concrete
implementation of a label data structure, a complete implementation
must be provided by "adapter" classes. To create a concrete labeling
model, you need to subclass the IlvLabelingModel
to
create the adapter class, and you need to provide an implementation
for the abstract methods. A special adapter class, IlvDefaultLabelingModel
, is provided in order to use an IlvManager
as the underlying label container data
structure.
Note that if an application uses the class IlvManager
, the manager can be attached directly to the
label layout instance without explicitly using a labeling model (see
the method
). In this case, the appropriate
labeling model (IlvLabelLayout.attach
IlvDefaultLabelingModel
) will be created
internally. If necessary, it can be retrieved using the method IlvLabelLayout.getLabelingModel()
, which in this case returns an
instance of IlvDefaultLabelingModel
.
The methods defined in this class can be divided into the following categories:
getLabels()
,
moveLabel(Object, double, double, boolean)
, and so on.getObstacles()
,
isObstacle(Object)
, and so on.boundingBox(Object)
, getLabelOverlap(Object, IlvRect, Object, IlvRect, double)
, and so
on.isPolylineObstacle(Object)
), in addition to
the generic methods, because these are likely to become subjects of
optimizations.
To improve performance, you can replace the default implementation of
the nonabstract methods with an overridden version in the adapter
class that is optimized for your particular data structure. The IlvDefaultLabelingModel
provides the optimized methods for the JViews
manager (IlvManager
).
dispose()
after detaching
the label layouts when you no longer need the labeling model instance;
otherwise, some objects may not be garbage collected. This is
necessary only if the labeling model instance is directly created by
your code. Calling dispose()
is not necessary if the labeling
model instance is created internally by the JViews Graph Layout
library, for instance when attaching directly an
IlvManager
to a layout instance using IlvLabelLayout.attach(IlvManager)
.IlvLabelLayout.attach(IlvLabelingModel)
,
IlvLabelLayout.attach(ilog.views.IlvManager)
,
IlvDefaultLabelingModel
Constructor and Description |
---|
IlvLabelingModel()
Creates a new
IlvLabelingModel . |
Modifier and Type | Method and Description |
---|---|
void |
addLabelingModelListener(LabelingModelListener listener)
Adds a listener to listen for modifications of the labeling model.
|
void |
adjustmentEnd()
Notifies the labeling model that this is the end of a series of
events.
|
protected void |
afterAttach(IlvLabelLayout layout)
Notifies the labeling model that it has been attached to a layout.
|
protected void |
afterDetach(IlvLabelLayout layout)
Notifies the labeling model that it has been detached from a layout.
|
void |
afterLayout(IlvLabelLayout layout,
IlvLabelLayoutReport layoutReport,
boolean redraw)
Notifies the labeling model that a layout session has finished.
|
void |
beforeLayout(IlvLabelLayout layout,
boolean redraw)
Notifies the labeling model that a layout session has been started.
|
abstract IlvRect |
boundingBox(Object labelOrObstacle)
Returns the bounding rectangle of a label or an obstacle.
|
IlvLabelingModel |
createLabelingModel(Object subgraph)
Creates a new labeling model for a subgraph.
|
void |
dispose()
Disposes of this
IlvLabelingModel and releases any
resources that it is using. |
protected void |
fireLabelingModelEvent(LabelingModelEvent event)
This method must be called by the adapter classes when the contents
have changed (labels or obstacles were added, moved, or removed).
|
void |
fireLabelingModelEvent(Object obstacleOrLabel,
int eventType,
boolean adjusting)
Notifies the labeling-model-event listeners that labels or obstacles
have been added or removed, or that their geometry has changed
(labels or obstacles were moved or resized).
|
void |
geometryChanged(boolean adjusting,
Object obstacleOrLabel)
Deprecated.
Beginning with JViews 5.5, use the method
fireLabelingModelEvent(Object, int, boolean) instead. |
int |
getInstanceId()
A utility method that returns a unique integer value for each labeling
model instance inside the same Java program.
|
abstract double |
getLabelOverlap(Object label1,
IlvRect bbox1,
Object label2,
IlvRect bbox2,
double minDist)
Returns the overlap between two labels, if the labels would be at the
given positions specified by the passed bounding boxes.
|
abstract Enumeration |
getLabels()
Returns the enumeration of all labels.
|
int |
getLabelsCount()
Returns the number of labels.
|
IlvManager |
getManager()
Returns the
IlvManager that stores the labels and the
obstacles. |
abstract double |
getObstacleOverlap(Object label,
IlvRect labelBBox,
Object obstacle,
IlvRect obstacleBBox,
double minDist)
Returns the overlap between the label and the obstacle, if the label
would be at the given position specified by the passed bounding box.
|
abstract Enumeration |
getObstacles()
Returns the enumeration of all obstacles.
|
int |
getObstaclesCount()
Returns the number of obstacles.
|
double |
getPolylineObstacleOverlap(Object label,
IlvRect labelBBox,
Object polylineObstacle,
IlvPoint[] pts,
double lineWidth,
double minDist)
Returns the overlap between the label and the polyline obstacle, if
the label would be at the given position specified by the passed
bounding box.
|
IlvPoint[] |
getPolylinePoints(Object polylineObstacle)
Returns the points that define the shape of a polyline obstacle.
|
double |
getPolylineWidth(Object polylineObstacle)
Returns the line width of a polyline obstacle.
|
Object |
getProperty(Object labelOrObstacle,
String key)
Returns the value of a property.
|
Object |
getProperty(String key)
Returns the value of a property of the labeling model.
|
boolean |
isBoundingBoxDependent()
Returns
true if two objects overlap only if their
bounding boxes overlap. |
abstract boolean |
isLabel(Object obj)
Returns
true if an object is a valid label and
false otherwise. |
boolean |
isLayoutNeeded(IlvLabelLayout layout)
Returns
true if a given layout that has been already
applied to this manager is still valid. |
abstract boolean |
isObstacle(Object obj)
Returns
true if an object is a valid obstacle and
false otherwise. |
boolean |
isPolylineObstacle(Object obj)
Returns
true if an object is a valid polyline obstacle
and false otherwise. |
abstract void |
moveLabel(Object label,
double x,
double y,
boolean redraw)
Changes the position of the specified label.
|
void |
removeLabelingModelListener(LabelingModelListener listener)
Removes a listener added with
addLabelingModelListener . |
void |
setProperty(Object labelOrObstacle,
String key,
Object value)
Sets the value of a property for a label or an obstacle.
|
void |
setProperty(String key,
Object value)
Sets the value of a property for the labeling model.
|
void |
structureChanged(boolean adjusting,
Object obstacleOrLabel)
Deprecated.
Beginning with JViews 5.5, use the method
fireLabelingModelEvent(Object, int, boolean) instead. |
public void dispose()
IlvLabelingModel
and releases any
resources that it is using. An IlvLabelingModel
object
cannot be used after the dispose
method has been called.
If there are any layouts still attached, they get automatically
detached from the labeling model.Object.finalize()
public final int getInstanceId()
public IlvManager getManager()
IlvManager
that stores the labels and the
obstacles. It returns null
if the labels and obstacles
are not stored by the JViews manager class (IlvManager
).
The default implementation always returns null
. The
method is overridden in the class IlvDefaultLabelingModel
.
public IlvLabelingModel createLabelingModel(Object subgraph)
Subclasses must override this method in order to return a new
instance of the appropriate subclass of
IlvLabelingModel
, encapsulating subgraph
.
subgraph
- The subgraph object.null
public abstract Enumeration getLabels()
getLabelsCount()
public int getLabelsCount()
getLabels()
.getLabels()
public abstract boolean isLabel(Object obj)
true
if an object is a valid label and
false
otherwise.obj
- The object to test.true
if the object is a label.public abstract void moveLabel(Object label, double x, double y, boolean redraw)
x
and
y
coordinates correspond to the top-left corner of the
rectangle that defines the label (see also the method boundingBox(Object)
).label
- The label.x
- The new x-position of the label.y
- The new y-position of the label.redraw
- If true
, the label is redrawn.public abstract double getLabelOverlap(Object label1, IlvRect bbox1, Object label2, IlvRect bbox2, double minDist)
0
indicates that there is no
overlap if the labels are moved to the given positions. For instance,
the size of the overlapped area can be used as the overlap value.
The overlap value should be symmetric, that is, the returned value should be the same for label pairs independent of the order in which the labels are passed as arguments.
label1
- The first label.bbox1
- The bounding box of the first label, translated to the
proposed position of the label.label2
- The second label.bbox2
- The bounding box of the second label, translated to the
proposed position of the label.minDist
- The desired minimal distance between labels.public abstract Enumeration getObstacles()
getObstaclesCount()
public int getObstaclesCount()
getObstacles()
.getObstacles()
public abstract boolean isObstacle(Object obj)
true
if an object is a valid obstacle and
false
otherwise.obj
- The object to test.true
if the object is an obstacle.isPolylineObstacle(java.lang.Object)
public abstract double getObstacleOverlap(Object label, IlvRect labelBBox, Object obstacle, IlvRect obstacleBBox, double minDist)
0
indicates that
there is no overlap if the label is moved to the given position. For
instance, the size of the overlapped area can be used as the overlap
value.label
- The label.labelBBox
- The bounding box of the label, translated to the
proposed position of the label.obstacle
- The obstacle.obstacleBBox
- The bounding box of the obstacle.minDist
- The desired minimal distance between label and obstacle.public boolean isPolylineObstacle(Object obj)
true
if an object is a valid polyline obstacle
and false
otherwise.
Typical polyline obstacles are IlvLine
,
IlvPolyline
, and IlvLinkImage
. If an object
is a polyline obstacle, the method isObstacle(java.lang.Object)
should also
return true
. Some labeling layout algorithms allow you
to handle polyline obstacles in a more efficient way than other
obstacles. If an obstacle is a polyline obstacle, the method
is called instead of the method getPolylineObstacleOverlap
to obtain the overlap value.
getObstacleOverlap
The default implementation always returns false
.
obj
- The object to test.true
if the object is a polyline obstacle.isObstacle(java.lang.Object)
public double getPolylineObstacleOverlap(Object label, IlvRect labelBBox, Object polylineObstacle, IlvPoint[] pts, double lineWidth, double minDist)
0
indicates that there is no overlap if the label is moved to the given
position.
The default implementation simply calls
. Labeling models may override this
method in order to handle polyline obstacles more efficiently. Label
layout algorithms should call this method for polyline obstacles
instead of getObstacleOverlap
. to allow the concrete labeling
model to optimize the treatment of polyline obstacles.
getObstacleOverlap
label
- The label.labelBBox
- The bounding box of the label, translated to the
proposed position of the label.polylineObstacle
- The polyline obstacle.pts
- The points that define the shape of the polyline obstacle.lineWidth
- The line width of the polyline obstacle.minDist
- The desired minimal distance between label and obstacle.isPolylineObstacle(java.lang.Object)
public double getPolylineWidth(Object polylineObstacle)
1
.polylineObstacle
- The polyline obstacle.isPolylineObstacle(java.lang.Object)
public IlvPoint[] getPolylinePoints(Object polylineObstacle)
null
.polylineObstacle
- The polyline obstacle.isPolylineObstacle(java.lang.Object)
public abstract IlvRect boundingBox(Object labelOrObstacle)
Note: The IlvRect
object returned by
this method may be modified using internal methods of JViews.
If the labeling model supports rotated labels, this method returns the unrotated bounding box of the label.
labelOrObstacle
- The label.public boolean isBoundingBoxDependent()
true
if two objects overlap only if their
bounding boxes overlap.
If the method
or getLabelOverlap
always
returns getObstacleOverlap
0
if the bounding boxes of the objects do not
overlap, then this method may return true
. If the method
or getLabelOverlap
may return a
nonzero value even though the bounding boxes of the objects do not
overlap, then this method must return getObstacleOverlap
false
.
If this method returns true
, then the label layout
algorithms may run faster due to possibilities for optimization.
The default implementation returns false
.
public boolean isLayoutNeeded(IlvLabelLayout layout)
true
if a given layout that has been already
applied to this manager is still valid. The method returns
true
if at least one of the following holds:
IlvLabelLayout.isParametersUpToDate()
called on
layout
returns false
.IlvLabelLayout.isGeometryUpToDate()
called on
layout
returns false
.IlvLabelLayout.isStructureUpToDate()
called on
layout
returns false
.false
public void beforeLayout(IlvLabelLayout layout, boolean redraw)
IlvLabelLayout.performLayout()
before the call to the method IlvLabelLayout.layout(boolean)
.
The default implementation does nothing. If necessary, you can override this method to perform preliminary operations before the layout.
layout
- The layout instance that is the origin of the
notification.redraw
- If true
, the layout algorithm will ask the
labeling model to redraw the objects when the method
afterLayout
is called (that is, it will pass
true
for its redraw
argument).afterLayout(ilog.views.graphlayout.labellayout.IlvLabelLayout, ilog.views.graphlayout.labellayout.IlvLabelLayoutReport, boolean)
public void afterLayout(IlvLabelLayout layout, IlvLabelLayoutReport layoutReport, boolean redraw)
IlvLabelLayout.performLayout()
after
the method IlvLabelLayout.layout(boolean)
has finished, even if an
exception is thrown during the layout process.
Note that you can detect whether the layout was performed
successfully using the test layoutReport.getCode() ==
IlvLabelLayoutReport.LAYOUT_DONE
.
The default implementation does nothing. Any implementation of this
method should redraw the objects if the argument redraw
is true
.
layout
- The layout instance that is the origin of the
notification.layoutReport
- The layout report.redraw
- If true
, the layout algorithm asks the
labeling model to redraw the graph.beforeLayout(ilog.views.graphlayout.labellayout.IlvLabelLayout, boolean)
protected void afterAttach(IlvLabelLayout layout)
IlvLabelLayout.attach(IlvLabelingModel)
.
The default implementation does nothing. If necessary, you can override this method in order to perform some operations.
layout
- The layout instance to which the model has been attached.afterDetach(ilog.views.graphlayout.labellayout.IlvLabelLayout)
,
IlvLabelLayout.attach(IlvLabelingModel)
protected void afterDetach(IlvLabelLayout layout)
IlvLabelLayout.detach()
.
The default implementation does nothing. If necessary, you can override this method in order to perform some operations.
layout
- The layout instance from which the model has been
detached.afterAttach(ilog.views.graphlayout.labellayout.IlvLabelLayout)
,
IlvLabelLayout.detach()
public void setProperty(Object labelOrObstacle, String key, Object value)
value
is null
, the property is removed.
Otherwise, the property value is set to value
.
The default implementation uses an internal hash table to store the property. A concrete labeling model that allows you to store properties directly in the labels and obstacles should override this method to gain more efficiency.
labelOrObstacle
- The label or obstacle for which the property is
to be set.key
- The key string for the property.value
- The new value of the property.getProperty(java.lang.Object, java.lang.String)
public Object getProperty(Object labelOrObstacle, String key)
null
if the property does not exist.
The default implementation uses an internal hash table to store the property. A concrete labeling model that allows you to store properties directly in the labels and obstacles should override this method to gain more efficiency.
labelOrObstacle
- The label or obstacle for which the property is
to be retrieved.key
- The key string for the property.setProperty(java.lang.Object, java.lang.String, java.lang.Object)
public void setProperty(String key, Object value)
value
is null
, the property is removed.
Otherwise, the property value is set to value
.
The default implementation uses an internal hash table to store the property. This is the same hash table as used for the properties of labels and obstacles. A concrete labeling model may override this method to gain more efficiency.
key
- The key string for the property.value
- The new value of the property.getProperty(java.lang.Object, java.lang.String)
public Object getProperty(String key)
null
if the property does not exist.
The default implementation uses an internal hash table to store the property. This is the same hash table as used for the properties of labels and obstacles. A concrete labeling model may override this method to gain more efficiency.
key
- The key string for the property.setProperty(java.lang.Object, java.lang.String, java.lang.Object)
public void addLabelingModelListener(LabelingModelListener listener)
listener
- The listener to add.removeLabelingModelListener(ilog.views.graphlayout.labellayout.LabelingModelListener)
public void removeLabelingModelListener(LabelingModelListener listener)
addLabelingModelListener
.listener
- The listener to remove.addLabelingModelListener(ilog.views.graphlayout.labellayout.LabelingModelListener)
public final void fireLabelingModelEvent(Object obstacleOrLabel, int eventType, boolean adjusting)
It is the responsibility of the labeling model subclasses to call
this method any time the contents of the model have changed (for
example, when changes are due to user interaction). The method
constructs the event and then calls fireLabelingModelEvent(LabelingModelEvent)
to pass the event to the
listeners.
This notification is needed to allow the label layout algorithms to
detect changes and avoid performing the label layout when it is not
needed. If a labeling model subclass does not call this method but a
change has occurred in the graph, you need to force a re-layout by
passing a force
flag of true
and calling
the method IlvLabelLayout.performLayout()
.
Furthermore, the notification is used by the default labeling model
(class IlvDefaultLabelingModel
to ensure that IlvLabelLayout.cleanLabel(ilog.views.graphlayout.labellayout.IlvLabelingModel, java.lang.Object)
and IlvLabelLayout.cleanObstacle(ilog.views.graphlayout.labellayout.IlvLabelingModel, java.lang.Object)
are called automatically at the right time. The default labeling
model calls this method with event type LabelingModelEvent.LABEL_REMOVED
or LabelingModelEvent.OBSTACLE_REMOVED
whenever a label or obstacle is
removed. If you do not use the default labeling model or if your
model does not fire these events, the cleanup is not done
automatically, so you need to call these cleaning methods yourself.
obstacleOrLabel
- The object that was added or removed, or
null
if the event concerns unknown obstacles or
labels.eventType
- The type of the event (a combination of the bit
masks, see LabelingModelEvent.getType()
).adjusting
- Indicates whether this event is in a series of
similar events.addLabelingModelListener(ilog.views.graphlayout.labellayout.LabelingModelListener)
,
adjustmentEnd()
,
fireLabelingModelEvent(LabelingModelEvent)
protected void fireLabelingModelEvent(LabelingModelEvent event)
event
- The labeling model event.removeLabelingModelListener(ilog.views.graphlayout.labellayout.LabelingModelListener)
,
addLabelingModelListener(ilog.views.graphlayout.labellayout.LabelingModelListener)
,
fireLabelingModelEvent(Object, int, boolean)
,
adjustmentEnd()
,
LabelingModelEvent
public final void adjustmentEnd()
It is the responsibility of the labeling model subclasses to call this method after a series of adjusting events.
This notification is needed to allow the label layout algorithms to
detect changes and avoid performing the label layout when it is not
needed. If a labeling model subclass does not call this method but a
change has occurred in the graph, you need to force a re-layout by
passing a force
flag of true
and calling
the method IlvLabelLayout.performLayout()
.
public final void structureChanged(boolean adjusting, Object obstacleOrLabel)
fireLabelingModelEvent(Object, int, boolean)
instead.public final void geometryChanged(boolean adjusting, Object obstacleOrLabel)
fireLabelingModelEvent(Object, int, boolean)
instead.© Copyright 2024 Rogue Wave Software, Inc., a Perforce company.. All Rights Reserved.