KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openide > awt > ToolbarPool


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.openide.awt;
21
22
23 import java.awt.*;
24 import java.awt.event.*;
25 import java.util.*;
26 import javax.accessibility.*;
27 import javax.swing.*;
28 import javax.swing.JComponent.AccessibleJComponent;
29 import javax.swing.border.Border JavaDoc;
30 import org.openide.cookies.InstanceCookie;
31 import org.openide.filesystems.*;
32 import org.openide.loaders.*;
33 import org.openide.util.*;
34
35 /**
36  * This class keeps track of the current toolbars and their names.
37  * @author David Peroutka, Libor Kramolis
38  */

39 public final class ToolbarPool extends JComponent implements Accessible {
40     /** Default ToolbarPool */
41     private static ToolbarPool defaultPool;
42
43     /** objects responsible for creation of the window */
44     private Folder instance;
45
46     /** DataFolder from which the pool was created */
47     private DataFolder folder;
48
49     /** Maps name to <code>Toolbar</code>s */
50     private Map<String JavaDoc, Toolbar> toolbars;
51     /** Maps name to <code>ToolbarPool.Configuration</code>s */
52     private Map<String JavaDoc, ToolbarPool.Configuration> toolbarConfigs;
53
54     /** Current name of selected configuration */
55     private String JavaDoc name = ""; // NOI18N
56

57     /** Center component */
58     private Component center;
59
60     /** Popup menu listener */
61     private PopupListener listener;
62
63     /** Accessible context */
64     private AccessibleContext toolbarAccessibleContext;
65
66     /** Name of default toolbar configuration. */
67     public static final String JavaDoc DEFAULT_CONFIGURATION = "Standard"; // NOI18N
68

69     private TPTaskListener taskListener;
70     
71     /** Preferred icon size. 2 sizes are supported now: 16 and 24. */
72     private int preferredIconSize = 24;
73     
74     /**
75      * Returns default toolbar pool.
76      * @return default system pool
77      */

78     public static synchronized ToolbarPool getDefault () {
79         if (defaultPool == null) {
80             FileObject fo = Repository.getDefault().getDefaultFileSystem().findResource("Toolbars"); // NOI18N
81
if (fo == null) throw new IllegalStateException JavaDoc("No Toolbars/"); // NOI18N
82
DataFolder folder = DataFolder.findFolder(fo);
83             defaultPool = new ToolbarPool(folder);
84             // we mustn't do this in constructor to prevent from
85
// nevereding recursive calls to this method.
86
defaultPool.instance.recreate();
87         }
88         return defaultPool;
89     }
90
91     static final long serialVersionUID =3420915387298484008L;
92
93
94     /**
95      * Creates a new <code>ToolbarPool</code>. Useful for modules that need they
96      * own toolbars.
97      *
98      * @param df the data folder to read toolbar definitions and configurations from
99      * @since 1.5
100      */

101     public ToolbarPool (DataFolder df) {
102         folder = df;
103
104         setLayout (new BorderLayout ());
105         listener = new PopupListener();
106         toolbars = new TreeMap<String JavaDoc, Toolbar>();
107         toolbarConfigs = new TreeMap<String JavaDoc, ToolbarPool.Configuration>();
108
109         instance = new Folder (df);
110
111         getAccessibleContext().setAccessibleName(instance.instanceName());
112         getAccessibleContext().setAccessibleDescription(instance.instanceName());
113
114         if ("Windows".equals(UIManager.getLookAndFeel().getID())) {
115             if( isXPTheme() ) {
116                 //Set up custom borders for XP
117
setBorder(BorderFactory.createCompoundBorder(
118                     upperBorder,
119                     BorderFactory.createCompoundBorder(
120                         BorderFactory.createMatteBorder(0, 0, 1, 0,
121                         fetchColor("controlShadow", Color.DARK_GRAY)),
122                         BorderFactory.createMatteBorder(0, 0, 1, 0, mid))
123                 )); //NOI18N
124
} else {
125                 setBorder( BorderFactory.createEtchedBorder() );
126             }
127         } else if ("GTK".equals(UIManager.getLookAndFeel().getID())) {
128             //No border
129
setBorder (BorderFactory.createEmptyBorder(0, 0, 0, 0));
130         }
131     }
132     
133     /**
134      * Gets preferred size of icons used by toolbar buttons. Default icon size
135      * is 24x24. Icon size 16x16 is also supported.
136      * @return preferred size of toolbar icons in pixels
137      * @since 4.15
138      */

139     public int getPreferredIconSize () {
140         return preferredIconSize;
141     }
142     
143     /**
144      * Sets preferred size of icons used by toolbar buttons.
145      * @param preferredIconSize size of toolbar icons in pixels; currently one of 16 or 24
146      * @throws IllegalArgumentException if an unsupported size is given
147      * @since 4.15
148      */

149     public void setPreferredIconSize (int preferredIconSize) throws IllegalArgumentException JavaDoc {
150         if ((preferredIconSize != 16) && (preferredIconSize != 24)) {
151             throw new IllegalArgumentException JavaDoc("Unsupported argument value:" + preferredIconSize); //NOI18N
152
}
153         this.preferredIconSize = preferredIconSize;
154     }
155
156     public Border JavaDoc getBorder() {
157         //Issue 36867, hide border if there are no toolbars. Not the most
158
//performant way to do it; if it has a measurable impact, can be
159
//improved
160
if (center != null && center instanceof Container &&
161            ((Container)center).getComponentCount() > 0) {
162                
163             boolean show = false;
164             for (int i=0; i < ((Container)center).getComponentCount(); i++) {
165                 Component c = ((Container)center).getComponent(i);
166                 if (c.isVisible()) {
167                     show = true;
168                     break;
169                 }
170             }
171             if (show) {
172                 return super.getBorder();
173             }
174         }
175         return lowerBorder;
176     }
177
178     private static Color fetchColor (String JavaDoc key, Color fallback) {
179         //Fix ExceptionInInitializerError from MainWindow on GTK L&F - use
180
//fallback colors
181
Color result = (Color) UIManager.get(key);
182         if (result == null) {
183             result = fallback;
184         }
185         return result;
186     }
187     
188     private static Color mid;
189     static {
190         Color lo = fetchColor("controlShadow", Color.DARK_GRAY); //NOI18N
191
Color hi = fetchColor("control", Color.GRAY); //NOI18N
192

193         int r = (lo.getRed() + hi.getRed()) / 2;
194         int g = (lo.getGreen() + hi.getGreen()) / 2;
195         int b = (lo.getBlue() + hi.getBlue()) / 2;
196         mid = new Color(r, g, b);
197     }
198     
199     private static final Border JavaDoc lowerBorder = BorderFactory.createCompoundBorder(
200         BorderFactory.createMatteBorder(0, 0, 1, 0,
201         fetchColor("controlShadow", Color.DARK_GRAY)),
202         BorderFactory.createMatteBorder(0, 0, 1, 0, mid)); //NOI18N
203

204     private static final Border JavaDoc upperBorder = BorderFactory.createCompoundBorder(
205         BorderFactory.createMatteBorder(1, 0, 0, 0,
206         fetchColor("controlShadow", Color.DARK_GRAY)),
207         BorderFactory.createMatteBorder(1, 0, 0, 0,
208         fetchColor("controlLtHighlight", Color.WHITE))); //NOI18N
209

210     
211     /** Allows to wait till the content of the pool is initialized. */
212     public final void waitFinished () {
213         instance.instanceFinished ();
214     }
215
216     /** Initialization of new values.
217      * @param toolbars map (String, Toolbar) of toolbars
218      * @param conf map (String, Configuration) of configs
219      */

220     void update (Map<String JavaDoc, Toolbar> toolbars, Map<String JavaDoc, ToolbarPool.Configuration> conf) {
221         this.toolbars = toolbars;
222         this.toolbarConfigs = conf;
223
224         if (!"".equals(name)) {
225             setConfiguration (name);
226         }
227     }
228
229     /** Updates the default configuration. */
230     private synchronized void updateDefault () {
231         Toolbar[] toolbars = getToolbars ();
232         name = ""; // NOI18N
233

234         if (toolbars.length == 1) {
235             revalidate(toolbars[0]);
236         } else {
237             JPanel tp = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
238             for (int i = 0; i < toolbars.length; i++) {
239                 tp.add(toolbars[i]);
240             }
241             revalidate(tp);
242         }
243     }
244
245     /** Activates a configuration.
246      * @param c configuration
247      */

248     private synchronized void activate (Configuration c) {
249         Component comp = c.activate ();
250         name = c.getName();
251         revalidate (comp);
252     }
253
254     /** Sets DnDListener to all Toolbars. */
255     public void setToolbarsListener (Toolbar.DnDListener l) {
256         for (Toolbar t: toolbars.values()) {
257             t.setDnDListener (l);
258         }
259     }
260
261     /** Uses new component as a cental one. */
262     private void revalidate (Component c) {
263         if (c != center) {
264             // exchange
265
if (center != null) {
266                 remove (center);
267                 center.removeMouseListener (listener);
268             }
269             add (center = c, BorderLayout.CENTER);
270             center.addMouseListener (listener);
271
272 // java.awt.Window w = javax.swing.SwingUtilities.windowForComponent (this);
273
// if (w != null) {
274
// w.validate();
275
// }
276
}
277     }
278
279     /**
280      * Returns a <code>Toolbar</code> to which this pool maps the given name.
281      * @param name a <code>String</code> that is to be a toolbar's name
282      * @return a <code>Toolbar</code> to which this pool maps the name
283      */

284     public final Toolbar findToolbar (String JavaDoc name) {
285         return toolbars.get (name);
286     }
287
288     /**
289      * Getter for the name of current configuration.
290      * @return the name of current configuration
291      */

292     public final String JavaDoc getConfiguration () {
293         return name;
294     }
295
296     /**
297      * Switch to toolbar configuration by specific config name
298      * @param n toolbar configuration name
299      */

300     public final void setConfiguration (String JavaDoc n) {
301         String JavaDoc old = name;
302         
303         // should be 'instance.waitFinished();' but some bug in isFinished ...
304
if (!instance.isFinished()) {
305             if (taskListener == null) {
306                 taskListener = new TPTaskListener();
307                 instance.addTaskListener(taskListener);
308             }
309             taskListener.setConfiguration(n);
310             return;
311         }
312         if (taskListener != null) {
313             instance.removeTaskListener(taskListener);
314             taskListener = null;
315         }
316
317         Configuration config = null;
318         if (n != null) {
319             config = toolbarConfigs.get (n);
320         }
321         if (config != null) { // if configuration found
322
activate (config);
323         } else if (toolbarConfigs.isEmpty()) { // if no toolbar configuration
324
updateDefault ();
325         } else {
326             // line below commented - bugfix, we need default configuration always when unknown config name is used:
327
// if (center == null) { // bad config name (n) and no configuration activated yet
328
config = toolbarConfigs.get (DEFAULT_CONFIGURATION);
329             if (config == null) {
330                 config = toolbarConfigs.values().iterator().next();
331             }
332             activate (config);
333         }
334         
335         firePropertyChange("configuration", old, name);
336     }
337
338     /**
339      * @return the <code>DataFolder</code> from which the pool was created.
340      */

341     public final DataFolder getFolder() {
342         return folder;
343     }
344
345     /**
346      * Returns the toolbars contained in this pool.
347      * @return the toolbars contained in this pool
348      */

349     public final synchronized Toolbar[] getToolbars() {
350         Toolbar[] arr = new Toolbar[toolbars.size ()];
351         return toolbars.values ().toArray (arr);
352     }
353
354     /**
355      * @return the names of toolbar configurations contained in this pool
356      */

357     public final synchronized String JavaDoc[] getConfigurations () {
358         ArrayList<String JavaDoc> list = new ArrayList<String JavaDoc>( toolbarConfigs.keySet() );
359         Collections.sort( list );
360         String JavaDoc[] arr = new String JavaDoc[ list.size() ];
361         return list.toArray( arr );
362     }
363
364         /** Read accessible context
365      * @return - accessible context
366      */

367     public AccessibleContext getAccessibleContext () {
368         if(toolbarAccessibleContext == null) {
369             toolbarAccessibleContext = new AccessibleJComponent() {
370                 public AccessibleRole getAccessibleRole() {
371                     return AccessibleRole.TOOL_BAR;
372                 }
373             };
374         }
375         return toolbarAccessibleContext;
376     }
377
378     /** Recognizes if XP theme is set.
379      * (copy & paste from org.openide.awt.Toolbar to avoid API changes)
380      * @return true if XP theme is set, false otherwise
381      */

382     private static Boolean JavaDoc isXP = null;
383     private static boolean isXPTheme () {
384         if (isXP == null) {
385             Boolean JavaDoc xp = (Boolean JavaDoc)Toolkit.getDefaultToolkit().
386             getDesktopProperty("win.xpstyle.themeActive"); //NOI18N
387
isXP = Boolean.TRUE.equals(xp)? Boolean.TRUE : Boolean.FALSE;
388         }
389         return isXP.booleanValue();
390     }
391     
392     /**
393      * @return True if the Toolbar Customizer is visible and toolbar buttons can be dragged.
394      */

395     boolean isInEditMode() {
396         return null != getClientProperty( "editMode" );
397     }
398
399     /**
400      * This class is used for delayed setting of configuration after instance
401      * creation is finished. It may happen during IDE start that
402      * ToolbarPool.setConfiguration is called before instance is created.
403      */

404     private class TPTaskListener implements TaskListener {
405         private String JavaDoc conf;
406         
407         TPTaskListener() {}
408         
409         public void taskFinished(Task task) {
410             ToolbarPool.this.setConfiguration(conf);
411             conf = null;
412         }
413         
414         void setConfiguration(String JavaDoc conf) {
415             // #23619: Don't reset already pending configuration to be set.
416
if(this.conf == null) {
417                 this.conf = conf;
418             }
419         }
420     }
421
422     /**
423      * This class can be used to produce a <code>ToolbarPool</code> instance
424      * from the given <code>DataFolder</code>.
425      */

426     private class Folder extends FolderInstance {
427         private WeakHashMap<DataFolder, InstanceCookie> foldersCache =
428                 new WeakHashMap<DataFolder, InstanceCookie> (15);
429
430         public Folder (DataFolder f) {
431             super (f);
432         }
433
434         /**
435          * Full name of the data folder's primary file separated by dots.
436          * @return the name
437          */

438         public String JavaDoc instanceName () {
439             return instanceClass().getName();
440         }
441
442         /**
443          * Returns the root class of all objects.
444          * @return Object.class
445          */

446         public Class JavaDoc instanceClass () {
447             return ToolbarPool.class;
448         }
449
450         /**
451          * Accepts only cookies that can provide <code>Configuration</code>.
452          * @param cookie the instance cookie to test
453          * @return true if the cookie can provide <code>Configuration</code>
454          */

455         protected InstanceCookie acceptCookie (InstanceCookie cookie)
456         throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
457             Class JavaDoc cls = cookie.instanceClass();
458             if (ToolbarPool.Configuration.class.isAssignableFrom (cls)) {
459                 return cookie;
460             }
461             if (Component.class.isAssignableFrom (cls)) {
462                 return cookie;
463             }
464             return null;
465         }
466
467         /**
468          * Returns a <code>Toolbar.Folder</code> cookie for the specified
469          * <code>DataFolder</code>.
470          * @param df a <code>DataFolder</code> to create the cookie for
471          * @return a <code>Toolbar.Folder</code> for the specified folder
472          */

473         protected InstanceCookie acceptFolder (DataFolder df) {
474             InstanceCookie ic = foldersCache.get (df);
475             if (ic == null) {
476                 ic = (FolderInstance)new Toolbar (df, true).waitFinished ();
477                 foldersCache.put (df, ic);
478             }
479             return ic;
480         }
481
482         /**
483          * Updates the <code>ToolbarPool</code> represented by this folder.
484          *
485          * @param cookies array of instance cookies for the folder
486          * @return the updated <code>ToolbarPool</code> representee
487          */

488         protected Object JavaDoc createInstance (InstanceCookie[] cookies)
489         throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
490             final int length = cookies.length;
491
492             final Map<String JavaDoc, Toolbar> toolbars = new TreeMap<String JavaDoc, Toolbar> ();
493             final Map<String JavaDoc, Configuration> conf = new TreeMap<String JavaDoc, Configuration> ();
494
495             for (int i = 0; i < length; i++) {
496                 try {
497                     java.lang.Object JavaDoc obj = cookies[i].instanceCreate();
498
499                     if (obj instanceof org.openide.awt.Toolbar) {
500                         org.openide.awt.Toolbar toolbar = (org.openide.awt.Toolbar) obj;
501
502                         // should be done by ToolbarPanel in add method
503
toolbar.removeMouseListener(listener);
504                         toolbar.addMouseListener(listener);
505                         toolbars.put(toolbar.getName(), toolbar);
506                         continue;
507                     }
508                     if (obj instanceof org.openide.awt.ToolbarPool.Configuration) {
509                         org.openide.awt.ToolbarPool.Configuration config = (org.openide.awt.ToolbarPool.Configuration) obj;
510                         java.lang.String JavaDoc name = config.getName();
511
512                         if (name == null) {
513                             name = cookies[i].instanceName();
514                         }
515                         conf.put(name, config);
516                         continue;
517                     }
518                     if (obj instanceof java.awt.Component JavaDoc) {
519                         java.awt.Component JavaDoc comp = (java.awt.Component JavaDoc) obj;
520                         java.lang.String JavaDoc name = comp.getName();
521
522                         if (name == null) {
523                             name = cookies[i].instanceName();
524                         }
525                         conf.put(name,
526                                  new org.openide.awt.ToolbarPool.ComponentConfiguration(comp));
527                         continue;
528                     }
529                 }
530                 catch (java.io.IOException JavaDoc ex) {
531                     Exceptions.printStackTrace(ex);
532                 }
533                 catch (java.lang.ClassNotFoundException JavaDoc ex) {
534                     Exceptions.printStackTrace(ex);
535                 }
536             }
537             update (toolbars, conf);
538
539             return ToolbarPool.this;
540         }
541
542         /** Recreate the instance in AWT thread.
543         */

544         protected Task postCreationTask (Runnable JavaDoc run) {
545             return new AWTTask (run);
546         }
547
548     } // end of Folder
549

550
551     /**
552      * Class to showing popup menu
553      */

554     private class PopupListener extends MouseUtils.PopupMouseAdapter {
555     PopupListener() {}
556         /**
557          * Called when the sequence of mouse events should lead to actual showing popup menu
558          */

559         protected void showPopup (MouseEvent e) {
560             Configuration conf = toolbarConfigs.get (name);
561             if (conf != null) {
562                 JPopupMenu pop = conf.getContextMenu();
563                 pop.show (e.getComponent (), e.getX (), e.getY ());
564             }
565         }
566     } // end of PopupListener
567

568
569     /**
570      * Abstract class for toolbar configuration
571      */

572     public static interface Configuration {
573         /** Activates the configuration and returns right
574         * component that can display the configuration.
575         * @return representation component
576         */

577         public abstract Component activate ();
578
579         /** Name of the configuration.
580         * @return the name
581         */

582         public abstract String JavaDoc getName ();
583
584         /** Popup menu that should be displayed when the users presses
585         * right mouse button on the panel. This menu can contain
586         * contains list of possible configurations, additional actions, etc.
587         *
588         * @return popup menu to be displayed
589         */

590         public abstract JPopupMenu getContextMenu ();
591     }
592
593
594     /** Implementation of configuration that reacts to one
595     * component */

596     private static final class ComponentConfiguration extends JPopupMenu
597         implements Configuration, ActionListener {
598         private Component comp;
599
600     ComponentConfiguration() {}
601
602         static final long serialVersionUID =-409474484612485719L;
603         /** @param comp component that represents this configuration */
604         public ComponentConfiguration (Component comp) {
605             this.comp = comp;
606         }
607
608         /** Simply returns the representation component */
609         public Component activate () {
610             return comp;
611         }
612
613         /** @return name of the component
614         */

615         public String JavaDoc getName () {
616             return comp.getName ();
617         }
618
619         /** Updates items in popup menu and returns itself.
620         */

621         public JPopupMenu getContextMenu () {
622             removeAll ();
623
624             // generate list of available toolbar panels
625
Iterator it = Arrays.asList (ToolbarPool.getDefault ().getConfigurations ()).iterator ();
626             ButtonGroup bg = new ButtonGroup ();
627             String JavaDoc current = ToolbarPool.getDefault ().getConfiguration ();
628             while (it.hasNext()) {
629                 final String JavaDoc name = (String JavaDoc)it.next ();
630                 JRadioButtonMenuItem mi = new JRadioButtonMenuItem (name, (name.compareTo (current) == 0));
631                 mi.addActionListener (this);
632                 bg.add (mi);
633                 this.add (mi);
634             }
635
636             return this;
637         }
638
639         /** Reacts to action in popup menu. Switches the configuration.
640         */

641         public void actionPerformed (ActionEvent evt) {
642             ToolbarPool.getDefault().setConfiguration (evt.getActionCommand ());
643         }
644
645     }
646
647 } // end of ToolbarPool
648

649
Popular Tags