001 /* 002 * Copyright (c) Holger Pfaff - http://pfaff.ws 003 * 004 * This software maybe used for any purpose provided the 005 * above copyright notice is retained. It is supplied as is. 006 * No warranty expressed or implied - Use at your own risk. 007 */ 008 009 import java.awt.*; 010 import java.awt.event.*; 011 import java.util.*; 012 import java.io.*; 013 import java.net.*; 014 import java.applet.*; 015 016 /** 017 * (#)Awt.java 018 * @author Holger Pfaff 019 * @version 3.2 19-Mar-2004<br><br> 020 * 021 * Implements some useful (static) AWT routines and acts as baseclass 022 * for several gui items 023 * <br> 024 * Overview of mode bits used in this class: 025 * <pre> 026 * misc effect position 027 * 0 0 0 0 0 0 0 0 0 0 0 0 028 * - - H F U B S R W S E N 029 * r i l u u a e o a o 030 * e l i l n i s u s r 031 * f l n k k s t t t t 032 * e e e h h 033 * n d 034 * </pre> 035 * This class also implements a simple text formating mechanism. Unicode 036 * escape sequences can be used to change fonts alignment, color etc. The 037 * syntax is pretty easy. A formatting directive is always constructed 038 * from <unicode esc> + <unicode format info>. The prefix for setting the 039 * font to serif and the color to white woud be Esc + Serif + Esc + White.<br> 040 * A summary of all attributes:<br> 041 * <pre> 042 * Font Family FFnn 043 * Serif FF00 044 * SansSerif FF01 045 * Monospaced FF02 046 * <br> 047 * Font style FBnn 048 * Plain FB00 049 * Bold FB01 050 * Italic FB02 051 * Bolditalic FB03 052 * 053 * Font Size rel. F0nn 054 * Smaller F000 two pixel smaller 055 * Larger F001 two pixel larger 056 * 057 * Font Size Absolut F5nn nn = size in pixel (hex) 058 * 059 * Text Alignment A00n 060 * North A001 061 * East A002 062 * South A004 063 * West A008 064 * NorthWest A009 065 * SouthWest A00C 066 * NorthEast A003 067 * SouthEast A00A 068 * Center A00F 069 * 070 * Text Tabs Dnnn Left tabs only nnn = no of char to tab 071 * Tab0 D000 072 * 073 * Effects Ennn 074 * Flat E000 default effect 075 * Raised E001 makes objects looking raised 076 * Sunken E002 makes objects looking sunken 077 * Bulk E003 actually a drawing mode @see setBorderType() 078 * Uline E004 underline 079 * Href E0D1 start of a href 080 * Hrefend E0D0 end of a href 081 * Darker E0C1 make foreground color darker 082 * Brighter E0C2 make foreground color brighter 083 * Background E0C3 make foreground equal to current backgroundcolor 084 * 085 * Colors Cnnn nnn = rgb - eight bits per color 086 * White C000 087 * Black CFFF 088 * </pre> 089 * 090 */ 091 092 public class Awt extends Panel implements MouseListener, MouseMotionListener, KeyListener, AdjustmentListener, FocusListener, ItemSelectable { 093 094 /** 095 * One special mode 096 */ 097 public final static int NONE = 0; 098 099 /** 100 * positions / directions mask - the lowest 4 bits 0-3 101 */ 102 public final static int POSITION_MASK = 0xF; 103 104 /** 105 * North position 106 */ 107 public final static int N = 0x1 << 0; 108 109 /** 110 * East position 111 */ 112 public final static int E = 0x1 << 1; 113 114 /** 115 * South position 116 */ 117 public final static int S = 0x1 << 2; 118 119 /** 120 * West position 121 */ 122 public final static int W = 0x1 << 3; 123 124 /** 125 * NorthWest position 126 */ 127 public final static int NW = N|W; 128 129 /** 130 * SouthWest position 131 */ 132 public final static int SW = S|W; 133 134 /** 135 * NorthEast position 136 */ 137 public final static int NE = N|E; 138 139 /** 140 * SouthEast position 141 */ 142 public final static int SE = S|E; 143 144 /** 145 * Center position 146 */ 147 public final static int C = N|E|S|W; 148 149 /** 150 * Center position 151 */ 152 public final static int CENTER = C; 153 154 /** 155 * Top position 156 */ 157 public final static int TOP = N; 158 159 /** 160 * Right position 161 */ 162 public final static int RIGHT = E; 163 164 /** 165 * Bottom position 166 */ 167 public final static int BOTTOM = S; 168 169 /** 170 * Left position 171 */ 172 public final static int LEFT = W; 173 174 /** 175 * effect mask - bits 4-7 176 */ 177 public final static int EFFECT_MASK = 0xF << 4; 178 179 /** 180 * a raised border 181 */ 182 public final static int RAISED = 0x1 << 4; 183 184 /** 185 * a sunken border 186 */ 187 public final static int SUNKEN = 0x1 << 5; 188 189 /** 190 * a highlighted border/text 191 */ 192 public final static int BULK = 0x1 << 6; 193 194 /** 195 * underline effect 196 */ 197 public final static int ULINE = 0x1 << 7; 198 199 /** 200 * mode mask - bits 8-11 201 */ 202 public final static int MISC_MASK = 0xF << 8; 203 204 /** 205 * fill object (rectangle/triangle) - Outline is default 206 */ 207 public final static int FILL = 0x1 << 8; 208 209 /** 210 * the following text is a href 211 */ 212 public final static int HREF = 0x1 << 9; 213 214 /** 215 * Unicode replacement char. Used as indicator that the 216 * following char is interpreted as formatting information 217 */ 218 public final static char Esc = '\uFFFD'; 219 220 /** 221 * Unicode null char. Not a char at all. Used as placeholder 222 */ 223 public final static char Null = '\uFFFF'; 224 225 /** 226 * reset all styles to default 227 */ 228 public final static char None = '\u0000'; 229 230 /** 231 * font family Serif 232 */ 233 public final static char Serif = '\uFF00'; 234 235 /** 236 * font family SansSerif 237 */ 238 public final static char SansSerif = '\uFF01'; 239 240 /** 241 * font family Monospaced 242 */ 243 public final static char Monospaced = '\uFF02'; 244 245 /** 246 * font style plain 247 */ 248 public final static char Plain = '\uFB00'; 249 250 /** 251 * font style bold 252 */ 253 public final static char Bold = '\uFB01'; 254 255 /** 256 * font style italic 257 */ 258 public final static char Italic = '\uFB02'; 259 260 /** 261 * font style bolditalic 262 */ 263 public final static char Bolditalic = '\uFB03'; 264 265 /** 266 * font size relative smaller 267 */ 268 public final static char Smaller = '\uF000'; 269 270 /** 271 * font size relative larger 272 */ 273 public final static char Larger = '\uF001'; 274 275 /** 276 * font sizes absolute 277 */ 278 public final static char FontSize0 = '\uF500'; 279 280 /** 281 * Mask for computing fontsizes 282 */ 283 public final static char FontMask = '\uFF00'; 284 285 /** 286 * Mask for computing fontsizes 287 */ 288 public final static char FontSizeMask = '\u00FF'; 289 290 /** 291 * North alignment 292 */ 293 public final static char North = '\uA001'; 294 295 /** 296 * East alignment 297 */ 298 public final static char East = '\uA002'; 299 300 /** 301 * South alignment 302 */ 303 public final static char South = '\uA004'; 304 305 /** 306 * West alignment 307 */ 308 public final static char West = '\uA008'; 309 310 /** 311 * NorthWest alignment 312 */ 313 public final static char NorthWest = '\uA009'; 314 315 /** 316 * SouthWest alignment 317 */ 318 public final static char SouthWest = '\uA00C'; 319 320 /** 321 * NorthEast alignment 322 */ 323 public final static char NorthEast = '\uA003'; 324 325 /** 326 * SouthEast alignment 327 */ 328 public final static char SouthEast = '\uA00A'; 329 330 /** 331 * Center alignment 332 */ 333 public final static char Center = '\uA00F'; 334 335 /** 336 * Tab positions absolute; Format: Dnnn nnn is the pos in hex ranging from 0 - 7FF 337 */ 338 public final static char Tab0 = '\uD000'; 339 340 /** 341 * Tab mask to determine tabs 342 */ 343 public final static char TabMask = '\uF000'; 344 345 /** 346 * Tab mask to determine tab positions 347 */ 348 public final static char TabSizeMask = '\u07FF'; 349 350 /** 351 * the default 'effect' 352 */ 353 public final static char Flat = '\uE000'; 354 355 /** 356 * shadow effect to emphasize text 357 */ 358 public final static char Raised = '\uE001'; 359 360 /** 361 * shadow effect to make text look inaktive 362 */ 363 public final static char Sunken = '\uE002'; 364 365 /** 366 * Used to specify a border mode in property files. not used for text 367 */ 368 public final static char Bulk = '\uE003'; 369 370 /** 371 * Underline text 372 */ 373 public final static char Uline = '\uE004'; 374 375 /** 376 * start of a href 377 */ 378 public final static char Href = '\uE0D1'; 379 380 /** 381 * end of a href (or use flat/default) 382 */ 383 public final static char Hrefend = '\uE0D0'; 384 385 /** 386 * make fg color darker 387 */ 388 public final static char Darker = '\uE0C1'; 389 390 /** 391 * make fg color brighter 392 */ 393 public final static char Brighter = '\uE0C2'; 394 395 /** 396 * make fg color equal to fg color (same as setting it to default) 397 */ 398 public final static char Foreground = '\uE0C3'; 399 400 /** 401 * make fg color equal to bg color 402 */ 403 public final static char Background = '\uE0C4'; 404 405 /** 406 * colors use the format C<r><g><b>, where each color value can range from 0 to F. See examples below 407 */ 408 public final static char ColorMask = '\uF000'; 409 410 /** 411 * used to determine the red portion of this color spec 412 */ 413 public final static char RedMask = '\u0F00'; 414 415 /** 416 * used to determine the green portion of this color spec 417 */ 418 public final static char GreenMask = '\u00F0'; 419 420 /** 421 * used to determine the blue portion of this color spec 422 */ 423 public final static char BlueMask = '\u000F'; 424 425 /** 426 * the color white 427 */ 428 public final static char White = '\uC000'; 429 430 /** 431 * the color black 432 */ 433 public final static char Black = '\uCFFF'; 434 435 /** 436 * java version 437 */ 438 protected final static String jversion = System.getProperty("java.version"); 439 440 /** 441 * java vendor 442 */ 443 protected final static String jvendor = System.getProperty("java.vendor"); 444 445 /** 446 * font cache 447 */ 448 protected final static Hashtable fonts = new Hashtable(); 449 450 /** 451 * insets around this comp 452 */ 453 protected Insets insets = new Insets(0,0,0,0); // borders around the component 454 455 /** 456 * insets within this comp 457 */ 458 protected Insets innerInsets = new Insets(0,0,0,0); // borders within the component 459 460 /** 461 * borderdepth - thickness of border 462 */ 463 protected int borderDepth = 0; 464 465 /** 466 * bordertype - one of NONE, RAISED, SUNKEN, BULK, TOP 467 */ 468 protected int borderType = NONE; 469 470 /** 471 * the dimension for comp 472 */ 473 protected Dimension minimumDimension = new Dimension(); 474 475 /** 476 * ActionListener to notify clients 477 */ 478 protected ActionListener actionListener = null; 479 480 /** 481 * ItemListener to notify clients 482 */ 483 protected ItemListener itemListener = null; 484 485 /** 486 * save components states if this panel is set to disable 487 */ 488 protected Hashtable componentStates = new Hashtable(); 489 490 /** 491 * our Background 492 */ 493 protected Object bg = null; 494 495 /** 496 * backing image for flickerfree drawing 497 */ 498 protected Image bim = null; 499 500 /** 501 * Grphics for bim 502 */ 503 protected Graphics big = null; 504 505 /** 506 * Creates a nicely formatted error popup. 507 * 508 * @param m the message; usually string or exception 509 * @param c comp used as parent for popup or null 510 */ 511 public static void error(Object m, Component c) { 512 String s[] = Debug.stackline(1); 513 String e = "" + Esc + Bold + Debug.msg(m); 514 if(s.length > 2) { 515 e += "\n" + Esc + Plain + "[" + s[1] + " at " + s[2] + "]"; 516 } 517 if(m instanceof Exception) { 518 e += "\n\n" + Esc + Italic + Debug.stack((Exception) m).replace('\t',' '); 519 } 520 DialogBox.errorDialog(e).show(c); 521 } 522 523 /** 524 * Creates an image from an InputStream 525 * 526 * @param n the name of the image. 527 */ 528 public static Image loadImageFromStream(InputStream i) { 529 try { 530 ByteArrayOutputStream b = new ByteArrayOutputStream(); 531 for(int c = i.read(); c >= 0; c = i.read()) { 532 b.write(c); 533 } 534 return Toolkit.getDefaultToolkit().createImage(b.toByteArray()); 535 } catch(Exception x) { 536 Debug.debug(Awt.class, x); 537 return null; 538 } 539 } 540 541 /** 542 * Creates an image from a Archive 543 * At least this is what Netscape 4.x does. 544 * @link <a href="http://developer.netscape.com/docs/technote/java/getresource/getresource.html">Technote getresource</a> 545 * Returns <code>null</code> on failure. 546 * 547 * @param n the name of the image. 548 */ 549 public static Image loadImageFromArchive(String n) { 550 return loadImageFromStream(Awt.class.getResourceAsStream(n)); 551 } 552 553 /** 554 * Creates an image from an url. 555 * Returns <code>null</code> on failure. 556 * 557 * @param n the name/url of the image. 558 */ 559 public static Image loadImageFromURL(String n) { 560 try { 561 return loadImageFromStream(new URL(n).openStream()); 562 } catch(Exception x) { 563 Debug.debug(Awt.class, x); 564 return null; 565 } 566 } 567 568 /** 569 * Creates an image either form URL or Archive 570 * Returns <code>null</code> on failure. 571 * 572 * @param n the name/url of the image. 573 */ 574 public Image loadImage(String n) { 575 Image i = loadImageFromURL(n); 576 if(i == null) { 577 i = loadImageFromArchive(n); 578 } 579 return i; 580 } 581 582 /** 583 * Check if this is a Netscape 4 JVM 584 * 585 * @return true if this is a Netscape 4 JVM 586 */ 587 public static boolean isNS4JVM() { 588 return jversion.equals("1.1.5") && jvendor.startsWith("Net"); 589 } 590 591 /** 592 * Check if this is a MS JVM 593 * 594 * @return true if this is a MS JVM 595 */ 596 public static boolean isMSJVM() { 597 return jversion.equals("1.1.4") && jvendor.startsWith("Mic"); 598 } 599 600 /** 601 * Center a window on screen. Reduces window size if larger 602 * than screen. 603 * 604 * @param w the window to center. 605 */ 606 public static void centerWindow(Window w) { 607 Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); 608 // not larger than screen ... 609 w.setSize(Math.min(d.width, w.getSize().width), Math.min(d.height, w.getSize().height)); 610 // Center Frame, Dialog or Window on screen 611 w.setLocation((d.width - w.getSize().width) / 2, (d.height - w.getSize().height) / 2); 612 } 613 614 /** 615 * Set BG color of a (AWT) component 616 * 617 * @param c Component 618 */ 619 public static void setBackground(Component c) { 620 if(c.getParent().getBackground() != null) { 621 c.setBackground(c instanceof TextComponent && (isNS4JVM() || isMSJVM()) ? c.getParent().getBackground().darker() : c.getParent().getBackground()); 622 } 623 } 624 625 /** 626 * Set FG color of a (AWT) component 627 * 628 * @param c Component 629 */ 630 public static void setForeground(Component c) { 631 if(c.getParent().getForeground() != null) { 632 c.setForeground(c.getParent().getForeground()); 633 } 634 } 635 636 /** 637 * Set font of a (AWT) textcomponent 638 * 639 * @param tc TextComponent 640 */ 641 public static void setFont(TextComponent tc) { 642 if(tc.getParent().getFont() != null) { 643 tc.setFont(tc.getParent().getFont()); 644 } 645 } 646 647 /** 648 * Refresh (force new layout) starting from component up the tree 649 * 650 * @param c the component to refresh. 651 */ 652 public static void refresh(Component c) { 653 c.invalidate(); 654 c.validate(); 655 if(isMSJVM()) c.repaint(); 656 if(c instanceof Container) { 657 Component[] cs = ((Container) c).getComponents(); 658 for(int i = 0; i < cs.length; ++i) { 659 if(cs[i] instanceof TextComponent) { 660 setFont((TextComponent) cs[i]); 661 } 662 if(cs[i] instanceof TextComponent || cs[i] instanceof Scrollbar) { 663 setForeground(cs[i]); 664 setBackground(cs[i]); 665 } 666 refresh(cs[i]); 667 } 668 } 669 if(c instanceof Window) { 670 ((Window) c).pack(); return; 671 } 672 } 673 674 /** 675 * Refresh (force new layout) starting from this component down the tree 676 */ 677 public void refresh() { 678 refresh(this); 679 } 680 681 /** 682 * Refresh (force new layout) starting from root component up the tree 683 */ 684 public void refreshAll() { 685 refresh(getTopComponent(this)); 686 refresh(getTopComponent(this)); 687 } 688 689 /** 690 * Gets the toplevel component (usually a frame) 691 * 692 * @param c the component to find the toplevel component for. 693 */ 694 public static Component getTopComponent(Component c) { 695 return (Component) c.getParent() == null || (c instanceof Main && ((Main)c).isApplet()) ? c : getTopComponent(c.getParent()); 696 } 697 698 /** 699 * Gets the current applet context if any 700 * 701 * @param c the component to find the applet context for. 702 */ 703 public static AppletContext getAppletContext(Component c) { 704 return getApplet(getTopComponent(c)).getAppletContext(); 705 } 706 707 /** 708 * Gets the current applet if any. Used internaly 709 * 710 * @param c the toplevel component to start with 711 */ 712 private static Applet getApplet(Component c) { 713 if(c instanceof Applet) { 714 return (Applet) c; 715 } 716 if(c instanceof Container) { 717 Container C = (Container) c; 718 for(int i = 0; i < C.getComponentCount(); ++i) { 719 Applet a = getApplet(C.getComponent(i)); 720 if(a != null) { 721 return a; 722 } 723 } 724 } 725 return null; 726 } 727 728 /** 729 * Try to get a font. <code>obj</code> can be a 730 * standard font name or already a font object. 731 * 732 * @return <code>null</code> on failure. 733 * 734 * @param obj color specification. 735 */ 736 public static Font getFont(Object o) { 737 if(o == null) { 738 return null; 739 } 740 if(o instanceof Font) { 741 return (Font) o; 742 } 743 return Font.decode(o.toString()); 744 } 745 746 /** 747 * Try to get a font from our cache. Create a new one if none was found. 748 * 749 * @param name Font name/family 750 * @param style Font.PAIN Font.BOLD Font.ITALIC 751 * @param size Font size in points 752 */ 753 public static Font getFont(String name, int style, int size) { 754 String idx = name + style + size; 755 if(fonts.containsKey(idx)) { 756 return (Font) fonts.get(idx); 757 } else { 758 Font font = new Font(name, style, size); 759 fonts.put(idx, font); getMetrics(font); 760 return font; 761 } 762 } 763 764 /** 765 * Returns Metrics for font 766 * @param f font to use. 767 */ 768 public static FontMetrics getMetrics(Font f) { 769 if(f != null) { 770 if(fonts.containsKey(f) == false) { 771 fonts.put(f, Toolkit.getDefaultToolkit().getFontMetrics(f)); 772 } 773 return (FontMetrics) fonts.get(f); 774 } 775 return null; 776 } 777 778 /** 779 * Returns a larger font with same family and style 780 * @param f use this as base font. 781 */ 782 public static Font larger(Font f) { 783 return getFont(f.getName(), f.getStyle(), f.getSize() + 2); 784 } 785 786 /** 787 * Returns a smaller font with same family and style 788 * @param f use this as base font. 789 */ 790 public static Font smaller(Font f) { 791 return getFont(f.getName(), f.getStyle(), f.getSize() > 1 ? f.getSize() - 2 : f.getSize()); 792 } 793 794 /** 795 * Returns a serif font with same size and style 796 * @param f use this as base font. 797 */ 798 public static Font serif(Font f) { 799 return getFont("Serif", f.getStyle(), f.getSize()); 800 } 801 802 /** 803 * Returns a sansserif font with same size and style 804 * @param f use this as base font. 805 */ 806 public static Font sansserif(Font f) { 807 return getFont("SansSerif", f.getStyle(), f.getSize()); 808 } 809 810 /** 811 * Returns a monospaced font with same size and style 812 * @param f use this as base font. 813 */ 814 public static Font monospaced(Font f) { 815 return getFont("Monospaced", f.getStyle(), f.getSize()); 816 } 817 818 /** 819 * Returns a bold font with same size and family 820 * @param f use this as base font. 821 */ 822 public static Font bold(Font f) { 823 return getFont(f.getName(), Font.BOLD, f.getSize()); 824 } 825 826 /** 827 * Returns a italic font with same size and family 828 * @param f use this as base font. 829 */ 830 public static Font italic(Font f) { 831 return getFont(f.getName(), Font.ITALIC, f.getSize()); 832 } 833 834 /** 835 * Returns a bolditalic font with same size and family 836 * @param f use this as base font. 837 */ 838 public static Font bolditalic(Font f) { 839 return getFont(f.getName(), Font.BOLD | Font.ITALIC, f.getSize()); 840 } 841 842 /** 843 * Returns a plain font with same size and family 844 * @param f use this as base font. 845 */ 846 public static Font plain(Font f) { 847 return getFont(f.getName(), Font.PLAIN, f.getSize()); 848 } 849 850 /** 851 * Returns the escape sequence for Color c 852 * @param c the color 853 */ 854 public static String Color2Esc(Color c) { 855 if(c == null) { 856 return ""; 857 } 858 int v = White + ((c.getRed() / 16) << 8) + ((c.getGreen() / 16) << 4) + ((c.getBlue() / 16) << 0); 859 char[] buf = {Esc, (char) v}; 860 return String.valueOf(buf); 861 } 862 863 /** 864 * Try to get color. <code>obj</code> can be color name 865 * or a numeric value or already a color object. 866 * 867 * @return <code>null</code> on failure. 868 * 869 * @param o color specification. 870 */ 871 public static Color getColor(Object o) { 872 if(o == null) { 873 return null; 874 } 875 if(o instanceof Color) { 876 return (Color) o; 877 } 878 try { 879 return Color.decode(o.toString()); 880 } catch(Exception x) { 881 return null; 882 } 883 } 884 885 /** 886 * Return a dimmed version of color <code>c</code> 887 * 888 * @param c original color 889 * @param v value to dim 890 */ 891 public static Color dim(Color c, int v) { 892 return c == null ? Color.white : 893 new Color(Math.max(Math.min(c.getRed() + v, 255),0), 894 Math.max(Math.min(c.getGreen() + v, 255),0), 895 Math.max(Math.min(c.getBlue() + v, 255),0)); 896 } 897 898 /** 899 * Return a brighter version of color <code>c</code> 900 * 901 * @param c original color 902 */ 903 public static Color brighter(Color c) { 904 return dim(c, 63); 905 } 906 907 /** 908 * Return a darker version of color <code>c</code> 909 * 910 * @param c original color 911 */ 912 public static Color darker(Color c) { 913 return dim(c, -63); 914 } 915 916 /** 917 * Return Insets from an int array (used to set Insets from property file) 918 * 919 * @param i insets values (as in Insets constructor) 920 */ 921 public static Insets Array2Insets(int[] i) { 922 return i != null && i.length == 4 ? new Insets(i[0], i[1], i[2], i[3]) : null; 923 } 924 925 /** 926 * Draws a line between the given points 927 * 928 * @param g Graphics object to use 929 * @param c color to use as base for shadow, or null 930 * @param x,y x,y coords of first point 931 * @param X,Y x,y coords of second point 932 * @param d thickness of line in pixel 933 * @param m RAISED or SUNKEN 934 */ 935 public static void drawLine(Graphics g, Color c, 936 int x, int y, int X, int Y, 937 int d, int m) { 938 Color C = g.getColor(); 939 g.setColor(c == null ? C : c); 940 941 if(isBulk(m)) { 942 d = d/2; 943 drawLine(g, isSunken(m) ? brighter(c) : darker(c), x, y, X, Y, d, m & ~EFFECT_MASK); 944 drawLine(g, isSunken(m) ? darker(c) : brighter(c), x + d, y + d, X + d, Y + d, d, m & ~EFFECT_MASK); 945 return; 946 } 947 948 g.drawLine(x, y, X, Y); 949 if(--d > 0) { 950 drawLine(g, c, x + 1, y + 1, X + 1, Y + 1, d, 0); 951 } 952 g.setColor(C); 953 } 954 955 /** 956 * Draws a rectangle within the given box 957 * 958 * @param g Graphics object to use 959 * @param c color to use as base for shadow, or null 960 * @param x x-position of describing rect 961 * @param y y-position of describing rect 962 * @param w width of describing rect 963 * @param h height of describing rect 964 * @param d thickness of the line in pixel 965 * @param m combination of FILL RAISED SUNKEN 966 */ 967 public static void drawRectangle(Graphics g, Color c, 968 int x, int y, int w, int h, 969 int d, int m) { 970 if(w < 1 || h < 1 || d < 1) { 971 return; 972 } 973 974 g = g.create(x, y, w + 1, h + 1); 975 976 if(c != null) { 977 g.setColor(c); 978 } 979 980 if(isFill(m)) { 981 g.fillRect(0, 0, w, h); 982 } 983 984 if(isBulk(m)) { 985 d = d/2; 986 drawRectangle(g, isSunken(m) ? brighter(c) : darker(c), 0, 0, w, h, d, m & ~EFFECT_MASK); 987 drawRectangle(g, isSunken(m) ? darker(c) : brighter(c), d, d, w - d - d, h - d - d, d, m & ~EFFECT_MASK); 988 g.dispose(); 989 return; 990 } 991 992 if(isEffect(m)) { 993 g.setColor(isRaised(m) ? brighter(c) : darker(c)); 994 } 995 g.drawLine(0, 0, w, 0); 996 g.drawLine(0, 0, 0, h); 997 998 if(isEffect(m)) { 999 g.setColor(isRaised(m) ? darker(c) : brighter(c)); 1000 } 1001 g.drawLine(w, h, w, 0); 1002 g.drawLine(w, h, 0, h); 1003 1004 if(--d > 0) { 1005 drawRectangle(g, c, 1, 1, w - 2, h - 2, d, m & ~FILL); 1006 } 1007 g.dispose(); 1008 } 1009 1010 /** 1011 * Draws a triangle within the given box 1012 * 1013 * @param g Graphics object to use 1014 * @param c color to use as base for shadow, or null 1015 * @param x x-position of describing rect 1016 * @param y y-position of describing rect 1017 * @param w width of describing rect 1018 * @param h height of describing rect 1019 * @param d thickness of the line in pixel 1020 * @param m combination of LINE FILL RAISED SUNKEN and Direction (N E S W etc) 1021 */ 1022 public static void drawTriangle(Graphics g, Color c, 1023 int x, int y, int w, int h, 1024 int d, int m) { 1025 if(w < 1 || h < 1 || d < 1) { 1026 return; 1027 } 1028 1029 int X[] = new int[3]; 1030 int Y[] = new int[3]; 1031 boolean drk = ((m & W) > 0 || getPosition(m) == N) == isSunken(m); 1032 1033 g = g.create(x, y, w + 1, h + 1); 1034 1035 if(c != null) { 1036 g.setColor(c); 1037 } 1038 1039 w--; h--; 1040 1041 switch(getPosition(m)) { 1042 case N: 1043 X[0]=w/2; X[1]=w; Y[1]=h; Y[2]=h; break; 1044 case W: 1045 X[1]=w; X[2]=w; Y[0]=h/2; Y[1]=h; break; 1046 case SW: 1047 X[1]=w; Y[1]=h; break; 1048 case NW: 1049 X[1]=w; Y[2]=h; break; 1050 case S: 1051 X[0]=w/2; X[2]=w; Y[0]=h; break; 1052 case E: 1053 X[0]=w; Y[0]=h/2; Y[2]=h; break; 1054 case SE: 1055 X[0]=w; X[2]=w; Y[0]=h; Y[1]=h; break; 1056 case NE: 1057 X[0]=w; X[2]=w; Y[2]=h; break; 1058 default: 1059 g.dispose(); 1060 return; 1061 } 1062 1063 if(isEffect(m)) { 1064 g.setColor(c); 1065 } 1066 1067 if(isFill(m)) { 1068 g.fillPolygon(X, Y, 3); 1069 } 1070 1071 if(isEffect(m)) { 1072 g.setColor(drk ? brighter(c) : darker(c)); 1073 } 1074 g.drawPolyline(X, Y, 3); 1075 1076 if(isEffect(m)) { 1077 g.setColor(drk ? darker(c) : brighter(c)); 1078 } 1079 g.drawLine(X[0], Y[0], X[2], Y[2]); 1080 1081 if(isFill(m)) { 1082 g.dispose(); 1083 return; 1084 } 1085 1086 if(--d > 0) { 1087 drawTriangle(g, c, 1, 1, w - 1, h - 1, d, m & ~FILL); 1088 } 1089 g.dispose(); 1090 } 1091 1092 /** 1093 * 1094 * Draws a string within the given box. 1095 * 1096 * @param g Graphics object to use 1097 * @param c color to use or null 1098 * @param f font to use or null 1099 * @param s the string 1100 * @param x x-position of describing rect 1101 * @param y y-position of describing rect 1102 * @param w width of describing rect 1103 * @param h height of describing rect 1104 * @param m mode including position & effect & misc 1105 */ 1106 public static Dimension drawString(Graphics g, Color c, Font f, String s, 1107 int x, int y, int w, int h, int m) { 1108 return drawString(g, c, f, s, x, y, w, h, m, null); 1109 } 1110 1111 /** 1112 * 1113 * Draws a string within the given box. 1114 * 1115 * @param g Graphics object to use 1116 * @param c color to use or null 1117 * @param f font to use or null 1118 * @param s the string 1119 * @param x x-position of describing rect 1120 * @param y y-position of describing rect 1121 * @param w width of describing rect 1122 * @param h height of describing rect 1123 * @param m mode including position & effect & misc 1124 * @param awt comp used as callback for hrefs 1125 */ 1126 public static Dimension drawString(Graphics g, Color c, Font f, String s, 1127 int x, int y, int w, int h, int m, Awt awt) { 1128 1129 Dimension d = new Dimension(); 1130 1131 if(s == null) { 1132 return d; 1133 } 1134 1135 if(f == null) { 1136 f = g.getFont(); 1137 } 1138 1139 if(c == null) { 1140 c = g.getColor(); 1141 } 1142 1143 g = g.create(x, y, w, h); 1144 d = measureString(s, f); 1145 1146 g.setFont(f); 1147 g.setColor(c); 1148 1149 if(d.width > w) { 1150 d.width = w; 1151 } 1152 1153 if(d.height > h) { 1154 d.height = h; 1155 } 1156 1157 if(awt != null && isHref(m)) { 1158 awt.doHref(s, x, y, d.width, h); 1159 g.setColor(Color.blue); 1160 m |= ULINE; 1161 } 1162 1163 if(isRaised(m) || isSunken(m)) { 1164 d = drawString(g, isRaised(m) ? brighter(c) : darker(c), f, s, 0, 0, w, h, m & ~EFFECT_MASK); 1165 d = drawString(g, isRaised(m) ? darker(c) : brighter(c), f, s, 1, 1, w, h, m & ~EFFECT_MASK); 1166 g.dispose(); 1167 return d; 1168 } 1169 1170 switch(getPosition(m)) { 1171 case N: 1172 case S: 1173 case C: x =(w - d.width) / 2; break; 1174 case NE: 1175 case E: 1176 case SE: x = w - d.width; break; 1177 default: x = 0; 1178 } 1179 1180 switch(getPosition(m)) { 1181 case E: 1182 case W: 1183 case C: y =(h - d.height) / 2; break; 1184 case SW: 1185 case S: 1186 case SE: y = h - d.height; break; 1187 default: y = 0; 1188 } 1189 1190 g.drawString(exString(s), x, y + g.getFontMetrics().getAscent()); 1191 1192 if(isUline(m)) { 1193 g.drawLine(x, y + g.getFontMetrics().getAscent() + 1, d.width, y + g.getFontMetrics().getAscent() + 1); 1194 } 1195 1196 g.dispose(); 1197 return d; 1198 } 1199 1200 /** 1201 * Calculates the box needed to draw the string 1202 * 1203 * @param s the string 1204 * @param f the base font to use 1205 */ 1206 public static Dimension measureString(String s, Font f) { 1207 if(f == null) { 1208 return new Dimension(); 1209 } 1210 FontMetrics m = getMetrics(f); 1211 return new Dimension(m.stringWidth(exString(s)), m.getHeight()); 1212 } 1213 1214 /** 1215 * 1216 * Draws a caption within the given box. drawCaption recognizes the 1217 * escape sequences above for changing text characteristics and supports 1218 * multiple lines 1219 * 1220 * @param g Graphics object to use 1221 * @param c color to use or null 1222 * @param f font to use or null 1223 * @param s the string 1224 * @param x x-position of describing rect 1225 * @param y y-position of describing rect 1226 * @param w width of describing rect 1227 * @param h height of describing rect 1228 * @param m mode including position & effect 1229 * @param dl the line delimiter usually "\n" specify "" for a single line 1230 */ 1231 public static void drawCaption(Graphics g, Color c, Font f, String s, 1232 int x, int y, int w, int h, int m, String dl) { 1233 drawCaption(g, c, f, s, x, y, w, h, m, dl, null); 1234 } 1235 1236 /** 1237 * 1238 * Draws a caption within the given box. drawCaption recognizes the 1239 * escape sequences above for changing text characteristics and supports 1240 * multiple lines 1241 * 1242 * @param g Graphics object to use 1243 * @param c color to use or null 1244 * @param f font to use or null 1245 * @param s the string 1246 * @param x x-position of describing rect 1247 * @param y y-position of describing rect 1248 * @param w width of describing rect 1249 * @param h height of describing rect 1250 * @param m mode including position & effect 1251 * @param dl the line delimiter usually "\n" specify "" for a single line 1252 * @param awt comp used as callback for hrefs 1253 */ 1254 public static void drawCaption(Graphics g, Color c, Font f, String s, 1255 int x, int y, int w, int h, int m, String dl, Awt awt) { 1256 1257 if(s == null) { 1258 return; 1259 } 1260 1261 if(c == null) { 1262 c = g.getColor(); 1263 } 1264 1265 if(f == null) { 1266 f = g.getFont(); 1267 } 1268 1269 Color dc = c; // default color 1270 Font df = f; // default font 1271 int dm = m; // default mode 1272 int X = 0; // current X 1273 Dimension D = measureCaption(s, f, df, dl); // total dims 1274 1275 if(D.width > w) { 1276 D.width = w; 1277 } 1278 1279 if(D.height > h) { 1280 D.height = h; 1281 } 1282 1283 switch(getPosition(m)) { 1284 case E: 1285 case W: 1286 case C: y += (h - D.height) / 2; break; 1287 case SW: 1288 case S: 1289 case SE: y += h - D.height; break; 1290 } 1291 1292 for(StringSplitter L = new StringSplitter(s, dl); L.hasMoreTokens();) { 1293 String l = L.nextToken(); // one line 1294 Dimension d = measureCaption(l, f, df, dl); // lines dimensions 1295 boolean p = false; // already started to paint ? 1296 if(d.width > w) { 1297 d.width = w; 1298 } 1299 if(d.height > h) { 1300 d.height = h; 1301 } 1302 for(StringSplitter T = new StringSplitter("" + Null + l, "" + Esc); T.hasMoreTokens();) { 1303 String t = T.nextToken(); // one token 1304 c = getColor(t.charAt(0), c, dc, awt == null ? dc : awt.getBackground()); 1305 f = getFont(t.charAt(0), f, df); 1306 m = getMode(t.charAt(0), m, dm); 1307 X = getTab(t.charAt(0), f, X); 1308 if(t.length() > 1) { 1309 if(p == false) { 1310 switch(getPosition(m)) { 1311 case N: 1312 case S: 1313 case C: X = x + (w - d.width) / 2; break; 1314 case NE: 1315 case E: 1316 case SE: X = x + w - d.width; break; 1317 default: X = x; break; 1318 } 1319 p = true; 1320 } 1321 X += drawString(g, c, f, t.substring(1), X, y, w, d.height, (m & POSITION_MASK) == C ? m & ~POSITION_MASK | W : m & ~E | W, awt).width; 1322 } 1323 } 1324 y += d.height; 1325 } 1326 } 1327 1328 /** 1329 * Calculates the box needed to draw the caption 1330 * 1331 * @param s the string 1332 * @param f the base font to use 1333 * @param df the default font to use 1334 * @param dl the line delimiter usually "\n" specify "" for a single line 1335 */ 1336 public static Dimension measureCaption(String s, Font f, Font df, String dl) { 1337 Dimension D = s.length() == 0 ? measureString("", f) : new Dimension(); 1338 for(StringSplitter L = new StringSplitter(s, dl); L.hasMoreTokens();) { 1339 int w = 0, h = 0; 1340 for(StringSplitter T = new StringSplitter("" + Null + L.nextToken(), "" + Esc); T.hasMoreTokens();) { 1341 String t = T.nextToken(); 1342 f = getFont(t.charAt(0), f, df); 1343 w = Math.max(w, getTab(t.charAt(0), f, w)); 1344 Dimension d = measureString(t.substring(1), f); 1345 w += d.width; 1346 if(w > 0 || T.hasMoreTokens() == false) { 1347 h = Math.max(d.height, h); 1348 } 1349 } 1350 D.height += h; 1351 D.width = Math.max(w, D.width);; 1352 } 1353 return D; 1354 } 1355 1356 /** 1357 * Returns the visible (right) part of a string resp. href. 1358 * Parts are separated using the unicode null char 1359 * 1360 * @param s the orig. string 1361 */ 1362 public static String exString(String s) { 1363 int i = s.indexOf(Null); 1364 return s.substring(i == -1 ? 0 : i + 1); 1365 } 1366 1367 /** 1368 * Returns the invisible (left or href) part of a string resp. href. 1369 * Parts are separated using the unicode null char 1370 * 1371 * @param s the orig. string 1372 */ 1373 public static String exHref(String s) { 1374 int i = s.indexOf(Null); 1375 return s.substring(0, i == -1 ? s.length() : i); 1376 } 1377 1378 /** 1379 * Returns the modified font for escape char u 1380 * leaves font unchanged if u does not descibe any font characteristics 1381 * 1382 * @param u the escape char 1383 * @param f the base font to use 1384 * @param df the default font to use 1385 */ 1386 public static Font getFont(char u, Font f, Font df) { 1387 if(f == null) { 1388 return null; 1389 } 1390 switch(u) { 1391 case Bold: return bold(f); 1392 case Plain: return plain(f); 1393 case Italic: return italic(f); 1394 case Bolditalic: return bolditalic(f); 1395 case Larger: return larger(f); 1396 case Smaller: return smaller(f); 1397 case Serif: return serif(f); 1398 case SansSerif: return sansserif(f); 1399 case Monospaced: return monospaced(f); 1400 case None: return df; 1401 } 1402 if((u & FontMask) == FontSize0) { 1403 return getFont(f.getName(), f.getStyle(), u & FontSizeMask); 1404 } 1405 return f; 1406 } 1407 1408 /** 1409 * Returns the modified color for escape char u 1410 * leaves color unchanged if u does not descibe any color characteristics 1411 * 1412 * @param u the escape char 1413 * @param c the base color to use 1414 * @param dc the default color to use 1415 * @param dc the background color to use 1416 */ 1417 public static Color getColor(char u, Color c, Color dc, Color bg) { 1418 switch(u) { 1419 case Darker: return darker(c); 1420 case Brighter: return brighter(c); 1421 case Background: return bg; 1422 case Foreground: return dc; 1423 case None: return dc; 1424 } 1425 if((u & ColorMask) == White) { 1426 return new Color(((u & RedMask) >> 8) * 17, ((u & GreenMask) >> 4) * 17, ((u & BlueMask) >> 0) * 17); 1427 } 1428 return c; 1429 } 1430 1431 /** 1432 * Returns the tab position for escape char u 1433 * return default tab if u does not descibe any tab position 1434 * 1435 * @param u the escape char 1436 * @param f the base font to use 1437 * @param dt the default tab to use 1438 */ 1439 public static int getTab(char u, Font f, int dt) { 1440 if((u & TabMask) == Tab0) { 1441 return (u & TabSizeMask) * getMetrics(f).charWidth('8'); 1442 } else { 1443 return dt; 1444 } 1445 } 1446 1447 /** 1448 * Returns the modified mode for escape char u 1449 * leaves mode unchanged if u does not descibe any mode characteristics 1450 * 1451 * @param u the escape char 1452 * @param m the base mode to use 1453 * @param dm the default mode to use 1454 */ 1455 public static int getMode(char u, int m, int dm) { 1456 switch(u) { 1457 case North: return m & ~POSITION_MASK | N; 1458 case East: return m & ~POSITION_MASK | E; 1459 case South: return m & ~POSITION_MASK | S; 1460 case West: return m & ~POSITION_MASK | W; 1461 case NorthWest: return m & ~POSITION_MASK | NW; 1462 case SouthWest: return m & ~POSITION_MASK | SW; 1463 case NorthEast: return m & ~POSITION_MASK | NE; 1464 case SouthEast: return m & ~POSITION_MASK | SE; 1465 case Center: return m & ~POSITION_MASK | C; 1466 1467 case Flat: return m & ~EFFECT_MASK; 1468 case Raised: return m & ~(RAISED|SUNKEN) | RAISED; 1469 case Sunken: return m & ~(RAISED|SUNKEN) | SUNKEN; 1470 case Uline: return m | ULINE; 1471 1472 case Hrefend: return m & ~MISC_MASK; 1473 case Href: return m & ~MISC_MASK | HREF; 1474 1475 case None: return dm; 1476 } 1477 return m; 1478 } 1479 1480 /** 1481 * Exctract position bits from m. 1482 * 1483 * @param m mode 1484 */ 1485 public static int getPosition(int m) { 1486 return (m & POSITION_MASK) == 0 ? NW : m & POSITION_MASK; 1487 } 1488 1489 /** 1490 * True if m describes an effect (see above). 1491 * 1492 * @param m mode 1493 */ 1494 public static boolean isEffect(int m) { 1495 return (m & EFFECT_MASK) > 0; 1496 } 1497 1498 /** 1499 * True if m describes effect Raised. 1500 * 1501 * @param m mode 1502 */ 1503 public static boolean isRaised(int m) { 1504 return (m & RAISED) == RAISED; 1505 } 1506 1507 /** 1508 * True if m describes effect Sunken. 1509 * 1510 * @param m mode 1511 */ 1512 public static boolean isSunken(int m) { 1513 return (m & SUNKEN) == SUNKEN; 1514 } 1515 1516 /** 1517 * True if m describes effect Bulk. 1518 * 1519 * @param m mode 1520 */ 1521 public static boolean isBulk(int m) { 1522 return (m & BULK) == BULK; 1523 } 1524 1525 /** 1526 * True if m describes effect Underline. 1527 * 1528 * @param m mode 1529 */ 1530 public static boolean isUline(int m) { 1531 return (m & ULINE) == ULINE; 1532 } 1533 1534 /** 1535 * True if we are in Href mode. 1536 * 1537 * @param m mode 1538 */ 1539 public static boolean isHref(int m) { 1540 return (m & HREF) == HREF; 1541 } 1542 1543 /** 1544 * True if m describes effect Fill. 1545 * 1546 * @param m mode 1547 */ 1548 public static boolean isFill(int m) { 1549 return (m & FILL) == FILL; 1550 } 1551 1552 /** 1553 * Contructor for an Awt component 1554 */ 1555 public Awt() { 1556 if(this instanceof BorderPanel == false && this instanceof TabbedPanel == false) super.setLayout(null); 1557 1558 } 1559 1560 /** 1561 * callback routine for dynamic caption content 1562 * should be overwritten by implementing classes 1563 * 1564 * @param s the href string (including href & text) 1565 * @param x x pos of describing rect 1566 * @param y y pos of describing rect 1567 * @param w width of describing rect 1568 * @param h height of describing rect 1569 */ 1570 public void doHref(String s, int x, int y, int w, int h) { 1571 } 1572 1573 /** 1574 * Overwrite Component.setBounds() to recognize resizing 1575 */ 1576 public void setBounds(int x, int y, int w, int h) { 1577 super.setBounds(x, y, w, h); 1578 bim = null; 1579 big = null; 1580 } 1581 1582 /** 1583 * Return currently needed Dimension 1584 * Should be overridden by Awt Components 1585 */ 1586 public Dimension measure() { 1587 return new Dimension(insets.left + borderDepth + innerInsets.left + innerInsets.right + borderDepth + insets.right, 1588 insets.top + borderDepth + innerInsets.top + innerInsets.bottom + borderDepth + insets.bottom); 1589 } 1590 1591 /** 1592 * Utility function for Awt Components 1593 * re-measures an invalidates if dims changed 1594 */ 1595 public void doMeasure() { 1596 Dimension nd = measure(); 1597 if(minimumDimension.equals(nd) == false) { 1598 minimumDimension = nd; 1599 invalidate(); 1600 } 1601 } 1602 1603 /** 1604 * Get this comps rectangle 1605 * totalsize - insets 1606 */ 1607 public Rectangle getRectangle() { 1608 return new Rectangle(insets.left, 1609 insets.top, 1610 getBounds().width - insets.left - insets.right, 1611 getBounds().height - insets.top - insets.bottom); 1612 } 1613 1614 /** 1615 * Get this comps rectangle within border 1616 * totalsize - insets - borderDepth 1617 */ 1618 public Rectangle getBorderRectangle() { 1619 Rectangle r = getRectangle(); 1620 return new Rectangle(r.x + borderDepth, 1621 r.y + borderDepth, 1622 r.width - borderDepth - borderDepth, 1623 r.height - borderDepth - borderDepth); 1624 } 1625 1626 /** 1627 * Get this comps inner rectangle 1628 * totalsize - insets - borderDepth - innerInsets 1629 */ 1630 public Rectangle getInnerRectangle() { 1631 Rectangle r = getBorderRectangle(); 1632 return new Rectangle(r.x + innerInsets.left, 1633 r.y + innerInsets.top, 1634 r.width - innerInsets.left - innerInsets.right, 1635 r.height - innerInsets.top - innerInsets.bottom); 1636 } 1637 1638 /** 1639 * Overwrite java.awt.component.invalidate() to do 1640 * measuring 1641 * . 1642 */ 1643 public void invalidate() { 1644 doMeasure(); 1645 super.invalidate(); 1646 } 1647 1648 /** 1649 * override java.awt.Panel.addNotify() 1650 * called shortly after instantiation 1651 * first chance to call measure() 1652 */ 1653 public void addNotify() { 1654 super.addNotify(); 1655 minimumDimension = measure(); 1656 } 1657 1658 /** 1659 * override java.awt.Panel.getPreferredSize() and return 1660 * our minimum size 1661 */ 1662 public Dimension getPreferredSize() { 1663 return minimumDimension; 1664 } 1665 1666 /** 1667 * override java.awt.Panel.getMinimumSize() 1668 * @see Awt#getPreferredSize() 1669 */ 1670 public Dimension getMinimumSize() { 1671 return minimumDimension; 1672 } 1673 1674 /** 1675 * Overwrite java.awt.component.update() to avoid flickering 1676 * . 1677 */ 1678 public void update(Graphics g) { 1679 if(g == null) return; 1680 paint(g); 1681 } 1682 1683 /** 1684 * Actually do the work ... this basic paint() routine just draws the 1685 * border. Should be overwritten. 1686 * 1687 * @param g Graphics object to use 1688 */ 1689 public void paint(Graphics g) { 1690 if(borderDepth > 0) { 1691 Rectangle r = getRectangle(); 1692 paintBorder(g, r.x, r.y, r.width - 1, r.height - 1); 1693 } 1694 } 1695 1696 /** 1697 * Paint the border 1698 * 1699 * @param g Graphics object to use 1700 * @param x x-position of describing rect 1701 * @param y y-position of describing rect 1702 * @param w width of describing rect 1703 * @param h height of describing rect 1704 */ 1705 public void paintBorder(Graphics g, int x, int y, int w, int h) { 1706 if(g == null) return; 1707 switch(borderType) { 1708 case TOP: 1709 drawLine(g, getBackground(), x, y, x + w, y, borderDepth, BULK); 1710 break; 1711 case BULK: 1712 case NONE: 1713 case RAISED: 1714 case SUNKEN: 1715 drawRectangle(g, getBackground(), x, y, w, h, borderDepth, borderType); 1716 break; 1717 } 1718 } 1719 1720 /** 1721 * Paint the Background 1722 * 1723 * @param g Graphics object to use 1724 */ 1725 public void paintBackground(Graphics g) { 1726 paintBackground(g, 0, 0, getBounds().width, getBounds().height); 1727 } 1728 1729 /** 1730 * Paint the Background 1731 * 1732 * @param g Graphics object to use 1733 * @param x x-position of describing rect 1734 * @param y y-position of describing rect 1735 * @param w width of describing rect 1736 * @param h height of describing rect 1737 */ 1738 public void paintBackground(Graphics g, int x, int y, int w, int h) { 1739 if(g == null) return; 1740 Awt a = getBGParent(); 1741 if(a == null || a.isShowing() == false || isShowing() == false || a.getBGImage() == null) { 1742 drawRectangle(g, getBackground(), x, y, w, h, 1, FILL); 1743 } else { 1744 int xo = getLocationOnScreen().x - a.getLocationOnScreen().x; 1745 int yo = getLocationOnScreen().y - a.getLocationOnScreen().y; 1746 g.drawImage(a.getBGImage(), 1747 x, y, x + w, y + h, 1748 x + xo, y + yo, x + xo + w, y + yo + h, this); 1749 } 1750 } 1751 1752 public void paintBim(Graphics g) { 1753 if(g == null || bim == null) return; 1754 g.drawImage(bim, 0, 0, this); 1755 } 1756 1757 public void makeBim() { 1758 if(bim == null) { 1759 bim = createImage(getBounds().width, getBounds().height); 1760 big = bim.getGraphics(); 1761 } 1762 } 1763 1764 /** 1765 * set the BG for this comp. BG can be one of 1766 * null - use parent BG (or none) 1767 * Image - use this Image 1768 * String - use this filename/URL to load an Image 1769 * Awt - inherit BG from this Awt component 1770 */ 1771 public void setBG(Object b) { 1772 bg = b; 1773 } 1774 1775 /** 1776 * set the BG for this comp only if none is currently present 1777 * (even from parent) 1778 */ 1779 public void setBGIfNull(Object b) { 1780 if(getBGParentImage() == null) bg = b; 1781 } 1782 1783 /** 1784 * return the object currently used as BG for this comp 1785 * Attn: all BG's are converted to Image the first time used 1786 * So this routine usually returns Object type Image 1787 */ 1788 public Object getBG() { 1789 return bg; 1790 } 1791 1792 /** 1793 * get the BG Image if any 1794 */ 1795 public Image getBGImage() { 1796 if(bg == null) { // no image ? -> ok 1797 return null; 1798 } 1799 if(bg instanceof Image) { // already an Image ? -> make sure it fits 1800 bg = tile((Image) bg, getSize()); 1801 return (Image) bg; 1802 } 1803 if(bg instanceof String) { // a String ? -> try to load image 1804 bg = waitForImage(loadImage((String) bg)); 1805 return getBGImage(); 1806 } 1807 if(bg instanceof Awt && bg != this) { // an Awt Component ? -> try to get image form there 1808 bg = ((Awt) bg).getBGParentImage(); 1809 return getBGImage(); 1810 } 1811 return null; 1812 } 1813 1814 /** 1815 * walk up the component tree to find a parent with a BG != null 1816 * 1817 * @param i the image 1818 */ 1819 public Awt getBGParent() { 1820 if(getBG() == null) { 1821 Container p = getParent(); 1822 if(p != null && p instanceof Awt) { 1823 return ((Awt) p).getBGParent(); 1824 } 1825 return null; 1826 } 1827 return this; 1828 } 1829 1830 /** 1831 * walk up the component tree to find a BG != null 1832 * 1833 * @param i the image 1834 */ 1835 public Image getBGParentImage() { 1836 Awt a = getBGParent(); 1837 return a == null ? null : a.getBGImage(); 1838 } 1839 1840 /** 1841 * wait for an Image to load completely 1842 * 1843 * @param i the image 1844 */ 1845 public Image waitForImage(Image i) { 1846 if(i == null) { 1847 return null; 1848 } 1849 try { 1850 MediaTracker t = new MediaTracker(this); 1851 t.addImage(i, 0); 1852 t.waitForID(0); 1853 } catch(InterruptedException x){ 1854 Debug.debug(this, x); 1855 return null; 1856 } 1857 return i; 1858 } 1859 1860 /** 1861 * scale (grow only) an Image to specified size by just 1862 * filling it with the original from left to right, top down 1863 * w, h will be rounded to the next multiple of original size 1864 * 1865 * @param i orinigal image 1866 * @param d new dims 1867 */ 1868 public Image tile(Image i, Dimension d) { 1869 return tile(i, d.width, d.height); 1870 } 1871 1872 /** 1873 * scale (grow only) an Image to specified size by just 1874 * filling it with the original from left to right, top down 1875 * w, h will be rounded to the next multiple of original size 1876 * 1877 * @param i orinigal image 1878 * @param w new width 1879 * @param h new height 1880 */ 1881 public Image tile(Image i, int w, int h) { 1882 if(i == null) { 1883 return null; 1884 } 1885 1886 int iw = i.getWidth(this); 1887 int ih = i.getHeight(this); 1888 1889 if(w > iw || h > ih) { 1890 1891 w = w / iw + 1; 1892 h = h / ih + 1; 1893 w *= iw; 1894 h *= ih; 1895 1896 Image I = createImage(w, h); 1897 for(int H = 0; H < h; H += i.getHeight(this)) { 1898 for(int W = 0; W < w; W += i.getWidth(this)) { 1899 I.getGraphics().drawImage(i, W, H, this); 1900 } 1901 } 1902 return waitForImage(I); 1903 } else { 1904 return i; 1905 } 1906 } 1907 1908 /** 1909 * override java.awt.Panel.setEnabled() 1910 * just to recocnize state change 1911 * 1912 * @param enabled enabled? 1913 */ 1914 public void setEnabled(boolean enabled) { 1915 if(enabled == super.isEnabled()) { 1916 return; 1917 } 1918 1919 super.setEnabled(enabled); 1920 1921 if(enabled) { 1922 for(Enumeration e = componentStates.keys(); e.hasMoreElements(); ) { 1923 ((Component) e.nextElement()).setEnabled(true); 1924 } 1925 componentStates.clear(); 1926 } else { 1927 for(int i = 0; i < getComponents().length; ++i) { 1928 Component c = getComponents()[i]; 1929 if(c.isEnabled()) { 1930 componentStates.put(c, this); 1931 c.setEnabled(false); 1932 } 1933 } 1934 } 1935 repaint(); 1936 } 1937 1938 /** 1939 * override java.awt.Panel.setVisible() 1940 * just to recocnize state change 1941 * 1942 * @param v visible? 1943 */ 1944 public void setVisible(boolean v) { 1945 super.setVisible(v); 1946 repaint(); 1947 } 1948 1949 /** 1950 * sets a new border 1951 * 1952 * @param i the border around the component 1953 */ 1954 public void setInsets(Insets i) { 1955 if(i != null && insets.equals(i) == false) { 1956 insets = i; 1957 doMeasure(); 1958 repaint(); 1959 } 1960 } 1961 1962 /** 1963 * get current border 1964 */ 1965 public Insets getInsets() { 1966 return insets; 1967 } 1968 1969 /** 1970 * sets a new border 1971 * 1972 * @param insets the border within the component 1973 */ 1974 public void setInnerInsets(Insets i) { 1975 if(i != null && innerInsets.equals(i) == false) { 1976 innerInsets = i; 1977 doMeasure(); 1978 repaint(); 1979 } 1980 } 1981 1982 /** 1983 * get current inner border 1984 */ 1985 public Insets getInnerInsets() { 1986 return innerInsets; 1987 } 1988 1989 /** 1990 * set borderdepth 1991 * @param d depth in pixel 1992 */ 1993 public void setBorderDepth(int d) { 1994 if(d >= 0 && borderDepth != d) { 1995 borderDepth = d; 1996 doMeasure(); 1997 repaint(); 1998 } 1999 } 2000 2001 /** 2002 * get borderdepth 2003 */ 2004 public int getBorderDepth() { 2005 return borderDepth; 2006 } 2007 2008 /** 2009 * set bodertype 2010 * @param t bordertype [TOP NONE BULK RAISED SUNKEN 2011 */ 2012 public void setBorderType(int t) { 2013 if(borderType != t) { 2014 borderType = t; 2015 doMeasure(); 2016 repaint(); 2017 } 2018 } 2019 2020 /** 2021 * set bodertype - String version (attributes from property file) 2022 * @param t bordertype [North(Top) None Bulk Raised Sundekn] 2023 */ 2024 public void setBorderType(String t) { 2025 if(t != null && t.length() == 2 && t.charAt(0) == Esc) { 2026 switch(t.charAt(1)) { 2027 case North: setBorderType(TOP); break; 2028 case None: setBorderType(NONE); break; 2029 case Bulk: setBorderType(BULK); break; 2030 case Raised: setBorderType(RAISED); break; 2031 case Sunken: setBorderType(SUNKEN); break; 2032 } 2033 } 2034 } 2035 2036 /** 2037 * get bodertype 2038 */ 2039 public int getBorderType() { 2040 return borderType; 2041 } 2042 2043 /** 2044 * override java.awt.Panel.setFont(Font font) 2045 * just to recognize the change 2046 */ 2047 public void setFont(Font f) { 2048 if(f != null) { 2049 super.setFont(f); 2050 doMeasure(); 2051 repaint(); 2052 } 2053 } 2054 2055 /** 2056 * implement java.awt.event.MouseListener 2057 */ 2058 public void mousePressed(MouseEvent e) { 2059 } 2060 2061 /** 2062 * implement java.awt.event.MouseListener 2063 */ 2064 public void mouseReleased(MouseEvent e) { 2065 } 2066 2067 /** 2068 * implement java.awt.event.MouseListener 2069 */ 2070 public void mouseExited(MouseEvent e) { 2071 } 2072 2073 /** 2074 * implement java.awt.event.MouseListener 2075 */ 2076 public void mouseEntered(MouseEvent e) { 2077 } 2078 2079 /** 2080 * implement java.awt.event.MouseListener 2081 */ 2082 public void mouseClicked(MouseEvent e) { 2083 } 2084 2085 /** 2086 * implement java.awt.event.MouseListener 2087 */ 2088 public void mouseMoved(MouseEvent e) { 2089 } 2090 2091 /** 2092 * implement java.awt.event.MouseListener 2093 */ 2094 public void mouseDragged(MouseEvent e) { 2095 } 2096 2097 /** 2098 * implement java.awt.event.KeyListener 2099 */ 2100 public void keyTyped(KeyEvent e) { 2101 } 2102 2103 /** 2104 * implement java.awt.event.KeyListener 2105 */ 2106 public void keyPressed(KeyEvent e) { 2107 } 2108 2109 /** 2110 * implement java.awt.event.KeyListener 2111 */ 2112 public void keyReleased(KeyEvent e) { 2113 } 2114 2115 /** 2116 * implement java.awt.event.AdjustmentListener 2117 */ 2118 public void adjustmentValueChanged(AdjustmentEvent e) { 2119 } 2120 2121 /** 2122 * implement java.awt.event.FocusListener 2123 */ 2124 public void focusGained(FocusEvent e) { 2125 } 2126 2127 /** 2128 * implement java.awt.event.FocusListener 2129 */ 2130 public void focusLost(FocusEvent e) { 2131 } 2132 2133 /** 2134 * implement java.awt.ItemSelectable 2135 */ 2136 public Object[] getSelectedObjects() { 2137 return null; 2138 } 2139 2140 /** 2141 * adds an actionListener 2142 * @param l the actionListener to add 2143 */ 2144 public void addActionListener(ActionListener l) { 2145 actionListener = AWTEventMulticaster.add(actionListener, l); 2146 } 2147 2148 /** 2149 * removes an actionListener 2150 * @param l the actionListener to remove 2151 */ 2152 public void removeActionListener(ActionListener l) { 2153 actionListener = AWTEventMulticaster.remove(actionListener, l); 2154 } 2155 2156 /** 2157 * notifies all actionListeners 2158 * @param e the event to post 2159 */ 2160 protected synchronized void notifyActionListeners(ActionEvent e) { 2161 if(actionListener != null) actionListener.actionPerformed(e); 2162 } 2163 2164 /** 2165 * adds an itemListener 2166 * @param l the itemListener to add 2167 */ 2168 public void addItemListener(ItemListener l) { 2169 itemListener = AWTEventMulticaster.add(itemListener, l); 2170 } 2171 2172 /** 2173 * removes an itemListener 2174 * @param l the itemListener to remove 2175 */ 2176 public void removeItemListener(ItemListener l) { 2177 itemListener = AWTEventMulticaster.remove(itemListener, l); 2178 } 2179 2180 /** 2181 * notifies all itemListeners 2182 * @param e the event to post 2183 */ 2184 protected synchronized void notifyItemListeners(ItemEvent e) { 2185 if(itemListener != null) itemListener.itemStateChanged(e); 2186 } 2187 }