| 1 package com.sshtools.ui.awt; 2 3 import java.awt.BorderLayout ; 4 import java.awt.Canvas ; 5 import java.awt.Color ; 6 import java.awt.Dimension ; 7 import java.awt.Font ; 8 import java.awt.Frame ; 9 import java.awt.GridBagConstraints ; 10 import java.awt.GridBagLayout ; 11 import java.awt.Image ; 12 import java.awt.Insets ; 13 import java.awt.Label ; 14 import java.awt.Panel ; 15 import java.awt.Window ; 16 import java.awt.event.ActionEvent ; 17 import java.awt.event.ActionListener ; 18 import java.awt.event.MouseEvent ; 19 import java.awt.event.MouseListener ; 20 import java.lang.reflect.Method ; 21 import java.util.Enumeration ; 22 import java.util.Vector ; 23 24 34 public class Toaster { 35 36 39 public final static int DEFAULT_TIMEOUT = 10000; 40 41 45 public final static int BOTTOM_RIGHT = 0; 46 47 51 public final static int BOTTOM_LEFT = 1; 52 53 57 public final static int TOP_LEFT = 2; 58 59 63 public final static int TOP_RIGHT = 3; 64 65 68 69 72 public static Color BACKGROUND_COLOR = null; 73 74 77 public static Color FOREGROUND_COLOR = null; 78 79 82 public static Color BORDER_COLOR = null; 83 84 87 public static Font TEXT_FONT = null; 88 89 92 public static Font TITLE_FONT = null; 93 94 97 static { 98 try { 99 if ("false".equals(System.getProperty("toaster.loadStyleFromUIManager", "false"))) { throw new Exception (Messages.getString("Toaster.disabled")); } 102 Class clazz = Class.forName("javax.swing.UIManager"); Method colorMethod = clazz.getMethod("getColor", new Class [] { Object .class }); Method fontMethod = clazz.getMethod("getFont", new Class [] { Object .class }); BACKGROUND_COLOR = (Color ) colorMethod.invoke(null, new Object [] { "ToolTip.background" }); FOREGROUND_COLOR = (Color ) colorMethod.invoke(null, new Object [] { "ToolTip.foreground" }); BORDER_COLOR = (Color ) colorMethod.invoke(null, new Object [] { "ToolTip.foreground" }); TEXT_FONT = (Font ) fontMethod.invoke(null, new Object [] { "ToolTip.font" }); TITLE_FONT = ((Font ) fontMethod.invoke(null, new Object [] { "Label.font" })); TITLE_FONT = new Font (TITLE_FONT.getName(), Font.BOLD, TITLE_FONT.getSize()); 111 } catch (Exception e) { 112 BACKGROUND_COLOR = Color.white; 113 FOREGROUND_COLOR = Color.black; 114 BORDER_COLOR = Color.black; 115 TEXT_FONT = new Font ("Arial", Font.PLAIN, 10); TITLE_FONT = new Font ("Arial", Font.BOLD, 11); } 118 } 119 120 122 private Vector messages; 123 private Color backgroundColor; 124 private Color foregroundColor; 125 private Color borderColor; 126 private Font textFont; 127 private Font titleFont; 128 private int position; 129 private float textAlign; 130 private Dimension popupSize; 131 private MagicThread magicThread; 132 133 private static Frame sharedFrame; 135 136 143 public Toaster(int position, Dimension popupSize) { 144 messages = new Vector (); 145 backgroundColor = BACKGROUND_COLOR; 146 foregroundColor = FOREGROUND_COLOR; 147 borderColor = BORDER_COLOR; 148 textFont = TEXT_FONT; 149 titleFont = TITLE_FONT; 150 this.popupSize = popupSize; 151 this.position = position; 152 textAlign = Canvas.CENTER_ALIGNMENT; 153 } 154 155 163 public void setTextAlign(float textAlign) { 164 this.textAlign = textAlign; 165 } 166 167 172 public void setPopupSize(Dimension popupSize) { 173 this.popupSize = popupSize; 174 } 175 176 181 public Dimension getPopupSize() { 182 return popupSize; 183 } 184 185 191 public void setPosition(int position) { 192 this.position = position; 193 } 194 195 201 public int getPosition() { 202 return position; 203 } 204 205 210 public Color getBackgroundColor() { 211 return backgroundColor; 212 } 213 214 219 public void setBackgroundColor(Color backgroundColor) { 220 this.backgroundColor = backgroundColor; 221 } 222 223 228 public Color getBorderColor() { 229 return borderColor; 230 } 231 232 237 public void setBorderColor(Color borderColor) { 238 this.borderColor = borderColor; 239 } 240 241 246 public Color getForegroundColor() { 247 return foregroundColor; 248 } 249 250 255 public void setForegroundColor(Color foregroundColor) { 256 this.foregroundColor = foregroundColor; 257 } 258 259 264 public Font getTextFont() { 265 return textFont; 266 } 267 268 273 public void setTextFont(Font textFont) { 274 this.textFont = textFont; 275 } 276 277 282 public Font getTitleFont() { 283 return titleFont; 284 } 285 286 291 public void setTitleFont(Font titleFont) { 292 this.titleFont = titleFont; 293 } 294 295 302 public synchronized void popup(ActionListener callback, String message, String title) { 303 popup(callback, message, title, null); 304 } 305 306 314 public synchronized void popup(ActionListener callback, String message, String title, Image image) { 315 popup(callback, message, title, image, -1); 316 } 317 318 327 public void popup(ActionListener callback, String message, String title, Image image, int timeout) { 328 if (timeout == -1) { 329 timeout = DEFAULT_TIMEOUT; 330 } 331 332 MessageWindow window = new MessageWindow(popupSize, callback, message, title, image, timeout); 334 window.pack(); 335 336 messages.addElement(window); 337 338 if (magicThread != null) { 340 magicThread.stopMagic(); 341 magicThread = null; 342 } 343 344 repositionPopups(); 346 } 347 348 void repositionPopups() { 349 350 synchronized (messages) { 351 Dimension d = null; 353 try { 354 Object genv = Class.forName("java.awt.GraphicsEnvironment") .getMethod("getLocalGraphicsEnvironment", new Class [] {}).invoke(null, new Object [] {}); Object [] devices = (Object []) genv.getClass().getMethod("getScreenDevices", new Class [] {}).invoke(genv, new Object [] {}); 358 Object mode = devices[0].getClass().getMethod("getDisplayMode", new Class [] {}).invoke(devices[0], new Object [] {}); d = new Dimension (((Integer ) mode.getClass().getMethod("getWidth", new Class [] {}).invoke(mode, new Object [] {})) .intValue(), ((Integer ) mode.getClass().getMethod("getHeight", new Class [] {}).invoke(mode, new Object [] {})).intValue()); 362 } catch (Exception e) { 363 d = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); 364 } 365 366 int wy = 0; 368 switch (position) { 369 case TOP_LEFT: 370 case TOP_RIGHT: 371 wy = 16; 372 break; 373 case BOTTOM_LEFT: 374 case BOTTOM_RIGHT: 375 wy = d.height - 48; 376 } 377 378 for (Enumeration e = messages.elements(); e.hasMoreElements();) { 380 MessageWindow w = (MessageWindow) e.nextElement(); 381 382 int wx = 0; 384 switch (position) { 385 case TOP_LEFT: 386 wx = 16; 387 break; 388 case BOTTOM_LEFT: 389 wy = wy - w.getPreferredSize().height; 390 wx = 16; 391 break; 392 case TOP_RIGHT: 393 wx = d.width - popupSize.width - 16; 394 break; 395 case BOTTOM_RIGHT: 396 wy = wy - w.getPreferredSize().height; 397 wx = d.width - popupSize.width - 16; 398 break; 399 } 400 int owy = wy; 401 402 switch (position) { 404 case TOP_LEFT: 405 case TOP_RIGHT: 406 wy += 16; 407 break; 408 case BOTTOM_LEFT: 409 case BOTTOM_RIGHT: 410 wy -= 16; 411 break; 412 } 413 414 if (!w.isVisible()) { 416 w.setLocation(wx, owy); 417 w.setTargetY(owy); 418 w.setVisible(true); 419 } else { 420 w.setTargetY(owy); 421 } 422 } 423 } 424 425 } 426 427 431 void hideAndRemove(MessageWindow messageWindow) { 432 synchronized (messages) { 433 messageWindow.setVisible(false); 434 messages.removeElement(messageWindow); 435 repositionPopups(); 436 437 if (messages.size() != 0 && (magicThread == null || !magicThread.isAlive())) { 439 magicThread = new MagicThread(); 440 } 441 } 442 } 443 444 447 static Frame getSharedFrame() { 448 if (sharedFrame == null) { 449 sharedFrame = new Frame (); 450 } 451 return sharedFrame; 452 } 453 454 460 public static void main(String [] args) throws Exception { 461 javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); 463 Toaster.BACKGROUND_COLOR = Color.white; 465 Toaster.FOREGROUND_COLOR = Color.black; 466 Toaster.BORDER_COLOR = Color.black; 467 final Toaster t = new Toaster(BOTTOM_RIGHT, new Dimension (260, 60)); 475 t.setTextAlign(Canvas.LEFT_ALIGNMENT); 476 t.popup(new ActionListener () { 477 public void actionPerformed(ActionEvent evt) { 478 System.exit(0); 479 } 480 }, "This is a test message blah blah blah blah", "Brett says", UIUtil.loadImage(Toaster.class, "/images/error-48x48.png")); ActionListener a = new ActionListener () { 482 public void actionPerformed(ActionEvent evt) { 483 t.popup(null, "This is a test message blah blah blah blah", "JB says", UIUtil.loadImage(Toaster.class, "/home/brett/Desktop/Modules/vpn-client/client/images/idle.gif")); } 487 }; 488 t.popup(a, "This is a test message blah blah blah blah", "JB says", UIUtil.loadImage(Toaster.class, "/home/brett/Desktop/Modules/vpn-client/client/images/idle.gif"), 2000); t.popup(a, "This is a test message 2", "Pete says", null, 7000); Thread.sleep(1000); 493 t.popup(a, "This is a multi\nline test message 3", "Lee Says"); t.popup(a, 495 "This is a test message blah blah blah blah that should push the size of the text box over the fixed dimensions provided. If it does not something has gone horibbly horibbly wrong. arrrrrrrrggggggggggh!!!!!!!!!!!!!", "JB says", UIUtil.loadImage(Toaster.class, "/home/brett/Desktop/Modules/vpn-client/client/images/idle.gif"), 5000); t.popup(a, 499 "This is a multiline test message blah\nblah blah blah that\nshould push the size of the text\nbox over the fixed dimensions\nprovided. If it does not something\nhas gone horibbly horibbly wrong. arrrrrrrrggggggggggh!!!!!!!!!!!!!", "JB says", UIUtil.loadImage(Toaster.class, "/home/brett/Desktop/Modules/vpn-client/client/images/idle.gif"), 8000); } 503 504 class MagicThread extends Thread { 505 506 boolean run = true; 507 int moved; 508 509 MagicThread() { 510 super("MagicThread"); start(); 512 } 513 514 public void run() { 515 moved = 1; 516 while (run && moved > 0) { 517 try { 518 Method invokeAndWaitMethod = Class.forName("java.awt.EventQueue").getMethod("invokeAndWait", new Class [] { Runnable .class }); Runnable r = new Runnable () { 520 public void run() { 521 moved = doMove(); 522 } 523 }; 524 invokeAndWaitMethod.invoke(null, new Object [] { r }); 525 } catch (Exception e) { 526 moved = doMove(); 527 } 528 yield(); 529 try { 530 sleep(5); 531 } catch (InterruptedException e1) { 532 } 533 } 534 } 535 536 public void stopMagic() { 537 run = false; 538 interrupt(); 539 } 540 541 int doMove() { 542 543 synchronized (messages) { 544 int moved = 0; 545 int ly, lx, wy; 546 MessageWindow w; 547 Enumeration e; 548 for (e = messages.elements(); e.hasMoreElements();) { 549 w = (MessageWindow) e.nextElement(); 550 ly = w.getLocation().y; 551 lx = w.getLocation().x; 552 wy = w.getTargetY(); 553 if (ly > wy) { 554 ly = Math.max(ly - 4, wy); 555 w.setLocation(lx, ly); 556 moved++; 557 } else if (ly < wy) { 558 ly = Math.min(ly + 4, wy); 559 w.setLocation(lx, ly); 560 moved++; 561 } 562 } 563 return moved; 564 } 565 } 566 } 567 568 class MessageWindow extends Window implements MouseListener { 569 570 ActionListener callback; 571 Dimension preferredSize; 572 int targetY; 573 574 MessageWindow(Dimension preferredSize, ActionListener callback, String message, String title, Image image, final int timeout) { 575 this(preferredSize, callback, message, title, image, timeout, null); 576 } 577 578 MessageWindow(Dimension preferredSize, ActionListener callback, String message, String title, Image image, final int timeout, String actionText) { 579 super(Toaster.getSharedFrame()); 580 this.preferredSize = preferredSize; 581 this.callback = callback; 582 try { 584 Method m = getClass().getMethod("setAlwaysOnTop", new Class [] { boolean.class }); m.invoke(this, new Object [] { Boolean.TRUE }); 586 } catch (Exception e) { 587 } 588 BorderPanel p = new BorderPanel(new GridBagLayout ()); 590 p.insets = new Insets (4, 4, 4, 4); 591 p.setBorderColor(borderColor); 592 p.setBackground(backgroundColor); 593 p.setForeground(foregroundColor); 594 GridBagConstraints gbc = new GridBagConstraints (); 595 gbc.anchor = GridBagConstraints.CENTER; 596 597 Label tl = new Label (title); 598 tl.setFont(titleFont); 599 UIUtil.gridBagAdd(p, tl, gbc, GridBagConstraints.REMAINDER); 600 601 WrappingLabel l = new WrappingLabel(); 602 l.setText(message); 603 l.setVAlignStyle(Canvas.TOP_ALIGNMENT); 604 l.setBackground(backgroundColor); 605 l.setForeground(foregroundColor); 606 gbc.fill = GridBagConstraints.BOTH; 607 gbc.weighty = 1.0; 608 l.setFont(textFont); 609 l.setHAlignStyle(textAlign); 610 gbc.weightx = 1.0; 611 if (image != null) { 612 Panel pi = new Panel (new BorderLayout (4, 0)); 613 pi.setBackground(backgroundColor); 614 pi.setForeground(foregroundColor); 615 UIUtil.waitFor(image, this); 616 ImageCanvas c = new ImageCanvas(image); 617 c.setValign(Canvas.TOP_ALIGNMENT); 618 pi.add(c, BorderLayout.WEST); 619 pi.add(l, BorderLayout.CENTER); 620 UIUtil.gridBagAdd(p, pi, gbc, GridBagConstraints.REMAINDER); 621 } else { 622 UIUtil.gridBagAdd(p, l, gbc, GridBagConstraints.REMAINDER); 623 } 624 625 p.addMouseListener(this); 626 l.addMouseListener(this); 627 tl.addMouseListener(this); 628 629 add(p); 630 631 if (timeout > 0) { 632 Thread t = new Thread () { 633 public void run() { 634 try { 635 Thread.sleep(timeout); 636 } catch (InterruptedException ie) { 637 } 638 hideAndRemove(MessageWindow.this); 639 } 640 }; 641 t.start(); 642 } 643 644 if(actionText != null) { 645 Label l2 = new Label (actionText); 646 l2.setAlignment(Label.CENTER); 647 l2.setFont(new Font (titleFont.getName(), Font.PLAIN, 10)); 648 gbc.anchor = GridBagConstraints.CENTER; 649 gbc.weightx = 1.0; 650 UIUtil.gridBagAdd(p, l2, gbc, GridBagConstraints.REMAINDER); 651 } 652 } 653 654 public void setTargetY(int targetY) { 655 this.targetY = targetY; 656 } 657 658 public int getTargetY() { 659 return targetY; 660 } 661 662 public Dimension getPreferredSize() { 663 Dimension s = super.getPreferredSize(); 664 if (s.height > preferredSize.height) { 665 return new Dimension (preferredSize.width, s.height); 666 } 667 return preferredSize; 668 } 669 670 public void mouseClicked(MouseEvent e) { 671 if (callback != null) { 672 callback.actionPerformed(new ActionEvent (this, ActionEvent.ACTION_PERFORMED, "clicked")); } 674 hideAndRemove(this); 675 } 676 677 public void mousePressed(MouseEvent e) { 678 } 679 680 public void mouseReleased(MouseEvent e) { 681 } 682 683 public void mouseEntered(MouseEvent e) { 684 } 685 686 public void mouseExited(MouseEvent e) { 687 } 688 } 689 690 } 691 | Popular Tags |