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.visualweb.designer;
042:
043: import java.awt.Color;
044: import java.awt.Cursor;
045: import java.awt.Graphics;
046: import java.awt.Point;
047: import java.awt.Rectangle;
048: import java.awt.event.InputEvent;
049: import java.awt.event.KeyEvent;
050: import java.awt.event.KeyListener;
051: import java.awt.event.MouseEvent;
052:
053: import javax.swing.ImageIcon;
054:
055: import org.w3c.dom.Element;
056:
057: import org.netbeans.modules.visualweb.css2.CssBox;
058:
059: /**
060: * Handle user interaction for a Table Resize operation; this refers
061: * to resizing the internal rows and columns. The overall table size itself
062: * is handled by the generic Resizer as for any other component.
063: *
064: * @todo Handle simultaneous row and column resizing?
065: * @todo I need some kind of user gesture for removing/unconstraining the span size
066: *
067: * @author Tor Norbye
068: */
069: public class TableResizer extends Interaction implements KeyListener {
070: /* Restore previous cursor after operation. */
071: protected transient Cursor previousCursor = null;
072: private WebForm webform;
073: private Element element;
074: private int prevX = -500;
075: private int prevY = -500;
076: private int prevMouseX = -500;
077: private int prevMouseY = -500;
078: // private MarkupDesignBean bean;
079: // private MarkupTableDesignInfo designInfo;
080: private Element tableComponentRootElement;
081:
082: private int direction;
083: private boolean leftTopSide;
084: private int spanLeft;
085: private int spanTop;
086: private int originalSize;
087: private int otherSize;
088: private int minimum;
089: private int maximum;
090: private int row;
091: private int column;
092:
093: /** Current size of the rectangle being resized. */
094: private Rectangle currentSize = null;
095:
096: /**
097: * Create a resizer which tracks resize mouse operations.
098: * @param webform The webform associated with the resized table
099: * @param bean The table component
100: * @param designInfo The markup table design info which coordinates model updates to the table
101: * @param direction CssBox.X_AXIS if we are resizing a row, CssBox.Y_AXIS if we
102: * are resizing a column.
103: * @param leftTopSide If you're resizing the column by dragging on the left side
104: * or the row by dragging on the top side, pass in true, otherwise false.
105: * @param spanLeft The x coordinate of the row or column (span) being resized
106: * @param spanTop The y coordinate of the row or column (span) being resized
107: * @param spanSize The current width or height of the row or column (span)
108: * @param otherSize The size of the other dimension of the row/column. This is typically
109: * the table height (if resizing a column) or the table width (if resizing a row)
110: * @param minimum The minimum size of the span. This value is not allowed to be negative.
111: * @param maximum The maximum size of the span. Pass in Integer.MAX_VALUE for unconstrained size.
112: */
113: public TableResizer(WebForm webform, /*MarkupDesignBean bean, MarkupTableDesignInfo designInfo,*/
114: Element tableComponentRootElement, int direction,
115: boolean leftTopSide, int spanLeft, int spanTop,
116: int spanSize, int otherSize, int minimum, int maximum,
117: int row, int column, Element element) {
118: this .webform = webform;
119: // this.bean = bean;
120: // this.designInfo = designInfo;
121: this .tableComponentRootElement = tableComponentRootElement;
122:
123: this .direction = direction;
124: this .leftTopSide = leftTopSide;
125: this .spanLeft = spanLeft;
126: this .spanTop = spanTop;
127: this .originalSize = spanSize;
128: this .otherSize = otherSize;
129: this .minimum = minimum;
130: this .maximum = maximum;
131: this .row = row;
132: this .column = column;
133: this .element = element;
134:
135: assert minimum >= 0;
136: assert minimum <= maximum;
137: }
138:
139: /** Cancel operation */
140: public void cancel(DesignerPane pane) {
141: pane.removeKeyListener(this );
142: cleanup(pane);
143: currentSize = null;
144: }
145:
146: private void cleanup(DesignerPane pane) {
147: // Restore the cursor to normal
148: pane.setCursor(previousCursor);
149:
150: // Restore status line
151: // StatusDisplayer_RAVE.getRaveDefault().clearPositionLabel();
152: // StatusDisplayer.getDefault().setStatusText(""); // TEMP
153:
154: // Clear
155: if (prevX != -500) {
156: Rectangle dirty = new Rectangle();
157: resize(dirty, prevX, prevY);
158: dirty.width++;
159: dirty.height++;
160: pane.repaint(dirty);
161: }
162: }
163:
164: /** When the mouse press is released, get rid of the drawn resizer,
165: * and ask the selection manager to select all the components contained
166: * within the resizer bounds.
167: */
168: public void mouseReleased(MouseEvent e) {
169: if ((e != null) && !e.isConsumed()) {
170: Point p = e.getPoint();
171: DesignerPane pane = webform.getPane();
172: pane.removeKeyListener(this );
173:
174: int x = p.x;
175: int y = p.y;
176:
177: Rectangle r = new Rectangle();
178: resize(r, x, y);
179:
180: // Set the column size
181: if (direction == CssBox.Y_AXIS) {
182: // designInfo.resizeColumn(bean, column, r.width);
183: webform.getDomProviderService().resizeColumn(
184: tableComponentRootElement, column, r.width);
185: } else {
186: assert direction == CssBox.X_AXIS;
187: // designInfo.resizeRow(bean, row, r.height);
188: webform.getDomProviderService().resizeRow(
189: tableComponentRootElement, row, r.height);
190: }
191:
192: cleanup(pane);
193:
194: e.consume();
195: }
196: }
197:
198: /**
199: * Moves the dragging rectangles
200: */
201: public void mouseDragged(MouseEvent e) {
202: Point p = e.getPoint();
203: prevMouseX = p.x;
204: prevMouseY = p.y;
205: update(e, p.x, p.y);
206: }
207:
208: /** Compute the visual dimensions of the resize rectangle anchored
209: * from (spanLeft, spanTop) to the given coordinate, constrained by
210: * the minimum and maximum allowed size for the table.
211: */
212: private void resize(Rectangle r, int x, int y) {
213: r.x = spanLeft;
214: r.y = spanTop;
215:
216: int size = 0;
217:
218: switch (direction) {
219: case CssBox.X_AXIS:
220:
221: if (leftTopSide) {
222: size = originalSize - (y - spanTop);
223: r.y = (spanTop + originalSize) - size;
224: } else {
225: size = y - spanTop;
226: }
227:
228: break;
229:
230: case CssBox.Y_AXIS:
231:
232: if (leftTopSide) {
233: size = originalSize - (x - spanLeft);
234: r.x = (spanLeft + originalSize) - size;
235: } else {
236: size = x - spanLeft;
237: }
238:
239: break;
240: }
241:
242: if (size < minimum) {
243: size = minimum;
244: }
245:
246: if (size > maximum) {
247: size = maximum;
248: }
249:
250: // Assign sizes, but allow table info to supply constraints too
251: switch (direction) {
252: case CssBox.X_AXIS:
253: r.width = otherSize;
254: // size = designInfo.testResizeRow(bean, row, column, size);
255: size = webform.getDomProviderService().testResizeRow(
256: tableComponentRootElement, row, column, size);
257:
258: if (size == -1) { // VERY surprising behavior by the table design info
259: size = 0;
260: }
261:
262: r.height = size;
263:
264: break;
265:
266: case CssBox.Y_AXIS:
267: // size = designInfo.testResizeColumn(bean, row, column, size);
268: size = webform.getDomProviderService().testResizeColumn(
269: tableComponentRootElement, row, column, size);
270:
271: if (size == -1) { // VERY surprising behavior by the table design info
272: size = 0;
273: }
274:
275: r.width = size;
276: r.height = otherSize;
277:
278: break;
279: }
280: }
281:
282: /** Draw the resize rectangle */
283: public void paint(Graphics g) {
284: if (currentSize != null) {
285: if (DesignerPane.useAlpha) {
286: g.setColor(webform.getColors().resizerColor);
287: g.fillRect(currentSize.x + 1, currentSize.y + 1,
288: currentSize.width - 1, currentSize.height - 1);
289: g.setColor(webform.getColors().resizerColorBorder);
290: } else {
291: g.setColor(Color.BLACK);
292: }
293:
294: g.drawRect(currentSize.x, currentSize.y, currentSize.width,
295: currentSize.height);
296: }
297: }
298:
299: /**
300: * Start the resizer by setting the dragging cursor and
301: * drawing dragging rectangles.
302: */
303: public void mousePressed(MouseEvent e) {
304: if (!e.isConsumed()) {
305: Point p = e.getPoint();
306: prevMouseX = p.x;
307: prevMouseY = p.y;
308:
309: DesignerPane pane = webform.getPane();
310: pane.addKeyListener(this );
311:
312: previousCursor = pane.getCursor();
313: pane.setCursor(Cursor.getPredefinedCursor(direction));
314:
315: update(e, prevMouseX, prevMouseY);
316:
317: ImageIcon imgIcon = new ImageIcon(
318: TableResizer.class
319: .getResource("/org/netbeans/modules/visualweb/designer/resources/drag_resize.gif"));
320: // StatusDisplayer_RAVE.getRaveDefault().setPositionLabelIcon(imgIcon);
321:
322: e.consume();
323: }
324: }
325:
326: private void update(InputEvent e, int px, int py) {
327: if (!e.isConsumed()) {
328: DesignerPane pane = webform.getPane();
329:
330: Rectangle dirty;
331:
332: if (currentSize != null) {
333: dirty = currentSize;
334: dirty.width++;
335: dirty.height++;
336: } else {
337: dirty = new Rectangle();
338: }
339:
340: prevX = px;
341: prevY = py;
342: currentSize = new Rectangle();
343: resize(currentSize, prevX, prevY);
344: dirty.add(currentSize.x, currentSize.y);
345: dirty.add(currentSize.x + currentSize.width, currentSize.y
346: + currentSize.height);
347: dirty.width++;
348: dirty.height++;
349: pane.repaint(dirty);
350:
351: int w = currentSize.width;
352: int h = currentSize.height;
353:
354: if (w < 0) {
355: w = 0;
356: }
357:
358: if (h < 0) {
359: h = 0;
360: }
361:
362: int size = (direction == CssBox.X_AXIS) ? currentSize.height
363: : currentSize.width;
364:
365: // StatusDisplayer_RAVE.getRaveDefault().setPositionLabelText(Integer.toString(size));
366: // StatusDisplayer.getDefault().setStatusText(Integer.toString(size));
367:
368: e.consume();
369: }
370: }
371:
372: // --- implements KeyListener ---
373: public void keyPressed(KeyEvent e) {
374: // Not yet used
375: // if (snapDisabled != e.isShiftDown()) {
376: // update(e, prevMouseX, prevMouseY);
377: // }
378: }
379:
380: public void keyReleased(KeyEvent e) {
381: // Not yet used
382: // if (snapDisabled != e.isShiftDown()) {
383: // update(e, prevMouseX, prevMouseY);
384: // }
385: }
386:
387: public void keyTyped(KeyEvent e) {
388: }
389: }
|