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.core.windows.view.dnd;
043:
044: import org.netbeans.swing.tabcontrol.*;
045: import java.awt.Dimension;
046: import java.awt.Point;
047: import java.awt.Rectangle;
048: import java.awt.Window;
049: import java.awt.dnd.DragGestureEvent;
050: import java.awt.dnd.DragSourceDragEvent;
051: import java.awt.event.ActionEvent;
052: import java.awt.event.ActionListener;
053: import java.awt.geom.Area;
054: import java.util.prefs.Preferences;
055: import javax.swing.SwingUtilities;
056: import org.netbeans.core.windows.nativeaccess.NativeWindowSystem;
057: import org.netbeans.core.windows.options.WinSysPrefs;
058: import org.netbeans.core.windows.view.ui.Tabbed;
059:
060: /**
061: *
062: * @author S. Aubrecht
063: */
064: public class DragAndDropFeedbackVisualizer {
065:
066: private static final Preferences prefs = WinSysPrefs.HANDLER;
067:
068: private DragWindow dragWindow = null;
069: private Tabbed source;
070: private Point originalLocationOnScreen;
071: private Point dragOffset;
072: private int tabIndex;
073:
074: public DragAndDropFeedbackVisualizer(Tabbed src, int tabIndex) {
075: this .source = src;
076: this .tabIndex = tabIndex;
077: }
078:
079: private DragWindow createDragWindow(int idx) {
080: Rectangle tabRectangle = source.getTabBounds(idx);
081: Dimension tabContentSize = source.getTopComponentAt(idx)
082: .getSize();
083: tabContentSize.width--;
084: tabContentSize.height--;
085:
086: Dimension size = new Dimension(tabContentSize);
087: if (prefs.getBoolean(WinSysPrefs.DND_SMALLWINDOWS, true)) {
088: int maxWidth = prefs.getInt(
089: WinSysPrefs.DND_SMALLWINDOWS_WIDTH, 250);
090: int maxHeight = prefs.getInt(
091: WinSysPrefs.DND_SMALLWINDOWS_HEIGHT, 250);
092: size.width = Math.min(maxWidth, size.width);
093: size.height = Math.min(maxHeight, size.height);
094:
095: tabRectangle.width = Math
096: .min(maxHeight, tabRectangle.width);
097: }
098: DragWindow w = new DragWindow(source, tabRectangle,
099: new Dimension(size), source.getTopComponentAt(idx));
100:
101: size.width += 2; //left & right 'border'
102: size.height += 2; //top & bottom 'border'
103: Dimension windowSize = new Dimension(size);
104: windowSize.height += tabRectangle.height;
105: w.setSize(windowSize);
106:
107: NativeWindowSystem nws = NativeWindowSystem.getDefault();
108: if (nws.isWindowAlphaSupported()
109: && prefs.getBoolean(WinSysPrefs.TRANSPARENCY_DRAGIMAGE,
110: true)) {
111: nws.setWindowAlpha(w, prefs.getFloat(
112: WinSysPrefs.TRANSPARENCY_DRAGIMAGE_ALPHA, 0.7f));
113: Area mask;
114: if (prefs.getBoolean(WinSysPrefs.DND_SMALLWINDOWS, true)) {
115: mask = new Area(new Rectangle(0, 0, tabRectangle.width,
116: tabRectangle.height));
117: mask.add(new Area(new Rectangle(0, tabRectangle.height,
118: size.width, size.height)));
119: } else {
120: mask = new Area(tabRectangle);
121: mask.add(new Area(new Rectangle(0, tabRectangle.height,
122: size.width, size.height)));
123: }
124: nws.setWindowMask(w, mask);
125: }
126: return w;
127: }
128:
129: public void start(final DragGestureEvent e) {
130: originalLocationOnScreen = source.getComponent()
131: .getLocationOnScreen();
132: final Rectangle tabRect = source.getTabBounds(tabIndex);
133: if (prefs.getBoolean(WinSysPrefs.DND_SMALLWINDOWS, true)) {
134: originalLocationOnScreen.x += tabRect.x;
135: }
136:
137: SwingUtilities.invokeLater(new Runnable() {
138:
139: public void run() {
140: DragWindow tmp = createDragWindow(tabIndex);
141: if (null != tmp) {
142: dragOffset = e.getDragOrigin();
143: if (prefs.getBoolean(WinSysPrefs.DND_SMALLWINDOWS,
144: true)) {
145: dragOffset.x -= tabRect.x;
146: }
147: //move the window of the visible screen area to avoid blinking
148: //TODO make sure the window is really not visible
149: // dragImageSize = w.getSize();
150: // w.setSize( new Dimension(1,1) );
151: tmp.setLocation(-1000, -1000);
152: //let the JNA transparency stuff to kick in
153: tmp.setVisible(true);
154: //make drag window visible, i.e. move to proper location,
155: //dragImage.setLocation( startingPoint );
156: dragWindow = tmp;
157: }
158: }
159: });
160: }
161:
162: public void update(DragSourceDragEvent e) {
163: if (null != dragWindow)
164: dragWindow.setLocation(e.getLocation().x - dragOffset.x, e
165: .getLocation().y
166: - dragOffset.y);
167: }
168:
169: public void dispose(boolean dropSuccessful) {
170: if (null == dragWindow)
171: return;
172: if (!dropSuccessful) {
173: returnDragWindowToOrigin();
174: } else {
175: dragWindow.dispose();
176: }
177: dragWindow = null;
178: }
179:
180: public void setDropFeedback(boolean dropEnabled) {
181: if (null != dragWindow) {
182: dragWindow.setDropFeedback(dropEnabled);
183: }
184: }
185:
186: private static final int SLIDE_INTERVAL = 1000 / 30;
187:
188: private void returnDragWindowToOrigin() {
189: final javax.swing.Timer timer = new javax.swing.Timer(
190: SLIDE_INTERVAL, null);
191: final Window returningWindow = dragWindow;
192: dragWindow.abort();
193: timer.addActionListener(new ActionListener() {
194: public void actionPerformed(ActionEvent e) {
195: Point location = returningWindow.getLocationOnScreen();
196: Point dst = new Point(originalLocationOnScreen);
197: int dx = (dst.x - location.x) / 2;
198: int dy = (dst.y - location.y) / 2;
199: if (dx != 0 || dy != 0) {
200: location.translate(dx, dy);
201: returningWindow.setLocation(location);
202: } else {
203: timer.stop();
204: returningWindow.dispose();
205: }
206: }
207: });
208: timer.setInitialDelay(0);
209: timer.start();
210: }
211: }
|