001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * SerialLayoutWithJustifications.java
044: *
045: * Created on November 29, 2006, 11:47 AM
046: *
047: * To change this template, choose Tools | Template Manager
048: * and open the template in the editor.
049: */
050:
051: package org.netbeans.modules.compapp.casaeditor.graph;
052:
053: import java.awt.Point;
054: import java.awt.Rectangle;
055: import java.util.Collection;
056: import org.netbeans.api.visual.layout.Layout;
057: import org.netbeans.api.visual.layout.LayoutFactory;
058: import org.netbeans.api.visual.widget.Widget;
059:
060: /**
061: * This is a SerialLayout which modified "justify" for right alignment of children.
062: *
063: * The regular layout can't RIGHT align child to that of parent right bound, because parent bounds are not yet known.
064: * Once all the layout's sizes determined, then "justify" will be called and this justify right align the children.
065: *
066: *
067: * @author rdara
068: */
069: public final class SerialLayoutWithJustifications implements Layout {
070:
071: private boolean verticalOrientation;
072: private LayoutFactory.SerialAlignment alignment;
073: private int gap;
074:
075: public SerialLayoutWithJustifications(boolean verticalOrientation,
076: LayoutFactory.SerialAlignment alignment, int gap) {
077: this .verticalOrientation = verticalOrientation;
078: this .alignment = alignment;
079: this .gap = gap;
080: }
081:
082: public void layout(Widget widget) {
083: int max = 0;
084: Collection<Widget> children = widget.getChildren();
085: if (verticalOrientation) {
086: for (Widget child : children) {
087: Rectangle preferredBounds = child.getPreferredBounds();
088: int i = preferredBounds.width;
089: if (i > max)
090: max = i;
091: }
092: int pos = 0;
093: for (Widget child : children) {
094: Rectangle preferredBounds = child.getPreferredBounds();
095: int x = preferredBounds.x;
096: int y = preferredBounds.y;
097: int width = preferredBounds.width;
098: int height = preferredBounds.height;
099: int lx = -x;
100: int ly = pos - y;
101: switch (alignment) {
102: case CENTER:
103: lx += (max - width) / 2;
104: break;
105: case JUSTIFY:
106: width = max;
107: break;
108: case LEFT_TOP:
109: break;
110: case RIGHT_BOTTOM:
111: lx += max - width;
112: break;
113: }
114: child.resolveBounds(new Point(lx, ly), new Rectangle(x,
115: y, width, height));
116: pos += height + gap;
117: }
118: } else {
119: for (Widget child : children) {
120: Rectangle preferredBounds = child.getPreferredBounds();
121: int i = preferredBounds.height;
122: if (i > max)
123: max = i;
124: }
125: int pos = 0;
126: for (Widget child : children) {
127: Rectangle preferredBounds = child.getPreferredBounds();
128: int x = preferredBounds.x;
129: int y = preferredBounds.y;
130: int width = preferredBounds.width;
131: int height = preferredBounds.height;
132: int lx = pos - x;
133: int ly = -y;
134:
135: switch (alignment) {
136: case CENTER:
137: ly += (max - height) / 2;
138: break;
139: case JUSTIFY:
140: height = max;
141: break;
142: case LEFT_TOP:
143: break;
144: case RIGHT_BOTTOM:
145: ly += max - height;
146: break;
147: }
148: child.resolveBounds(new Point(lx, ly), new Rectangle(x,
149: y, width, height));
150: pos += width + gap;
151: }
152: }
153: }
154:
155: public boolean requiresJustification(Widget widget) {
156: return true;
157: }
158:
159: public void justify(Widget widget) {
160: Rectangle bounds = widget.getParentWidget().getClientArea();
161:
162: if (alignment == LayoutFactory.SerialAlignment.JUSTIFY
163: || alignment == LayoutFactory.SerialAlignment.RIGHT_BOTTOM) {
164: justifyChildren(widget, bounds);
165: }
166:
167: // Ensure the widget stretches to the width of the parent.
168: Rectangle widgetBounds = widget.getPreferredBounds();
169: widgetBounds.width = bounds.width;
170: widget.resolveBounds(widget.getLocation(), widgetBounds);
171: }
172:
173: // right-align the children
174: private void justifyChildren(Widget widget, Rectangle bounds) {
175: int childrenWidth = 0 - gap;
176: for (Widget child : widget.getChildren()) {
177: childrenWidth += child.getPreferredBounds().width;
178: childrenWidth += gap;
179: }
180: int childX = bounds.x + bounds.width - childrenWidth;
181: for (Widget child : widget.getChildren()) {
182: Point location = child.getLocation();
183: Rectangle childBounds = child.getBounds();
184:
185: if (verticalOrientation) {
186: int parentX1 = bounds.x;
187: int parentX2 = parentX1 + bounds.width;
188: int childX1 = location.x + childBounds.x;
189: int childX2 = childX1 + childBounds.width;
190:
191: childBounds.x = Math.min(parentX1, childX1);
192: childBounds.width = Math.max(parentX2, childX2)
193: - childBounds.x;
194: childBounds.x -= location.x;
195: child.resolveBounds(location, childBounds);
196: } else {
197: int parentY1 = bounds.y;
198: int parentY2 = parentY1 + bounds.height;
199: int childY1 = location.y + childBounds.y;
200: int childY2 = childY1 + childBounds.height;
201:
202: childBounds.y = Math.min(parentY1, childY1);
203: childBounds.height = Math.max(parentY2, childY2)
204: - childBounds.y;
205: childBounds.y -= location.y;
206:
207: switch (alignment) {
208: case RIGHT_BOTTOM:
209: location.x = childX;
210: childX += (childBounds.width + gap);
211: child.resolveBounds(location, null);
212: break;
213: case CENTER:
214: case JUSTIFY:
215: case LEFT_TOP:
216: child.resolveBounds(location, childBounds);
217: break;
218: }
219: }
220: }
221: }
222: }
|