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.ResizeProvider;
044: import org.netbeans.api.visual.action.ResizeStrategy;
045: import org.netbeans.api.visual.action.WidgetAction;
046: import org.netbeans.api.visual.action.ResizeControlPointResolver;
047: import org.netbeans.api.visual.widget.Widget;
048:
049: import java.awt.*;
050: import java.awt.event.MouseEvent;
051:
052: /**
053: * Rezing a widget based on insets of the widget border.
054: *
055: * @author David Kaspar
056: */
057: public final class ResizeAction extends WidgetAction.LockedAdapter {
058:
059: private ResizeStrategy strategy;
060: private ResizeControlPointResolver resolver;
061: private ResizeProvider provider;
062:
063: private Widget resizingWidget = null;
064: private ResizeProvider.ControlPoint controlPoint;
065: private Rectangle originalSceneRectangle = null;
066: private Insets insets;
067: private Point dragSceneLocation = null;
068:
069: public ResizeAction(ResizeStrategy strategy,
070: ResizeControlPointResolver resolver, ResizeProvider provider) {
071: this .strategy = strategy;
072: this .resolver = resolver;
073: this .provider = provider;
074: }
075:
076: protected boolean isLocked() {
077: return resizingWidget != null;
078: }
079:
080: public State mousePressed(Widget widget, WidgetMouseEvent event) {
081: if (isLocked())
082: return State.createLocked(widget, this );
083: if (event.getButton() == MouseEvent.BUTTON1
084: && event.getClickCount() == 1) {
085: insets = widget.getBorder().getInsets();
086: controlPoint = resolver.resolveControlPoint(widget, event
087: .getPoint());
088: if (controlPoint != null) {
089: resizingWidget = widget;
090: originalSceneRectangle = null;
091: if (widget.isPreferredBoundsSet())
092: originalSceneRectangle = widget
093: .getPreferredBounds();
094: if (originalSceneRectangle == null)
095: originalSceneRectangle = widget.getBounds();
096: if (originalSceneRectangle == null)
097: originalSceneRectangle = widget
098: .getPreferredBounds();
099: dragSceneLocation = widget.convertLocalToScene(event
100: .getPoint());
101: provider.resizingStarted(widget);
102: return State.createLocked(widget, this );
103: }
104: }
105: return State.REJECTED;
106: }
107:
108: public State mouseReleased(Widget widget, WidgetMouseEvent event) {
109: boolean state = resize(widget, event.getPoint());
110: if (state) {
111: resizingWidget = null;
112: provider.resizingFinished(widget);
113: }
114: return state ? State.CONSUMED : State.REJECTED;
115: }
116:
117: public State mouseDragged(Widget widget, WidgetMouseEvent event) {
118: return resize(widget, event.getPoint()) ? State.createLocked(
119: widget, this ) : State.REJECTED;
120: }
121:
122: private boolean resize(Widget widget, Point newLocation) {
123: if (resizingWidget != widget)
124: return false;
125:
126: newLocation = widget.convertLocalToScene(newLocation);
127: int dx = newLocation.x - dragSceneLocation.x;
128: int dy = newLocation.y - dragSceneLocation.y;
129: int minx = insets.left + insets.right;
130: int miny = insets.top + insets.bottom;
131:
132: Rectangle rectangle = new Rectangle(originalSceneRectangle);
133: switch (controlPoint) {
134: case BOTTOM_CENTER:
135: resizeToBottom(miny, rectangle, dy);
136: break;
137: case BOTTOM_LEFT:
138: resizeToLeft(minx, rectangle, dx);
139: resizeToBottom(miny, rectangle, dy);
140: break;
141: case BOTTOM_RIGHT:
142: resizeToRight(minx, rectangle, dx);
143: resizeToBottom(miny, rectangle, dy);
144: break;
145: case CENTER_LEFT:
146: resizeToLeft(minx, rectangle, dx);
147: break;
148: case CENTER_RIGHT:
149: resizeToRight(minx, rectangle, dx);
150: break;
151: case TOP_CENTER:
152: resizeToTop(miny, rectangle, dy);
153: break;
154: case TOP_LEFT:
155: resizeToLeft(minx, rectangle, dx);
156: resizeToTop(miny, rectangle, dy);
157: break;
158: case TOP_RIGHT:
159: resizeToRight(minx, rectangle, dx);
160: resizeToTop(miny, rectangle, dy);
161: break;
162: }
163:
164: widget.setPreferredBounds(strategy.boundsSuggested(widget,
165: originalSceneRectangle, rectangle, controlPoint));
166: return true;
167: }
168:
169: private static void resizeToTop(int miny, Rectangle rectangle,
170: int dy) {
171: if (rectangle.height - dy < miny)
172: dy = rectangle.height - miny;
173: rectangle.y += dy;
174: rectangle.height -= dy;
175: }
176:
177: private static void resizeToBottom(int miny, Rectangle rectangle,
178: int dy) {
179: if (rectangle.height + dy < miny)
180: dy = miny - rectangle.height;
181: rectangle.height += dy;
182: }
183:
184: private static void resizeToLeft(int minx, Rectangle rectangle,
185: int dx) {
186: if (rectangle.width - dx < minx)
187: dx = rectangle.width - minx;
188: rectangle.x += dx;
189: rectangle.width -= dx;
190: }
191:
192: private static void resizeToRight(int minx, Rectangle rectangle,
193: int dx) {
194: if (rectangle.width + dx < minx)
195: dx = minx - rectangle.width;
196: rectangle.width += dx;
197: }
198:
199: // public static class SnapToGridStrategy implements Strategy {
200: //
201: // private int horizontalGridSize;
202: // private int verticalGridSize;
203: //
204: // public SnapToGridStrategy (int horizontalGridSize, int verticalGridSize) {
205: // assert horizontalGridSize > 0 && verticalGridSize > 0;
206: // this.horizontalGridSize = horizontalGridSize;
207: // this.verticalGridSize = verticalGridSize;
208: // }
209: //
210: // public Rectangle boundsSuggested (Widget widget, Rectangle originalBounds, Rectangle suggestedBounds, ControlPoint controlPoint) {
211: // switch (controlPoint) {
212: // case BOTTOM_CENTER:
213: // snapToBottom (suggestedBounds);
214: // break;
215: // case BOTTOM_LEFT:
216: // snapToBottom (suggestedBounds);
217: // snapToLeft (suggestedBounds);
218: // break;
219: // case BOTTOM_RIGHT:
220: // snapToBottom (suggestedBounds);
221: // snapToRight (suggestedBounds);
222: // break;
223: // case CENTER_LEFT:
224: // snapToLeft (suggestedBounds);
225: // break;
226: // case CENTER_RIGHT:
227: // snapToRight (suggestedBounds);
228: // break;
229: // case TOP_CENTER:
230: // snapToTop (suggestedBounds);
231: // break;
232: // case TOP_LEFT:
233: // snapToTop (suggestedBounds);
234: // snapToLeft (suggestedBounds);
235: // break;
236: // case TOP_RIGHT:
237: // snapToTop (suggestedBounds);
238: // snapToRight (suggestedBounds);
239: // break;
240: // }
241: // return suggestedBounds;
242: // }
243: //
244: // }
245:
246: }
|