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 }