Source code: novaworx/swing/XPopup.java
1 /*
2 Novaworx Development Environment
3 Copyright (C) 2000-2003 Mark Soderquist
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to:
17
18 Free Software Foundation, Inc.
19 59 Temple Place, Suite 330
20 Boston, MA 02111-1307 USA
21 */
22
23 package novaworx.swing;
24
25 import java.awt.*;
26 import java.awt.event.*;
27 import java.awt.image.*;
28 import java.util.*;
29 import javax.swing.*;
30 import javax.swing.event.*;
31 import novaworx.swing.event.*;
32
33 /**
34 The <code>XPopup</code> class allows backgrounds to be drawn
35 for non-opaque components that are transparent or semi-transparent.
36 Popup components are intended to be displayed over the top of other
37 components in the popup layer of a <code>JLayeredPane</code>.
38 */
39 public class XPopup extends JComponent {
40
41 private static transient XPopup moPopup;
42
43 private static transient PopupHider moHider;
44
45 private transient Vector mvListeners;
46
47 private transient JLayeredPane moLayeredPane;
48
49 private transient Image moBackgroundImage;
50
51 static {
52 moHider = new PopupHider();
53 }
54
55 /**
56 Construct an <code>XPopup</code>.
57 */
58 public XPopup() {
59 super();
60
61 mvListeners = new Vector();
62
63 setOpaque( false );
64 setBackground( new Color( 0, 0, 0, 0 ) );
65 }
66
67 /**
68 Lays out the container so that it uses the minimum space
69 needed to display its contents.
70 */
71 public void pack() {
72 //
73 }
74
75 /**
76 Show the popup at the specified location relative to the specified
77 component.
78 */
79 public void show( JComponent aoComponent, int aiX, int aiY ) {
80 moPopup = this;
81 Dimension oSize = getSize();
82 XWallpaper oWallpaper = getWallpaper( aoComponent );
83
84 if( oWallpaper == null ) {
85 // Set the background color opaque.
86 //setBackground( new XColor( getBackground(), 255 ) );
87 } else {
88 // Use the wallpaper to paint the background.
89 Point oLocation = SwingUtilities.convertPoint( aoComponent, aiX, aiY, oWallpaper );
90 moBackgroundImage = oWallpaper.getSubimage( oLocation.x, oLocation.y, oSize.width, oSize.height );
91 //setOpaque( true );
92 }
93
94 // Get the layered pane to add the popup to.
95 moLayeredPane = aoComponent.getRootPane().getLayeredPane();
96
97 // Adjust the point of origin.
98 if( aoComponent != null ) {
99 Point oOrigin = new Point( aiX, aiY );
100 Point oLocation = SwingUtilities.convertPoint( aoComponent, oOrigin, moLayeredPane );
101 setLocation( oLocation );
102 } else {
103 setLocation( aiX, aiY );
104 }
105
106 // Grab the containers.
107 moHider.grab( aoComponent );
108
109 moLayeredPane.add( this, JLayeredPane.POPUP_LAYER );
110
111 // Show the popup.
112 setVisible( true );
113 }
114
115 /**
116 Show the popup at the specified location relative to the specified
117 component.
118 */
119 /*
120 public void show( JComponent aoComponent, int aiX, int aiY, XWallpaper aoWallpaper ) {
121 setOpaque( true );
122 Dimension oSize = getSize();
123
124 // Create an image the size of the popup.
125 moBackgroundImage = aoWallpaper.getSubimage( oLocation.x, oLocation.y, oSize.width, oSize.height );
126
127 show( aoComponent, aiX, aiY );
128 }
129 */
130
131 /**
132 Hide the popup.
133 */
134 public void cancel() {
135 setVisible( false );
136 moLayeredPane.remove( this );
137 moHider.ungrab();
138 moPopup = null;
139 }
140
141 /**
142 Only need to override the paint method.
143 */
144 public void paint( Graphics aoGraphics ) {
145 // Draw the background.
146 if( moBackgroundImage == null ) {
147 aoGraphics.setColor( getBackground() );
148 aoGraphics.fillRect( 0, 0, getWidth(), getHeight() );
149 } else {
150 aoGraphics.drawImage( moBackgroundImage, 0, 0, this );
151 aoGraphics.setColor( getBackground() );
152 aoGraphics.fillRect( 0, 0, getWidth(), getHeight() );
153 }
154
155 super.paint( aoGraphics );
156 }
157
158 /**
159 Go up the component hierarchy and find an <code>XWallpaper</code>component.
160 */
161 private static XWallpaper getWallpaper( Component aoParent ) {
162 while( aoParent != null && !( aoParent instanceof XWallpaper ) ) aoParent = aoParent.getParent();
163 return (XWallpaper)aoParent;
164 }
165
166 /**
167 Add a <code>PopupListener</code>.
168 */
169 public void addPopupListener( PopupListener aoListener ) {
170 mvListeners.add( aoListener );
171 }
172
173 /**
174 Remove a <code>PopupListener</code>.
175 */
176 public void removePopupListener( PopupListener aoListener ) {
177 mvListeners.remove( aoListener );
178 }
179
180 /**
181 Fire a selection made event.
182 */
183 protected void fireSelectionMade( Object aoSelection ) {
184 PopupEvent oEvent = new PopupEvent( this, aoSelection );
185 int iCount = mvListeners.size();
186 for( int iIndex = 0; iIndex < iCount; iIndex++ ) {
187 ((PopupListener)mvListeners.get( iIndex )).selectionMade( oEvent );
188 }
189 }
190
191 /**
192 Handles events to hide the popup.
193 */
194 private static class PopupHider implements MouseListener, MouseMotionListener, MouseWheelListener, WindowListener, ComponentListener {
195
196 Vector mvGrabbed = new Vector();
197
198 public PopupHider() {}
199
200 void grab( Component aoCompnent ) {
201 grabContainer( getWindow( aoCompnent ), moPopup );
202 }
203
204 void ungrab() {
205 ungrabContainers();
206 }
207
208 void cancelPopup() {
209 if( moPopup != null ) moPopup.cancel();
210 }
211
212 void grabContainer( Container aoContainer, Component aoExcluded ) {
213 if( aoContainer == aoExcluded ) return;
214
215 if( aoContainer instanceof Window ) {
216 ((Window)aoContainer).addWindowListener( this );
217 ((Window)aoContainer).addComponentListener( this );
218 mvGrabbed.addElement( aoContainer );
219 }
220
221 synchronized( aoContainer.getTreeLock() ) {
222 int iComponentCount = aoContainer.getComponentCount();
223 Component[] aComponents = aoContainer.getComponents();
224 for( int iIndex = 0; iIndex < iComponentCount; iIndex++ ) {
225 Component oComponent = aComponents[ iIndex ];
226 if( !oComponent.isVisible() ) continue;
227 oComponent.addMouseListener( this );
228 oComponent.addMouseMotionListener( this );
229 oComponent.addMouseWheelListener( this );
230 mvGrabbed.addElement( oComponent );
231
232 if( oComponent instanceof Container ) {
233 Container oContainer = (Container)oComponent;
234 grabContainer( oContainer, aoExcluded );
235 }
236 }
237 }
238 }
239
240 void ungrabContainers() {
241 Component oComponent;
242
243 int iCount = mvGrabbed.size();
244 for( int iIndex = 0; iIndex < iCount; iIndex++ ) {
245 oComponent = (Component)mvGrabbed.elementAt( 0 );
246 if( oComponent instanceof Window ) {
247 ((Window)oComponent).removeWindowListener( this );
248 ((Window)oComponent).removeComponentListener( this );
249 } else {
250 oComponent.removeMouseListener( this );
251 oComponent.removeMouseMotionListener( this );
252 oComponent.removeMouseWheelListener( this );
253 }
254 }
255 mvGrabbed = new Vector();
256 }
257
258 private static Window getWindow( Component aoComponent ) {
259 Component oWindow = aoComponent;
260
261 while( !( oWindow instanceof Window ) && ( oWindow != null ) ) {
262 oWindow = oWindow.getParent();
263 }
264
265 return (Window)oWindow;
266 }
267
268 public void mousePressed(MouseEvent e) {
269 cancelPopup();
270 }
271
272 public void mouseReleased(MouseEvent e) {}
273
274 public void mouseEntered(MouseEvent e) {}
275
276 public void mouseExited(MouseEvent e) {}
277
278 public void mouseMoved(MouseEvent e) {}
279
280 public void mouseDragged(MouseEvent e) {}
281
282 public void mouseClicked(MouseEvent e) {}
283
284 public void mouseWheelMoved(MouseWheelEvent e) {
285 cancelPopup();
286 }
287
288 public void componentResized(ComponentEvent e) {
289 cancelPopup();
290 }
291
292 public void componentMoved(ComponentEvent e) {
293 cancelPopup();
294 }
295
296 public void componentShown(ComponentEvent e) {
297 cancelPopup();
298 }
299
300 public void componentHidden(ComponentEvent e) {
301 cancelPopup();
302 }
303
304 public void windowOpened(WindowEvent e) {}
305
306 public void windowClosing(WindowEvent e) {
307 cancelPopup();
308 }
309
310 public void windowClosed(WindowEvent e) {
311 cancelPopup();
312 }
313
314 public void windowIconified(WindowEvent e) {
315 cancelPopup();
316 }
317
318 public void windowDeiconified(WindowEvent e) {}
319
320 public void windowActivated(WindowEvent e) {}
321
322 public void windowDeactivated(WindowEvent e) {}
323 }
324
325 }