KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sshtools > ui > swing > Toaster


1 package com.sshtools.ui.swing;
2
3 import java.awt.BorderLayout JavaDoc;
4 import java.awt.Color JavaDoc;
5 import java.awt.Component JavaDoc;
6 import java.awt.Dimension JavaDoc;
7 import java.awt.Font JavaDoc;
8 import java.awt.GridBagConstraints JavaDoc;
9 import java.awt.GridBagLayout JavaDoc;
10 import java.awt.Image JavaDoc;
11 import java.awt.event.ActionEvent JavaDoc;
12 import java.awt.event.ActionListener JavaDoc;
13 import java.awt.event.MouseEvent JavaDoc;
14 import java.awt.event.MouseListener JavaDoc;
15 import java.lang.reflect.Method JavaDoc;
16 import java.util.Enumeration JavaDoc;
17 import java.util.Vector JavaDoc;
18
19 import javax.swing.BorderFactory JavaDoc;
20 import javax.swing.ImageIcon JavaDoc;
21 import javax.swing.JFrame JavaDoc;
22 import javax.swing.JLabel JavaDoc;
23 import javax.swing.JPanel JavaDoc;
24 import javax.swing.JWindow JavaDoc;
25
26 /**
27  *
28  * UI component that display <i>toaster</i> style messages. When a request to
29  * display a message is made, the message will appear at a specified location on
30  * the users desktop. It will stay visible for a specified amount of time. If
31  * more messages are sent in the meantime, they will appear in a new window
32  * either just above or just below the last messages.
33  *
34  * @author Brett Smith <a HREF="mailto: brett@3sp.com">&lt;brett@3sp.com&gt;</a>
35  */

36 public class Toaster {
37
38     /**
39      * Default timeout
40      */

41     public final static int DEFAULT_TIMEOUT = 10000;
42
43     /**
44      * Toaster appears at the bottom right of the screen with messages flowing
45      * up from bottom to top
46      */

47     public final static int BOTTOM_RIGHT = 0;
48
49     /**
50      * Toaster appears at the bottom left of the screen with messages flowing up
51      * from bottom to top
52      */

53     public final static int BOTTOM_LEFT = 1;
54
55     /**
56      * Toaster appears at the top left of the screen with messages flowing down
57      * from top to bottom
58      */

59     public final static int TOP_LEFT = 2;
60
61     /**
62      * Toaster appears at the top right of the screen with messages flowing down
63      * from top to bottom
64      */

65     public final static int TOP_RIGHT = 3;
66
67     /*
68      * Configurable statics
69      */

70
71     /**
72      * Default background color for new toasters
73      */

74     public static Color JavaDoc BACKGROUND_COLOR = null;
75
76     /**
77      * Default foreground color for new toasters
78      */

79     public static Color JavaDoc FOREGROUND_COLOR = null;
80
81     /**
82      * Default border color for new toasters
83      */

84     public static Color JavaDoc BORDER_COLOR = null;
85
86     /**
87      * Default text font for new toasters
88      */

89     public static Font JavaDoc TEXT_FONT = null;
90
91     /**
92      * Default title font for new toasters
93      */

94     public static Font JavaDoc TITLE_FONT = null;
95
96     /*
97      * Intialise depending on environment
98      */

99     static {
100         try {
101             if("false".equals(System.getProperty("toaster.loadStyleFromUIManager", "false"))) {
102                 throw new Exception JavaDoc("Disabled");
103             }
104             Class JavaDoc clazz = Class.forName("javax.swing.UIManager");
105             Method JavaDoc colorMethod = clazz.getMethod("getColor", new Class JavaDoc[] { Object JavaDoc.class });
106             Method JavaDoc fontMethod = clazz.getMethod("getFont", new Class JavaDoc[] { Object JavaDoc.class });
107             BACKGROUND_COLOR = (Color JavaDoc) colorMethod.invoke(null, new Object JavaDoc[] { "ToolTip.background" });
108             FOREGROUND_COLOR = (Color JavaDoc) colorMethod.invoke(null, new Object JavaDoc[] { "ToolTip.foreground" });
109             BORDER_COLOR = (Color JavaDoc) colorMethod.invoke(null, new Object JavaDoc[] { "ToolTip.foreground" });
110             TEXT_FONT = (Font JavaDoc) fontMethod.invoke(null, new Object JavaDoc[] { "ToolTip.font" });
111             TITLE_FONT = ((Font JavaDoc) fontMethod.invoke(null, new Object JavaDoc[] { "Label.font" })).deriveFont(Font.BOLD);
112         } catch (Exception JavaDoc e) {
113             BACKGROUND_COLOR = Color.white;
114             FOREGROUND_COLOR = Color.black;
115             BORDER_COLOR = Color.black;
116             TEXT_FONT = new Font JavaDoc("Arial", Font.PLAIN, 10);
117             TITLE_FONT = new Font JavaDoc("Arial", Font.BOLD, 11);
118         }
119     }
120
121     // Private instance variables
122

123     private Vector JavaDoc messages;
124     private Color JavaDoc backgroundColor;
125     private Color JavaDoc foregroundColor;
126     private Color JavaDoc borderColor;
127     private Font JavaDoc textFont;
128     private Font JavaDoc titleFont;
129     private int position;
130     private float textAlign;
131     private Dimension JavaDoc popupSize;
132     private MagicThread magicThread;
133
134     // Private static variables
135
private static JFrame JavaDoc sharedFrame;
136
137     /**
138      * Constructor.
139      *
140      * @param position
141      * @param popupSize popup size
142      * @see #setPosition(int)
143      */

144     public Toaster(int position, Dimension JavaDoc popupSize) {
145         messages = new Vector JavaDoc();
146         backgroundColor = BACKGROUND_COLOR;
147         foregroundColor = FOREGROUND_COLOR;
148         borderColor = BORDER_COLOR;
149         textFont = TEXT_FONT;
150         titleFont = TITLE_FONT;
151         this.popupSize = popupSize;
152         this.position = position;
153         textAlign = Component.CENTER_ALIGNMENT;
154     }
155
156     /**
157      * Set the text alignment. May be one of
158      * {@link java.awt.Component#LEFT_ALIGNMENT},
159      * {@link java.awt.Component#CENTER_ALIGNMENT} or
160      * {@link java.awt.Component#RIGHT_ALIGNMENT}.
161      *
162      * @param textAlign text alignment
163      */

164     public void setTextAlign(float textAlign) {
165         this.textAlign = textAlign;
166     }
167
168     /**
169      * Set the size of the popups. This will only take affect on new messages.
170      *
171      * @param popupSize popup size
172      */

173     public void setPopupSize(Dimension JavaDoc popupSize) {
174         this.popupSize = popupSize;
175     }
176
177     /**
178      * Get the size of the popups.
179      *
180      * @return popup size
181      */

182     public Dimension JavaDoc getPopupSize() {
183         return popupSize;
184     }
185
186     /**
187      * Set the position of messages. Can be one of {@link #TOP_LEFT},
188      * {@link #TOP_RIGHT}, {@link #BOTTOM_LEFT} or {@link #BOTTOM_RIGHT}.
189      *
190      * @param position position
191      */

192     public void setPosition(int position) {
193         this.position = position;
194     }
195
196     /**
197      * Get the position of messages. Can be one of {@link #TOP_LEFT},
198      * {@link #TOP_RIGHT}, {@link #BOTTOM_LEFT} or {@link #BOTTOM_RIGHT}.
199      *
200      * @return position
201      */

202     public int getPosition() {
203         return position;
204     }
205
206     /**
207      * Get the background color
208      *
209      * @return background color
210      */

211     public Color JavaDoc getBackgroundColor() {
212         return backgroundColor;
213     }
214
215     /**
216      * Set the background color. This will only take affect on new messages.
217      *
218      * @param backgroundColor background color
219      */

220     public void setBackgroundColor(Color JavaDoc backgroundColor) {
221         this.backgroundColor = backgroundColor;
222     }
223
224     /**
225      * Get the border color
226      *
227      * @return border color
228      */

229     public Color JavaDoc getBorderColor() {
230         return borderColor;
231     }
232
233     /**
234      * Set the border color. This will only take affect on new messages.
235      *
236      * @param borderColor border color
237      */

238     public void setBorderColor(Color JavaDoc borderColor) {
239         this.borderColor = borderColor;
240     }
241
242     /**
243      * Get the foreground color
244      *
245      * @return foreground color
246      */

247     public Color JavaDoc getForegroundColor() {
248         return foregroundColor;
249     }
250
251     /**
252      * Set the foreground color. This will only take affect on new messages.
253      *
254      * @param foregroundColor
255      */

256     public void setForegroundColor(Color JavaDoc foregroundColor) {
257         this.foregroundColor = foregroundColor;
258     }
259
260     /**
261      * Get the text text
262      *
263      * @return text font
264      */

265     public Font JavaDoc getTextFont() {
266         return textFont;
267     }
268
269     /**
270      * Set the text font. This will only take affect on new messages.
271      *
272      * @param textFont text font
273      */

274     public void setTextFont(Font JavaDoc textFont) {
275         this.textFont = textFont;
276     }
277
278     /**
279      * Get the title font. This will only take affect on new messages.
280      *
281      * @return title font
282      */

283     public Font JavaDoc getTitleFont() {
284         return titleFont;
285     }
286
287     /**
288      * Set the title font. This will only take affect on new messages.
289      *
290      * @param titleFont title font
291      */

292     public void setTitleFont(Font JavaDoc titleFont) {
293         this.titleFont = titleFont;
294     }
295
296     /**
297      * Popup a new message for 10 seconds.
298      *
299      * @param callback invoked when message is clicked
300      * @param message message to display
301      * @param title title of message
302      */

303     public synchronized void popup(ActionListener JavaDoc callback, String JavaDoc message, String JavaDoc title) {
304         popup(callback, message, title, null);
305     }
306
307     /**
308      * Popup a new message for 10 seconds with an option image.
309      *
310      * @param callback invoked when message is clicked
311      * @param message message to display
312      * @param title title of message
313      * @param image image or <code>null</code>
314      */

315     public synchronized void popup(ActionListener JavaDoc callback, String JavaDoc message, String JavaDoc title, Image JavaDoc image) {
316         popup(callback, message, title, image, -1);
317     }
318
319     /**
320      * Popup a new message.
321      *
322      * @param callback invoked when message is clicked
323      * @param message message to display
324      * @param title title of message
325      * @param timeout time to display message for
326      * @param image image or <code>null</code>
327      */

328     public void popup(ActionListener JavaDoc callback, String JavaDoc message, String JavaDoc title, Image JavaDoc image, int timeout) {
329         if (timeout == -1) {
330             timeout = DEFAULT_TIMEOUT;
331         }
332
333         // Create the new message window and add it to our Vector
334
MessageWindow window = new MessageWindow(popupSize, callback, message, title, image, timeout);
335         window.pack();
336
337         messages.addElement(window);
338
339         // Stop the magic thread
340
if (magicThread != null) {
341             magicThread.stopMagic();
342             magicThread = null;
343         }
344
345         // Reposition and show the messages windows
346
repositionPopups();
347     }
348
349     void repositionPopups() {
350
351         synchronized (messages) {
352             // Get the screeb suze
353
Dimension JavaDoc d = null;
354             try {
355                 Object JavaDoc genv = Class.forName("java.awt.GraphicsEnvironment")
356                                 .getMethod("getLocalGraphicsEnvironment", new Class JavaDoc[] {}).invoke(null, new Object JavaDoc[] {});
357                 Object JavaDoc[] devices = (Object JavaDoc[]) genv.getClass().getMethod("getScreenDevices", new Class JavaDoc[] {}).invoke(genv,
358                     new Object JavaDoc[] {});
359                 Object JavaDoc mode = devices[0].getClass().getMethod("getDisplayMode", new Class JavaDoc[] {}).invoke(devices[0], new Object JavaDoc[] {});
360                 d = new Dimension JavaDoc(((Integer JavaDoc) mode.getClass().getMethod("getWidth", new Class JavaDoc[] {}).invoke(mode, new Object JavaDoc[] {}))
361                                 .intValue(), ((Integer JavaDoc) mode.getClass().getMethod("getHeight", new Class JavaDoc[] {}).invoke(mode,
362                     new Object JavaDoc[] {})).intValue());
363             } catch (Exception JavaDoc e) {
364                 d = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
365             }
366
367             // Calculate the starting position
368
int wy = 0;
369             switch (position) {
370                 case TOP_LEFT:
371                 case TOP_RIGHT:
372                     wy = 16;
373                     break;
374                 case BOTTOM_LEFT:
375                 case BOTTOM_RIGHT:
376                     wy = d.height - 48;
377             }
378
379             // Set the target positions on all of the windows
380
for (Enumeration JavaDoc e = messages.elements(); e.hasMoreElements();) {
381                 MessageWindow w = (MessageWindow) e.nextElement();
382
383                 // Calculate the x (and y where appropriate) position
384
int wx = 0;
385                 switch (position) {
386                     case TOP_LEFT:
387                         wx = 16;
388                         break;
389                     case BOTTOM_LEFT:
390                         wy = wy - w.getPreferredSize().height;
391                         wx = 16;
392                         break;
393                     case TOP_RIGHT:
394                         wx = d.width - popupSize.width - 16;
395                         break;
396                     case BOTTOM_RIGHT:
397                         wy = wy - w.getPreferredSize().height;
398                         wx = d.width - popupSize.width - 16;
399                         break;
400                 }
401                 int owy = wy;
402
403                 // Increment the y position
404
switch (position) {
405                     case TOP_LEFT:
406                     case TOP_RIGHT:
407                         wy += 16;
408                         break;
409                     case BOTTOM_LEFT:
410                     case BOTTOM_RIGHT:
411                         wy -= 16;
412                         break;
413                 }
414
415                 // Show the window if it is not visible
416
if (!w.isVisible()) {
417                     w.setLocation(wx, owy);
418                     w.setTargetY(owy);
419                     w.setVisible(true);
420                 } else {
421                     w.setTargetY(owy);
422                 }
423             }
424         }
425
426     }
427
428     /*
429      * Hide a popup, remove it from the list and move other popups to their new
430      * position
431      */

432     void hideAndRemove(MessageWindow messageWindow) {
433         synchronized (messages) {
434             messageWindow.setVisible(false);
435             messages.removeElement(messageWindow);
436             repositionPopups();
437
438             // Start the magic thread if its not running
439
if (messages.size() != 0 && (magicThread == null || !magicThread.isAlive())) {
440                 magicThread = new MagicThread();
441             }
442         }
443     }
444
445     /*
446      * Get a shared parent frame
447      */

448     public static JFrame JavaDoc getSharedFrame() {
449         if (sharedFrame == null) {
450             sharedFrame = new JFrame JavaDoc();
451         }
452         return sharedFrame;
453     }
454
455     class MagicThread extends Thread JavaDoc {
456
457         boolean run = true;
458         int moved;
459
460         MagicThread() {
461             super("MagicThread");
462             start();
463         }
464
465         public void run() {
466             moved = 1;
467             while (run && moved > 0) {
468                 try {
469                     Method JavaDoc invokeAndWaitMethod = Class.forName("java.awt.EventQueue").getMethod("invokeAndWait", new Class JavaDoc[] { Runnable JavaDoc.class });
470                     Runnable JavaDoc r = new Runnable JavaDoc() {
471                         public void run() {
472                             moved = doMove();
473                         }
474                     };
475                     invokeAndWaitMethod.invoke(null, new Object JavaDoc[] { r });
476                 }
477                 catch(Exception JavaDoc e) {
478                     moved = doMove();
479                 }
480                 yield();
481                 try {
482                     sleep(5);
483                 } catch (InterruptedException JavaDoc e1) {
484                 }
485             }
486         }
487
488         public void stopMagic() {
489             run = false;
490             interrupt();
491         }
492
493         int doMove() {
494
495             synchronized (messages) {
496                 int moved = 0;
497                 int ly, lx, wy;
498                 MessageWindow w;
499                 Enumeration JavaDoc e;
500                 for (e = messages.elements(); e.hasMoreElements();) {
501                     w = (MessageWindow) e.nextElement();
502                     ly = w.getLocation().y;
503                     lx = w.getLocation().x;
504                     wy = w.getTargetY();
505                     if (ly > wy) {
506                         ly = Math.max(ly - 4, wy);
507                         w.setLocation(lx, ly);
508                         moved++;
509                     } else if (ly < wy) {
510                         ly = Math.min(ly + 4, wy);
511                         w.setLocation(lx, ly);
512                         moved++;
513                     }
514                 }
515                 return moved;
516             }
517         }
518     }
519
520     class MessageWindow extends JWindow JavaDoc implements MouseListener JavaDoc {
521
522         ActionListener JavaDoc callback;
523         Dimension JavaDoc preferredSize;
524         int targetY;
525
526         MessageWindow(Dimension JavaDoc preferredSize, ActionListener JavaDoc callback, String JavaDoc message, String JavaDoc title, Image JavaDoc image, final int timeout) {
527             super(Toaster.getSharedFrame());
528             setFocusable(false);
529             this.preferredSize = preferredSize;
530             this.callback = callback;
531             // #ifdef JAVA2
532
try {
533                 Method JavaDoc m = getClass().getMethod("setAlwaysOnTop", new Class JavaDoc[] { boolean.class });
534                 m.invoke(this, new Object JavaDoc[] { Boolean.TRUE });
535             } catch (Exception JavaDoc e) {
536             }
537             // #endif
538
JPanel JavaDoc p = new JPanel JavaDoc(new GridBagLayout JavaDoc());
539             p.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor), BorderFactory.createEmptyBorder(4, 4, 4, 4)));
540             p.setBackground(backgroundColor);
541             p.setForeground(foregroundColor);
542             GridBagConstraints JavaDoc gbc = new GridBagConstraints JavaDoc();
543             gbc.anchor = GridBagConstraints.CENTER;
544
545             JLabel JavaDoc tl = new JLabel JavaDoc(title);
546             tl.setFont(titleFont);
547             UIUtil.jGridBagAdd(p, tl, gbc, GridBagConstraints.REMAINDER);
548
549             WrappingLabel l = new WrappingLabel();
550             l.setText(message);
551             l.setVAlignStyle(Component.TOP_ALIGNMENT);
552             l.setBackground(backgroundColor);
553             l.setForeground(foregroundColor);
554             gbc.fill = GridBagConstraints.BOTH;
555             gbc.weighty = 1.0;
556             l.setFont(textFont);
557             l.setHAlignStyle(textAlign);
558             gbc.weightx = 1.0;
559             if (image != null) {
560                 JPanel JavaDoc pi = new JPanel JavaDoc(new BorderLayout JavaDoc(4, 0));
561                 pi.setBackground(backgroundColor);
562                 pi.setForeground(foregroundColor);
563                 JLabel JavaDoc c = new JLabel JavaDoc(new ImageIcon JavaDoc(image));
564                 pi.add(c, BorderLayout.WEST);
565                 pi.add(l, BorderLayout.CENTER);
566                 UIUtil.jGridBagAdd(p, pi, gbc, GridBagConstraints.REMAINDER);
567             } else {
568                 UIUtil.jGridBagAdd(p, l, gbc, GridBagConstraints.REMAINDER);
569             }
570
571             p.addMouseListener(this);
572             l.addMouseListener(this);
573             tl.addMouseListener(this);
574
575             add(p);
576
577             Thread JavaDoc t = new Thread JavaDoc() {
578                 public void run() {
579                     try {
580                         Thread.sleep(timeout);
581                     } catch (InterruptedException JavaDoc ie) {
582                     }
583                     hideAndRemove(MessageWindow.this);
584                 }
585             };
586             t.start();
587         }
588
589         public void setTargetY(int targetY) {
590             this.targetY = targetY;
591         }
592
593         public int getTargetY() {
594             return targetY;
595         }
596
597         public Dimension JavaDoc getPreferredSize() {
598             Dimension JavaDoc s = super.getPreferredSize();
599             if (s.height > preferredSize.height) {
600                 return new Dimension JavaDoc(preferredSize.width, s.height);
601             }
602             return preferredSize;
603         }
604
605         public void mouseClicked(MouseEvent JavaDoc e) {
606             if (callback != null) {
607                 callback.actionPerformed(new ActionEvent JavaDoc(this, ActionEvent.ACTION_PERFORMED, "clicked"));
608             }
609             hideAndRemove(this);
610         }
611
612         public void mousePressed(MouseEvent JavaDoc e) {
613         }
614
615         public void mouseReleased(MouseEvent JavaDoc e) {
616         }
617
618         public void mouseEntered(MouseEvent JavaDoc e) {
619         }
620
621         public void mouseExited(MouseEvent JavaDoc e) {
622         }
623     }
624
625 }
626
Popular Tags