Using nested managers
Describes nested managers and explains how to create them and work with them.
Explains how to add a manager to a top-level manager with a simple example.
Explains how to optimize the addition of submanagers to a manager.
Describes the methods for retrieving information on the manager hierarchy.
Explains the position and size of a submanager and how the coordinate system works when objects are moved or resized.
Explains how to manipulate graphic objects in a manager with recursion into submanagers.
Describes how to associate views with a nested manager.
Adding a nested manager
The
IlvManager class inherits from the
IlvGraphic class; as a consequence, a manager and a grapher can be added to another manager or grapher just like any other graphic object. To add a manager to a manager, you use the
addObject method of the
IlvManager class.
Example: Adding a nested manager
The following code shows a simple nested manager.
import ilog.views.*;
import ilog.views.graphic.*;
import javax.swing.*;
import java.awt.*;
public class SubManagerExample
{
public static void main(String[] args) {
IlvGraphic obj;
IlvManager toplevel = new IlvManager();
IlvManager subManager = new IlvManager();
obj = new IlvRectangle(new IlvRect(10,10,50,50), false, true);
subManager.addObject(obj, false);
obj = new IlvRectangle(new IlvRect(100,100,50,50), false, true);
subManager.addObject(obj, false);
toplevel.addObject(subManager, false);
obj = new IlvRectangle(new IlvRect(10,200,50,50), false, true);
toplevel.addObject(obj, false);
final IlvManagerView view = new IlvManagerView(toplevel);
view.setBackground(Color.blue);
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
JFrame frame = new JFrame("Sub manager Example");
frame.getContentPane().add(view);
frame.setSize(200,200);
frame.setVisible(true);
}
});
}
This simple example creates two IlvManager objects, the top-level manager (variable toplevel ) that will be displayed in the view and the submanager (variable subManager ). The submanager is added to the top-level manager by the line:
toplevel.addObject(subManager, false);
Two rectangles are also added to the submanager. Another rectangle is added at the top level.
The following figure shows the resulting application.
Submanager example
The white area is the submanager containing two rectangles.
NOTE Adding a manager to a manager can be done to an infinite level. The library will just make sure that you do not create cycles in the hierarchy of nested managers.
Optimizing the addition of nested managers
It is possible to add submanagers to a manager in two different ways:
This first approach requires multiple recalculations of the bounds of the parent manager while filling the submanager. Adding an object to the submanager might not only change the bounds of the submanager but also the bounds of all its ancestor managers.
1. Add the submanager to its parent manager.
2. Fill the submanager
The second approach avoids changing the bounds of all its ancestor managers and is always faster. Generally, it is faster to add a subobject to a manager after all the customizations of the subobject are completed.
1. Fill the submanager.
2. Add it to its parent manager.
However, it is not always possible to control the order in which objects are added to managers. In this case, insertion adjusting sessions help:
manager.setInsertionAdjusting(true);
try {
... add nested managers and nodes recursively in any order ..
} finally {
manager.setInsertionAdjusting(false);
}
This ensures that the performance is optimal even when submanagers and their contents are added in the wrong order. It ensures that the bounding boxes of the manager and its all submanagers are only recalculated when setting the insertion adjusting flag to false. Events related to the change of the bounds of the managers are also delayed until this time.
The insertion adjusting flag needs only to be set at the top level manager, and it will be automatically propagated to all existing and newly created submanagers. The insertion adjusting flag affects only the performance when objects are added. It has no effect when objects are removed.
Traversing nested managers
Once a manager has been added in a manager, it is no different from any other graphic object. Nevertheless, the manager contains a set of methods that allow you to have quick access to the managers added in a manager and to the manager hierarchy in general.
You can obtain an enumeration of the managers present in a submanager using the method
getManagers and a count of how many managers are present with the method
getManagersCount.
The same methods can be applied to a particular layer:
getManagers and
getManagersCount.
Note that these methods will return the submanagers at the first level of the hierarchy only. Using these methods is much more efficient than traversing the list of all objects present in a manager.
You can also traverse up the hierarchy of managers, using the method
getParent.
In the simple example (see
Example: Adding a nested manager) the following line would return
toplevel :
subManager.getParent()
For a manager at the top level, this method returns null.
Coordinate system in nested managers
The position and size of a submanager depend on the position and size of the objects that are contained in the submanager. As a consequence, all objects that are contained in the submanager are always displayed, and the size and position of the submanager may change when a graphic object contained in this manager changes position or size.
Note that in the simple example (see
Example: Adding a nested manager), the position and size of the submanager has not been specified.
As for any graphic object, you can move and resize a submanager using the
moveObject or
reshapeObject methods. In the example you could do something like:
toplevel.moveObject(subManager, 100,100, true)
When a nested manager is resized or moved, the objects contained in the manager do not change position in the submanager coordinate system. The submanager will move because an
affine transformation (an
IlvTransformer) will be specified in the submanager to define a new relative coordinate system for the submanager. In the line for moving the
subManager to
(100,100), the transformation is a simple translation of
(100,100).
To obtain the affine transform that defines the coordinate system of the submanager, you can use the method
getTransformer.
If the submanager has not been moved or reshaped, this returns the identity transformation.
To know what transformation is used to draw a submanager in a specified view, you can use the following method of the
IlvManager class:
getDrawingTransformer.
This method returns the affine transformation used to draw the objects in a manager. If the specified view is a view of the manager, then it simply returns the affine transform of the view; otherwise, the method will compose the transformation of all the parents of the manager and also the transformation of the view to give the result.
Working with graphic objects in nested managers
The API you use to manipulate graphic objects stored in a nested manager is the same as the one you use when working on a top-level manager. For example, you use the
moveObject or
reshapeObject method of the
IlvManager class to move or reshape an object in a nested manager. You also use the
applyToObject method of
IlvManager when modifying a property of a graphic object that changes the bounding box of a graphic object. The only difference for a nested manager is that when a graphic object is stored in a nested manager, changing its size or moving it can change the size of the manager itself, proceeding recursively up the hierarchy of the manager.
The IlvManager class provides some convenient methods for working with graphic objects in nested managers; these methods have a traverse parameter that when set to true means that the method applies also to nested managers in this manager.
You can access all the objects in the hierarchy of managers using the following methods with the traverse parameter set to true :
To return the total number of objects in the hierarchy use the method:
int getCardinal(boolean traverse)
To return an enumeration of all objects use the method:
IlvGraphicEnumeration getObjects(boolean traverse)
You can locate an object under a certain point using:
IlvGraphic getObject(IlvPoint p, IlvManagerView view, boolean traverse)
Finally, you traverse the hierarchy of objects to apply a function:
void map(IlvApplyObject f, Object arg, boolean traverse)
This method applies the function f to all objects of the hierarchy when the traverse parameter is set to true.
void mapIntersects(IlvApplyObject f, Object arg,IlvRect rect, IlvTransformer
t, boolean traverse)
This method applies the function to all graphic objects that intersects the specified rectangle in the hierarchy of nested managers.
void mapInside(IlvApplyObject f, Object arg, IlvRect rect, IlvTransformer t,
boolean traverse)
This method applies the function to all graphic objects that are inside the specified rectangle in the hierarchy of the nested manager.
Some methods allow you to deal with selection and deselection of objects in a hierarchy of nested managers. This is explained in
Selection in nested managers.
Views on a nested manager
It is possible to view the contents of a nested manager in several views (
IlvManagerView) just as you can do for a top-level manager.
Any modification of an object in a nested manager will be reflected in all the views in which the object appears, which are:
All the views of the submanager that contain the object.
All the views of the parent manager, and proceeding recursively.
The association of the view with a submanager is no different from the association of the view for the top-level manager.
Views on nested manager
Copyright © 2018, Rogue Wave Software, Inc. All Rights Reserved.