KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > windows > view > ui > toolbars > ToolbarConfiguration


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.netbeans.core.windows.view.ui.toolbars;
21
22 import java.util.logging.Logger JavaDoc;
23 import org.netbeans.core.NbPlaces;
24 import org.openide.awt.JPopupMenuPlus;
25 import org.openide.awt.Toolbar;
26 import org.openide.awt.ToolbarPool;
27 import org.openide.filesystems.FileLock;
28 import org.openide.filesystems.FileObject;
29 import org.openide.filesystems.FileSystem;
30 import org.openide.loaders.XMLDataObject;
31 import org.openide.util.NbBundle;
32 import org.openide.util.Utilities;
33 import org.xml.sax.*;
34
35 import javax.swing.*;
36 import java.awt.*;
37 import java.awt.event.ActionEvent JavaDoc;
38 import java.awt.event.ActionListener JavaDoc;
39 import java.beans.PropertyChangeEvent JavaDoc;
40 import java.beans.PropertyChangeListener JavaDoc;
41 import java.beans.PropertyChangeSupport JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.io.InputStream JavaDoc;
44 import java.io.OutputStream JavaDoc;
45 import java.io.OutputStreamWriter JavaDoc;
46 import java.io.Writer JavaDoc;
47 import java.util.*;
48 import java.util.logging.Level JavaDoc;
49 import org.netbeans.core.IDESettings;
50 /** Toolbar configuration.
51  * It can load configuration from DOM Document, store configuration int XML file.
52  * Toolbar configuration contains list of all correct toolbars (toolbars which are
53  * represented int ToolbarPool too), waiting toolbars (toolbars which was described
54  * [it's position, visibility] but there is representation int ToolbarPool).
55  * There is list of rows (ToolbarRow) and map of invisible toolbars.
56  *
57  * @author Libor Kramolis
58  */

59 public final class ToolbarConfiguration extends Object JavaDoc
60 implements ToolbarPool.Configuration, PropertyChangeListener JavaDoc {
61     /** location outside the IDE */
62     protected static final String JavaDoc TOOLBAR_DTD_WEB =
63         "http://www.netbeans.org/dtds/toolbar.dtd"; // NOI18N
64
/** toolbar dtd public id */
65     protected static final String JavaDoc TOOLBAR_DTD_PUBLIC_ID =
66         "-//NetBeans IDE//DTD toolbar//EN"; // NOI18N
67
/** toolbar prcessor class */
68     protected static final Class JavaDoc TOOLBAR_PROCESSOR_CLASS = ToolbarProcessor.class;
69     /** toolbar icon base */
70     protected static final String JavaDoc TOOLBAR_ICON_BASE =
71         "/org/netbeans/core/windows/toolbars/xmlToolbars"; // NOI18N
72

73     /** error manager */
74     private static Logger JavaDoc ERR = Logger.getLogger("org.netbeans.core.windows.toolbars"); // NOI18N
75

76     /** last time the document has been reloaded */
77     private volatile long lastReload;
78     
79     /** xml extension */
80     protected static final String JavaDoc EXT_XML = "xml"; // NOI18N
81
// /** xmlinfo extension */
82
// protected static final String EXT_XMLINFO = "xmlinfo"; // NOI18N
83

84     /** xml element for configuration (root element) */
85     protected static final String JavaDoc TAG_CONFIG = "Configuration"; // NOI18N
86
/** xml element for row */
87     protected static final String JavaDoc TAG_ROW = "Row"; // NOI18N
88
/** xml element for toolbar */
89     protected static final String JavaDoc TAG_TOOLBAR = "Toolbar"; // NOI18N
90
/** xml attribute for toolbar name */
91     protected static final String JavaDoc ATT_TOOLBAR_NAME = "name"; // NOI18N
92
/** xml attribute for toolbar position */
93     protected static final String JavaDoc ATT_TOOLBAR_POSITION = "position"; // NOI18N
94
/** xml attribute for toolbar visible */
95     protected static final String JavaDoc ATT_TOOLBAR_VISIBLE = "visible"; // NOI18N
96

97     /** standard panel for all configurations */
98     private static JPanel toolbarPanel;
99     /** mapping from configuration instances to their names */
100     private static WeakHashMap<ToolbarConfiguration, String JavaDoc> confs2Names =
101             new WeakHashMap<ToolbarConfiguration, String JavaDoc>(10);
102     
103     /** toolbar layout manager for this configuration */
104     private ToolbarLayout toolbarLayout;
105     /** toolbar drag and drop listener */
106     private ToolbarDnDListener toolbarListener;
107
108     /** All toolbars which are represented in ToolbarPool too. */
109     private WeakHashMap<String JavaDoc, ToolbarConstraints> allToolbars;
110     /** List of visible toolbar rows. */
111     private Vector<ToolbarRow> toolbarRows;
112     /** All invisible toolbars (visibility==false || tb.isCorrect==false). */
113     private HashMap<ToolbarConstraints,Integer JavaDoc> invisibleToolbars;
114     
115     /** Toolbar menu is global so it is static. It it the same for all toolbar
116      configurations. */

117     private static JMenu toolbarMenu;
118     
119     /** Toolbars which was described in DOM Document,
120     but which aren't represented in ToolbarPool.
121     For exapmle ComponentPalette and first start of IDE. */

122     private WeakHashMap<String JavaDoc, ToolbarConstraints> waitingToolbars;
123     /** Name of configuration. */
124     private String JavaDoc configName;
125     /** Display name of configuration. */
126     private String JavaDoc configDisplayName;
127     /** Cached preferred width. */
128     private int prefWidth;
129     /** variable to signal that we are just writing the content of configuration
130      * and we should ignore all changes. In such case set to Boolean.TRUE
131      */

132     private final ThreadLocal JavaDoc<Boolean JavaDoc> WRITE_IN_PROGRESS = new ThreadLocal JavaDoc<Boolean JavaDoc> ();
133
134    // private static final ResourceBundle bundle = NbBundle.getBundle (ToolbarConfiguration.class);
135

136     /** Creates new empty toolbar configuration for specific name.
137      * @param name new configuration name
138      */

139     public ToolbarConfiguration (String JavaDoc name, String JavaDoc displayName) {
140         configName = name;
141         configDisplayName = displayName;
142         // fix #44537 - just doing the simple thing of hacking the extension out of the display name.. node.getDisplayName is too unpredictable.
143
if (configDisplayName.endsWith(".xml")) {
144             configDisplayName = configDisplayName.substring(0, configDisplayName.length() - ".xml".length());
145         }
146         initInstance ();
147         // asociate name and configuration instance
148
confs2Names.put(this, name);
149     }
150
151     /** Creates new toolbar configuration for specific name and from specific XMLDataObject
152      * @param name new configuration name
153      * @param xml XMLDataObject representing a toolbar configuration
154      */

155     public ToolbarConfiguration(XMLDataObject xml) throws IOException JavaDoc {
156         this(xml.getNodeDelegate().getName(), xml.getNodeDelegate().getDisplayName());
157         readConfig(xml);
158     }
159
160     private void readConfig(XMLDataObject xml) throws IOException JavaDoc {
161         Parser parser = xml.createParser();
162         
163
164         ToolbarParser handler = new ToolbarParser();
165         parser.setEntityResolver(handler);
166         parser.setDocumentHandler(handler);
167      
168         InputStream JavaDoc is = null;
169         try {
170             is = xml.getPrimaryFile().getInputStream();
171             parser.parse(new InputSource(is));
172         } catch (Exception JavaDoc saxe) {
173             throw (IOException JavaDoc) new IOException JavaDoc(saxe.toString()).initCause(saxe);
174         } finally {
175             try {
176                 if (is != null) {
177                     is.close();
178                 }
179             } catch (IOException JavaDoc exc) {
180                 Logger.getLogger(ToolbarConfiguration.class.getName()).log(Level.WARNING, null, exc);
181             }
182         }
183         checkToolbarRows();
184     }
185     
186     private class ToolbarParser extends HandlerBase implements EntityResolver {
187         private ToolbarRow currentRow = null;
188         private int toolbarIndex = 0;
189         
190         public void startElement(String JavaDoc name, AttributeList amap) throws SAXException {
191             if (TAG_ROW.equals(name)) {
192                 toolbarIndex = 0;
193                 currentRow = new ToolbarRow(ToolbarConfiguration.this);
194                 addRow(currentRow);
195             }
196             else if (currentRow != null && TAG_TOOLBAR.equals(name)) {
197                 String JavaDoc tbname = amap.getValue(ATT_TOOLBAR_NAME);
198                 if (tbname == null || tbname.equals("")) // NOI18N
199
return;
200                 
201                 String JavaDoc posStr = amap.getValue(ATT_TOOLBAR_POSITION);
202                 Integer JavaDoc pos = null;
203                 if (posStr != null)
204                     pos = new Integer JavaDoc(posStr);
205                 
206                 String JavaDoc visStr = amap.getValue(ATT_TOOLBAR_VISIBLE);
207                 Boolean JavaDoc vis;
208                 if (visStr != null)
209                     vis = Boolean.valueOf(visStr);
210                 else
211                     vis = Boolean.TRUE;
212                 
213                 addToolbar(currentRow, checkToolbarConstraints (tbname, pos, vis, toolbarIndex++));
214             }
215         }
216         
217         public void endElement(String JavaDoc name) throws SAXException {
218             if (TAG_ROW.equals(name)) {
219                 currentRow = null;
220             }
221         }
222         
223         public InputSource resolveEntity(String JavaDoc pubid, String JavaDoc sysid) {
224             return new InputSource(new java.io.ByteArrayInputStream JavaDoc(new byte[0]));
225         }
226     };
227     /** Clean all the configuration parameters.
228      */

229     private void initInstance () {
230         allToolbars = new WeakHashMap<String JavaDoc, ToolbarConstraints>();
231         waitingToolbars = new WeakHashMap<String JavaDoc, ToolbarConstraints>();
232         toolbarRows = new Vector<ToolbarRow>();
233         invisibleToolbars = new HashMap<ToolbarConstraints, Integer JavaDoc>();
234         toolbarListener = new ToolbarDnDListener (this);
235     }
236     
237     /** @return returns string from bundle for given string pattern */
238     static final String JavaDoc getBundleString (String JavaDoc bundleStr) {
239         return NbBundle.getMessage(ToolbarConfiguration.class, bundleStr);
240     }
241     
242     /** Finds toolbar configuration which has given name.
243      * @return toolbar configuration instance which ID is given name or null
244      * if no such configuration can be found */

245     public static final ToolbarConfiguration findConfiguration (String JavaDoc name) {
246         Map.Entry curEntry = null;
247         for (Iterator iter = confs2Names.entrySet().iterator(); iter.hasNext(); ) {
248             curEntry = (Map.Entry)iter.next();
249             if (name.equals((String JavaDoc)curEntry.getValue())) {
250                 return (ToolbarConfiguration)curEntry.getKey();
251             }
252         }
253         // no luck
254
return null;
255     }
256
257     /** Add toolbar to list of all toolbars.
258      * If specified toolbar constraints represents visible component
259      * it is added to specified toolbar row.
260      * Othewise toolbar constraints is added to invisible toolbars.
261      *
262      * @param row toolbar row of new toolbar is part
263      * @param tc added toolbar represented by ToolbarConstraints
264      */

265     void addToolbar (ToolbarRow row, ToolbarConstraints tc) {
266         if (tc == null)
267             return;
268
269         if (tc.isVisible())
270             row.addToolbar (tc);
271         else {
272             int rI;
273             if (row == null)
274                 rI = toolbarRows.size();
275             else
276                 rI = toolbarRows.indexOf (row);
277             invisibleToolbars.put (tc, Integer.valueOf(rI));
278         }
279         allToolbars.put (tc.getName(), tc);
280     }
281
282     /** Remove toolbar from list of all toolbars.
283      * This could mean that toolbar is represented only in DOM document.
284      *
285      * @param name name of removed toolbar
286      */

287     ToolbarConstraints removeToolbar (String JavaDoc name) {
288         ToolbarConstraints tc = allToolbars.remove (name);
289         if (tc.destroy())
290             checkToolbarRows();
291         return tc;
292     }
293
294     /** Add toolbar row as last row.
295      * @param row added toolbar row
296      */

297     void addRow (ToolbarRow row) {
298         addRow (row, toolbarRows.size());
299     }
300
301     /** Add toolbar row to specific index.
302      * @param row added toolbar row
303      * @param index specified index of toolbar position
304      */

305     void addRow (ToolbarRow row, int index) {
306     /* It is important to recompute row neighbournhood. */
307         ToolbarRow prev = null;
308         ToolbarRow next = null;
309         int rowCount = toolbarRows.size();
310         if( index > 0 && index <= rowCount )
311             prev = toolbarRows.elementAt( index - 1 );
312         if( index >= 0 && index < rowCount )
313             next = toolbarRows.elementAt (index);
314
315         if (prev != null)
316             prev.setNextRow (row);
317         row.setPrevRow (prev);
318         row.setNextRow (next);
319         if (next != null)
320             next.setPrevRow (row);
321
322         toolbarRows.insertElementAt (row, index);
323         updateBounds (row);
324     }
325
326     /** Remove toolbar row from list of all rows.
327      * @param row removed toolbar row
328      */

329     void removeRow (ToolbarRow row) {
330     /* It is important to recompute row neighbournhood. */
331         ToolbarRow prev = row.getPrevRow();
332         ToolbarRow next = row.getNextRow();
333         if (prev != null) {
334             prev.setNextRow (next);
335         }
336         if (next != null) {
337             next.setPrevRow (prev);
338         }
339
340         toolbarRows.removeElement (row);
341         updateBounds (next);
342         revalidateWindow();
343     }
344
345     /** Update toolbar row cached bounds.
346      * @param row updated row
347      */

348     void updateBounds (ToolbarRow row) {
349         while (row != null) {
350             row.updateBounds();
351             row = row.getNextRow();
352         }
353     }
354     
355     private static final ToolbarPool toolbarPool () {
356         return ToolbarPool.getDefault ();
357     }
358
359     /** Revalidates toolbar pool window.
360      * It is important for change height when number of rows is changed.
361      */

362     void revalidateWindow () {
363         // PENDING
364
toolbarPanel().revalidate();
365         // #15930. Always replane even we are in AWT thread already.
366
// SwingUtilities.invokeLater(new Runnable () {
367
// public void run () {
368
// doRevalidateWindow();
369
// }
370
// });
371
}
372     
373 // /** Performs revalidating work */
374
// private void doRevalidateWindow () {
375
// toolbarPanel().revalidate();
376
// java.awt.Window w = SwingUtilities.windowForComponent (toolbarPool ());
377
// if (w != null) {
378
// w.validate ();
379
// }
380
// } // PENDING
381

382     /**
383      * @param row specified toolbar row
384      * @return index of toolbar row
385      */

386     int rowIndex (ToolbarRow row) {
387         return toolbarRows.indexOf (row);
388     }
389
390     /** Updates cached preferred width of toolbar configuration.
391      */

392     void updatePrefWidth () {
393         prefWidth = 0;
394         for (ToolbarRow tr: toolbarRows) {
395             prefWidth = Math.max (prefWidth, tr.getPrefWidth());
396         }
397     }
398
399     /**
400      * @return configuration preferred width
401      */

402     int getPrefWidth () {
403         return prefWidth;
404     }
405
406     /**
407      * @return configuration preferred height, sum of preferred heights of rows.
408      * If there is no row, preferred height is 0.
409      */

410     int getPrefHeight () {
411         if (getRowCount() == 0) return 0;
412         ToolbarRow lastRow = (ToolbarRow)toolbarRows.lastElement();
413         return getRowVertLocation(lastRow) + lastRow.getPreferredHeight();
414     }
415
416     /** Checks toolbar rows. If there is some empty row it is removed.
417      */

418     void checkToolbarRows () {
419         Object JavaDoc[] rows = toolbarRows.toArray();
420         ToolbarRow row;
421
422         for (int i = rows.length - 1; i >= 0; i--) {
423             row = (ToolbarRow)rows[i];
424             if (row.isEmpty())
425                 removeRow (row);
426         }
427     }
428
429     /**
430      * @return number of rows.
431      */

432     int getRowCount () {
433         return toolbarRows.size();
434     }
435
436     /**
437      * @param name toolbar constraints name
438      * @return toolbar constraints of specified name
439      */

440     ToolbarConstraints getToolbarConstraints (String JavaDoc name) {
441         return allToolbars.get (name);
442     }
443
444     /** Checks toolbars constraints if there is some of specific name.
445      * If isn't then is created new toolbar constraints. Othewise is old
446      * toolbar constraints confronted with new values (position, visibility).
447      * @param name name of checked toolbar
448      * @param position position of toolbar
449      * @param visible visibility of toolbar
450      * @param toolbarIndex index of the toolbar as defined by the order of
451      * declarations in layers
452      * @return toolbar constraints for specifed toolbar name
453      */

454     ToolbarConstraints checkToolbarConstraints (String JavaDoc name, Integer JavaDoc position, Boolean JavaDoc visible, int toolbarIndex) {
455         ToolbarConstraints tc = allToolbars.get (name);
456         if (tc == null)
457             tc = new ToolbarConstraints (this, name, position, visible, toolbarIndex);
458         else
459             tc.checkNextPosition (position, visible);
460         return tc;
461     }
462
463     /** Checks whole toolbar configuration.
464      * It confronts list of all toolbars and waiting toolbars
465      * with toolbars represented by ToolbarPool.
466      *
467      * @return true if there is some change and is important another check.
468      */

469     boolean checkConfigurationOver () {
470         boolean change = false;
471         String JavaDoc name;
472         String JavaDoc[] waNas = waitingToolbars.keySet().toArray(new String JavaDoc[0]);
473         String JavaDoc[] names = allToolbars.keySet().toArray(new String JavaDoc[0]);
474         
475         /* Checks ToolbarPool with waiting list. */
476         for (int i = 0; i < waNas.length; i++) {
477             name = waNas[i];
478             if (toolbarPool ().findToolbar (name) != null) { /* If there is new toolbar in the pool
479                                   which was sometimes described ... */

480                 ToolbarConstraints tc = (ToolbarConstraints)waitingToolbars.remove (name);
481                                                    /* ... it's removed from waiting ... */
482                 allToolbars.put (name, tc); /* ... so it's added to correct toolbars ... */
483                 addVisible (tc); /* ... and added to visible toolbars. */
484                 change = true;
485             }
486         }
487
488         /* Checks ToolbarPool with list of all toolbars ... reverse process than previous for. */
489         for (int i = 0; i < names.length; i++) {
490             name = names[i];
491             if (toolbarPool ().findToolbar (name) == null) { /* If there is toolbar which is not represented int pool ... */
492                 ToolbarConstraints tc = removeToolbar (name); /* ... so let's remove toolbar from all toolbars ... */
493                 waitingToolbars.put (name, tc); /* ... and add to waiting list. */
494                 invisibleToolbars.put (tc, Integer.valueOf(tc.rowIndex()));
495                 change = true;
496             }
497         }
498         if (change || Utilities.arrayHashCode(toolbarPool().getConfigurations()) != lastConfigurationHash) {
499             rebuildMenu();
500         }
501         return change;
502     }
503
504     void refresh() {
505         rebuildPanel();
506         rebuildMenu();
507     }
508     
509     private int lastConfigurationHash = -1;
510     private void rebuildMenu() {
511         if (toolbarMenu != null) {
512             toolbarMenu.removeAll();
513             fillToolbarsMenu(toolbarMenu);
514             revalidateWindow();
515         }
516     }
517     
518     /** Removes toolbar from visible toolbars.
519      * @param tc specified toolbar
520      */

521     private void removeVisible (ToolbarConstraints tc) {
522         invisibleToolbars.put (tc, Integer.valueOf (tc.rowIndex()));
523         if (tc.destroy())
524             checkToolbarRows();
525         tc.setVisible (false);
526
527         //reflectChanges();
528
}
529
530     /** Adds toolbar from list of invisible to visible toolbars.
531      * @param tc specified toolbar
532      */

533     private void addVisible (ToolbarConstraints tc) {
534         int rC = toolbarRows.size();
535         int pos = invisibleToolbars.remove (tc).intValue();
536         tc.setVisible (true);
537         for (int i = pos; i < pos + tc.getRowCount(); i++) {
538             getRow (i).addToolbar (tc, tc.getPosition());
539         }
540
541         if (rC != toolbarRows.size())
542             revalidateWindow();
543         //reflectChanges();
544
}
545
546     /**
547      * @param rI index of required row
548      * @return toolbar row of specified index.
549      * If rI is out of bounds then new row is created.
550      */

551     ToolbarRow getRow (int rI) {
552         ToolbarRow row;
553         int s = toolbarRows.size();
554         if (rI < 0) {
555             row = new ToolbarRow (this);
556             addRow (row, 0);
557         } else if (rI >= s) {
558             row = new ToolbarRow (this);
559             addRow (row);
560         } else {
561             row = (ToolbarRow)toolbarRows.elementAt (rI);
562         }
563         return row;
564     }
565
566     /**
567      * @return toolbar row at last row position.
568      */

569     ToolbarRow createLastRow () {
570         return getRow (toolbarRows.size());
571     }
572
573     /** Reactivate toolbar panel.
574      * All components are removed and again added using ToolbarPool's list of correct toolbars.
575      *
576      * @param someBarRemoved if some toolbar was previously removed and is important to reflect changes
577      * @param writeAtAll if false the content of disk will not be updated at all
578      */

579     void reactivatePanel (boolean someBarRemoved, boolean writeAtAll) {
580         toolbarPanel().removeAll();
581         prefWidth = 0;
582
583         Toolbar tbs[] = toolbarPool ().getToolbars();
584         Toolbar tb;
585         ToolbarConstraints tc;
586         String JavaDoc name;
587         ToolbarRow lastRow = null;
588
589         for (int i = 0; i < tbs.length; i++) {
590             tb = tbs[i];
591             name = tb.getName();
592             tc = (ToolbarConstraints)allToolbars.get (name);
593             if (tc == null) { /* If there is no toolbar constraints description defined yet ... */
594                 if (lastRow == null) {
595                     if( toolbarRows.isEmpty() )
596                         lastRow = createLastRow();
597                     else
598                         lastRow = getRow( toolbarRows.size()-1 );
599                 }
600                 tc = new ToolbarConstraints (this, name, null, Boolean.TRUE); /* ... there is created a new constraints. */
601                 addToolbar (lastRow, tc);
602             }
603             toolbarPanel().add (tb, tc);
604         }
605         
606         revalidateWindow();
607
608     }
609     
610     /** Rebuild toolbar panel when size of icons is changed.
611      * All components are removed and again added using ToolbarPool's list of correct toolbars.
612      */

613     private void rebuildPanel () {
614         toolbarPanel().removeAll();
615         prefWidth = 0;
616
617         Toolbar tbs[] = toolbarPool ().getToolbars();
618         Toolbar tb;
619         ToolbarConstraints tc;
620         String JavaDoc name;
621         ToolbarRow newRow = null;
622         boolean smallToolbarIcons = (ToolbarPool.getDefault().getPreferredIconSize() == 16);
623         for (int i = 0; i < tbs.length; i++) {
624             tb = tbs[i];
625             name = tb.getName();
626             Component [] comps = tb.getComponents();
627             for (int j = 0; j < comps.length; j++) {
628                 if (comps[j] instanceof JComponent) {
629                     if (smallToolbarIcons) {
630                         ((JComponent) comps[j]).putClientProperty("PreferredIconSize",null); //NOI18N
631
} else {
632                         ((JComponent) comps[j]).putClientProperty("PreferredIconSize",Integer.valueOf(24)); //NOI18N
633
}
634                 }
635             }
636             tc = (ToolbarConstraints)allToolbars.get (name);
637             if (tc == null) { /* If there is no toolbar constraints description defined yet ... */
638                 if (newRow == null) {
639                     newRow = createLastRow();
640                 }
641                 tc = new ToolbarConstraints (this, name, null, Boolean.TRUE); /* ... there is created a new constraints. */
642                 addToolbar (newRow, tc);
643             }
644             toolbarPanel().add (tb, tc);
645         }
646         revalidateWindow();
647     }
648     
649     /**
650      * @return true if if important reactivate component.
651      */

652     boolean isImportantActivateComponent () {
653         Object JavaDoc[] names = allToolbars.keySet().toArray();
654         Toolbar[] toolbars = toolbarPool ().getToolbars();
655
656     /* Is number of toolbars int local list and toolbar pool list different? */
657         if (names.length != toolbars.length)
658             return true;
659
660     /* Is name of current configuration differrent of last toolbar pool configuration? */
661         if (! configName.equals (toolbarPool ().getConfiguration()))
662             return true;
663
664         return false;
665     }
666
667     /** Reflects configuration changes ... write it to document.
668      */

669     void reflectChanges () {
670         try {
671             writeDocument();
672         } catch (IOException JavaDoc e) { /* ??? */ }
673     }
674
675     /////////////////////////////////
676
// from ToolbarPool.Configuration
677

678     /** Activates the configuration and returns right
679      * component that can display the configuration.
680      * @return representation component
681      */

682     public Component activate () {
683         return activate (isImportantActivateComponent (), true);
684     }
685         
686         
687     /** Activate.
688      * @param isImportant is the change of structure important
689      * @param writeAtAll write changes to disk or not?
690      */

691     private Component activate (boolean isImportant, boolean writeAtAll) {
692         toolbarPool().setToolbarsListener (toolbarListener);
693
694         boolean someBarRemoved = checkConfigurationOver();
695
696         if (isImportant || someBarRemoved) {
697             toolbarLayout = new ToolbarLayout (this);
698             toolbarPanel().setLayout (toolbarLayout);
699             reactivatePanel (someBarRemoved, writeAtAll);
700             rebuildMenu();
701         }
702
703         return toolbarPanel();
704     }
705
706     /** Name of the configuration.
707      * @return the name
708      */

709     public String JavaDoc getName () {
710         return configName;
711     }
712     
713     public String JavaDoc getDisplayName () {
714         return configDisplayName;
715     }
716
717     /** Popup menu that should be displayed when the users presses
718      * right mouse button on the panel. This menu can contain
719      * contains list of possible configurations, additional actions, etc.
720      *
721      * @return popup menu to be displayed
722      */

723     public JPopupMenu getContextMenu () {
724         JPopupMenu menu = new JPopupMenuPlus();
725         fillToolbarsMenu(menu);
726         return menu;
727     }
728
729     /** Fills given menu with toolbars and configurations items and returns
730      * filled menu. */

731     public JMenu getToolbarsMenu (JMenu menu) {
732         fillToolbarsMenu(menu);
733         toolbarMenu = menu;
734         return menu;
735     }
736     
737     public static void resetToolbarIconSize() {
738         ToolbarPool.getDefault().setPreferredIconSize(24);
739         //Rebuild toolbar panel
740
String JavaDoc name = ToolbarPool.getDefault().getConfiguration();
741         ToolbarConfiguration tbConf = findConfiguration(name);
742         if (tbConf != null) {
743             tbConf.rebuildPanel();
744             tbConf.rebuildMenu();
745         }
746     }
747     
748     /** Fills given menu instance with list of toolbars and configurations */
749     private void fillToolbarsMenu (JComponent menu) {
750         lastConfigurationHash = Utilities.arrayHashCode(ToolbarPool.getDefault().getConfigurations());
751         // generate list of available toolbars
752
Iterator it = Arrays.asList (ToolbarPool.getDefault ().getToolbars ()).iterator ();
753         while (it.hasNext()) {
754             final Toolbar tb = (Toolbar)it.next();
755             final String JavaDoc tbName = tb.getName();
756             ToolbarConstraints tc =
757                 (ToolbarConstraints)allToolbars.get (tb.getName());
758 /*
759             if (tc == null) {
760                 System.err.println("ToolbarConfiguration.java - error"); // NOI18N
761                 System.err.println("name: " + name); // NOI18N
762                 System.err.println(" all: " + allToolbars); // NOI18N
763                 continue;
764             }
765 */

766             if (tc == null || tb == null) {
767                 //a toolbar configuration has been renamed (for whatever reason,
768
//we permit this - I'm sure it's a popular feature).
769
checkConfigurationOver();
770             }
771
772             
773             if (tc != null && tb != null) {
774                 //May be null if a toolbar has been renamed
775
JCheckBoxMenuItem mi = new JCheckBoxMenuItem (
776                     tb.getDisplayName(), tc.isVisible()
777                 );
778                 mi.putClientProperty("ToolbarName", tbName); //NOI18N
779
mi.addActionListener (new ActionListener JavaDoc () {
780                     public void actionPerformed (ActionEvent JavaDoc ae) {
781                         // #39741 fix
782
// for some reason (unknown to me - mkleint) the menu gets recreated repeatedly, which
783
// can cause the formerly final ToolbarConstraints instance to be obsolete.
784
// that's why we each time look up the current instance on the allToolbars map.
785
ToolbarConstraints tc = (ToolbarConstraints)allToolbars.get (tbName );
786                         setToolbarVisible(tb, !tc.isVisible());
787                     }
788                 });
789                 menu.add (mi);
790             }
791         }
792         menu.add (new JPopupMenu.Separator());
793         
794         //Bigger toolbar icons
795
boolean smallToolbarIcons = (ToolbarPool.getDefault().getPreferredIconSize() == 16);
796         
797         JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem (
798             getBundleString("PROP_smallToolbarIcons"), smallToolbarIcons
799         );
800         cbmi.addActionListener (new ActionListener JavaDoc () {
801               public void actionPerformed (ActionEvent JavaDoc ev) {
802                   if (ev.getSource() instanceof JCheckBoxMenuItem) {
803                       JCheckBoxMenuItem cb = (JCheckBoxMenuItem) ev.getSource();
804                       boolean state = cb.getState();
805                       if (state) {
806                           ToolbarPool.getDefault().setPreferredIconSize(16);
807                       } else {
808                           ToolbarPool.getDefault().setPreferredIconSize(24);
809                       }
810                       //Rebuild toolbar panel
811
//#43652: Find current toolbar configuration
812
String JavaDoc name = ToolbarPool.getDefault().getConfiguration();
813                       ToolbarConfiguration tbConf = findConfiguration(name);
814                       if (tbConf != null) {
815                           tbConf.rebuildPanel();
816                       }
817                       rebuildMenu();
818                   }
819               }
820         });
821         menu.add (cbmi);
822         
823         menu.add( new JPopupMenu.Separator() );
824
825         JMenuItem menuItem = new JMenuItem( new ResetToolbarsAction() );
826         menu.add( menuItem );
827         
828         menuItem = new JMenuItem(getBundleString( "CTL_CustomizeToolbars" ) );
829         menuItem.addActionListener(new ActionListener JavaDoc() {
830             public void actionPerformed (ActionEvent JavaDoc event) {
831                 ConfigureToolbarPanel.showConfigureDialog();
832             }
833         });
834         menu.add( menuItem );
835         
836     } // getContextMenu
837

838     /** Make toolbar visible/invisible in this configuration
839      * @param tb toolbar
840      * @param b true to make toolbar visible
841      */

842     public void setToolbarVisible(Toolbar tb, boolean b) {
843         ToolbarConstraints tc = getToolbarConstraints(tb.getName());
844         if (b) {
845             addVisible(tc);
846         } else {
847             removeVisible(tc);
848         }
849         if (toolbarMenu != null) {
850             //#39808 - somoewhat bruteforce approach, but works and is simple enough.
851
// assumes the toolbar selection is always processed through the setToolbarVisible() method.
852
//correct selection of the toolbar checkboxes in the main menu..
853
Component[] elements = toolbarMenu.getMenuComponents();
854             for (int i = 0; i < elements.length; i++) {
855                 JComponent component = (JComponent)elements[i];
856                 String JavaDoc tcmenu = (String JavaDoc)component.getClientProperty("ToolbarName"); //NOI18N
857
if (tcmenu != null && tcmenu.equals(tb.getName())) {
858                     ((JCheckBoxMenuItem)component).setSelected(b);
859                     break;
860                 }
861             }
862         }
863         tb.setVisible(b);
864         reflectChanges();
865         firePropertyChange();
866     }
867     
868     /** Returns true if the toolbar is visible in this configuration
869      * @param tb toolbar
870      * @return true if the toolbar is visible
871      */

872     public boolean isToolbarVisible(Toolbar tb) {
873         ToolbarConstraints tc = getToolbarConstraints(tb.getName());
874         return tc.isVisible();
875     }
876     
877     PropertyChangeSupport JavaDoc pcs;
878     
879     public void addPropertyChangeListener(PropertyChangeListener JavaDoc l) {
880         if (pcs == null) {
881             pcs = new PropertyChangeSupport JavaDoc(this);
882         }
883         pcs.addPropertyChangeListener(l);
884     }
885     
886     public void removePropertyChangeListener(PropertyChangeListener JavaDoc l) {
887         if (pcs != null) {
888             pcs.removePropertyChangeListener(l);
889         }
890     }
891     
892     private void firePropertyChange() {
893         if (pcs != null) {
894             pcs.firePropertyChange("constraints", null, null); // some constraints have changed
895
}
896     }
897
898     //// writting
899

900     /** Write actual toolbar configuration. */
901     public void writeDocument () throws IOException JavaDoc {
902         writeDocument (configName);
903     }
904
905     /** Write toolbar configuration for specified file name to xml.
906      * @param cn configuration file name
907      */

908     private void writeDocument (final String JavaDoc cn) throws IOException JavaDoc {
909         ERR.fine("writeDocument: " + cn); // NOI18N
910
WritableToolbarConfiguration wtc = new WritableToolbarConfiguration (toolbarRows, invisibleToolbars);
911         final StringBuffer JavaDoc sb = new StringBuffer JavaDoc ("<?xml version=\"1.0\"?>\n\n"); // NOI18N
912
sb.append ("<!DOCTYPE ").append (TAG_CONFIG).append (" PUBLIC \""). // NOI18N
913
append (TOOLBAR_DTD_PUBLIC_ID).append ("\" \"").append (TOOLBAR_DTD_WEB).append ("\">\n\n").append (wtc.toString()); // NOI18N
914

915         final FileObject tbFO = NbPlaces.getDefault().toolbars().getPrimaryFile();
916         final FileSystem tbFS = tbFO.getFileSystem();
917
918         Boolean JavaDoc prev = WRITE_IN_PROGRESS.get ();
919         try {
920             WRITE_IN_PROGRESS.set (Boolean.TRUE);
921             tbFS.runAtomicAction (new FileSystem.AtomicAction () {
922         public void run () throws IOException JavaDoc {
923             FileLock lock = null;
924             OutputStream JavaDoc os = null;
925             FileObject xmlFO = tbFO.getFileObject(cn, EXT_XML);
926             if (xmlFO == null)
927             xmlFO = tbFO.createData (cn, EXT_XML);
928             try {
929             lock = xmlFO.lock ();
930             os = xmlFO.getOutputStream (lock);
931             
932             Writer JavaDoc writer = new OutputStreamWriter JavaDoc(os, "UTF-8"); // NOI18N
933
writer.write(sb.toString());
934             writer.close();
935             } finally {
936                         lastReload = System.currentTimeMillis ();
937                         ERR.fine("Setting last reload: " + lastReload); // NOI18N
938

939             if (os != null)
940                 os.close ();
941             if (lock != null)
942                 lock.releaseLock ();
943             }
944         }
945         });
946         } finally {
947             WRITE_IN_PROGRESS.set (prev);
948         }
949         ERR.fine("writeDocument finished"); // NOI18N
950
}
951
952     /** lazy init of toolbar panel */
953     private static final synchronized JPanel toolbarPanel () {
954         if (toolbarPanel == null) {
955             toolbarPanel = new JPanel();
956             toolbarPanel.setLayout(new FlowLayout (FlowLayout.LEFT));
957         }
958         return toolbarPanel;
959     }
960
961     /** Listens on changes in the document.
962      */

963     public void propertyChange(PropertyChangeEvent JavaDoc ev) {
964         if (!XMLDataObject.PROP_DOCUMENT.equals(ev.getPropertyName ())) {
965             // interested only in PROP_DOCUMENT properties
966
return;
967         }
968         if (Boolean.TRUE.equals (WRITE_IN_PROGRESS.get ())) {
969             return;
970         }
971         
972         updateConfiguration((XMLDataObject)ev.getSource());
973     }
974
975     /** Updates configuration and also 'configuration over'.
976      * @see #readConfig
977      * @see #checkConfigurationOver */

978     void updateConfiguration(final XMLDataObject xmlDataObject) {
979         long mod = xmlDataObject.getPrimaryFile ().lastModified().getTime ();
980         ERR.fine("Checking modified: " + lastReload); // NOI18N
981
//Bugfix #10196, this condition commented to make sure that all changes
982
//will be applied.
983
/*if (lastReload >= mod) {
984             // not changed since last refresh
985             return;
986         }*/

987         
988         // [dafe] - code below demonstrates data integrity problem that occurs
989
// in current toolbar impl. data in toolbar pool and data in toolbar
990
// rows are not maintained centrally, and because of this invoke later,
991
// they are inconsistent for a while (toolbar rows have older data, while
992
// toolbar pool has already new content)
993
// needs architecture redesign IMO
994
SwingUtilities.invokeLater(new Runnable JavaDoc() {
995
996             public void run() {
997                 try {
998                     initInstance();
999                     readConfig(xmlDataObject);
1000                    checkConfigurationOver();
1001                    if (configName.equals(toolbarPool().getConfiguration())) {
1002                        ERR.fine("Activating the configuration");
1003                        // 1st argument is true because the change is important
1004
// 2nd argument is false, because it should prevent the system
1005
// to write anything do
1006
activate(true, false);
1007                    }
1008                }
1009                catch (IOException JavaDoc ex) {
1010                    Logger.getLogger(ToolbarConfiguration.class.getName()).log(Level.WARNING, null, ex);
1011                }
1012            }
1013        });
1014    }
1015    
1016    /** @return upper vertical location of specified row
1017     */

1018    int getRowVertLocation (ToolbarRow row) {
1019        int index = rowIndex(row);
1020        int vertLocation = index * ToolbarLayout.VGAP;
1021        Iterator iter = toolbarRows.iterator();
1022        for (int i = 0; i < index; i++) {
1023            vertLocation += ((ToolbarRow)iter.next()).getPreferredHeight();
1024        }
1025        return vertLocation;
1026    }
1027
1028    // class WritableToolbarConfiguration
1029
static class WritableToolbarConfiguration {
1030    /** List of rows. */
1031        Vector<ToolbarRow.WritableToolbarRow> rows;
1032
1033    /** Create new WritableToolbarConfiguration.
1034     * @param rs list of rows
1035     * @param iv map of invisible toolbars
1036     */

1037        public WritableToolbarConfiguration (Vector<ToolbarRow> rs, Map iv) {
1038            initRows (rs);
1039            initInvisible (iv);
1040            removeEmptyRows();
1041        }
1042
1043        /** Init list of writable rows.
1044     * @param rs list of rows
1045     */

1046        void initRows (Vector<ToolbarRow> rs) {
1047            rows = new Vector<ToolbarRow.WritableToolbarRow>();
1048            for (ToolbarRow r: rs) {
1049                rows.addElement (new ToolbarRow.WritableToolbarRow (r));
1050            }
1051        }
1052
1053    /** Init invisible toolbars in toolbar rows.
1054     * @param iv map of invisible toolbars
1055     */

1056        void initInvisible (Map iv) {
1057            Iterator it = iv.keySet().iterator();
1058            ToolbarConstraints tc;
1059            int row;
1060            while (it.hasNext()) {
1061                tc = (ToolbarConstraints)it.next();
1062                row = ((Integer JavaDoc)iv.get (tc)).intValue();
1063                for (int i = row; i < row + tc.getRowCount(); i++) {
1064                    getRow (i).addToolbar (tc);
1065                }
1066            }
1067        }
1068
1069    /** Removes empty rows. */
1070        void removeEmptyRows () {
1071            ToolbarRow.WritableToolbarRow row;
1072            for (int i = rows.size() - 1; i >= 0; i--) {
1073                row = (ToolbarRow.WritableToolbarRow)rows.elementAt (i);
1074                if (row.isEmpty())
1075                    rows.removeElement (row);
1076            }
1077        }
1078
1079    /**
1080     * @param r row index
1081     * @return WritableToolbarRow for specified row index
1082     */

1083        ToolbarRow.WritableToolbarRow getRow (int r) {
1084            try {
1085                return rows.elementAt (r);
1086            } catch (ArrayIndexOutOfBoundsException JavaDoc e) {
1087                rows.addElement (new ToolbarRow.WritableToolbarRow ());
1088                return getRow (r);
1089            }
1090        }
1091
1092        /** @return ToolbarConfiguration in xml format. */
1093        public String JavaDoc toString () {
1094            StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1095
1096            sb.append ("<").append (TAG_CONFIG).append (">\n"); // NOI18N
1097
Iterator it = rows.iterator();
1098            while (it.hasNext()) {
1099                sb.append (it.next().toString());
1100            }
1101            sb.append ("</").append (TAG_CONFIG).append (">\n"); // NOI18N
1102

1103            return sb.toString();
1104        }
1105    } // end of class WritableToolbarConfiguration
1106
} // end of class Configuration
1107
Popular Tags