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.AlphaComposite;
046: import java.awt.Color;
047: import java.awt.Component;
048: import java.awt.Dimension;
049: import java.awt.Graphics;
050: import java.awt.Graphics2D;
051: import java.awt.GraphicsConfiguration;
052: import java.awt.GraphicsEnvironment;
053: import java.awt.Rectangle;
054: import java.awt.Window;
055: import java.awt.event.ActionEvent;
056: import java.awt.event.ActionListener;
057: import java.awt.geom.AffineTransform;
058: import java.awt.image.BufferedImage;
059: import javax.swing.JWindow;
060: import javax.swing.SwingUtilities;
061: import javax.swing.Timer;
062: import org.netbeans.core.windows.options.WinSysPrefs;
063: import org.netbeans.core.windows.view.ui.Tabbed;
064: import org.openide.util.RequestProcessor;
065:
066: /**
067: *
068: * @author sa
069: */
070: class DragWindow extends JWindow {
071:
072: private boolean useFadeEffects = !Boolean
073: .getBoolean("winsys.dnd.nofadeeffects");
074:
075: private Tabbed container;
076: private Rectangle tabRectangle;
077: private BufferedImage tabImage;
078: private BufferedImage contentImage;
079: private BufferedImage imageBuffer;
080: private float contentAlpha = 0.15f;
081: private Color contentBackground = Color.white;
082:
083: private Timer currentEffect;
084:
085: public DragWindow(Tabbed container, Rectangle tabRectangle,
086: final Dimension contentSize, final Component content) {
087: this .tabRectangle = tabRectangle;
088: this .container = container;
089:
090: setAlwaysOnTop(true);
091:
092: tabImage = createTabImage();
093:
094: Runnable imageCreator = new Runnable() {
095: public void run() {
096: contentImage = createContentImage(content, contentSize);
097: if (useFadeEffects) {
098: imageBuffer = createImageBuffer(contentImage);
099: currentEffect = createInitialEffect();
100: currentEffect.start();
101: } else {
102: contentAlpha = 1.0f;
103: }
104: repaint();
105: }
106: };
107: RequestProcessor.getDefault().post(imageCreator);
108: }
109:
110: private BufferedImage createTabImage() {
111: GraphicsConfiguration config = GraphicsEnvironment
112: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
113: .getDefaultConfiguration();
114:
115: //the tab rectangle must be painted by top-level window otherwise the transparent
116: //button icons will be messed up
117: Window parentWindow = SwingUtilities
118: .getWindowAncestor(container.getComponent());
119: Rectangle rect = SwingUtilities.convertRectangle(container
120: .getComponent(), tabRectangle, parentWindow);
121: BufferedImage res = config.createCompatibleImage(
122: tabRectangle.width, tabRectangle.height);
123: Graphics2D g = res.createGraphics();
124: g.translate(-rect.x, -rect.y);
125: g.setClip(rect);
126: parentWindow.paint(g);
127: return res;
128: }
129:
130: private BufferedImage createContentImage(Component c,
131: Dimension contentSize) {
132: GraphicsConfiguration config = GraphicsEnvironment
133: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
134: .getDefaultConfiguration();
135:
136: BufferedImage res = config.createCompatibleImage(
137: contentSize.width, contentSize.height);
138: Graphics2D g = res.createGraphics();
139: if (WinSysPrefs.HANDLER.getBoolean(
140: WinSysPrefs.DND_SMALLWINDOWS, true)
141: && c.getWidth() > 0 && c.getHeight() > 0) {
142: double xScale = contentSize.getWidth() / c.getWidth();
143: double yScale = contentSize.getHeight() / c.getHeight();
144: g.setTransform(AffineTransform.getScaleInstance(xScale,
145: yScale));
146: }
147: c.paint(g);
148: return res;
149: }
150:
151: private BufferedImage createImageBuffer(BufferedImage src) {
152: GraphicsConfiguration config = GraphicsEnvironment
153: .getLocalGraphicsEnvironment().getDefaultScreenDevice()
154: .getDefaultConfiguration();
155: BufferedImage res = config.createCompatibleImage(
156: src.getWidth(), src.getHeight());
157: Graphics2D g = res.createGraphics();
158: g.setColor(contentBackground);
159: g.fillRect(0, 0, res.getWidth(), res.getHeight());
160: g.setComposite(AlphaComposite.getInstance(
161: AlphaComposite.SRC_OVER, contentAlpha));
162: g.drawImage(src, 0, 0, null);
163: return res;
164: }
165:
166: @Override
167: public void paint(Graphics g) {
168: Graphics2D g2d = (Graphics2D) g.create();
169: g2d.setColor(Color.white);
170: g2d.fillRect(0, 0, getWidth(), tabRectangle.height);
171: g2d.setColor(Color.gray);
172: g2d.drawRect(0, tabRectangle.height, getWidth() - 1,
173: getHeight() - tabRectangle.height - 1);
174:
175: if (WinSysPrefs.HANDLER.getBoolean(
176: WinSysPrefs.DND_SMALLWINDOWS, true))
177: g2d.drawImage(tabImage, 0, 0, null);
178: else
179: g2d.drawImage(tabImage, tabRectangle.x, tabRectangle.y,
180: null);
181: if (useFadeEffects) {
182: if (null != imageBuffer) {
183: g2d.drawImage(imageBuffer, 1, tabRectangle.height + 1,
184: null);
185: }
186: } else {
187: g2d.setColor(Color.black);
188: g2d.fillRect(1, tabRectangle.height + 1, getWidth() - 2,
189: getHeight() - tabRectangle.height - 2);
190: g2d.setComposite(AlphaComposite.getInstance(
191: AlphaComposite.SRC_OVER, contentAlpha));
192: g2d.drawImage(contentImage, 1, tabRectangle.height + 1,
193: null);
194: }
195: g2d.dispose();
196: }
197:
198: private boolean dropEnabled = true;
199:
200: public void setDropFeedback(boolean dropEnabled) {
201: boolean prevState = this .dropEnabled;
202: this .dropEnabled = dropEnabled;
203: if (prevState != this .dropEnabled) {
204: if (null != currentEffect) {
205: currentEffect.stop();
206: }
207: if (useFadeEffects) {
208: contentBackground = Color.black;
209: currentEffect = dropEnabled ? createDropEnabledEffect()
210: : createNoDropEffect();
211: currentEffect.start();
212: } else {
213: contentAlpha = dropEnabled ? 1.0f : NO_DROP_ALPHA;
214: repaint();
215: }
216: }
217: }
218:
219: private Timer createInitialEffect() {
220: final Timer timer = new Timer(100, null);
221: timer.addActionListener(new ActionListener() {
222: public void actionPerformed(ActionEvent e) {
223: if (contentAlpha < 1.0f) {
224: contentAlpha += ALPHA_INCREMENT;
225: if (contentAlpha > 1.0f)
226: contentAlpha = 1.0f;
227: repaintImageBuffer();
228: repaint();
229: } else {
230: timer.stop();
231: }
232: }
233: });
234: timer.setInitialDelay(0);
235: return timer;
236: }
237:
238: private Timer createDropEnabledEffect() {
239: return createInitialEffect();
240: }
241:
242: private static final float NO_DROP_ALPHA = 0.5f;
243: private static final float ALPHA_INCREMENT = 0.085f;
244:
245: private Timer createNoDropEffect() {
246: final Timer timer = new Timer(100, null);
247: timer.addActionListener(new ActionListener() {
248: public void actionPerformed(ActionEvent e) {
249: if (contentAlpha > NO_DROP_ALPHA) {
250: contentAlpha -= ALPHA_INCREMENT;
251: if (contentAlpha < NO_DROP_ALPHA)
252: contentAlpha = NO_DROP_ALPHA;
253: repaintImageBuffer();
254: repaint();
255: } else {
256: timer.stop();
257: }
258: }
259: });
260: timer.setInitialDelay(0);
261: return timer;
262: }
263:
264: private void repaintImageBuffer() {
265: if (!useFadeEffects)
266: return;
267: // #128324 - image might not be created yet
268: if (null == imageBuffer) {
269: return;
270: }
271: Graphics2D g2d = imageBuffer.createGraphics();
272: g2d.setColor(contentBackground);
273: g2d.fillRect(0, 0, imageBuffer.getWidth(), imageBuffer
274: .getHeight());
275: g2d.setComposite(AlphaComposite.getInstance(
276: AlphaComposite.SRC_OVER, contentAlpha));
277: g2d.drawImage(contentImage, 0, 0, null);
278: g2d.dispose();
279: }
280:
281: void abort() {
282: if (null != currentEffect) {
283: currentEffect.stop();
284: currentEffect = null;
285: }
286: dropEnabled = true;
287: contentAlpha = 1.0f;
288: repaintImageBuffer();
289: repaint();
290: }
291: }
|