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-2006 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: package org.netbeans.modules.apisupport.project.ui.customizer;
043:
044: import java.awt.BasicStroke;
045: import java.awt.Color;
046: import java.awt.Cursor;
047: import java.awt.Dimension;
048: import java.awt.Graphics;
049: import java.awt.Graphics2D;
050: import java.awt.Point;
051: import java.awt.Rectangle;
052: import java.awt.Stroke;
053: import java.awt.datatransfer.DataFlavor;
054: import java.awt.datatransfer.StringSelection;
055: import java.awt.dnd.DnDConstants;
056: import java.awt.dnd.DragGestureEvent;
057: import java.awt.dnd.DragGestureListener;
058: import java.awt.dnd.DragGestureRecognizer;
059: import java.awt.dnd.DragSource;
060: import java.awt.dnd.DragSourceDragEvent;
061: import java.awt.dnd.DragSourceDropEvent;
062: import java.awt.dnd.DragSourceEvent;
063: import java.awt.dnd.DragSourceListener;
064: import java.awt.dnd.DropTarget;
065: import java.awt.dnd.DropTargetDragEvent;
066: import java.awt.dnd.DropTargetDropEvent;
067: import java.awt.dnd.DropTargetEvent;
068: import java.awt.dnd.DropTargetListener;
069: import java.awt.event.MouseEvent;
070: import java.awt.event.MouseMotionListener;
071: import java.awt.geom.Line2D;
072: import java.awt.geom.Rectangle2D;
073: import java.util.ArrayList;
074: import java.util.Iterator;
075: import java.util.List;
076: import javax.swing.JComponent;
077:
078: /**
079: *
080: * @author Radek Matous
081: */
082: final class DragManager implements DragGestureListener,
083: DragSourceListener, DropTargetListener, MouseMotionListener {
084:
085: private JComponent component;
086:
087: // XXX assigned to but never read from; delete?
088: private DragGestureRecognizer dRecognizer;
089: private DragSource dSource;
090: // XXX assigned to but never read from; delete?
091: private DropTarget dTarget;
092:
093: private int translateX;
094: private int translateY;
095:
096: private final Cursor oCursor;
097:
098: List<DragItem> allItems = new ArrayList<DragItem>();
099: private DragItem activeDragItem = null;
100:
101: /** Creates a new instance of SplashDnDSupport */
102: DragManager(JComponent component) {
103: this .component = component;
104: dSource = new DragSource();
105: dRecognizer = dSource.createDefaultDragGestureRecognizer(
106: this .component, DnDConstants.ACTION_MOVE, this );
107: dTarget = new DropTarget(this .component,
108: DnDConstants.ACTION_MOVE, this );
109: component.addMouseMotionListener(this );
110: oCursor = component.getCursor();
111: }
112:
113: DragItem createNewItem() {
114: DragItem retval = new DragItem();
115: allItems.add(retval);
116: return retval;
117: }
118:
119: void setTranslate(int translateX, int translateY) {
120: this .translateX = -translateX;
121: this .translateY = -translateY;
122:
123: SplashComponentPreview scomp = (SplashComponentPreview) component;
124: Rectangle bounds = new Rectangle(new Dimension(scomp.image
125: .getWidth(null), scomp.image.getHeight(null)));
126: for (DragItem elem : allItems) {
127: elem.setBounds(bounds);
128: }
129: }
130:
131: public void paint(Graphics g) {
132: g.setXORMode(Color.white); //Color of line varies
133:
134: for (Iterator it = allItems.iterator(); it.hasNext();) {
135: DragItem elem = (DragItem) it.next();
136: elem.paint(g);
137: }
138: }
139:
140: public void dragGestureRecognized(DragGestureEvent dge) {
141: Point gesturePoint = dge.getDragOrigin();
142: DragItem item = getDragItem(transformMousePoint(gesturePoint));
143: if (item != null) {
144: activeDragItem = item;
145: activeDragItem.setGesturePoint(gesturePoint);
146: Cursor curs = activeDragItem.getCursor();
147: assert curs != null;
148: dge.startDrag(curs, new StringSelection(""), this );
149: component.repaint();
150: }
151:
152: }
153:
154: private Point transformMousePoint(Point mousePoint) {
155: return new Point(mousePoint.x + translateX, mousePoint.y
156: + translateY);
157: }
158:
159: public void dragEnter(DragSourceDragEvent dsde) {
160: }
161:
162: public void dragOver(DragSourceDragEvent dsde) {
163: }
164:
165: public void dropActionChanged(DragSourceDragEvent dsde) {
166: }
167:
168: public void dragExit(DragSourceEvent dse) {
169: }
170:
171: public void dragDropEnd(DragSourceDropEvent dsde) {
172: if (!dsde.getDropSuccess() && activeDragItem != null) {
173: activeDragItem.dragAccepted();
174: }
175:
176: }
177:
178: public void dragEnter(DropTargetDragEvent dtde) {
179: }
180:
181: public void dragOver(DropTargetDragEvent dtde) {
182: dragOverImpl(dtde.getLocation());
183: }
184:
185: private void dragOverImpl(final Point p) {
186: if (activeDragItem != null) {
187: activeDragItem.recalculateSize(p);
188: activeDragItem.updateSize();
189: activeDragItem.scroll(component);
190: component.repaint();
191: }
192: }
193:
194: public void dropActionChanged(DropTargetDragEvent dtde) {
195: }
196:
197: public void dragExit(DropTargetEvent dte) {
198: }
199:
200: public void drop(DropTargetDropEvent dtde) {
201: if (dtde.isDataFlavorSupported(DataFlavor.stringFlavor)) {
202: dtde.dropComplete(true);
203: if (activeDragItem != null) {
204: activeDragItem.dragAccepted();
205: }
206: } else {
207: dtde.rejectDrop();
208: }
209: component.setCursor(oCursor);
210: activeDragItem = null;
211: component.repaint();
212: }
213:
214: public void mouseDragged(MouseEvent e) {
215: }
216:
217: public void mouseMoved(MouseEvent e) {
218: activeDragItem = null;
219: DragItem item = null;
220: for (Iterator it = allItems.iterator(); it.hasNext();) {
221: DragItem elem = (DragItem) it.next();
222: if (elem.contains(transformMousePoint(e.getPoint()))) {
223: item = elem;
224: break;
225: }
226: }
227: if (item != null) {
228: Cursor c = item.getCursor();
229: component.setCursor(c);
230: } else {
231: component.setCursor(oCursor);
232: }
233: }
234:
235: DragItem getDragItem(Point p2Compare) {
236: DragItem retval = null;
237: for (Iterator it = allItems.iterator(); it.hasNext();) {
238: DragItem elem = (DragItem) it.next();
239: if (elem.contains(p2Compare)) {
240: retval = elem;
241: break;
242: }
243: }
244: return retval;
245: }
246:
247: interface DropHandler {
248: void dragAccepted(Rectangle original, Rectangle afterDrag);
249: }
250:
251: static class DragItem implements Mode {
252: private Point gesturePoint = new Point();
253: private Rectangle rectangle = new Rectangle();
254: private Rectangle currentDragRect = new Rectangle();
255: private Mode dragMode;//DnDController should have instead of Mode -> RectangleEntity
256: private DropHandler dHandler;
257: private Rectangle bounds;
258: private Mode[] allmodes = new Mode[9];
259: private boolean enabled = true;
260:
261: DragItem() {
262: allmodes[0] = new OneSideScaleMode(
263: OneSideScaleMode.N_RESIZE_MODE);
264: allmodes[1] = new OneSideScaleMode(
265: OneSideScaleMode.S_RESIZE_MODE);
266: allmodes[2] = new OneSideScaleMode(
267: OneSideScaleMode.W_RESIZE_MODE);
268: allmodes[3] = new OneSideScaleMode(
269: OneSideScaleMode.E_RESIZE_MODE);
270: allmodes[4] = new ScaleMode(ScaleMode.NW_RESIZE_MODE);
271: allmodes[5] = new ScaleMode(ScaleMode.NE_RESIZE_MODE);
272: allmodes[6] = new ScaleMode(ScaleMode.SW_RESIZE_MODE);
273: allmodes[7] = new ScaleMode(ScaleMode.SE_RESIZE_MODE);
274: allmodes[8] = new MoveMode();
275: }
276:
277: void setDropHandler(DropHandler dHandler) {
278: this .dHandler = dHandler;
279: }
280:
281: public void dragAccepted() {
282: if (dHandler != null) {
283: dHandler.dragAccepted(rectangle, currentDragRect);
284: }
285: }
286:
287: void setRectangle(Rectangle rectangle) {
288: this .rectangle.setBounds(rectangle);
289: this .currentDragRect.setBounds(rectangle);
290: updateSize(rectangle);
291: }
292:
293: void setGesturePoint(Point gesturePoint) {
294: this .gesturePoint = gesturePoint;
295: }
296:
297: Point getGesturePoint() {
298: return this .gesturePoint;
299: }
300:
301: public boolean contains(Point point) {
302: Mode mode = null;
303: if (isEnabled()) {
304: for (int i = 0; i < allmodes.length; i++) {
305: if (allmodes[i].contains(point)) {
306: mode = allmodes[i];
307: break;
308: }
309: }
310: }
311: dragMode = mode;
312: return mode != null;
313: }
314:
315: public void updateSize() {
316: updateSize(currentDragRect);
317: }
318:
319: public void updateSize(Rectangle rec) {
320: for (int i = 0; i < allmodes.length; i++) {
321: allmodes[i].updateSize(rec);
322: }
323: }
324:
325: public void recalculateSize(Point p) {
326: if (dragMode != null && !p.equals(gesturePoint)) {
327: Rectangle oldtDragRect = new Rectangle();
328: oldtDragRect.setBounds(currentDragRect);
329: dragMode.recalculateSize(p);
330: int x = currentDragRect.x;
331: int y = currentDragRect.y;
332: int w = currentDragRect.width;
333: int h = currentDragRect.height;
334:
335: if (bounds != null && !bounds.contains(currentDragRect)) {
336: if (h + y > bounds.height + bounds.y) {
337: if (y == oldtDragRect.y) {
338: h = (bounds.height + bounds.y) - y;
339: } else {
340: y = (bounds.height + bounds.y) - h;
341: }
342: }
343: if (w + x > bounds.width + bounds.x) {
344: if (x == oldtDragRect.x) {
345: w = (bounds.width + bounds.x) - x;
346: } else {
347: x = (bounds.width + bounds.x) - w;
348: }
349: }
350: if (x < bounds.x) {
351: x = bounds.x;
352: }
353: if (y < bounds.y) {
354: y = bounds.y;
355: }
356: currentDragRect.setBounds(x, y, w, h);
357: }
358: if (w <= 3 || h <= 3 && !(dragMode instanceof MoveMode)) {
359: currentDragRect.setBounds(oldtDragRect);
360: }
361: }
362:
363: }
364:
365: public void scroll(JComponent component) {
366: component.scrollRectToVisible(currentDragRect);
367: }
368:
369: void setBounds(Rectangle bounds) {
370: this .bounds = bounds;
371: }
372:
373: public void paint(Graphics g) {
374: if (isEnabled()) {
375: for (int i = 0; i < allmodes.length; i++) {
376: allmodes[i].paint(g);
377: }
378: }
379: }
380:
381: public Cursor getCursor() {
382: return (dragMode != null) ? dragMode.getCursor() : null;
383: }
384:
385: private class MoveMode implements Mode {
386: public boolean contains(Point point) {
387: return (currentDragRect != null && currentDragRect
388: .contains(point));
389: }
390:
391: public void updateSize(Rectangle rec) {
392: }
393:
394: public void paint(Graphics g) {
395: }
396:
397: public Cursor getCursor() {
398: return Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
399: }
400:
401: public void recalculateSize(Point p) {
402: currentDragRect.setBounds((p.x - gesturePoint.x)
403: + rectangle.x, (p.y - gesturePoint.y)
404: + rectangle.y, rectangle.width,
405: rectangle.height);
406: }
407: }
408:
409: private class ScaleMode implements Mode {
410: static final int NW_RESIZE_MODE = 0;
411: static final int NE_RESIZE_MODE = 1;
412: static final int SW_RESIZE_MODE = 2;
413: static final int SE_RESIZE_MODE = 3;
414: //private static final int MOVE_MODE = 4;
415:
416: private int resizeMode = -1;
417: private Rectangle rec = new Rectangle();
418:
419: ScaleMode(int resizeMode) {
420: this .resizeMode = resizeMode;
421: }
422:
423: public boolean contains(Point point) {
424: assert resizeMode != -1;
425: assert rec != null;
426: return rec.contains(point);
427: }
428:
429: public void updateSize(Rectangle currentDragRect) {
430: assert resizeMode != -1;
431: int inset = Math.min(Math.min(5,
432: currentDragRect.width / 5), Math.min(5,
433: currentDragRect.height / 5));
434: Dimension d = new Dimension(inset * 2, inset * 2);
435: Point origin = new Point(currentDragRect.x - inset,
436: currentDragRect.y - inset);
437: switch (resizeMode) {
438: case ScaleMode.NW_RESIZE_MODE:
439: rec = new Rectangle(origin, d);
440: break;
441: case ScaleMode.NE_RESIZE_MODE:
442: rec = new Rectangle(new Point(origin.x
443: + currentDragRect.width, origin.y), d);
444: break;
445: case ScaleMode.SW_RESIZE_MODE:
446: rec = new Rectangle(new Point(origin.x, origin.y
447: + currentDragRect.height), d);
448: break;
449: case ScaleMode.SE_RESIZE_MODE:
450: rec = new Rectangle(new Point(origin.x
451: + currentDragRect.width, origin.y
452: + currentDragRect.height), d);
453: break;
454: }
455: }
456:
457: public void paint(Graphics g) {
458: assert resizeMode != -1;
459: assert rec != null;
460:
461: g.fillRect(rec.x, rec.y, rec.width, rec.height);
462: }
463:
464: public Cursor getCursor() {
465: assert resizeMode != -1;
466: assert rec != null;
467:
468: Cursor retval = null;
469: switch (resizeMode) {
470: case ScaleMode.NW_RESIZE_MODE:
471: retval = Cursor
472: .getPredefinedCursor(Cursor.NW_RESIZE_CURSOR);
473: break;
474: case ScaleMode.NE_RESIZE_MODE:
475: retval = Cursor
476: .getPredefinedCursor(Cursor.NE_RESIZE_CURSOR);
477: break;
478: case ScaleMode.SW_RESIZE_MODE:
479: retval = Cursor
480: .getPredefinedCursor(Cursor.SW_RESIZE_CURSOR);
481: break;
482: case ScaleMode.SE_RESIZE_MODE:
483: retval = Cursor
484: .getPredefinedCursor(Cursor.SE_RESIZE_CURSOR);
485: break;
486: }
487: assert retval != null;
488: return retval;
489: }
490:
491: public void recalculateSize(Point p) {
492: int xDelta = (p.x - gesturePoint.x);
493: int yDelta = (p.y - gesturePoint.y);
494: switch (resizeMode) {
495: case ScaleMode.NW_RESIZE_MODE:
496: currentDragRect
497: .setBounds(rectangle.x + xDelta,
498: rectangle.y + yDelta,
499: rectangle.width - xDelta,
500: rectangle.height - yDelta);
501: break;
502: case ScaleMode.NE_RESIZE_MODE:
503: currentDragRect.setBounds(rectangle.x, rectangle.y
504: + yDelta, rectangle.width + xDelta,
505: rectangle.height - yDelta);
506: break;
507: case ScaleMode.SW_RESIZE_MODE:
508: currentDragRect.setBounds(rectangle.x + xDelta,
509: rectangle.y, rectangle.width - xDelta,
510: rectangle.height + yDelta);
511: break;
512: case ScaleMode.SE_RESIZE_MODE:
513: currentDragRect.setBounds(rectangle.x, rectangle.y,
514: rectangle.width + xDelta, rectangle.height
515: + yDelta);
516: break;
517: }
518: }
519: }
520:
521: private class OneSideScaleMode implements Mode {
522: static final int N_RESIZE_MODE = 5;
523: static final int E_RESIZE_MODE = 6;
524: static final int S_RESIZE_MODE = 7;
525: static final int W_RESIZE_MODE = 8;
526:
527: private int resizeMode = -1;
528: private Rectangle rec = new Rectangle();
529:
530: OneSideScaleMode(int resizeMode) {
531: this .resizeMode = resizeMode;
532: }
533:
534: public boolean contains(Point point) {
535: assert resizeMode != -1;
536: assert rec != null;
537: return rec.contains(point);
538: }
539:
540: public void updateSize(Rectangle currentDragRect) {
541: assert resizeMode != -1;
542: int inset = 5;
543: switch (resizeMode) {
544: case OneSideScaleMode.N_RESIZE_MODE:
545: rec = new Rectangle(currentDragRect.x + inset,
546: currentDragRect.y - 2 * inset,
547: currentDragRect.width - inset, 2 * inset);
548: break;
549: case OneSideScaleMode.E_RESIZE_MODE:
550: rec = new Rectangle(currentDragRect.x
551: + currentDragRect.width, currentDragRect.y
552: + inset, 2 * inset, currentDragRect.height
553: - inset);
554: break;
555: case OneSideScaleMode.S_RESIZE_MODE:
556: rec = new Rectangle(currentDragRect.x + inset,
557: currentDragRect.y + currentDragRect.height,
558: currentDragRect.width - inset, 2 * inset);
559: break;
560: case OneSideScaleMode.W_RESIZE_MODE:
561: rec = new Rectangle(currentDragRect.x - 2 * inset,
562: currentDragRect.y + inset, 2 * inset,
563: currentDragRect.height - inset);
564: break;
565: }
566:
567: }
568:
569: public void paint(Graphics g) {
570: assert resizeMode != -1;
571: assert rec != null;
572: int inset = 5;
573: Graphics2D g2d = (Graphics2D) g;
574: Stroke oStroke = g2d.getStroke();
575: g2d.setStroke(new BasicStroke(1.0f,
576: BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
577: 10.0f, new float[] { 3.0f }, 0.0f));
578: Rectangle2D rec2d = rec.getBounds2D();
579: Line2D line = null;
580: switch (resizeMode) {
581: case OneSideScaleMode.N_RESIZE_MODE:
582: line = new Line2D.Double(rec2d.getMinX(), rec2d
583: .getMaxY(), rec2d.getMaxX() - inset, rec2d
584: .getMaxY());
585: break;
586: case OneSideScaleMode.E_RESIZE_MODE:
587: line = new Line2D.Double(rec2d.getMinX(), rec2d
588: .getMinY(), rec2d.getMinX(), rec2d
589: .getMaxY()
590: - inset);
591: break;
592: case OneSideScaleMode.S_RESIZE_MODE:
593: line = new Line2D.Double(rec2d.getMinX(), rec2d
594: .getMinY(), rec2d.getMaxX() - inset, rec2d
595: .getMinY());
596: break;
597: case OneSideScaleMode.W_RESIZE_MODE:
598: line = new Line2D.Double(rec2d.getMaxX(), rec2d
599: .getMinY(), rec2d.getMaxX(), rec2d
600: .getMaxY()
601: - inset);
602: break;
603: }
604: g2d.draw(line);
605: g2d.setStroke(oStroke);
606: }
607:
608: public Cursor getCursor() {
609: assert resizeMode != -1;
610: assert rec != null;
611: Cursor retval = null;
612: switch (resizeMode) {
613: case OneSideScaleMode.N_RESIZE_MODE:
614: retval = Cursor
615: .getPredefinedCursor(Cursor.N_RESIZE_CURSOR);
616: break;
617: case OneSideScaleMode.E_RESIZE_MODE:
618: retval = Cursor
619: .getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
620: break;
621: case OneSideScaleMode.S_RESIZE_MODE:
622: retval = Cursor
623: .getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
624: break;
625: case OneSideScaleMode.W_RESIZE_MODE:
626: retval = Cursor
627: .getPredefinedCursor(Cursor.W_RESIZE_CURSOR);
628: break;
629: }
630: assert retval != null;
631: return retval;
632: }
633:
634: public void recalculateSize(Point p) {
635: int xDelta = (p.x - gesturePoint.x);
636: int yDelta = (p.y - gesturePoint.y);
637: switch (resizeMode) {
638: case OneSideScaleMode.N_RESIZE_MODE:
639: currentDragRect.setBounds(rectangle.x, rectangle.y
640: + yDelta, rectangle.width, rectangle.height
641: - yDelta);
642: break;
643: case OneSideScaleMode.E_RESIZE_MODE:
644: currentDragRect.setBounds(rectangle.x, rectangle.y,
645: rectangle.width + xDelta, rectangle.height);
646: break;
647: case OneSideScaleMode.S_RESIZE_MODE:
648: currentDragRect.setBounds(rectangle.x, rectangle.y,
649: rectangle.width, rectangle.height + yDelta);
650: break;
651: case OneSideScaleMode.W_RESIZE_MODE:
652: currentDragRect.setBounds(rectangle.x + xDelta,
653: rectangle.y, rectangle.width - xDelta,
654: rectangle.height);
655: break;
656: }
657: }
658: }
659:
660: boolean isEnabled() {
661: return enabled;
662: }
663:
664: void setEnabled(boolean enabled) {
665: this .enabled = enabled;
666: }
667:
668: }
669:
670: private interface Mode {
671: boolean contains(Point point);
672:
673: void updateSize(Rectangle rec);
674:
675: void recalculateSize(Point p);
676:
677: void paint(Graphics g);
678:
679: Cursor getCursor();
680: }
681: }
|