001: package prefuse.action.layout;
002:
003: import java.awt.Insets;
004: import java.awt.geom.Point2D;
005: import java.awt.geom.Rectangle2D;
006:
007: import prefuse.Display;
008: import prefuse.action.GroupAction;
009: import prefuse.util.PrefuseLib;
010: import prefuse.visual.VisualItem;
011:
012: /**
013: * Abstract base class providing convenience methods for layout algorithms.
014: *
015: * @author <a href="http://jheer.org">jeffrey heer</a>
016: */
017: public abstract class Layout extends GroupAction {
018:
019: /** The explicitly set layout bounds. May be null. */
020: protected Rectangle2D m_bounds = null;
021: /** The explicitly set anchor point at which the layout can
022: * be centered or rooted. May be null. */
023: protected Point2D m_anchor = null;
024:
025: protected boolean m_margin = false;
026: protected Insets m_insets = new Insets(0, 0, 0, 0);
027: protected double[] m_bpts = new double[4];
028: protected Rectangle2D m_tmpb = new Rectangle2D.Double();
029: protected Point2D m_tmpa = new Point2D.Double();
030:
031: // ------------------------------------------------------------------------
032:
033: /**
034: * Create a new Layout.
035: */
036: public Layout() {
037: super ();
038: }
039:
040: /**
041: * Create a new Layout.
042: * @param group the data group to layout.
043: */
044: public Layout(String group) {
045: super (group);
046: }
047:
048: public Layout(String group, long duration) {
049: super (group, duration);
050: }
051:
052: // ------------------------------------------------------------------------
053:
054: /**
055: * Set the margins the layout should observe within its layout bounds.
056: * @param top the top margin, in pixels
057: * @param left the left margin, in pixels
058: * @param bottom the bottom margin, in pixels
059: * @param right the right margin, in pixels
060: */
061: public void setMargin(int top, int left, int bottom, int right) {
062: m_insets.top = top;
063: m_insets.left = left;
064: m_insets.bottom = bottom;
065: m_insets.right = right;
066: m_margin = true;
067: }
068:
069: /**
070: * Returns the bounds in which the layout should be computed. If the
071: * bounds have been explicitly set, that value is used. Otherwise,
072: * an attempt is made to compute the bounds based upon the display
073: * region of the first display found in this action's associated
074: * Visualization.
075: * @return the layout bounds within which to constain the layout.
076: */
077: public Rectangle2D getLayoutBounds() {
078: if (m_bounds != null)
079: return m_bounds;
080:
081: if (m_vis != null && m_vis.getDisplayCount() > 0) {
082: Display d = m_vis.getDisplay(0);
083: Insets i = m_margin ? m_insets : d.getInsets(m_insets);
084: m_bpts[0] = i.left;
085: m_bpts[1] = i.top;
086: m_bpts[2] = d.getWidth() - i.right;
087: m_bpts[3] = d.getHeight() - i.bottom;
088: d.getInverseTransform().transform(m_bpts, 0, m_bpts, 0, 2);
089: m_tmpb.setRect(m_bpts[0], m_bpts[1], m_bpts[2] - m_bpts[0],
090: m_bpts[3] - m_bpts[1]);
091: return m_tmpb;
092: } else {
093: return null;
094: }
095: }
096:
097: /**
098: * Explicitly set the layout bounds. A reference to the input rectangle
099: * instance is maintained, not a copy, and so any subsequent changes to
100: * the rectangle object will also change the layout bounds.
101: * @param b a rectangle specifying the layout bounds. A reference to this
102: * same instance is kept.
103: */
104: public void setLayoutBounds(Rectangle2D b) {
105: m_bounds = b;
106: }
107:
108: /**
109: * Return the layout anchor at which to center or root the layout. How this
110: * point is used (if it is used at all) is dependent on the particular
111: * Layout implementation. If no anchor point has been explicitly set, the
112: * center coordinate for the first display found in this action's
113: * associated Visualization is used, if available.
114: * @return the layout anchor point.
115: */
116: public Point2D getLayoutAnchor() {
117: if (m_anchor != null)
118: return m_anchor;
119:
120: m_tmpa.setLocation(0, 0);
121: if (m_vis != null) {
122: Display d = m_vis.getDisplay(0);
123: m_tmpa.setLocation(d.getWidth() / 2.0, d.getHeight() / 2.0);
124: d.getInverseTransform().transform(m_tmpa, m_tmpa);
125: }
126: return m_tmpa;
127: }
128:
129: /**
130: * Explicitly set the layout anchor point. The provided object will be
131: * used directly (rather than copying its values), so subsequent
132: * changes to that point object will change the layout anchor.
133: * @param a the layout anchor point to use
134: */
135: public void setLayoutAnchor(Point2D a) {
136: m_anchor = a;
137: }
138:
139: /**
140: * Convenience method for setting an x-coordinate. The start value of the
141: * x-coordinate will be set to the current value, and the current and end
142: * values will be set to the provided x-coordinate. If the current value
143: * is not a number (NaN), the x-coordinate of the provided referrer
144: * item (if non null) will be used to set the start coordinate.
145: * @param item the item to set
146: * @param referrer the referrer item to use for the start location if
147: * the current valu eis not a number (NaN)
148: * @param x the x-coordinate value to set. This will be set for both
149: * the current and end values.
150: * @see prefuse.util.PrefuseLib#setX(VisualItem, VisualItem, double)
151: */
152: public void setX(VisualItem item, VisualItem referrer, double x) {
153: PrefuseLib.setX(item, referrer, x);
154: }
155:
156: /**
157: * Convenience method for setting an y-coordinate. The start value of the
158: * y-coordinate will be set to the current value, and the current and end
159: * values will be set to the provided y-coordinate. If the current value
160: * is not a number (NaN), the y-coordinate of the provided referrer
161: * item (if non null) will be used to set the start coordinate.
162: * @param item the item to set
163: * @param referrer the referrer item to use for the start location if
164: * the current valu eis not a number (NaN)
165: * @param y the y-coordinate value to set. This will be set for both
166: * the current and end values.
167: * @see prefuse.util.PrefuseLib#setY(VisualItem, VisualItem, double)
168: */
169: public void setY(VisualItem item, VisualItem referrer, double y) {
170: PrefuseLib.setY(item, referrer, y);
171: }
172:
173: } // end of abstract class Layout
|