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: package org.netbeans.modules.visual.action;
042:
043: import org.netbeans.api.visual.action.AlignWithWidgetCollector;
044: import org.netbeans.api.visual.action.AlignWithMoveDecorator;
045: import org.netbeans.api.visual.widget.LayerWidget;
046: import org.netbeans.api.visual.widget.ConnectionWidget;
047: import org.netbeans.api.visual.widget.Widget;
048:
049: import java.awt.*;
050: import java.util.Collection;
051: import java.util.Arrays;
052: import java.util.Collections;
053:
054: /**
055: * @author David Kaspar
056: */
057: public class AlignWithSupport {
058:
059: private static final int GRAVITY = 10;
060:
061: private AlignWithWidgetCollector collector;
062: private LayerWidget interractionLayer;
063: private AlignWithMoveDecorator decorator;
064:
065: private ConnectionWidget lineWidget1, lineWidget2;
066:
067: public AlignWithSupport(AlignWithWidgetCollector collector,
068: LayerWidget interractionLayer,
069: AlignWithMoveDecorator decorator) {
070: this .collector = collector;
071: this .interractionLayer = interractionLayer;
072: this .decorator = decorator;
073: }
074:
075: protected Point locationSuggested(Widget widget,
076: Rectangle sceneWidgetBounds, Point suggestedLocation,
077: boolean horizontal, boolean vertical, boolean bothSides,
078: boolean snapHack) {
079: Point point = new Point(suggestedLocation);
080: Collection<Rectangle> regions = collector.getRegions(widget);
081:
082: if (horizontal) {
083: boolean snap = false;
084: int xs = 0, x = 0, dx = 0, y1 = 0, y2 = 0;
085:
086: int b1 = sceneWidgetBounds.x;
087: int b2 = sceneWidgetBounds.x + sceneWidgetBounds.width;
088:
089: for (Rectangle rectangle : regions) {
090: int a1 = rectangle.x;
091: int a2 = a1 + rectangle.width;
092:
093: int d;
094: boolean snapNow = false;
095:
096: d = Math.abs(a1 - b1);
097: if ((snap && d < dx) || (!snap && d < GRAVITY)) {
098: snap = snapNow = true;
099: x = xs = a1;
100: dx = d;
101: }
102:
103: if (bothSides) {
104: d = Math.abs(a1 - b2);
105: if ((snap && d < dx) || (!snap && d < GRAVITY)) {
106: snap = snapNow = true;
107: x = a1;
108: xs = a1 - sceneWidgetBounds.width;
109: dx = d;
110: }
111: }
112:
113: d = Math.abs(a2 - b1);
114: if ((snap && d < dx) || (!snap && d < GRAVITY)) {
115: snap = snapNow = true;
116: x = xs = a2;
117: dx = d;
118: }
119:
120: if (bothSides) {
121: d = Math.abs(a2 - b2);
122: if ((snap && d < dx) || (!snap && d < GRAVITY)) {
123: snap = snapNow = true;
124: x = a2;
125: xs = a2 - sceneWidgetBounds.width;
126: dx = d;
127: }
128: }
129:
130: if (snapNow) {
131: y1 = rectangle.y;
132: y2 = rectangle.y + rectangle.height;
133: }
134: }
135:
136: if (snap) {
137: point.x = xs;
138: if (snapHack)
139: point.x -= widget.getBounds().x;
140: }
141:
142: if (interractionLayer != null)
143: lineWidget1
144: .setControlPoints(
145: snap ? Arrays
146: .asList(
147: new Point(
148: x,
149: Math
150: .min(
151: sceneWidgetBounds.y,
152: y1)),
153: new Point(
154: x,
155: Math
156: .max(
157: sceneWidgetBounds.y
158: + sceneWidgetBounds.height,
159: y2)))
160: : Collections
161: .<Point> emptyList(),
162: true);
163: }
164:
165: if (vertical) {
166: boolean snap = false;
167: int ys = 0, y = 0, dy = 0, x1 = 0, x2 = 0;
168:
169: int b1 = sceneWidgetBounds.y;
170: int b2 = sceneWidgetBounds.y + sceneWidgetBounds.height;
171:
172: for (Rectangle rectangle : regions) {
173: int a1 = rectangle.y;
174: int a2 = a1 + rectangle.height;
175:
176: int d;
177: boolean snapNow = false;
178:
179: d = Math.abs(a1 - b1);
180: if ((snap && d < dy) || (!snap && d < GRAVITY)) {
181: snap = snapNow = true;
182: y = ys = a1;
183: dy = d;
184: }
185:
186: d = Math.abs(a1 - b2);
187: if ((snap && d < dy) || (!snap && d < GRAVITY)) {
188: snap = snapNow = true;
189: ys = a1 - sceneWidgetBounds.height;
190: y = a1;
191: dy = d;
192: }
193:
194: d = Math.abs(a2 - b1);
195: if ((snap && d < dy) || (!snap && d < GRAVITY)) {
196: snap = snapNow = true;
197: y = ys = a2;
198: dy = d;
199: }
200:
201: d = Math.abs(a2 - b2);
202: if ((snap && d < dy) || (!snap && d < GRAVITY)) {
203: snap = snapNow = true;
204: ys = a2 - sceneWidgetBounds.height;
205: y = a2;
206: dy = d;
207: }
208:
209: if (snapNow) {
210: x1 = rectangle.x;
211: x2 = rectangle.x + rectangle.width;
212: }
213: }
214: if (snap) {
215: point.y = ys;
216: if (snapHack)
217: point.y -= widget.getBounds().y;
218: }
219:
220: if (interractionLayer != null)
221: lineWidget2.setControlPoints(snap ? Arrays
222: .asList(new Point(Math.min(sceneWidgetBounds.x,
223: x1), y), new Point(Math.max(
224: sceneWidgetBounds.x
225: + sceneWidgetBounds.width, x2),
226: y)) : Collections.<Point> emptyList(),
227: true);
228: }
229:
230: return point;
231: }
232:
233: public void show() {
234: if (interractionLayer != null) {
235: if (lineWidget1 == null)
236: lineWidget1 = decorator
237: .createLineWidget(interractionLayer.getScene());
238: if (lineWidget2 == null)
239: lineWidget2 = decorator
240: .createLineWidget(interractionLayer.getScene());
241: interractionLayer.addChild(lineWidget1);
242: interractionLayer.addChild(lineWidget2);
243: lineWidget1.setControlPoints(
244: Collections.<Point> emptySet(), true);
245: lineWidget2.setControlPoints(
246: Collections.<Point> emptySet(), true);
247: }
248: }
249:
250: public void hide() {
251: if (interractionLayer != null) {
252: interractionLayer.removeChild(lineWidget1);
253: interractionLayer.removeChild(lineWidget2);
254: }
255: }
256:
257: }
|