1 package com.sshtools.ui.swing; 2 3 import java.awt.BorderLayout ; 4 import java.awt.Color ; 5 import java.awt.Component ; 6 import java.awt.Dimension ; 7 import java.awt.Font ; 8 import java.awt.GridBagConstraints ; 9 import java.awt.GridBagLayout ; 10 import java.awt.Image ; 11 import java.awt.event.ActionEvent ; 12 import java.awt.event.ActionListener ; 13 import java.awt.event.MouseEvent ; 14 import java.awt.event.MouseListener ; 15 import java.lang.reflect.Method ; 16 import java.util.Enumeration ; 17 import java.util.Vector ; 18 19 import javax.swing.BorderFactory ; 20 import javax.swing.ImageIcon ; 21 import javax.swing.JFrame ; 22 import javax.swing.JLabel ; 23 import javax.swing.JPanel ; 24 import javax.swing.JWindow ; 25 26 36 public class Toaster { 37 38 41 public final static int DEFAULT_TIMEOUT = 10000; 42 43 47 public final static int BOTTOM_RIGHT = 0; 48 49 53 public final static int BOTTOM_LEFT = 1; 54 55 59 public final static int TOP_LEFT = 2; 60 61 65 public final static int TOP_RIGHT = 3; 66 67 70 71 74 public static Color BACKGROUND_COLOR = null; 75 76 79 public static Color FOREGROUND_COLOR = null; 80 81 84 public static Color BORDER_COLOR = null; 85 86 89 public static Font TEXT_FONT = null; 90 91 94 public static Font TITLE_FONT = null; 95 96 99 static { 100 try { 101 if("false".equals(System.getProperty("toaster.loadStyleFromUIManager", "false"))) { 102 throw new Exception ("Disabled"); 103 } 104 Class clazz = Class.forName("javax.swing.UIManager"); 105 Method colorMethod = clazz.getMethod("getColor", new Class [] { Object .class }); 106 Method fontMethod = clazz.getMethod("getFont", new Class [] { Object .class }); 107 BACKGROUND_COLOR = (Color ) colorMethod.invoke(null, new Object [] { "ToolTip.background" }); 108 FOREGROUND_COLOR = (Color ) colorMethod.invoke(null, new Object [] { "ToolTip.foreground" }); 109 BORDER_COLOR = (Color ) colorMethod.invoke(null, new Object [] { "ToolTip.foreground" }); 110 TEXT_FONT = (Font ) fontMethod.invoke(null, new Object [] { "ToolTip.font" }); 111 TITLE_FONT = ((Font ) fontMethod.invoke(null, new Object [] { "Label.font" })).deriveFont(Font.BOLD); 112 } catch (Exception e) { 113 BACKGROUND_COLOR = Color.white; 114 FOREGROUND_COLOR = Color.black; 115 BORDER_COLOR = Color.black; 116 TEXT_FONT = new Font ("Arial", Font.PLAIN, 10); 117 TITLE_FONT = new Font ("Arial", Font.BOLD, 11); 118 } 119 } 120 121 123 private Vector messages; 124 private Color backgroundColor; 125 private Color foregroundColor; 126 private Color borderColor; 127 private Font textFont; 128 private Font titleFont; 129 private int position; 130 private float textAlign; 131 private Dimension popupSize; 132 private MagicThread magicThread; 133 134 private static JFrame sharedFrame; 136 137 144 public Toaster(int position, Dimension popupSize) { 145 messages = new Vector (); 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 164 public void setTextAlign(float textAlign) { 165 this.textAlign = textAlign; 166 } 167 168 173 public void setPopupSize(Dimension popupSize) { 174 this.popupSize = popupSize; 175 } 176 177 182 public Dimension getPopupSize() { 183 return popupSize; 184 } 185 186 192 public void setPosition(int position) { 193 this.position = position; 194 } 195 196 202 public int getPosition() { 203 return position; 204 } 205 206 211 public Color getBackgroundColor() { 212 return backgroundColor; 213 } 214 215 220 public void setBackgroundColor(Color backgroundColor) { 221 this.backgroundColor = backgroundColor; 222 } 223 224 229 public Color getBorderColor() { 230 return borderColor; 231 } 232 233 238 public void setBorderColor(Color borderColor) { 239 this.borderColor = borderColor; 240 } 241 242 247 public Color getForegroundColor() { 248 return foregroundColor; 249 } 250 251 256 public void setForegroundColor(Color foregroundColor) { 257 this.foregroundColor = foregroundColor; 258 } 259 260 265 public Font getTextFont() { 266 return textFont; 267 } 268 269 274 public void setTextFont(Font textFont) { 275 this.textFont = textFont; 276 } 277 278 283 public Font getTitleFont() { 284 return titleFont; 285 } 286 287 292 public void setTitleFont(Font titleFont) { 293 this.titleFont = titleFont; 294 } 295 296 303 public synchronized void popup(ActionListener callback, String message, String title) { 304 popup(callback, message, title, null); 305 } 306 307 315 public synchronized void popup(ActionListener callback, String message, String title, Image image) { 316 popup(callback, message, title, image, -1); 317 } 318 319 328 public void popup(ActionListener callback, String message, String title, Image image, int timeout) { 329 if (timeout == -1) { 330 timeout = DEFAULT_TIMEOUT; 331 } 332 333 MessageWindow window = new MessageWindow(popupSize, callback, message, title, image, timeout); 335 window.pack(); 336 337 messages.addElement(window); 338 339 if (magicThread != null) { 341 magicThread.stopMagic(); 342 magicThread = null; 343 } 344 345 repositionPopups(); 347 } 348 349 void repositionPopups() { 350 351 synchronized (messages) { 352 Dimension d = null; 354 try { 355 Object genv = Class.forName("java.awt.GraphicsEnvironment") 356 .getMethod("getLocalGraphicsEnvironment", new Class [] {}).invoke(null, new Object [] {}); 357 Object [] devices = (Object []) genv.getClass().getMethod("getScreenDevices", new Class [] {}).invoke(genv, 358 new Object [] {}); 359 Object mode = devices[0].getClass().getMethod("getDisplayMode", new Class [] {}).invoke(devices[0], new Object [] {}); 360 d = new Dimension (((Integer ) mode.getClass().getMethod("getWidth", new Class [] {}).invoke(mode, new Object [] {})) 361 .intValue(), ((Integer ) mode.getClass().getMethod("getHeight", new Class [] {}).invoke(mode, 362 new Object [] {})).intValue()); 363 } catch (Exception e) { 364 d = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); 365 } 366 367 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 for (Enumeration e = messages.elements(); e.hasMoreElements();) { 381 MessageWindow w = (MessageWindow) e.nextElement(); 382 383 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 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 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 432 void hideAndRemove(MessageWindow messageWindow) { 433 synchronized (messages) { 434 messageWindow.setVisible(false); 435 messages.removeElement(messageWindow); 436 repositionPopups(); 437 438 if (messages.size() != 0 && (magicThread == null || !magicThread.isAlive())) { 440 magicThread = new MagicThread(); 441 } 442 } 443 } 444 445 448 public static JFrame getSharedFrame() { 449 if (sharedFrame == null) { 450 sharedFrame = new JFrame (); 451 } 452 return sharedFrame; 453 } 454 455 class MagicThread extends Thread { 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 invokeAndWaitMethod = Class.forName("java.awt.EventQueue").getMethod("invokeAndWait", new Class [] { Runnable .class }); 470 Runnable r = new Runnable () { 471 public void run() { 472 moved = doMove(); 473 } 474 }; 475 invokeAndWaitMethod.invoke(null, new Object [] { r }); 476 } 477 catch(Exception e) { 478 moved = doMove(); 479 } 480 yield(); 481 try { 482 sleep(5); 483 } catch (InterruptedException 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 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 implements MouseListener { 521 522 ActionListener callback; 523 Dimension preferredSize; 524 int targetY; 525 526 MessageWindow(Dimension preferredSize, ActionListener callback, String message, String title, Image image, final int timeout) { 527 super(Toaster.getSharedFrame()); 528 setFocusable(false); 529 this.preferredSize = preferredSize; 530 this.callback = callback; 531 try { 533 Method m = getClass().getMethod("setAlwaysOnTop", new Class [] { boolean.class }); 534 m.invoke(this, new Object [] { Boolean.TRUE }); 535 } catch (Exception e) { 536 } 537 JPanel p = new JPanel (new GridBagLayout ()); 539 p.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createLineBorder(borderColor), BorderFactory.createEmptyBorder(4, 4, 4, 4))); 540 p.setBackground(backgroundColor); 541 p.setForeground(foregroundColor); 542 GridBagConstraints gbc = new GridBagConstraints (); 543 gbc.anchor = GridBagConstraints.CENTER; 544 545 JLabel tl = new JLabel (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 pi = new JPanel (new BorderLayout (4, 0)); 561 pi.setBackground(backgroundColor); 562 pi.setForeground(foregroundColor); 563 JLabel c = new JLabel (new ImageIcon (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 t = new Thread () { 578 public void run() { 579 try { 580 Thread.sleep(timeout); 581 } catch (InterruptedException 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 getPreferredSize() { 598 Dimension s = super.getPreferredSize(); 599 if (s.height > preferredSize.height) { 600 return new Dimension (preferredSize.width, s.height); 601 } 602 return preferredSize; 603 } 604 605 public void mouseClicked(MouseEvent e) { 606 if (callback != null) { 607 callback.actionPerformed(new ActionEvent (this, ActionEvent.ACTION_PERFORMED, "clicked")); 608 } 609 hideAndRemove(this); 610 } 611 612 public void mousePressed(MouseEvent e) { 613 } 614 615 public void mouseReleased(MouseEvent e) { 616 } 617 618 public void mouseEntered(MouseEvent e) { 619 } 620 621 public void mouseExited(MouseEvent e) { 622 } 623 } 624 625 } 626 | Popular Tags |