001 /*
002 * $Id: JXGlassBox.java,v 1.4 2005/10/10 18:02:02 rbair Exp $
003 *
004 * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005 * Santa Clara, California 95054, U.S.A. All rights reserved.
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020 */
021
022 package org.jdesktop.swingx;
023
024 import java.applet.Applet;
025 import java.awt.Color;
026 import java.awt.Component;
027 import java.awt.Container;
028 import java.awt.Dimension;
029 import java.awt.Graphics;
030 import java.awt.Point;
031 import java.awt.Rectangle;
032 import java.awt.Window;
033 import java.awt.event.ActionEvent;
034 import java.awt.event.ActionListener;
035 import java.awt.event.MouseAdapter;
036 import java.awt.event.MouseEvent;
037
038 import javax.swing.JComponent;
039 import javax.swing.SwingConstants;
040 import javax.swing.SwingUtilities;
041 import javax.swing.Timer;
042
043
044
045
046 /**
047 * Component used to display transluscent user-interface content.
048 * This component and all of its content will be displayed with the specified
049 * "alpha" transluscency property value. When this component is made visible,
050 * it's content will fade in until the alpha transluscency level is reached.
051 * <p>
052 * If the glassbox's "dismissOnClick" property is <code>true</code>
053 * (the default) then the glassbox will be made invisible when the user
054 * clicks on it.</p>
055 * <p>
056 * This component is particularly useful for displaying transient messages
057 * on the glasspane.</p>
058 *
059 * @author Amy Fowler
060 * @version 1.0
061 */
062
063 public class JXGlassBox extends JXPanel {
064 private static final int SHOW_DELAY = 30; // ms
065 private static final int TIMER_INCREMENT = 10; // ms
066
067 private float alphaStart = 0.01f;
068 private float alphaEnd = 0.8f;
069
070 private Timer animateTimer;
071 private float alphaIncrement = 0.02f;
072
073 private boolean dismissOnClick = false;
074 private MouseAdapter dismissListener = null;
075
076 public JXGlassBox() {
077 setOpaque(false);
078 setAlpha(alphaStart);
079 setBackground(Color.white);
080 setDismissOnClick(true);
081
082 animateTimer = new Timer(TIMER_INCREMENT, new ActionListener() {
083 public void actionPerformed(ActionEvent e) {
084 setAlpha(getAlpha() + alphaIncrement);
085 }
086 });
087 }
088
089 public JXGlassBox(float alpha) {
090 this();
091 setAlpha(alpha);
092 }
093
094 public void setAlpha(float alpha) {
095 super.setAlpha(alpha);
096 this.alphaIncrement = (alphaEnd - alphaStart)/(SHOW_DELAY/TIMER_INCREMENT);
097 }
098
099 public void setDismissOnClick(boolean dismissOnClick) {
100 boolean oldDismissOnClick = this.dismissOnClick;
101 this.dismissOnClick = dismissOnClick;
102 if (dismissOnClick && !oldDismissOnClick) {
103 if (dismissListener == null) {
104 dismissListener = new MouseAdapter() {
105 public void mouseClicked(MouseEvent e) {
106 JComponent glassBox = JXGlassBox.this;
107 JComponent parent = (JComponent) glassBox.getParent();
108 Container toplevel = parent.getTopLevelAncestor();
109 parent.remove(glassBox);
110 toplevel.validate();
111 toplevel.repaint();
112 }
113 };
114 }
115 addMouseListener(dismissListener);
116 }
117 else if (!dismissOnClick && oldDismissOnClick) {
118 removeMouseListener(dismissListener);
119 }
120 }
121
122 public void paint(Graphics g) {
123 super.paint(g);
124 if (!animateTimer.isRunning() && getAlpha() < alphaEnd ) {
125 animateTimer.start();
126 }
127 if (animateTimer.isRunning() && getAlpha() >= alphaEnd) {
128 animateTimer.stop();
129 }
130 }
131
132 public void setVisible(boolean visible) {
133 setAlpha(alphaStart);
134 super.setVisible(visible);
135 }
136
137 private Container getTopLevel() {
138 Container p = getParent();
139 while (p != null && !(p instanceof Window || p instanceof Applet)) {
140 p = p.getParent();
141 }
142 return p;
143 }
144
145 public void showOnGlassPane(Container glassPane, Component component,
146 int componentX, int componentY, int positionHint) {
147 Dimension boxPrefSize = getPreferredSize();
148 Dimension glassSize = glassPane.getSize();
149 Rectangle compRect = component.getBounds();
150 int boxX = 0;
151 int boxY = 0;
152 int boxWidth = Math.min(boxPrefSize.width, glassSize.width);
153 int boxHeight = Math.min(boxPrefSize.height, glassSize.height);
154
155 Point compLocation = SwingUtilities.convertPoint(component.getParent(),
156 compRect.x, compRect.y,
157 glassPane);
158
159 if (positionHint == SwingConstants.TOP) {
160 if (compLocation.x + componentX + boxWidth <= glassSize.width) {
161 boxX = compLocation.x + componentX;
162 } else {
163 boxX = glassSize.width - boxWidth;
164 }
165 boxY = compLocation.y - boxHeight;
166 if (boxY < 0) {
167 if (compLocation.y + compRect.height <= glassSize.height) {
168 boxY = compLocation.y + compRect.height;
169 }
170 else {
171 boxY = 0;
172 }
173 }
174 }
175
176 glassPane.setLayout(null);
177 setBounds(boxX, boxY, boxWidth, boxHeight);
178 glassPane.add(this);
179 glassPane.setVisible(true);
180
181 Container topLevel = getTopLevel();
182 topLevel.validate();
183 topLevel.repaint();
184
185 }
186
187 public void showOnGlassPane(Container glassPane, int originX, int originY) {
188 Dimension boxPrefSize = getPreferredSize();
189 Dimension glassSize = glassPane.getSize();
190 int boxX = 0;
191 int boxY = 0;
192 int boxWidth = 0;
193 int boxHeight = 0;
194
195 boxWidth = Math.min(boxPrefSize.width, glassSize.width);
196 boxHeight = Math.min(boxPrefSize.height, glassSize.height);
197
198 if (originY - boxHeight >= 0) {
199 boxY = originY - boxHeight;
200 } else if (originY + boxHeight <= glassSize.height) {
201 boxY = originY;
202 } else {
203 boxY = glassSize.height - boxHeight;
204 }
205
206 if (originX + boxWidth <= glassSize.width) {
207 boxX = originX;
208 } else if (originX >= boxWidth) {
209 boxX = originX - boxWidth;
210 } else {
211 boxX = glassSize.width - boxWidth;
212 }
213
214 glassPane.setLayout(null);
215 setBounds(boxX, boxY, boxWidth, boxHeight);
216 glassPane.add(this);
217 glassPane.setVisible(true);
218
219 Container topLevel = getTopLevel();
220 topLevel.validate();
221 topLevel.repaint();
222 }
223
224 }