Frames | No Frames |
1: /* JToolBar.java -- 2: Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.swing; 40: 41: import gnu.java.lang.CPStringBuilder; 42: 43: import java.awt.Component; 44: import java.awt.Container; 45: import java.awt.Dimension; 46: import java.awt.Graphics; 47: import java.awt.Insets; 48: import java.awt.LayoutManager; 49: import java.beans.PropertyChangeListener; 50: 51: import javax.accessibility.Accessible; 52: import javax.accessibility.AccessibleContext; 53: import javax.accessibility.AccessibleRole; 54: import javax.accessibility.AccessibleStateSet; 55: import javax.swing.plaf.ToolBarUI; 56: 57: /** 58: * JToolBar is a component that provides a toolbar to Swing programs. Users 59: * can add buttons (or actions that will be represented by JButtons) as well 60: * as other components to the JToolBar. JToolBars can be dragged in and out 61: * of their parent components. If the JToolBar is dragged out of the parent, 62: * then it will be displayed in its own RootPaneContainer. For dragging to 63: * work properly, JToolBars need to be placed in a Container that has a 64: * BorderLayout. That parent Container cannot have components in the NORTH, 65: * EAST, SOUTH, or WEST components (that is not the JToolBar). 66: */ 67: public class JToolBar extends JComponent implements SwingConstants, Accessible 68: { 69: /** 70: * Provides the accessibility features for the <code>JToolBar</code> 71: * component. 72: */ 73: protected class AccessibleJToolBar extends AccessibleJComponent 74: { 75: private static final long serialVersionUID = -5516888265903814215L; 76: 77: /** 78: * Creates a new <code>AccessibleJToolBar</code> instance. 79: */ 80: protected AccessibleJToolBar() 81: { 82: // Nothing to do here. 83: } 84: 85: /** 86: * Returns a set containing the current state of the {@link JToolBar} 87: * component. The current implementation simply calls the superclass. 88: * 89: * @return The accessible state set. 90: */ 91: public AccessibleStateSet getAccessibleStateSet() 92: { 93: // running tests against the reference implementation, I was unable 94: // to find any state information that is set specifically by the 95: // tool bar... 96: return super.getAccessibleStateSet(); 97: } 98: 99: /** 100: * Returns the accessible role for the <code>JToolBar</code> component. 101: * 102: * @return {@link AccessibleRole#TOOL_BAR}. 103: */ 104: public AccessibleRole getAccessibleRole() 105: { 106: return AccessibleRole.TOOL_BAR; 107: } 108: } 109: 110: /** 111: * This is the private JToolBar layout manager. 112: */ 113: private class DefaultToolBarLayout implements LayoutManager 114: { 115: /** 116: * This method is called when a new component is added to the container. 117: * 118: * @param name The name of the component added. 119: * @param comp The component that was added. 120: */ 121: public void addLayoutComponent(String name, Component comp) 122: { 123: // Do nothing. 124: } 125: 126: /** 127: * This method is called to lay out the given container to position and 128: * size the child components. 129: * 130: * @param c The container to lay out. 131: * 132: * @throws Error DOCUMENT ME! 133: */ 134: public void layoutContainer(Container c) 135: { 136: if (! (c instanceof JToolBar)) 137: throw new Error("DefaultToolBarLayout can only be used on JToolBars."); 138: Insets insets = getInsets(); 139: Insets margin = getMargin(); 140: int middle; 141: if (margin != null) 142: { 143: insets.left += margin.left; 144: insets.top += margin.top; 145: insets.bottom += margin.bottom; 146: insets.right += margin.right; 147: } 148: Component[] components = c.getComponents(); 149: Dimension tdims = c.getSize(); 150: int start = 0; 151: Dimension pref; 152: 153: if (getOrientation() == SwingUtilities.HORIZONTAL) 154: { 155: start += insets.left; 156: for (int i = 0; i < components.length; i++) 157: { 158: if (components[i] != null && components[i].isVisible()) 159: { 160: pref = components[i].getPreferredSize(); 161: if (pref != null) 162: { 163: middle = (tdims.height - pref.height) / 2; 164: components[i].setBounds(start, middle, pref.width, 165: pref.height); 166: start += pref.width; 167: } 168: } 169: } 170: } 171: else 172: { 173: start += insets.top; 174: for (int i = 0; i < components.length; i++) 175: { 176: if (components[i] != null && components[i].isVisible()) 177: { 178: pref = components[i].getPreferredSize(); 179: if (pref != null) 180: { 181: middle = (tdims.width - pref.width) / 2; 182: components[i].setBounds(middle, start, pref.width, 183: pref.height); 184: start += pref.height; 185: } 186: } 187: } 188: } 189: } 190: 191: /** 192: * This method returns the minimum size of the given container given the 193: * child components. 194: * 195: * @param parent The container to measure. 196: * 197: * @return The minimum size of the given container. 198: */ 199: public Dimension minimumLayoutSize(Container parent) 200: { 201: return preferredLayoutSize(parent); 202: } 203: 204: /** 205: * This method returns the preferred size of the given container given the 206: * child components. 207: * 208: * @param parent The container to measure. 209: * 210: * @return The preferred size of the given container. 211: */ 212: public Dimension preferredLayoutSize(Container parent) 213: { 214: int orientation = getOrientation(); 215: Component[] components = getComponents(); 216: 217: int limit = 0; 218: int total = 0; 219: Dimension dims; 220: 221: int w = 0; 222: int h = 0; 223: 224: if (orientation == SwingConstants.HORIZONTAL) 225: { 226: for (int i = 0; i < components.length; i++) 227: { 228: dims = components[i].getPreferredSize(); 229: if (dims != null) 230: { 231: if (dims.height > limit) 232: limit = dims.height; 233: total += dims.width; 234: } 235: } 236: w = total; 237: h = limit; 238: } 239: else 240: { 241: for (int i = 0; i < components.length; i++) 242: { 243: dims = components[i].getPreferredSize(); 244: if (dims != null) 245: { 246: if (dims.width > limit) 247: limit = dims.width; 248: total += dims.height; 249: } 250: } 251: w = limit; 252: h = total; 253: } 254: 255: Insets insets = getInsets(); 256: w += insets.left + insets.right; 257: h += insets.top + insets.bottom; 258: 259: Insets margin = getMargin(); 260: if (margin != null) 261: { 262: w += margin.left + margin.right; 263: h += margin.top + margin.bottom; 264: } 265: 266: return new Dimension(w, h); 267: } 268: 269: /** 270: * This method is called when the given component is removed from the 271: * container. 272: * 273: * @param comp The component removed. 274: */ 275: public void removeLayoutComponent(Component comp) 276: { 277: // Do nothing. 278: } 279: } 280: 281: /** 282: * This is an extension of JSeparator used in toolbars. Unlike JSeparator, 283: * nothing is painted for this Separator, it is only blank space that 284: * separates components. 285: */ 286: public static class Separator extends JSeparator 287: { 288: /** DOCUMENT ME! */ 289: private static final long serialVersionUID = -1656745644823105219L; 290: 291: /** 292: * Creates a new Separator object. 293: */ 294: public Separator() 295: { 296: super(); 297: } // Separator() 298: 299: /** 300: * Creates a new Separator object with the given size. 301: * 302: * @param size The size of the separator. 303: */ 304: public Separator(Dimension size) 305: { 306: setPreferredSize(size); 307: } // Separator() 308: 309: /** 310: * This method returns the String ID of the UI class of Separator. 311: * 312: * @return The UI class' String ID. 313: */ 314: public String getUIClassID() 315: { 316: return "ToolBarSeparatorUI"; 317: } // getUIClassID() 318: 319: /** 320: * This method returns the preferred size of the Separator. 321: * 322: * @return The preferred size of the Separator. 323: */ 324: public Dimension getPreferredSize() 325: { 326: return super.getPreferredSize(); 327: } // getPreferredSize() 328: 329: /** 330: * This method returns the maximum size of the Separator. 331: * 332: * @return The maximum size of the Separator. 333: */ 334: public Dimension getMaximumSize() 335: { 336: return super.getPreferredSize(); 337: } // getMaximumSize() 338: 339: /** 340: * This method returns the minimum size of the Separator. 341: * 342: * @return The minimum size of the Separator. 343: */ 344: public Dimension getMinimumSize() 345: { 346: return super.getPreferredSize(); 347: } // getMinimumSize() 348: 349: /** 350: * This method returns the size of the Separator. 351: * 352: * @return The size of the Separator. 353: */ 354: public Dimension getSeparatorSize() 355: { 356: return super.getPreferredSize(); 357: } // getSeparatorSize() 358: 359: /** 360: * This method sets the size of the Separator. 361: * 362: * @param size The new size of the Separator. 363: */ 364: public void setSeparatorSize(Dimension size) 365: { 366: setPreferredSize(size); 367: } // setSeparatorSize() 368: } // Separator 369: 370: /** DOCUMENT ME! */ 371: private static final long serialVersionUID = -1269915519555129643L; 372: 373: /** Whether the JToolBar paints its border. */ 374: private transient boolean paintBorder = true; 375: 376: /** The extra insets around the JToolBar. */ 377: private transient Insets margin; 378: 379: /** Whether the JToolBar can float (and be dragged around). */ 380: private transient boolean floatable = true; 381: 382: /** Whether the buttons will have rollover borders. */ 383: private transient boolean rollover; 384: 385: /** The orientation of the JToolBar. */ 386: private int orientation = HORIZONTAL; 387: 388: /** 389: * This method creates a new JToolBar object with horizontal orientation 390: * and no name. 391: */ 392: public JToolBar() 393: { 394: this(null, HORIZONTAL); 395: } // JToolBar() 396: 397: /** 398: * This method creates a new JToolBar with the given orientation and no 399: * name. 400: * 401: * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL) 402: */ 403: public JToolBar(int orientation) 404: { 405: this(null, orientation); 406: } // JToolBar() 407: 408: /** 409: * This method creates a new JToolBar object with the given name and 410: * horizontal orientation. 411: * 412: * @param name Name assigned to undocked tool bar. 413: */ 414: public JToolBar(String name) 415: { 416: this(name, HORIZONTAL); 417: } // JToolBar() 418: 419: /** 420: * This method creates a new JToolBar object with the given name and 421: * orientation. 422: * 423: * @param name Name assigned to undocked tool bar. 424: * @param orientation JToolBar orientation (HORIZONTAL or VERTICAL) 425: */ 426: public JToolBar(String name, int orientation) 427: { 428: setName(name); 429: setOrientation(orientation); 430: setLayout(new DefaultToolBarLayout()); 431: revalidate(); 432: setOpaque(true); 433: updateUI(); 434: } 435: 436: /** 437: * This method adds a new JButton that performs the given Action to the 438: * JToolBar. 439: * 440: * @param action The Action to add to the JToolBar. 441: * 442: * @return The JButton that wraps the Action. 443: */ 444: public JButton add(Action action) 445: { 446: JButton b = createActionComponent(action); 447: add(b); 448: return b; 449: } // add() 450: 451: /** 452: * This method paints the border if the borderPainted property is true. 453: * 454: * @param graphics The graphics object to paint with. 455: */ 456: protected void paintBorder(Graphics graphics) 457: { 458: if (paintBorder && isFloatable()) 459: super.paintBorder(graphics); 460: } // paintBorder() 461: 462: /** 463: * This method returns the UI class used to paint this JToolBar. 464: * 465: * @return The UI class for this JToolBar. 466: */ 467: public ToolBarUI getUI() 468: { 469: return (ToolBarUI) ui; 470: } // getUI() 471: 472: /** 473: * This method sets the UI used with the JToolBar. 474: * 475: * @param ui The UI used with the JToolBar. 476: */ 477: public void setUI(ToolBarUI ui) 478: { 479: super.setUI(ui); 480: } // setUI() 481: 482: /** 483: * This method resets the UI used to the Look and Feel defaults. 484: */ 485: public void updateUI() 486: { 487: setUI((ToolBarUI) UIManager.getUI(this)); 488: } 489: 490: /** 491: * This method returns the String identifier for the UI class to the used 492: * with the JToolBar. 493: * 494: * @return The String identifier for the UI class. 495: */ 496: public String getUIClassID() 497: { 498: return "ToolBarUI"; 499: } // getUIClassID() 500: 501: /** 502: * This method sets the rollover property for the JToolBar. In rollover 503: * mode, JButtons inside the JToolBar will only display their borders when 504: * the mouse is moving over them. 505: * 506: * @param b The new rollover property. 507: */ 508: public void setRollover(boolean b) 509: { 510: if (b != rollover) 511: { 512: rollover = b; 513: firePropertyChange("rollover", ! rollover, rollover); 514: revalidate(); 515: repaint(); 516: } 517: } 518: 519: /** 520: * This method returns the rollover property. 521: * 522: * @return The rollover property. 523: */ 524: public boolean isRollover() 525: { 526: return rollover; 527: } 528: 529: /** 530: * This method returns the index of the given component. 531: * 532: * @param component The component to find. 533: * 534: * @return The index of the given component. 535: */ 536: public int getComponentIndex(Component component) 537: { 538: Component[] components = getComponents(); 539: if (components == null) 540: return -1; 541: 542: for (int i = 0; i < components.length; i++) 543: if (components[i] == component) 544: return i; 545: 546: return -1; 547: } // getComponentIndex() 548: 549: /** 550: * This method returns the component at the given index. 551: * 552: * @param index The index of the component. 553: * 554: * @return The component at the given index. 555: */ 556: public Component getComponentAtIndex(int index) 557: { 558: return getComponent(index); 559: } // getComponentAtIndex() 560: 561: /** 562: * This method returns the margin property. 563: * 564: * @return The margin property. 565: */ 566: public Insets getMargin() 567: { 568: return margin; 569: } // getMargin() 570: 571: /** 572: * This method sets the margin property. The margin property determines the 573: * extra space between the children components of the JToolBar and the 574: * border. 575: * 576: * @param margin The margin property. 577: */ 578: public void setMargin(Insets margin) 579: { 580: if ((this.margin != null && margin == null) 581: || (this.margin == null && margin != null) 582: || (margin != null && this.margin != null 583: && (margin.left != this.margin.left 584: || margin.right != this.margin.right || margin.top != this.margin.top 585: || margin.bottom != this.margin.bottom))) 586: { 587: Insets oldMargin = this.margin; 588: this.margin = margin; 589: firePropertyChange("margin", oldMargin, this.margin); 590: revalidate(); 591: repaint(); 592: } 593: } // setMargin() 594: 595: /** 596: * This method returns the borderPainted property. 597: * 598: * @return The borderPainted property. 599: */ 600: public boolean isBorderPainted() 601: { 602: return paintBorder; 603: } // isBorderPainted() 604: 605: /** 606: * This method sets the borderPainted property. If set to false, the border 607: * will not be painted. 608: * 609: * @param painted Whether the border will be painted. 610: */ 611: public void setBorderPainted(boolean painted) 612: { 613: if (painted != paintBorder) 614: { 615: paintBorder = painted; 616: firePropertyChange("borderPainted", ! paintBorder, 617: paintBorder); 618: repaint(); 619: } 620: } // setBorderPainted() 621: 622: /** 623: * This method returns the floatable property. 624: * 625: * @return The floatable property. 626: */ 627: public boolean isFloatable() 628: { 629: return floatable; 630: } // isFloatable() 631: 632: /** 633: * This method sets the floatable property. If set to false, the JToolBar 634: * cannot be dragged. 635: * 636: * @param floatable Whether the JToolBar can be dragged. 637: */ 638: public void setFloatable(boolean floatable) 639: { 640: if (floatable != this.floatable) 641: { 642: this.floatable = floatable; 643: firePropertyChange("floatable", ! floatable, floatable); 644: } 645: } // setFloatable() 646: 647: /** 648: * This method returns the orientation of the JToolBar. 649: * 650: * @return The orientation of the JToolBar. 651: */ 652: public int getOrientation() 653: { 654: return orientation; 655: } // getOrientation() 656: 657: /** 658: * This method sets the layout manager to be used with the JToolBar. 659: * 660: * @param mgr The Layout Manager used with the JToolBar. 661: */ 662: public void setLayout(LayoutManager mgr) 663: { 664: super.setLayout(mgr); 665: revalidate(); 666: repaint(); 667: } // setLayout() 668: 669: /** 670: * This method sets the orientation property for JToolBar. 671: * 672: * @param orientation The new orientation for JToolBar. 673: * 674: * @throws IllegalArgumentException If the orientation is not HORIZONTAL or 675: * VERTICAL. 676: */ 677: public void setOrientation(int orientation) 678: { 679: if (orientation != HORIZONTAL && orientation != VERTICAL) 680: throw new IllegalArgumentException(orientation 681: + " is not a legal orientation"); 682: if (orientation != this.orientation) 683: { 684: int oldOrientation = this.orientation; 685: this.orientation = orientation; 686: firePropertyChange("orientation", oldOrientation, this.orientation); 687: revalidate(); 688: repaint(); 689: } 690: } // setOrientation() 691: 692: /** 693: * This method adds a Separator of default size to the JToolBar. 694: */ 695: public void addSeparator() 696: { 697: add(new Separator()); 698: } // addSeparator() 699: 700: /** 701: * This method adds a Separator with the given size to the JToolBar. 702: * 703: * @param size The size of the Separator. 704: */ 705: public void addSeparator(Dimension size) 706: { 707: add(new Separator(size)); 708: } // addSeparator() 709: 710: /** 711: * This method is used to create JButtons which can be added to the JToolBar 712: * for the given action. 713: * 714: * @param action The action to create a JButton for. 715: * 716: * @return The JButton created from the action. 717: */ 718: protected JButton createActionComponent(Action action) 719: { 720: return new JButton(action); 721: } // createActionComponent() 722: 723: /** 724: * This method creates a pre-configured PropertyChangeListener which updates 725: * the control as changes are made to the Action. However, this is no 726: * longer the recommended way of adding Actions to Containers. As such, 727: * this method returns null. 728: * 729: * @param button The JButton to configure a PropertyChangeListener for. 730: * 731: * @return null. 732: */ 733: protected PropertyChangeListener createActionChangeListener(JButton button) 734: { 735: // XXX: As specified, this returns null. But seems kind of strange, usually deprecated methods don't just return null, verify! 736: return null; 737: } // createActionChangeListener() 738: 739: /** 740: * This method overrides Container's addImpl method. If a JButton is added, 741: * it is disabled. 742: * 743: * @param component The Component to add. 744: * @param constraints The Constraints placed on the component. 745: * @param index The index to place the Component at. 746: */ 747: protected void addImpl(Component component, Object constraints, int index) 748: { 749: // XXX: Sun says disable button but test cases show otherwise. 750: super.addImpl(component, constraints, index); 751: 752: // if we added a Swing Button then adjust this a little 753: if (component instanceof AbstractButton) 754: { 755: AbstractButton b = (AbstractButton) component; 756: b.setRolloverEnabled(rollover); 757: } 758: 759: } // addImpl() 760: 761: /** 762: * Returns a string describing the attributes for the <code>JToolBar</code> 763: * component, for use in debugging. The return value is guaranteed to be 764: * non-<code>null</code>, but the format of the string may vary between 765: * implementations. 766: * 767: * @return A string describing the attributes of the <code>JToolBar</code>. 768: */ 769: protected String paramString() 770: { 771: CPStringBuilder sb = new CPStringBuilder(super.paramString()); 772: sb.append(",floatable=").append(floatable); 773: sb.append(",margin="); 774: if (margin != null) 775: sb.append(margin); 776: sb.append(",orientation="); 777: if (orientation == HORIZONTAL) 778: sb.append("HORIZONTAL"); 779: else 780: sb.append(VERTICAL); 781: sb.append(",paintBorder=").append(paintBorder); 782: return sb.toString(); 783: } 784: 785: /** 786: * Returns the object that provides accessibility features for this 787: * <code>JToolBar</code> component. 788: * 789: * @return The accessible context (an instance of {@link AccessibleJToolBar}). 790: */ 791: public AccessibleContext getAccessibleContext() 792: { 793: if (accessibleContext == null) 794: accessibleContext = new AccessibleJToolBar(); 795: 796: return accessibleContext; 797: } 798: }