32 import java.awt.Dimension;
33 import java.awt.Graphics;
34 import java.awt.Insets;
35 import java.awt.LayoutManager;
36 import java.awt.LayoutManager2;
37 import java.awt.event.*;
38 import java.beans.*;
39
40 import javax.swing.border.Border;
41 import javax.swing.plaf.*;
42 import javax.accessibility.*;
43
44 import java.io.Serializable;
45 import java.io.ObjectOutputStream;
46 import java.io.ObjectInputStream;
47 import java.io.IOException;
48 import java.util.Hashtable;
49
50
51 /**
52 * <code>JToolBar</code> provides a component that is useful for
53 * displaying commonly used <code>Action</code>s or controls.
54 * For examples and information on using tool bars see
55 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/toolbar.html">How to Use Tool Bars</a>,
56 * a section in <em>The Java Tutorial</em>.
57 *
58 * <p>
59 * With most look and feels,
60 * the user can drag out a tool bar into a separate window
61 * (unless the <code>floatable</code> property is set to <code>false</code>).
62 * For drag-out to work correctly, it is recommended that you add
63 * <code>JToolBar</code> instances to one of the four "sides" of a
64 * container whose layout manager is a <code>BorderLayout</code>,
65 * and do not add children to any of the other four "sides".
66 * <p>
67 * <strong>Warning:</strong> Swing is not thread safe. For more
68 * information see <a
69 * href="package-summary.html#threading">Swing's Threading
70 * Policy</a>.
71 * <p>
72 * <strong>Warning:</strong>
73 * Serialized objects of this class will not be compatible with
74 * future Swing releases. The current serialization support is
75 * appropriate for short term storage or RMI between applications running
76 * the same version of Swing. As of 1.4, support for long term storage
77 * of all JavaBeans™
78 * has been added to the <code>java.beans</code> package.
79 * Please see {@link java.beans.XMLEncoder}.
80 *
81 * @beaninfo
82 * attribute: isContainer true
83 * description: A component which displays commonly used controls or Actions.
84 *
85 * @author Georges Saab
86 * @author Jeff Shapiro
87 * @see Action
88 * @since 1.2
89 */
90 @SuppressWarnings("serial") // Same-version serialization only
91 public class JToolBar extends JComponent implements SwingConstants, Accessible
92 {
93 /**
94 * @see #getUIClassID
95 * @see #readObject
96 */
97 private static final String uiClassID = "ToolBarUI";
98
99 private boolean paintBorder = true;
100 private Insets margin = null;
101 private boolean floatable = true;
102 private int orientation = HORIZONTAL;
103
104 /**
105 * Creates a new tool bar; orientation defaults to <code>HORIZONTAL</code>.
106 */
107 public JToolBar()
108 {
109 this( HORIZONTAL );
110 }
111
112 /**
113 * Creates a new tool bar with the specified <code>orientation</code>.
114 * The <code>orientation</code> must be either <code>HORIZONTAL</code>
115 * or <code>VERTICAL</code>.
116 *
117 * @param orientation the orientation desired
118 */
119 public JToolBar( int orientation )
120 {
121 this(null, orientation);
122 }
123
124 /**
125 * Creates a new tool bar with the specified <code>name</code>. The
126 * name is used as the title of the undocked tool bar. The default
127 * orientation is <code>HORIZONTAL</code>.
128 *
129 * @param name the name of the tool bar
130 * @since 1.3
131 */
132 public JToolBar( String name ) {
133 this(name, HORIZONTAL);
134 }
135
136 /**
137 * Creates a new tool bar with a specified <code>name</code> and
138 * <code>orientation</code>.
139 * All other constructors call this constructor.
140 * If <code>orientation</code> is an invalid value, an exception will
141 * be thrown.
142 *
143 * @param name the name of the tool bar
144 * @param orientation the initial orientation -- it must be
145 * either <code>HORIZONTAL</code> or <code>VERTICAL</code>
146 * @exception IllegalArgumentException if orientation is neither
147 * <code>HORIZONTAL</code> nor <code>VERTICAL</code>
148 * @since 1.3
149 */
150 public JToolBar( String name , int orientation) {
151 setName(name);
152 checkOrientation( orientation );
153
154 this.orientation = orientation;
155 DefaultToolBarLayout layout = new DefaultToolBarLayout( orientation );
156 setLayout( layout );
157
158 addPropertyChangeListener( layout );
159
160 updateUI();
161 }
162
163 /**
164 * Returns the tool bar's current UI.
165 *
166 * @return the tool bar's current UI.
167 * @see #setUI
168 */
169 public ToolBarUI getUI() {
170 return (ToolBarUI)ui;
171 }
172
173 /**
174 * Sets the L&F object that renders this component.
175 *
176 * @param ui the <code>ToolBarUI</code> L&F object
177 * @see UIDefaults#getUI
178 * @beaninfo
179 * bound: true
180 * hidden: true
181 * attribute: visualUpdate true
182 * description: The UI object that implements the Component's LookAndFeel.
183 */
184 public void setUI(ToolBarUI ui) {
185 super.setUI(ui);
186 }
187
188 /**
189 * Notification from the <code>UIFactory</code> that the L&F has changed.
190 * Called to replace the UI with the latest version from the
191 * <code>UIFactory</code>.
192 *
193 * @see JComponent#updateUI
194 */
195 public void updateUI() {
196 setUI((ToolBarUI)UIManager.getUI(this));
197 // GTKLookAndFeel installs a different LayoutManager, and sets it
198 // to null after changing the look and feel, so, install the default
199 // if the LayoutManager is null.
200 if (getLayout() == null) {
201 setLayout(new DefaultToolBarLayout(getOrientation()));
202 }
203 invalidate();
204 }
205
206
207
208 /**
209 * Returns the name of the L&F class that renders this component.
210 *
211 * @return the string "ToolBarUI"
212 * @see JComponent#getUIClassID
213 * @see UIDefaults#getUI
214 */
215 public String getUIClassID() {
216 return uiClassID;
217 }
218
219
220 /**
221 * Returns the index of the specified component.
222 * (Note: Separators occupy index positions.)
223 *
224 * @param c the <code>Component</code> to find
225 * @return an integer indicating the component's position,
226 * where 0 is first
227 */
228 public int getComponentIndex(Component c) {
229 int ncomponents = this.getComponentCount();
230 Component[] component = this.getComponents();
231 for (int i = 0 ; i < ncomponents ; i++) {
232 Component comp = component[i];
233 if (comp == c)
234 return i;
235 }
236 return -1;
237 }
238
239 /**
240 * Returns the component at the specified index.
241 *
242 * @param i the component's position, where 0 is first
243 * @return the <code>Component</code> at that position,
244 * or <code>null</code> for an invalid index
245 *
246 */
247 public Component getComponentAtIndex(int i) {
248 int ncomponents = this.getComponentCount();
249 if ( i >= 0 && i < ncomponents) {
250 Component[] component = this.getComponents();
251 return component[i];
252 }
253 return null;
254 }
255
256 /**
257 * Sets the margin between the tool bar's border and
258 * its buttons. Setting to <code>null</code> causes the tool bar to
259 * use the default margins. The tool bar's default <code>Border</code>
260 * object uses this value to create the proper margin.
261 * However, if a non-default border is set on the tool bar,
262 * it is that <code>Border</code> object's responsibility to create the
263 * appropriate margin space (otherwise this property will
264 * effectively be ignored).
265 *
266 * @param m an <code>Insets</code> object that defines the space
267 * between the border and the buttons
268 * @see Insets
269 * @beaninfo
270 * description: The margin between the tool bar's border and contents
271 * bound: true
272 * expert: true
273 */
274 public void setMargin(Insets m)
275 {
276 Insets old = margin;
277 margin = m;
278 firePropertyChange("margin", old, m);
279 revalidate();
280 repaint();
281 }
282
283 /**
284 * Returns the margin between the tool bar's border and
285 * its buttons.
286 *
287 * @return an <code>Insets</code> object containing the margin values
288 * @see Insets
289 */
290 public Insets getMargin()
291 {
292 if(margin == null) {
293 return new Insets(0,0,0,0);
294 } else {
295 return margin;
296 }
297 }
298
299 /**
300 * Gets the <code>borderPainted</code> property.
301 *
302 * @return the value of the <code>borderPainted</code> property
303 * @see #setBorderPainted
304 */
305 public boolean isBorderPainted()
306 {
307 return paintBorder;
308 }
309
310
311 /**
312 * Sets the <code>borderPainted</code> property, which is
313 * <code>true</code> if the border should be painted.
314 * The default value for this property is <code>true</code>.
315 * Some look and feels might not implement painted borders;
316 * they will ignore this property.
317 *
318 * @param b if true, the border is painted
319 * @see #isBorderPainted
320 * @beaninfo
321 * description: Does the tool bar paint its borders?
322 * bound: true
323 * expert: true
324 */
325 public void setBorderPainted(boolean b)
326 {
327 if ( paintBorder != b )
328 {
329 boolean old = paintBorder;
330 paintBorder = b;
331 firePropertyChange("borderPainted", old, b);
332 revalidate();
333 repaint();
334 }
335 }
336
337 /**
338 * Paints the tool bar's border if the <code>borderPainted</code> property
339 * is <code>true</code>.
340 *
341 * @param g the <code>Graphics</code> context in which the painting
342 * is done
343 * @see JComponent#paint
344 * @see JComponent#setBorder
345 */
346 protected void paintBorder(Graphics g)
347 {
348 if (isBorderPainted())
349 {
350 super.paintBorder(g);
351 }
352 }
353
354 /**
355 * Gets the <code>floatable</code> property.
356 *
357 * @return the value of the <code>floatable</code> property
358 *
359 * @see #setFloatable
360 */
361 public boolean isFloatable()
362 {
363 return floatable;
364 }
365
366 /**
367 * Sets the <code>floatable</code> property,
368 * which must be <code>true</code> for the user to move the tool bar.
369 * Typically, a floatable tool bar can be
370 * dragged into a different position within the same container
371 * or out into its own window.
372 * The default value of this property is <code>true</code>.
373 * Some look and feels might not implement floatable tool bars;
374 * they will ignore this property.
375 *
376 * @param b if <code>true</code>, the tool bar can be moved;
377 * <code>false</code> otherwise
378 * @see #isFloatable
379 * @beaninfo
380 * description: Can the tool bar be made to float by the user?
381 * bound: true
382 * preferred: true
383 */
384 public void setFloatable( boolean b )
385 {
386 if ( floatable != b )
387 {
388 boolean old = floatable;
389 floatable = b;
390
391 firePropertyChange("floatable", old, b);
392 revalidate();
393 repaint();
394 }
395 }
396
397 /**
398 * Returns the current orientation of the tool bar. The value is either
399 * <code>HORIZONTAL</code> or <code>VERTICAL</code>.
400 *
401 * @return an integer representing the current orientation -- either
402 * <code>HORIZONTAL</code> or <code>VERTICAL</code>
403 * @see #setOrientation
404 */
405 public int getOrientation()
406 {
407 return this.orientation;
408 }
409
410 /**
411 * Sets the orientation of the tool bar. The orientation must have
412 * either the value <code>HORIZONTAL</code> or <code>VERTICAL</code>.
413 * If <code>orientation</code> is
414 * an invalid value, an exception will be thrown.
415 *
416 * @param o the new orientation -- either <code>HORIZONTAL</code> or
417 * <code>VERTICAL</code>
418 * @exception IllegalArgumentException if orientation is neither
419 * <code>HORIZONTAL</code> nor <code>VERTICAL</code>
420 * @see #getOrientation
421 * @beaninfo
422 * description: The current orientation of the tool bar
423 * bound: true
424 * preferred: true
425 * enum: HORIZONTAL SwingConstants.HORIZONTAL
426 * VERTICAL SwingConstants.VERTICAL
427 */
428 public void setOrientation( int o )
429 {
430 checkOrientation( o );
431
432 if ( orientation != o )
433 {
434 int old = orientation;
435 orientation = o;
436
437 firePropertyChange("orientation", old, o);
438 revalidate();
439 repaint();
485 case HORIZONTAL:
486 break;
487 default:
488 throw new IllegalArgumentException( "orientation must be one of: VERTICAL, HORIZONTAL" );
489 }
490 }
491
492 /**
493 * Appends a separator of default size to the end of the tool bar.
494 * The default size is determined by the current look and feel.
495 */
496 public void addSeparator()
497 {
498 addSeparator(null);
499 }
500
501 /**
502 * Appends a separator of a specified size to the end
503 * of the tool bar.
504 *
505 * @param size the <code>Dimension</code> of the separator
506 */
507 public void addSeparator( Dimension size )
508 {
509 JToolBar.Separator s = new JToolBar.Separator( size );
510 add(s);
511 }
512
513 /**
514 * Adds a new <code>JButton</code> which dispatches the action.
515 *
516 * @param a the <code>Action</code> object to add as a new menu item
517 * @return the new button which dispatches the action
518 */
519 public JButton add(Action a) {
520 JButton b = createActionComponent(a);
521 b.setAction(a);
522 add(b);
523 return b;
524 }
525
526 /**
527 * Factory method which creates the <code>JButton</code> for
528 * <code>Action</code>s added to the <code>JToolBar</code>.
529 * The default name is empty if a <code>null</code> action is passed.
530 *
531 * @param a the <code>Action</code> for the button to be added
532 * @return the newly created button
533 * @see Action
534 * @since 1.3
535 */
536 protected JButton createActionComponent(Action a) {
537 JButton b = new JButton() {
538 protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
539 PropertyChangeListener pcl = createActionChangeListener(this);
540 if (pcl==null) {
541 pcl = super.createActionPropertyChangeListener(a);
542 }
543 return pcl;
544 }
545 };
546 if (a != null && (a.getValue(Action.SMALL_ICON) != null ||
547 a.getValue(Action.LARGE_ICON_KEY) != null)) {
548 b.setHideActionText(true);
549 }
550 b.setHorizontalTextPosition(JButton.CENTER);
551 b.setVerticalTextPosition(JButton.BOTTOM);
552 return b;
553 }
554
555 /**
556 * Returns a properly configured <code>PropertyChangeListener</code>
557 * which updates the control as changes to the <code>Action</code> occur,
558 * or <code>null</code> if the default
559 * property change listener for the control is desired.
560 *
561 * @param b a {@code JButton}
562 * @return {@code null}
563 */
564 protected PropertyChangeListener createActionChangeListener(JButton b) {
565 return null;
566 }
567
568 /**
569 * If a <code>JButton</code> is being added, it is initially
570 * set to be disabled.
571 *
572 * @param comp the component to be enhanced
573 * @param constraints the constraints to be enforced on the component
574 * @param index the index of the component
575 *
576 */
577 protected void addImpl(Component comp, Object constraints, int index) {
578 if (comp instanceof Separator) {
579 if (getOrientation() == VERTICAL) {
580 ( (Separator)comp ).setOrientation(JSeparator.HORIZONTAL);
581 } else {
582 ( (Separator)comp ).setOrientation(JSeparator.VERTICAL);
583 }
584 }
585 super.addImpl(comp, constraints, index);
586 if (comp instanceof JButton) {
587 ((JButton)comp).setDefaultCapable(false);
588 }
589 }
592 /**
593 * A toolbar-specific separator. An object with dimension but
594 * no contents used to divide buttons on a tool bar into groups.
595 */
596 public static class Separator extends JSeparator
597 {
598 private Dimension separatorSize;
599
600 /**
601 * Creates a new toolbar separator with the default size
602 * as defined by the current look and feel.
603 */
604 public Separator()
605 {
606 this( null ); // let the UI define the default size
607 }
608
609 /**
610 * Creates a new toolbar separator with the specified size.
611 *
612 * @param size the <code>Dimension</code> of the separator
613 */
614 public Separator( Dimension size )
615 {
616 super( JSeparator.HORIZONTAL );
617 setSeparatorSize(size);
618 }
619
620 /**
621 * Returns the name of the L&F class that renders this component.
622 *
623 * @return the string "ToolBarSeparatorUI"
624 * @see JComponent#getUIClassID
625 * @see UIDefaults#getUI
626 */
627 public String getUIClassID()
628 {
629 return "ToolBarSeparatorUI";
630 }
631
632 /**
633 * Sets the size of the separator.
634 *
635 * @param size the new <code>Dimension</code> of the separator
636 */
637 public void setSeparatorSize( Dimension size )
638 {
639 if (size != null) {
640 separatorSize = size;
641 } else {
642 super.updateUI();
643 }
644 this.invalidate();
645 }
646
647 /**
648 * Returns the size of the separator
649 *
650 * @return the <code>Dimension</code> object containing the separator's
651 * size (This is a reference, NOT a copy!)
652 */
653 public Dimension getSeparatorSize()
654 {
655 return separatorSize;
656 }
657
658 /**
659 * Returns the minimum size for the separator.
660 *
661 * @return the <code>Dimension</code> object containing the separator's
662 * minimum size
663 */
664 public Dimension getMinimumSize()
665 {
666 if (separatorSize != null) {
667 return separatorSize.getSize();
668 } else {
669 return super.getMinimumSize();
670 }
671 }
672
673 /**
674 * Returns the maximum size for the separator.
675 *
676 * @return the <code>Dimension</code> object containing the separator's
677 * maximum size
678 */
679 public Dimension getMaximumSize()
680 {
681 if (separatorSize != null) {
682 return separatorSize.getSize();
683 } else {
684 return super.getMaximumSize();
685 }
686 }
687
688 /**
689 * Returns the preferred size for the separator.
690 *
691 * @return the <code>Dimension</code> object containing the separator's
692 * preferred size
693 */
694 public Dimension getPreferredSize()
695 {
696 if (separatorSize != null) {
697 return separatorSize.getSize();
698 } else {
699 return super.getPreferredSize();
700 }
701 }
702 }
703
704
705 /**
706 * See <code>readObject</code> and <code>writeObject</code> in
707 * <code>JComponent</code> for more
708 * information about serialization in Swing.
709 */
710 private void writeObject(ObjectOutputStream s) throws IOException {
711 s.defaultWriteObject();
712 if (getUIClassID().equals(uiClassID)) {
713 byte count = JComponent.getWriteObjCounter(this);
714 JComponent.setWriteObjCounter(this, --count);
715 if (count == 0 && ui != null) {
716 ui.installUI(this);
717 }
718 }
719 }
720
721
722 /**
723 * Returns a string representation of this <code>JToolBar</code>.
724 * This method
725 * is intended to be used only for debugging purposes, and the
726 * content and format of the returned string may vary between
727 * implementations. The returned string may be empty but may not
728 * be <code>null</code>.
729 *
730 * @return a string representation of this <code>JToolBar</code>.
731 */
732 protected String paramString() {
733 String paintBorderString = (paintBorder ?
734 "true" : "false");
735 String marginString = (margin != null ?
736 margin.toString() : "");
737 String floatableString = (floatable ?
738 "true" : "false");
739 String orientationString = (orientation == HORIZONTAL ?
740 "HORIZONTAL" : "VERTICAL");
741
742 return super.paramString() +
743 ",floatable=" + floatableString +
744 ",margin=" + marginString +
745 ",orientation=" + orientationString +
746 ",paintBorder=" + paintBorderString;
747 }
748
749
750 private class DefaultToolBarLayout
828 ////////////////
829
830 /**
831 * Gets the AccessibleContext associated with this JToolBar.
832 * For tool bars, the AccessibleContext takes the form of an
833 * AccessibleJToolBar.
834 * A new AccessibleJToolBar instance is created if necessary.
835 *
836 * @return an AccessibleJToolBar that serves as the
837 * AccessibleContext of this JToolBar
838 */
839 public AccessibleContext getAccessibleContext() {
840 if (accessibleContext == null) {
841 accessibleContext = new AccessibleJToolBar();
842 }
843 return accessibleContext;
844 }
845
846 /**
847 * This class implements accessibility support for the
848 * <code>JToolBar</code> class. It provides an implementation of the
849 * Java Accessibility API appropriate to toolbar user-interface elements.
850 */
851 protected class AccessibleJToolBar extends AccessibleJComponent {
852
853 /**
854 * Get the state of this object.
855 *
856 * @return an instance of AccessibleStateSet containing the current
857 * state set of the object
858 * @see AccessibleState
859 */
860 public AccessibleStateSet getAccessibleStateSet() {
861 AccessibleStateSet states = super.getAccessibleStateSet();
862 // FIXME: [[[WDW - need to add orientation from BoxLayout]]]
863 // FIXME: [[[WDW - need to do SELECTABLE if SelectionModel is added]]]
864 return states;
865 }
866
867 /**
868 * Get the role of this object.
|
32 import java.awt.Dimension;
33 import java.awt.Graphics;
34 import java.awt.Insets;
35 import java.awt.LayoutManager;
36 import java.awt.LayoutManager2;
37 import java.awt.event.*;
38 import java.beans.*;
39
40 import javax.swing.border.Border;
41 import javax.swing.plaf.*;
42 import javax.accessibility.*;
43
44 import java.io.Serializable;
45 import java.io.ObjectOutputStream;
46 import java.io.ObjectInputStream;
47 import java.io.IOException;
48 import java.util.Hashtable;
49
50
51 /**
52 * {@code JToolBar} provides a component that is useful for
53 * displaying commonly used {@code Action}s or controls.
54 * For examples and information on using tool bars see
55 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/components/toolbar.html">How to Use Tool Bars</a>,
56 * a section in <em>The Java Tutorial</em>.
57 *
58 * <p>
59 * With most look and feels,
60 * the user can drag out a tool bar into a separate window
61 * (unless the {@code floatable} property is set to {@code false}).
62 * For drag-out to work correctly, it is recommended that you add
63 * {@code JToolBar} instances to one of the four "sides" of a
64 * container whose layout manager is a {@code BorderLayout},
65 * and do not add children to any of the other four "sides".
66 * <p>
67 * <strong>Warning:</strong> Swing is not thread safe. For more
68 * information see <a
69 * href="package-summary.html#threading">Swing's Threading
70 * Policy</a>.
71 * <p>
72 * <strong>Warning:</strong>
73 * Serialized objects of this class will not be compatible with
74 * future Swing releases. The current serialization support is
75 * appropriate for short term storage or RMI between applications running
76 * the same version of Swing. As of 1.4, support for long term storage
77 * of all JavaBeans™
78 * has been added to the {@code java.beans} package.
79 * Please see {@link java.beans.XMLEncoder}.
80 *
81 * @beaninfo
82 * attribute: isContainer true
83 * description: A component which displays commonly used controls or Actions.
84 *
85 * @author Georges Saab
86 * @author Jeff Shapiro
87 * @see Action
88 * @since 1.2
89 */
90 @SuppressWarnings("serial") // Same-version serialization only
91 public class JToolBar extends JComponent implements SwingConstants, Accessible
92 {
93 /**
94 * @see #getUIClassID
95 * @see #readObject
96 */
97 private static final String uiClassID = "ToolBarUI";
98
99 private boolean paintBorder = true;
100 private Insets margin = null;
101 private boolean floatable = true;
102 private int orientation = HORIZONTAL;
103
104 /**
105 * Creates a new tool bar; orientation defaults to {@code HORIZONTAL}.
106 */
107 public JToolBar()
108 {
109 this( HORIZONTAL );
110 }
111
112 /**
113 * Creates a new tool bar with the specified {@code orientation}.
114 * The {@code orientation} must be either {@code HORIZONTAL}
115 * or {@code VERTICAL}.
116 *
117 * @param orientation the orientation desired
118 */
119 public JToolBar( int orientation )
120 {
121 this(null, orientation);
122 }
123
124 /**
125 * Creates a new tool bar with the specified {@code name}. The
126 * name is used as the title of the undocked tool bar. The default
127 * orientation is {@code HORIZONTAL}.
128 *
129 * @param name the name of the tool bar
130 * @since 1.3
131 */
132 public JToolBar( String name ) {
133 this(name, HORIZONTAL);
134 }
135
136 /**
137 * Creates a new tool bar with a specified {@code name} and
138 * {@code orientation}.
139 * All other constructors call this constructor.
140 * If {@code orientation} is an invalid value, an exception will
141 * be thrown.
142 *
143 * @param name the name of the tool bar
144 * @param orientation the initial orientation -- it must be
145 * either {@code HORIZONTAL} or {@code VERTICAL}
146 * @exception IllegalArgumentException if orientation is neither
147 * {@code HORIZONTAL} nor {@code VERTICAL}
148 * @since 1.3
149 */
150 public JToolBar( String name , int orientation) {
151 setName(name);
152 checkOrientation( orientation );
153
154 this.orientation = orientation;
155 DefaultToolBarLayout layout = new DefaultToolBarLayout( orientation );
156 setLayout( layout );
157
158 addPropertyChangeListener( layout );
159
160 updateUI();
161 }
162
163 /**
164 * Returns the tool bar's current UI.
165 *
166 * @return the tool bar's current UI.
167 * @see #setUI
168 */
169 public ToolBarUI getUI() {
170 return (ToolBarUI)ui;
171 }
172
173 /**
174 * Sets the L&F object that renders this component.
175 *
176 * @param ui the {@code ToolBarUI} L&F object
177 * @see UIDefaults#getUI
178 * @beaninfo
179 * bound: true
180 * hidden: true
181 * attribute: visualUpdate true
182 * description: The UI object that implements the Component's LookAndFeel.
183 */
184 public void setUI(ToolBarUI ui) {
185 super.setUI(ui);
186 }
187
188 /**
189 * Notification from the {@code UIFactory} that the L&F has changed.
190 * Called to replace the UI with the latest version from the
191 * {@code UIFactory}.
192 *
193 * @see JComponent#updateUI
194 */
195 public void updateUI() {
196 setUI((ToolBarUI)UIManager.getUI(this));
197 // GTKLookAndFeel installs a different LayoutManager, and sets it
198 // to null after changing the look and feel, so, install the default
199 // if the LayoutManager is null.
200 if (getLayout() == null) {
201 setLayout(new DefaultToolBarLayout(getOrientation()));
202 }
203 invalidate();
204 }
205
206
207
208 /**
209 * Returns the name of the L&F class that renders this component.
210 *
211 * @return the string "ToolBarUI"
212 * @see JComponent#getUIClassID
213 * @see UIDefaults#getUI
214 */
215 public String getUIClassID() {
216 return uiClassID;
217 }
218
219
220 /**
221 * Returns the index of the specified component.
222 * (Note: Separators occupy index positions.)
223 *
224 * @param c the {@code Component} to find
225 * @return an integer indicating the component's position,
226 * where 0 is first
227 */
228 public int getComponentIndex(Component c) {
229 int ncomponents = this.getComponentCount();
230 Component[] component = this.getComponents();
231 for (int i = 0 ; i < ncomponents ; i++) {
232 Component comp = component[i];
233 if (comp == c)
234 return i;
235 }
236 return -1;
237 }
238
239 /**
240 * Returns the component at the specified index.
241 *
242 * @param i the component's position, where 0 is first
243 * @return the {@code Component} at that position,
244 * or {@code null} for an invalid index
245 *
246 */
247 public Component getComponentAtIndex(int i) {
248 int ncomponents = this.getComponentCount();
249 if ( i >= 0 && i < ncomponents) {
250 Component[] component = this.getComponents();
251 return component[i];
252 }
253 return null;
254 }
255
256 /**
257 * Sets the margin between the tool bar's border and
258 * its buttons. Setting to {@code null} causes the tool bar to
259 * use the default margins. The tool bar's default {@code Border}
260 * object uses this value to create the proper margin.
261 * However, if a non-default border is set on the tool bar,
262 * it is that {@code Border} object's responsibility to create the
263 * appropriate margin space (otherwise this property will
264 * effectively be ignored).
265 *
266 * @param m an {@code Insets} object that defines the space
267 * between the border and the buttons
268 * @see Insets
269 * @beaninfo
270 * description: The margin between the tool bar's border and contents
271 * bound: true
272 * expert: true
273 */
274 public void setMargin(Insets m)
275 {
276 Insets old = margin;
277 margin = m;
278 firePropertyChange("margin", old, m);
279 revalidate();
280 repaint();
281 }
282
283 /**
284 * Returns the margin between the tool bar's border and
285 * its buttons.
286 *
287 * @return an {@code Insets} object containing the margin values
288 * @see Insets
289 */
290 public Insets getMargin()
291 {
292 if(margin == null) {
293 return new Insets(0,0,0,0);
294 } else {
295 return margin;
296 }
297 }
298
299 /**
300 * Gets the {@code borderPainted} property.
301 *
302 * @return the value of the {@code borderPainted} property
303 * @see #setBorderPainted
304 */
305 public boolean isBorderPainted()
306 {
307 return paintBorder;
308 }
309
310
311 /**
312 * Sets the {@code borderPainted} property, which is
313 * {@code true} if the border should be painted.
314 * The default value for this property is {@code true}.
315 * Some look and feels might not implement painted borders;
316 * they will ignore this property.
317 *
318 * @param b if true, the border is painted
319 * @see #isBorderPainted
320 * @beaninfo
321 * description: Does the tool bar paint its borders?
322 * bound: true
323 * expert: true
324 */
325 public void setBorderPainted(boolean b)
326 {
327 if ( paintBorder != b )
328 {
329 boolean old = paintBorder;
330 paintBorder = b;
331 firePropertyChange("borderPainted", old, b);
332 revalidate();
333 repaint();
334 }
335 }
336
337 /**
338 * Paints the tool bar's border if the {@code borderPainted} property
339 * is {@code true}.
340 *
341 * @param g the {@code Graphics} context in which the painting
342 * is done
343 * @see JComponent#paint
344 * @see JComponent#setBorder
345 */
346 protected void paintBorder(Graphics g)
347 {
348 if (isBorderPainted())
349 {
350 super.paintBorder(g);
351 }
352 }
353
354 /**
355 * Gets the {@code floatable} property.
356 *
357 * @return the value of the {@code floatable} property
358 *
359 * @see #setFloatable
360 */
361 public boolean isFloatable()
362 {
363 return floatable;
364 }
365
366 /**
367 * Sets the {@code floatable} property,
368 * which must be {@code true} for the user to move the tool bar.
369 * Typically, a floatable tool bar can be
370 * dragged into a different position within the same container
371 * or out into its own window.
372 * The default value of this property is {@code true}.
373 * Some look and feels might not implement floatable tool bars;
374 * they will ignore this property.
375 *
376 * @param b if {@code true}, the tool bar can be moved;
377 * {@code false} otherwise
378 * @see #isFloatable
379 * @beaninfo
380 * description: Can the tool bar be made to float by the user?
381 * bound: true
382 * preferred: true
383 */
384 public void setFloatable( boolean b )
385 {
386 if ( floatable != b )
387 {
388 boolean old = floatable;
389 floatable = b;
390
391 firePropertyChange("floatable", old, b);
392 revalidate();
393 repaint();
394 }
395 }
396
397 /**
398 * Returns the current orientation of the tool bar. The value is either
399 * {@code HORIZONTAL} or {@code VERTICAL}.
400 *
401 * @return an integer representing the current orientation -- either
402 * {@code HORIZONTAL} or {@code VERTICAL}
403 * @see #setOrientation
404 */
405 public int getOrientation()
406 {
407 return this.orientation;
408 }
409
410 /**
411 * Sets the orientation of the tool bar. The orientation must have
412 * either the value {@code HORIZONTAL} or {@code VERTICAL}.
413 * If {@code orientation} is
414 * an invalid value, an exception will be thrown.
415 *
416 * @param o the new orientation -- either {@code HORIZONTAL} or
417 * {@code VERTICAL}
418 * @exception IllegalArgumentException if orientation is neither
419 * {@code HORIZONTAL} nor {@code VERTICAL}
420 * @see #getOrientation
421 * @beaninfo
422 * description: The current orientation of the tool bar
423 * bound: true
424 * preferred: true
425 * enum: HORIZONTAL SwingConstants.HORIZONTAL
426 * VERTICAL SwingConstants.VERTICAL
427 */
428 public void setOrientation( int o )
429 {
430 checkOrientation( o );
431
432 if ( orientation != o )
433 {
434 int old = orientation;
435 orientation = o;
436
437 firePropertyChange("orientation", old, o);
438 revalidate();
439 repaint();
485 case HORIZONTAL:
486 break;
487 default:
488 throw new IllegalArgumentException( "orientation must be one of: VERTICAL, HORIZONTAL" );
489 }
490 }
491
492 /**
493 * Appends a separator of default size to the end of the tool bar.
494 * The default size is determined by the current look and feel.
495 */
496 public void addSeparator()
497 {
498 addSeparator(null);
499 }
500
501 /**
502 * Appends a separator of a specified size to the end
503 * of the tool bar.
504 *
505 * @param size the {@code Dimension} of the separator
506 */
507 public void addSeparator( Dimension size )
508 {
509 JToolBar.Separator s = new JToolBar.Separator( size );
510 add(s);
511 }
512
513 /**
514 * Adds a new {@code JButton} which dispatches the action.
515 *
516 * @param a the {@code Action} object to add as a new menu item
517 * @return the new button which dispatches the action
518 */
519 public JButton add(Action a) {
520 JButton b = createActionComponent(a);
521 b.setAction(a);
522 add(b);
523 return b;
524 }
525
526 /**
527 * Factory method which creates the {@code JButton} for
528 * {@code Action}s added to the {@code JToolBar}.
529 * The default name is empty if a {@code null} action is passed.
530 *
531 * @param a the {@code Action} for the button to be added
532 * @return the newly created button
533 * @see Action
534 * @since 1.3
535 */
536 protected JButton createActionComponent(Action a) {
537 JButton b = new JButton() {
538 protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
539 PropertyChangeListener pcl = createActionChangeListener(this);
540 if (pcl==null) {
541 pcl = super.createActionPropertyChangeListener(a);
542 }
543 return pcl;
544 }
545 };
546 if (a != null && (a.getValue(Action.SMALL_ICON) != null ||
547 a.getValue(Action.LARGE_ICON_KEY) != null)) {
548 b.setHideActionText(true);
549 }
550 b.setHorizontalTextPosition(JButton.CENTER);
551 b.setVerticalTextPosition(JButton.BOTTOM);
552 return b;
553 }
554
555 /**
556 * Returns a properly configured {@code PropertyChangeListener}
557 * which updates the control as changes to the {@code Action} occur,
558 * or {@code null} if the default
559 * property change listener for the control is desired.
560 *
561 * @param b a {@code JButton}
562 * @return {@code null}
563 */
564 protected PropertyChangeListener createActionChangeListener(JButton b) {
565 return null;
566 }
567
568 /**
569 * If a {@code JButton} is being added, it is initially
570 * set to be disabled.
571 *
572 * @param comp the component to be enhanced
573 * @param constraints the constraints to be enforced on the component
574 * @param index the index of the component
575 *
576 */
577 protected void addImpl(Component comp, Object constraints, int index) {
578 if (comp instanceof Separator) {
579 if (getOrientation() == VERTICAL) {
580 ( (Separator)comp ).setOrientation(JSeparator.HORIZONTAL);
581 } else {
582 ( (Separator)comp ).setOrientation(JSeparator.VERTICAL);
583 }
584 }
585 super.addImpl(comp, constraints, index);
586 if (comp instanceof JButton) {
587 ((JButton)comp).setDefaultCapable(false);
588 }
589 }
592 /**
593 * A toolbar-specific separator. An object with dimension but
594 * no contents used to divide buttons on a tool bar into groups.
595 */
596 public static class Separator extends JSeparator
597 {
598 private Dimension separatorSize;
599
600 /**
601 * Creates a new toolbar separator with the default size
602 * as defined by the current look and feel.
603 */
604 public Separator()
605 {
606 this( null ); // let the UI define the default size
607 }
608
609 /**
610 * Creates a new toolbar separator with the specified size.
611 *
612 * @param size the {@code Dimension} of the separator
613 */
614 public Separator( Dimension size )
615 {
616 super( JSeparator.HORIZONTAL );
617 setSeparatorSize(size);
618 }
619
620 /**
621 * Returns the name of the L&F class that renders this component.
622 *
623 * @return the string "ToolBarSeparatorUI"
624 * @see JComponent#getUIClassID
625 * @see UIDefaults#getUI
626 */
627 public String getUIClassID()
628 {
629 return "ToolBarSeparatorUI";
630 }
631
632 /**
633 * Sets the size of the separator.
634 *
635 * @param size the new {@code Dimension} of the separator
636 */
637 public void setSeparatorSize( Dimension size )
638 {
639 if (size != null) {
640 separatorSize = size;
641 } else {
642 super.updateUI();
643 }
644 this.invalidate();
645 }
646
647 /**
648 * Returns the size of the separator
649 *
650 * @return the {@code Dimension} object containing the separator's
651 * size (This is a reference, NOT a copy!)
652 */
653 public Dimension getSeparatorSize()
654 {
655 return separatorSize;
656 }
657
658 /**
659 * Returns the minimum size for the separator.
660 *
661 * @return the {@code Dimension} object containing the separator's
662 * minimum size
663 */
664 public Dimension getMinimumSize()
665 {
666 if (separatorSize != null) {
667 return separatorSize.getSize();
668 } else {
669 return super.getMinimumSize();
670 }
671 }
672
673 /**
674 * Returns the maximum size for the separator.
675 *
676 * @return the {@code Dimension} object containing the separator's
677 * maximum size
678 */
679 public Dimension getMaximumSize()
680 {
681 if (separatorSize != null) {
682 return separatorSize.getSize();
683 } else {
684 return super.getMaximumSize();
685 }
686 }
687
688 /**
689 * Returns the preferred size for the separator.
690 *
691 * @return the {@code Dimension} object containing the separator's
692 * preferred size
693 */
694 public Dimension getPreferredSize()
695 {
696 if (separatorSize != null) {
697 return separatorSize.getSize();
698 } else {
699 return super.getPreferredSize();
700 }
701 }
702 }
703
704
705 /**
706 * See {@code readObject} and {@code writeObject} in
707 * {@code JComponent} for more
708 * information about serialization in Swing.
709 */
710 private void writeObject(ObjectOutputStream s) throws IOException {
711 s.defaultWriteObject();
712 if (getUIClassID().equals(uiClassID)) {
713 byte count = JComponent.getWriteObjCounter(this);
714 JComponent.setWriteObjCounter(this, --count);
715 if (count == 0 && ui != null) {
716 ui.installUI(this);
717 }
718 }
719 }
720
721
722 /**
723 * Returns a string representation of this {@code JToolBar}.
724 * This method
725 * is intended to be used only for debugging purposes, and the
726 * content and format of the returned string may vary between
727 * implementations. The returned string may be empty but may not
728 * be {@code null}.
729 *
730 * @return a string representation of this {@code JToolBar}.
731 */
732 protected String paramString() {
733 String paintBorderString = (paintBorder ?
734 "true" : "false");
735 String marginString = (margin != null ?
736 margin.toString() : "");
737 String floatableString = (floatable ?
738 "true" : "false");
739 String orientationString = (orientation == HORIZONTAL ?
740 "HORIZONTAL" : "VERTICAL");
741
742 return super.paramString() +
743 ",floatable=" + floatableString +
744 ",margin=" + marginString +
745 ",orientation=" + orientationString +
746 ",paintBorder=" + paintBorderString;
747 }
748
749
750 private class DefaultToolBarLayout
828 ////////////////
829
830 /**
831 * Gets the AccessibleContext associated with this JToolBar.
832 * For tool bars, the AccessibleContext takes the form of an
833 * AccessibleJToolBar.
834 * A new AccessibleJToolBar instance is created if necessary.
835 *
836 * @return an AccessibleJToolBar that serves as the
837 * AccessibleContext of this JToolBar
838 */
839 public AccessibleContext getAccessibleContext() {
840 if (accessibleContext == null) {
841 accessibleContext = new AccessibleJToolBar();
842 }
843 return accessibleContext;
844 }
845
846 /**
847 * This class implements accessibility support for the
848 * {@code JToolBar} class. It provides an implementation of the
849 * Java Accessibility API appropriate to toolbar user-interface elements.
850 */
851 protected class AccessibleJToolBar extends AccessibleJComponent {
852
853 /**
854 * Get the state of this object.
855 *
856 * @return an instance of AccessibleStateSet containing the current
857 * state set of the object
858 * @see AccessibleState
859 */
860 public AccessibleStateSet getAccessibleStateSet() {
861 AccessibleStateSet states = super.getAccessibleStateSet();
862 // FIXME: [[[WDW - need to add orientation from BoxLayout]]]
863 // FIXME: [[[WDW - need to do SELECTABLE if SelectionModel is added]]]
864 return states;
865 }
866
867 /**
868 * Get the role of this object.
|