KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > swingwtx > swing > JToolBar


1 /*
2    SwingWT
3    Copyright(c)2003-2004, R. Rawson-Tetley
4  
5    For more information on distributing and using this program, please
6    see the accompanying "COPYING" file.
7  
8    Contact me by electronic mail: bobintetley@users.sourceforge.net
9  
10    $Log: JToolBar.java,v $
11    Revision 1.28 2004/05/05 12:43:21 bobintetley
12    Patches/new files from Laurent Martell
13
14    Revision 1.27 2004/05/04 00:57:03 dannaab
15    Sun java and javax package naming improvements. Fix ambiguous class names by hardcoding SWT full class name
16
17    Revision 1.26 2004/04/28 08:38:12 bobintetley
18    Hierarchy fixes, code cleanup for base classes, additional javadocs and use of flag to identify JComponent descendants with peers
19
20    Revision 1.25 2004/03/31 08:16:40 bobintetley
21    Code clean up and separating out of JButtonMappedAction class
22
23    Revision 1.24 2004/03/30 10:42:46 bobintetley
24    Many minor bug fixes, event improvements by Dan Naab. Full swing.Icon support
25
26    Revision 1.23 2004/03/01 15:58:47 bobintetley
27    Various little bug fixes
28
29    Revision 1.22 2004/02/13 22:55:29 djspiewak
30    Improved the JToolBar class and added two new methods
31
32    Revision 1.21 2004/01/26 08:11:00 bobsintetley
33    Many bugfixes and addition of SwingSet
34
35    Revision 1.20 2004/01/23 08:05:31 bobintetley
36    JComboBox fixes and better Action implementation
37
38    Revision 1.19 2004/01/15 15:20:30 bobintetley
39    Java2D work
40
41    Revision 1.18 2004/01/09 11:47:27 bobintetley
42    Automatic JButton mapping!
43
44    Revision 1.17 2004/01/09 10:33:57 bobintetley
45    Changes for JToolBar to allow platform ToolBars, mixed with other components
46
47    Revision 1.2 2004/01/06 08:32:25 bobintetley
48    Added logging
49  */

50
51
52 package swingwtx.swing;
53
54 import java.util.Vector JavaDoc;
55
56 import org.eclipse.swt.SWT;
57 import org.eclipse.swt.events.SelectionAdapter;
58 import org.eclipse.swt.events.SelectionEvent;
59 import org.eclipse.swt.layout.RowLayout;
60 import org.eclipse.swt.widgets.Listener;
61 import org.eclipse.swt.widgets.Menu;
62 import org.eclipse.swt.widgets.ToolBar;
63 import org.eclipse.swt.widgets.ToolItem;
64
65 import swingwt.awt.Component;
66 import swingwt.awt.Container;
67 import swingwt.awt.Insets;
68 import swingwt.awt.event.ActionEvent;
69
70 /**
71  * This class is now not only fully 'swing-y',
72  * but also mirrors correctly to SWT. Also,
73  * this class's peer, JToolBar has the option
74  * to be contained within a CoolBar.
75  *
76  * Rob: Unfortunately, this class can never support
77  * embedded components the way that Swing does, so we can't use
78  * this as the "main" Toolbar implementation. Instead, this allows
79  * Swing functionality with actions to the platform toolbar, regular
80  * JToolBar will behave like Swing.
81  *
82  * Daniel: Au cantrare, my pessimistic friend! :)
83  * I have done what you say this class can never do.
84  * This class really is now fully swing-y and does
85  * support placing strange components within itself.
86  * The key to the hack is not having the JToolbar class
87  * control a ToolBar peer, but a Composite peer. Then
88  * we add ToolBar(s) and Composite(s) as needed to
89  * give the native look within the CoolBar or without
90  * the CoolBar if nessissary. You have to admit, this
91  * class has earned the right to be the default implementation.
92  * Perhaps we could do a JToolBarNonNative? ;)
93  *
94  * Rob: Very funny - I'll hack on this a bit and we'll use it
95  * as the main implmentation (you win!)
96  *
97  * Daniel: I made some minor changes to this class, adding
98  * the overloaded methods to add(JCheckBox) and add(JRadioButton)
99  * so as to enable the corresponding SWT widget functionality in
100  * SwingWT.
101  *
102  * @author Daniel Spiewak
103  * @author Robin Rawson-Tetley
104  */

105 public class JToolBar extends JComponent implements SwingConstants {
106     
107     /** Last added component - used to determine when to use
108      * ToolBar/Composite */

109     protected org.eclipse.swt.widgets.Composite lastAdd;
110     
111     protected int orientation = HORIZONTAL;
112     protected String JavaDoc titleString = "";
113     protected boolean coolbar = false;
114     protected Container parent = null;
115     protected org.eclipse.swt.widgets.Composite ppeer = null;
116     
117     private boolean cached = false;
118     private Vector JavaDoc cache = new Vector JavaDoc();
119     
120     /** Used for returning objects in a thread safe manner */
121     private Object JavaDoc threadSafeObjectRetValue = null;
122     private boolean threadSafeBoolean = false;
123     
124     public JToolBar() {
125         this("", SwingConstants.HORIZONTAL);
126     }
127     
128     public JToolBar(String JavaDoc titleString) {
129         this(titleString, SwingConstants.HORIZONTAL);
130     }
131     
132     public JToolBar(int orientation) {
133         this("", orientation);
134     }
135     
136     public JToolBar(String JavaDoc titleString, int orientation) {
137         this.titleString = titleString;
138         this.orientation = orientation;
139     }
140     
141     public int getOrientation() {
142         return orientation;
143     }
144     
145     /**
146      *
147      * @param orientation
148      */

149     public void setOrientation(int orientation) {
150         this.orientation = orientation;
151     }
152     
153     /**
154      * @param index
155      * @return
156      */

157     public Component getComponentAtIndex(int index) {
158         return (Component) comps.get(index);
159     }
160     
161     /**
162      * @param c
163      * @return
164      */

165     public int getComponentIndex(Component c) {
166         
167         for (int i = 0; i < comps.size(); i++) {
168             if (comps.get(i).equals(c)) return i;
169         }
170         
171         return 0;
172     }
173     
174     /**
175      * @return insets The margin of the Composite peer in Insets form.
176      */

177     public Insets getMargin() {
178         org.eclipse.swt.graphics.Rectangle bounds = ppeer.getBounds();
179         org.eclipse.swt.graphics.Rectangle client = ppeer.getClientArea();
180         Insets insets = new Insets();
181         
182         insets.left = client.x;
183         insets.top = client.y;
184         insets.right = bounds.width - (client.width + client.x);
185         insets.bottom = bounds.height - (client.height + client.y);
186         
187         return insets;
188     }
189     
190     /**
191      * Sorry, controlled by the native widgets.
192      *
193      * @param insets
194      */

195     public void setMargin(Insets insets) {}
196     
197     /**
198      * Overrides normal component invalidation as we are using
199      * an SWT layout.
200      */

201     public void invalidate() {
202         if (!SwingWTUtils.isSWTControlAvailable(ppeer)) return;
203         SwingUtilities.invokeSync(new Runnable JavaDoc() {
204             public void run() {
205                 ppeer.layout();
206                 parent.invalidate();
207             }
208         });
209     }
210     
211     /*
212      * Actually, I want to include these methods to allow for compilation.
213      * No one said that they actually have to do anything. They just have
214      * to be here.
215      */

216     public ToolBarUI getUI() {
217         return null;
218     }
219     
220     public void setUI(ToolBarUI ui) {}
221     
222     /**
223      * Controlled by the native widget. Implemented
224      * solely to allow compilation.
225      *
226      * @param b
227      */

228     public void setBorderPainted(boolean b) {}
229     
230     /**
231      * I have no clue which platforms support
232      * border painting and which don't.
233      *
234      * @return
235      */

236     public boolean isBorderPainted() {
237         return false;
238     }
239     
240     /**
241      * Controlled by the native widget, but to the best
242      * of my knowledge, carbon is the only platform without
243      * rollovers.
244      *
245      * @return
246      */

247     public boolean isRollover() {
248         if (SWT.getPlatform().equals("carbon")) return false;
249         return true;
250     }
251     
252     /**
253      * This is controlled by the native widget and
254      * we can't tamper with it.
255      *
256      * @param b
257      */

258     public void setRollover(boolean b) { }
259     
260     public boolean isFloatable() {
261         return false;
262     }
263     
264     /**
265      * I've dropped these. The toolbar simply can't support it, and
266      * the one-coolbar per shell thing is too inflexible. The Swing-y
267      * way is to use JCoolBar - even though it isn't a real Swing thing.
268      * After all, who uses floatable toolbars????
269      *
270      * Daniel: Actually, I use floatable ToolBars and I need this
271      * functionality. Since we don't want to put it in JToolBar, we
272      * might want to leave the JCoolBar class in place.
273      */

274     public void setFloatable(final boolean b) {
275     }
276     
277     public void addSeparator() {
278         SwingUtilities.invokeSync(new Runnable JavaDoc() {
279             public void run() {
280                 if (!SwingWTUtils.isSWTControlAvailable(ppeer)) {
281                     cache.add(new JSeparator());
282                 }
283                 else {
284                     ToolBar peer;
285                     if (lastAdd instanceof ToolBar)
286                         peer = (ToolBar) lastAdd;
287                     else
288                         peer = new ToolBar(ppeer, orientation);
289                     new ToolItem(peer, SWT.SEPARATOR);
290                     // We added to a toolbar last
291
lastAdd = peer;
292                 }
293             }
294         });
295     }
296     
297     public void setSwingWTParent(swingwt.awt.Container parent) throws Exception JavaDoc {
298         descendantHasPeer = true;
299         
300         this.parent = parent;
301         
302         ppeer = new org.eclipse.swt.widgets.Composite(parent.getComposite(), SWT.NONE);
303         lastAdd = ppeer;
304         peer = ppeer;
305         composite = ppeer;
306
307         RowLayout lay = null;
308         if (orientation == SwingConstants.HORIZONTAL)
309             lay = new RowLayout(SWT.HORIZONTAL);
310         else
311             lay = new RowLayout(SWT.VERTICAL);
312         lay.fill = true;
313         lay.wrap = false;
314         ppeer.setLayout(lay);
315         
316         if (cached) {
317             for (int i = 0; i < cache.size(); i++) {
318                 if (cache.get(i) instanceof Action)
319                     add((Action) cache.get(i));
320                 else if (cache.get(i) instanceof JSeparator)
321                     addSeparator();
322                 else
323                     add((Component) cache.get(i));
324             }
325             cached = false;
326         }
327     }
328     
329     /**
330      * This handy overload will map JButtons to Actions
331      * for you - making your buttons look ace :)
332      */

333     public Component add(JButton b) {
334         
335         // For true Swing behaviour, buttons with mnemonics assigned, but
336
// no text should show no text but still work. This is workable
337
// within SWT, but we need to add the "real" JButton for this
338
// to happen. This bit of logic ensures we always get it right -
339
// you get push buttons for mnemonic/no text and toolitem buttons
340
// for anything else.
341
if (b.pText != null && (b.pText.length() ==2) && b.pText.startsWith("&")) {
342             add((Component) b);
343             return b;
344         }
345         
346         JButtonMappedAction x = new JButtonMappedAction(b);
347         x.putValue(Action.NAME, b.getText());
348         x.putValue(Action.SHORT_DESCRIPTION, b.getToolTipText());
349         x.putValue(Action.SMALL_ICON, b.getIcon());
350         x.putValue(Action.DISABLED_ICON, b.getIcon());
351         x.putValue(Action.MNEMONIC_KEY, new Integer JavaDoc(b.getMnemonic()));
352         b.setAction(x, false); // Don't make the button add the action as a listener, since the button is never created
353
add(x);
354         
355         return b;
356     }
357     
358     /**
359      * map to a SWT.CHECK style ToolItem
360      *
361      * @param checkBox
362      */

363     public Component add(JCheckBox checkBox) {
364         return checkBox;
365     }
366     
367     /**
368      * map to a SWT.RADIO style ToolItem
369      *
370      * @param radioButton
371      */

372     public Component add(JRadioButton radioButton) {
373         return radioButton;
374     }
375     
376     /**
377      * We can add a component through
378      * this method to the JToolBar and have it go side
379      * by side with the ToolItems.
380      * Rob: Added support for separators
381      */

382     public Component add(final Component c) {
383         
384         comps.add(c);
385         
386         if (!SwingWTUtils.isSWTControlAvailable(ppeer)) {
387             cached = true;
388             cache.add(c);
389             return c;
390         }
391         
392         final Container me = this;
393         SwingUtilities.invokeSync(new Runnable JavaDoc() {
394             public void run() {
395                 
396                 // No need to mess about with toolbars here -
397
// we know this component is mapped to a composite,
398
// so just add the damn thing to that.
399

400                 // We could have used the standard container routine
401
// here if we didn't need the cache mechanism.
402

403                 try {
404                     // Assign the component onto the container,
405
// set it's base properties and register all its events
406
c.setSwingWTParent(me);
407                     c.setCachedProperties();
408                     c.registerEvents();
409                 }
410                 catch (Exception JavaDoc e) {
411                     e.printStackTrace();
412                 }
413                 
414                 // This reminds us that we added a component last, and that
415
// a new ToolBar will need to be created for any actions.
416
lastAdd = ppeer;
417             }
418         });
419         
420         return c;
421     }
422     
423     /**
424      * What the heck is this method supposed to return?
425      *
426      * Rob: Create a protected constructor for JButton for this eventuality, and use it to
427      * create a wrapper for the ToolItem.
428      * Rob: 9/1/04 Done it :-)
429      *
430      * Daniel: I made some minor changes to this class and specifically
431      * this method to enable rollovers. Hope you aprove! :-)
432      *
433      * @param a
434      */

435     public JButton add(final Action a) {
436         
437         if (!SwingWTUtils.isSWTControlAvailable(ppeer)) {
438             cached = true;
439             cache.add(a);
440             return null;
441         }
442         
443         SwingUtilities.invokeSync(new Runnable JavaDoc() {
444             public void run() {
445         
446                 ToolBar toolbar; // gotta create a new toolbar for each ToolItem unless there is another one that we can use
447
final ToolItem peer;
448                 
449                 // If the Action was created from a JButton, then we only need to return
450
// that, rather than waste resources creating a new one
451
JButton btnWrapper;
452                 if (a instanceof JButtonMappedAction)
453                     btnWrapper = ((JButtonMappedAction) a).getJButton();
454                 else
455                     // Create a new JButton wrapper for the action
456
btnWrapper = new JButton(a, false);
457                                                     // ^ Since this wrapper will also never be on screen, don't map action events
458
// (see AbstractButton.setAction(Action, bool) for more info)
459

460                 if (lastAdd instanceof ToolBar)
461                     toolbar = (ToolBar) lastAdd; // if there is a previous toolbar, use it!
462
else
463                     toolbar = new ToolBar(ppeer,
464                         ((orientation == SwingConstants.HORIZONTAL ? SWT.HORIZONTAL : SWT.VERTICAL) | SWT.FLAT)); // create a new one if we need to
465

466                 if (a.getValue(Action.DROP_MENU) != null) { // new
467
peer = new ToolItem(toolbar, SWT.DROP_DOWN);
468                 } else {
469                     peer = new ToolItem(toolbar, SWT.PUSH);
470                 }
471                 
472                 // Set it against the JButton wrapper
473
btnWrapper.pSWTToolButton = peer;
474
475                 if (a.getValue(Action.SMALL_ICON) != null)
476                     peer.setHotImage(SwingWTUtils.getSWTImageFromSwingIcon(btnWrapper, ((Icon) a.getValue(Action.SMALL_ICON))));
477                 if (a.getValue(Action.NAME) != null)
478                     peer.setText((String JavaDoc) a.getValue(Action.NAME));
479                 if (a.getValue(Action.SHORT_DESCRIPTION) != null)
480                     peer.setToolTipText((String JavaDoc) a.getValue(Action.SHORT_DESCRIPTION));
481
482                 if (!SWT.getPlatform().equals("carbon")) // OS X tool items don't use grey disabled items
483
if (a.getValue(Action.DISABLED_ICON) != null)
484                             peer.setImage(SwingWTUtils.getSWTImageFromSwingIcon(btnWrapper, ((Icon) a.getValue(Action.DISABLED_ICON))));
485
486                 if (a.getValue(Action.DROP_MENU) != null) {
487                     final JPopupMenu jmenu = (JPopupMenu) a.getValue(Action.DROP_MENU);
488
489                     // we have to create a new pop-up menu with the specified components in the current shell
490
try {
491                         jmenu.setSwingWTParent(ppeer.getShell());
492                         
493                         // Rob: Add components to popup and map their events here?
494

495                     } catch (Exception JavaDoc e) {
496                         e.printStackTrace();
497                     }
498
499                     // this is how to display a pop-up menu (sort of)
500
peer.addListener(SWT.Selection, new Listener() {
501                         public void handleEvent(org.eclipse.swt.widgets.Event e) {
502                             if (e.detail == SWT.ARROW) {
503                                 Menu menu = jmenu.menu;
504                                 org.eclipse.swt.graphics.Rectangle rect = peer.getBounds();
505                                 org.eclipse.swt.graphics.Point pt = new org.eclipse.swt.graphics.Point(rect.x, rect.y + rect.height);
506                                 pt = ppeer.toDisplay(pt);
507                                 menu.setLocation(pt);
508                                 menu.setVisible(true);
509                             }
510                         }
511                     });
512                 }
513                 
514                 final JButton btnWrapper2 = btnWrapper;
515                 peer.addSelectionListener(new SelectionAdapter() {
516                     public void widgetSelected(SelectionEvent e) {
517                         a.actionPerformed(new ActionEvent(btnWrapper2, 0));
518                     }
519                 });
520
521                 threadSafeObjectRetValue = btnWrapper;
522                 
523                 lastAdd = toolbar;
524             }
525         });
526         
527         return (JButton) threadSafeObjectRetValue;
528     }
529     
530     /**
531      * Temparary storage for the ToolBarUI class.
532      * THIS ISN'T PERMANENT!
533      *
534      * @author Daniel Spiewak
535      */

536     public class ToolBarUI {
537         
538     }
539 }
540
541
Popular Tags