|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core.windows.view.ui.toolbars; import org.netbeans.core.NbPlaces; import org.netbeans.core.windows.WindowManagerImpl; import org.netbeans.core.windows.services.ToolbarFolderNode; import org.openide.DialogDescriptor; import org.openide.ErrorManager; import org.openide.NotifyDescriptor; import org.openide.awt.JPopupMenuPlus; import org.openide.awt.Toolbar; import org.openide.awt.ToolbarPool; import org.openide.filesystems.FileLock; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileSystem; import org.openide.loaders.XMLDataObject; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.xml.sax.*; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.text.MessageFormat; import java.util.*; import java.util.List; import org.netbeans.core.IDESettings; /** Toolbar configuration. * It can load configuration from DOM Document, store configuration int XML file. * Toolbar configuration contains list of all correct toolbars (toolbars which are * represented int ToolbarPool too), waiting toolbars (toolbars which was described * [it's position, visibility] but there is representation int ToolbarPool). * There is list of rows (ToolbarRow) and map of invisible toolbars. * * @author Libor Kramolis */ public final class ToolbarConfiguration extends Object implements ToolbarPool.Configuration, PropertyChangeListener { /** location outside the IDE */ protected static final String TOOLBAR_DTD_WEB = "http://www.netbeans.org/dtds/toolbar.dtd"; // NOI18N /** toolbar dtd public id */ protected static final String TOOLBAR_DTD_PUBLIC_ID = "-//NetBeans IDE//DTD toolbar//EN"; // NOI18N /** toolbar prcessor class */ protected static final Class TOOLBAR_PROCESSOR_CLASS = ToolbarProcessor.class; /** toolbar icon base */ protected static final String TOOLBAR_ICON_BASE = "/org/netbeans/core/windows/toolbars/xmlToolbars"; // NOI18N /** error manager */ private static ErrorManager ERR = ErrorManager.getDefault ().getInstance ("org.netbeans.core.windows.toolbars"); // NOI18N /** last time the document has been reloaded */ private volatile long lastReload; /** xml extension */ protected static final String EXT_XML = "xml"; // NOI18N // /** xmlinfo extension */ // protected static final String EXT_XMLINFO = "xmlinfo"; // NOI18N /** xml element for configuration (root element) */ protected static final String TAG_CONFIG = "Configuration"; // NOI18N /** xml element for row */ protected static final String TAG_ROW = "Row"; // NOI18N /** xml element for toolbar */ protected static final String TAG_TOOLBAR = "Toolbar"; // NOI18N /** xml attribute for toolbar name */ protected static final String ATT_TOOLBAR_NAME = "name"; // NOI18N /** xml attribute for toolbar position */ protected static final String ATT_TOOLBAR_POSITION = "position"; // NOI18N /** xml attribute for toolbar visible */ protected static final String ATT_TOOLBAR_VISIBLE = "visible"; // NOI18N /** standard panel for all configurations */ private static JPanel toolbarPanel; /** mapping from configuration instances to their names */ private static WeakHashMap confs2Names = new WeakHashMap(10); /** toolbar layout manager for this configuration */ private ToolbarLayout toolbarLayout; /** toolbar drag and drop listener */ private ToolbarDnDListener toolbarListener; /** All toolbars which are represented in ToolbarPool too. */ private WeakHashMap allToolbars; /** List of visible toolbar rows. */ private Vector toolbarRows; /** All invisible toolbars (visibility==false || tb.isCorrect==false). */ private HashMap invisibleToolbars; /** Toolbar menu is global so it is static. It it the same for all toolbar configurations. */ private static JMenu toolbarMenu; /** Toolbars which was described in DOM Document, but which aren't represented in ToolbarPool. For exapmle ComponentPalette and first start of IDE. */ private WeakHashMap waitingToolbars; /** Name of configuration. */ private String configName; /** Display name of configuration. */ private String configDisplayName; /** Cached preferred width. */ private int prefWidth; /** variable to signal that we are just writing the content of configuration * and we should ignore all changes. In such case set to Boolean.TRUE */ private final ThreadLocal WRITE_IN_PROGRESS = new ThreadLocal (); // private static final ResourceBundle bundle = NbBundle.getBundle (ToolbarConfiguration.class); /** Creates new empty toolbar configuration for specific name. * @param name new configuration name */ public ToolbarConfiguration (String name, String displayName) { configName = name; configDisplayName = displayName; // fix #44537 - just doing the simple thing of hacking the extension out of the display name.. node.getDisplayName is too unpredictable. if (configDisplayName.endsWith(".xml")) { configDisplayName = configDisplayName.substring(0, configDisplayName.length() - ".xml".length()); } initInstance (); // asociate name and configuration instance confs2Names.put(this, name); } /** Creates new toolbar configuration for specific name and from specific XMLDataObject * @param name new configuration name * @param xml XMLDataObject representing a toolbar configuration */ public ToolbarConfiguration(XMLDataObject xml) throws IOException { this(xml.getNodeDelegate().getName(), xml.getNodeDelegate().getDisplayName()); readConfig(xml); } private void readConfig(XMLDataObject xml) throws IOException { Parser parser = xml.createParser(); parser.setEntityResolver(new EntityResolver() { public InputSource resolveEntity(String pubid, String sysid) { return new InputSource(new java.io.ByteArrayInputStream(new byte[0])); } }); HandlerBase handler = new HandlerBase() { private ToolbarRow currentRow = null; public void startElement(String name, AttributeList amap) throws SAXException { if (TAG_ROW.equals(name)) { currentRow = new ToolbarRow(ToolbarConfiguration.this); addRow(currentRow); } else if (currentRow != null && TAG_TOOLBAR.equals(name)) { String tbname = amap.getValue(ATT_TOOLBAR_NAME); if (tbname == null || tbname.equals("")) // NOI18N return; String posStr = amap.getValue(ATT_TOOLBAR_POSITION); Integer pos = null; if (posStr != null) pos = new Integer(posStr); String visStr = amap.getValue(ATT_TOOLBAR_VISIBLE); Boolean vis; if (visStr != null) vis = Boolean.valueOf(visStr); else vis = Boolean.TRUE; addToolbar(currentRow, checkToolbarConstraints (tbname, pos, vis)); } } public void endElement(String name) throws SAXException { if (TAG_ROW.equals(name)) { currentRow = null; } } }; //parser.setErrorHandler(listener); parser.setDocumentHandler(handler); try { parser.parse(new InputSource(xml.getPrimaryFile().getInputStream())); } catch (Exception saxe) { IOException ex = new IOException (saxe.toString()); ErrorManager.getDefault().annotate(ex, saxe); throw ex; } checkToolbarRows(); } /** Clean all the configuration parameters. */ private void initInstance () { allToolbars = new WeakHashMap(); waitingToolbars = new WeakHashMap(); toolbarRows = new Vector(); invisibleToolbars = new HashMap(); toolbarListener = new ToolbarDnDListener (this); } /** @return returns string from bundle for given string pattern */ static final String getBundleString (String bundleStr) { return NbBundle.getMessage(ToolbarConfiguration.class, bundleStr); } /** Finds toolbar configuration which has given name. * @return toolbar configuration instance which ID is given name or null * if no such configuration can be found */ public static final ToolbarConfiguration findConfiguration (String name) { Map.Entry curEntry = null; for (Iterator iter = confs2Names.entrySet().iterator(); iter.hasNext(); ) { curEntry = (Map.Entry)iter.next(); if (name.equals((String)curEntry.getValue())) { return (ToolbarConfiguration)curEntry.getKey(); } } // no luck return null; } /** Add toolbar to list of all toolbars. * If specified toolbar constraints represents visible component * it is added to specified toolbar row. * Othewise toolbar constraints is added to invisible toolbars. * * @param row toolbar row of new toolbar is part * @param tc added toolbar represented by ToolbarConstraints */ void addToolbar (ToolbarRow row, ToolbarConstraints tc) { if (tc == null) return; if (tc.isVisible()) row.addToolbar (tc); else { int rI; if (row == null) rI = toolbarRows.size(); else rI = toolbarRows.indexOf (row); invisibleToolbars.put (tc, new Integer (rI)); } allToolbars.put (tc.getName(), tc); } /** Remove toolbar from list of all toolbars. * This could mean that toolbar is represented only in DOM document. * * @param name name of removed toolbar */ ToolbarConstraints removeToolbar (String name) { ToolbarConstraints tc = (ToolbarConstraints)allToolbars.remove (name); if (tc.destroy()) checkToolbarRows(); return tc; } /** Add toolbar row as last row. * @param row added toolbar row */ void addRow (ToolbarRow row) { addRow (row, toolbarRows.size()); } /** Add toolbar row to specific index. * @param row added toolbar row * @param index specified index of toolbar position */ void addRow (ToolbarRow row, int index) { /* It is important to recompute row neighbournhood. */ ToolbarRow prev = null; ToolbarRow next = null; try { prev = (ToolbarRow)toolbarRows.elementAt (index - 1); } catch (ArrayIndexOutOfBoundsException e) { } try { next = (ToolbarRow)toolbarRows.elementAt (index); } catch (ArrayIndexOutOfBoundsException e) { } if (prev != null) prev.setNextRow (row); row.setPrevRow (prev); row.setNextRow (next); if (next != null) next.setPrevRow (row); toolbarRows.insertElementAt (row, index); updateBounds (row); } /** Remove toolbar row from list of all rows. * @param row removed toolbar row */ void removeRow (ToolbarRow row) { /* It is important to recompute row neighbournhood. */ ToolbarRow prev = row.getPrevRow(); ToolbarRow next = row.getNextRow(); if (prev != null) { prev.setNextRow (next); } if (next != null) { next.setPrevRow (prev); } toolbarRows.removeElement (row); updateBounds (next); revalidateWindow(); } /** Update toolbar row cached bounds. * @param row updated row */ void updateBounds (ToolbarRow row) { while (row != null) { row.updateBounds(); row = row.getNextRow(); } } private static final ToolbarPool toolbarPool () { return ToolbarPool.getDefault (); } /** Revalidates toolbar pool window. * It is important for change height when number of rows is changed. */ void revalidateWindow () { // PENDING toolbarPanel().revalidate(); IDESettings settings = (IDESettings)IDESettings.findObject(IDESettings.class, true); int uiMode = settings.getUIMode(); if (uiMode == 1) { // perform in SDI only java.awt.Window w = SwingUtilities.windowForComponent(toolbarPanel()); if (w != null) { // w.validate(); int width = toolbarPanel().getRootPane().getSize().width; int height = toolbarPanel().getRootPane().getPreferredSize().height; Insets insets = w.getInsets(); w.setSize(new Dimension(width + insets.left + insets.right, height + insets.top + insets.bottom)); w.validate(); } } // #15930. Always replane even we are in AWT thread already. // SwingUtilities.invokeLater(new Runnable () { // public void run () { // doRevalidateWindow(); // } // }); } // /** Performs revalidating work */ // private void doRevalidateWindow () { // toolbarPanel().revalidate(); // java.awt.Window w = SwingUtilities.windowForComponent (toolbarPool ()); // if (w != null) { // w.validate (); // } // } // PENDING /** * @param row specified toolbar row * @return index of toolbar row */ int rowIndex (ToolbarRow row) { return toolbarRows.indexOf (row); } /** Updates cached preferred width of toolbar configuration. */ void updatePrefWidth () { Iterator it = toolbarRows.iterator(); prefWidth = 0; int tryPrefWidth; while (it.hasNext()) { prefWidth = Math.max (prefWidth, ((ToolbarRow)it.next()).getPrefWidth()); } } /** * @return configuration preferred width */ int getPrefWidth () { return prefWidth; } /** * @return configuration preferred height, sum of preferred heights of rows. * If there is no row, preferred height is 0. */ int getPrefHeight () { if (getRowCount() == 0) return 0; ToolbarRow lastRow = (ToolbarRow)toolbarRows.lastElement(); return getRowVertLocation(lastRow) + lastRow.getPreferredHeight(); } /** Checks toolbar rows. If there is some empty row it is removed. */ void checkToolbarRows () { Object[] rows = toolbarRows.toArray(); ToolbarRow row; for (int i = rows.length - 1; i >= 0; i--) { row = (ToolbarRow)rows[i]; if (row.isEmpty()) removeRow (row); } } /** * @return number of rows. */ int getRowCount () { return toolbarRows.size(); } /** * @param name toolbar constraints name * @return toolbar constraints of specified name */ ToolbarConstraints getToolbarConstraints (String name) { return (ToolbarConstraints)allToolbars.get (name); } /** Checks toolbars constraints if there is some of specific name. * If isn't then is created new toolbar constraints. Othewise is old * toolbar constraints confronted with new values (position, visibility). * @param name name of checked toolbar * @param position position of toolbar * @param visible visibility of toolbar * @return toolbar constraints for specifed toolbar name */ ToolbarConstraints checkToolbarConstraints (String name, Integer position, Boolean visible) { ToolbarConstraints tc = (ToolbarConstraints)allToolbars.get (name); if (tc == null) tc = new ToolbarConstraints (this, name, position, visible); else tc.checkNextPosition (position, visible); return tc; } /** Checks whole toolbar configuration. * It confronts list of all toolbars and waiting toolbars * with toolbars represented by ToolbarPool. * * @return true if there is some change and is important another check. */ boolean checkConfigurationOver () { boolean change = false; String name; Object[] waNas = waitingToolbars.keySet().toArray(); Object[] names = allToolbars.keySet().toArray(); /* Checks ToolbarPool with waiting list. */ for (int i = 0; i < waNas.length; i++) { name = (String)waNas[i]; if (toolbarPool ().findToolbar (name) != null) { /* If there is new toolbar in the pool which was sometimes described ... */ ToolbarConstraints tc = (ToolbarConstraints)waitingToolbars.remove (name); /* ... it's removed from waiting ... */ allToolbars.put (name, tc); /* ... so it's added to correct toolbars ... */ addVisible (tc); /* ... and added to visible toolbars. */ change = true; } } /* Checks ToolbarPool with list of all toolbars ... reverse process than previous for. */ for (int i = 0; i < names.length; i++) { name = (String)names[i]; if (toolbarPool ().findToolbar (name) == null) { /* If there is toolbar which is not represented int pool ... */ ToolbarConstraints tc = removeToolbar (name); /* ... so let's remove toolbar from all toolbars ... */ waitingToolbars.put (name, tc); /* ... and add to waiting list. */ invisibleToolbars.put (tc, new Integer (tc.rowIndex())); change = true; } } if (change || Utilities.arrayHashCode(toolbarPool().getConfigurations()) != lastConfigurationHash) { rebuildMenu(); } return change; } private int lastConfigurationHash = -1; private void rebuildMenu() { if (toolbarMenu != null) { toolbarMenu.removeAll(); fillToolbarsMenu(toolbarMenu); revalidateWindow(); } } /** Removes toolbar from visible toolbars. * @param tc specified toolbar */ private void removeVisible (ToolbarConstraints tc) { invisibleToolbars.put (tc, new Integer (tc.rowIndex())); if (tc.destroy()) checkToolbarRows(); tc.setVisible (false); //reflectChanges(); } /** Adds toolbar from list of invisible to visible toolbars. * @param tc specified toolbar */ private void addVisible (ToolbarConstraints tc) { int rC = toolbarRows.size(); int pos = ((Integer)invisibleToolbars.remove (tc)).intValue(); tc.setVisible (true); for (int i = pos; i < pos + tc.getRowCount(); i++) { getRow (i).addToolbar (tc, tc.getPosition()); } if (rC != toolbarRows.size()) revalidateWindow(); //reflectChanges(); } /** * @param rI index of required row * @return toolbar row of specified index. * If rI is out of bounds then new row is created. */ ToolbarRow getRow (int rI) { ToolbarRow row; int s = toolbarRows.size(); if (rI < 0) { row = new ToolbarRow (this); addRow (row, 0); } else if (rI >= s) { row = new ToolbarRow (this); addRow (row); } else { row = (ToolbarRow)toolbarRows.elementAt (rI); } return row; } /** * @return toolbar row at last row position. */ ToolbarRow createLastRow () { return getRow (toolbarRows.size()); } /** Reactivate toolbar panel. * All components are removed and again added using ToolbarPool's list of correct toolbars. * * @param someBarRemoved if some toolbar was previously removed and is important to reflect changes * @param writeAtAll if false the content of disk will not be updated at all */ void reactivatePanel (boolean someBarRemoved, boolean writeAtAll) { toolbarPanel().removeAll(); prefWidth = 0; Toolbar tbs[] = toolbarPool ().getToolbars(); Toolbar tb; ToolbarConstraints tc; String name; ToolbarRow newRow = null; boolean someBarAdded = false; for (int i = 0; i < tbs.length; i++) { tb = tbs[i]; name = tb.getName(); tc = (ToolbarConstraints)allToolbars.get (name); if (tc == null) { /* If there is no toolbar constraints description defined yet ... */ if (newRow == null) newRow = createLastRow(); tc = new ToolbarConstraints (this, name, null, Boolean.TRUE); /* ... there is created a new constraints. */ addToolbar (newRow, tc); someBarAdded = true; } toolbarPanel().add (tb, tc); } revalidateWindow(); } /** Rebuild toolbar panel when size of icons is changed. * All components are removed and again added using ToolbarPool's list of correct toolbars. */ private void rebuildPanel () { toolbarPanel().removeAll(); prefWidth = 0; Toolbar tbs[] = toolbarPool ().getToolbars(); Toolbar tb; ToolbarConstraints tc; String name; ToolbarRow newRow = null; boolean someBarAdded = false; boolean smallToolbarIcons = (ToolbarPool.getDefault().getPreferredIconSize() == 16); for (int i = 0; i < tbs.length; i++) { tb = tbs[i]; name = tb.getName(); Component [] comps = tb.getComponents(); for (int j = 0; j < comps.length; j++) { if (comps[j] instanceof JComponent) { if (smallToolbarIcons) { ((JComponent) comps[j]).putClientProperty("PreferredIconSize",null); //NOI18N } else { ((JComponent) comps[j]).putClientProperty("PreferredIconSize",new Integer(24)); //NOI18N } } } tc = (ToolbarConstraints)allToolbars.get (name); if (tc == null) { /* If there is no toolbar constraints description defined yet ... */ if (newRow == null) { newRow = createLastRow(); } tc = new ToolbarConstraints (this, name, null, Boolean.TRUE); /* ... there is created a new constraints. */ addToolbar (newRow, tc); someBarAdded = true; } toolbarPanel().add (tb, tc); } revalidateWindow(); } /** * @return true if if important reactivate component. */ boolean isImportantActivateComponent () { Object[] names = allToolbars.keySet().toArray(); Toolbar[] toolbars = toolbarPool ().getToolbars(); /* Is number of toolbars int local list and toolbar pool list different? */ if (names.length != toolbars.length) return true; /* Is name of current configuration differrent of last toolbar pool configuration? */ if (! configName.equals (toolbarPool ().getConfiguration())) return true; return false; } /** Reflects configuration changes ... write it to document. */ void reflectChanges () { try { writeDocument(); } catch (IOException e) { /* ??? */ } } ///////////////////////////////// // from ToolbarPool.Configuration /** Activates the configuration and returns right * component that can display the configuration. * @return representation component */ public Component activate () { return activate (isImportantActivateComponent (), true); } /** Activate. * @param isImportant is the change of structure important * @param writeAtAll write changes to disk or not? */ private Component activate (boolean isImportant, boolean writeAtAll) { toolbarPool().setToolbarsListener (toolbarListener); boolean someBarRemoved = checkConfigurationOver(); if (isImportant || someBarRemoved) { if (toolbarLayout == null) { toolbarLayout = new ToolbarLayout (this); } toolbarPanel().setLayout (toolbarLayout); reactivatePanel (someBarRemoved, writeAtAll); } return toolbarPanel(); } /** Name of the configuration. * @return the name */ public String getName () { return configName; } public String getDisplayName () { return configDisplayName; } /** Popup menu that should be displayed when the users presses * right mouse button on the panel. This menu can contain * contains list of possible configurations, additional actions, etc. * * @return popup menu to be displayed */ public JPopupMenu getContextMenu () { JPopupMenu menu = new JPopupMenuPlus(); fillToolbarsMenu(menu); return menu; } /** Fills given menu with toolbars and configurations items and returns * filled menu. */ public JMenu getToolbarsMenu (JMenu menu) { fillToolbarsMenu(menu); toolbarMenu = menu; return menu; } /** Fills given menu instance with list of toolbars and configurations */ private void fillToolbarsMenu (JComponent menu) { lastConfigurationHash = Utilities.arrayHashCode(ToolbarPool.getDefault().getConfigurations()); // generate list of available toolbars Iterator it = Arrays.asList (ToolbarPool.getDefault ().getToolbars ()).iterator (); while (it.hasNext()) { final Toolbar tb = (Toolbar)it.next(); final String tbName = tb.getName(); ToolbarConstraints tc = (ToolbarConstraints)allToolbars.get (tb.getName()); /* if (tc == null) { System.err.println("ToolbarConfiguration.java - error"); // NOI18N System.err.println("name: " + name); // NOI18N System.err.println(" all: " + allToolbars); // NOI18N continue; } */ if (tc == null || tb == null) { //a toolbar configuration has been renamed (for whatever reason, //we permit this - I'm sure it's a popular feature). checkConfigurationOver(); } if (tc != null && tb != null) { //May be null if a toolbar has been renamed JCheckBoxMenuItem mi = new JCheckBoxMenuItem ( tb.getDisplayName(), tc.isVisible() ); mi.putClientProperty("ToolbarName", tbName); //NOI18N mi.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent ae) { // #39741 fix // for some reason (unknown to me - mkleint) the menu gets recreated repeatedly, which // can cause the formerly final ToolbarConstraints instance to be obsolete. // that's why we each time look up the current instance on the allToolbars map. ToolbarConstraints tc = (ToolbarConstraints)allToolbars.get (tbName ); setToolbarVisible(tb, !tc.isVisible()); } }); menu.add (mi); } } menu.add (new JPopupMenu.Separator()); //Bigger toolbar icons boolean smallToolbarIcons = (ToolbarPool.getDefault().getPreferredIconSize() == 16); JCheckBoxMenuItem cbmi = new JCheckBoxMenuItem ( getBundleString("PROP_smallToolbarIcons"), smallToolbarIcons ); cbmi.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent ev) { if (ev.getSource() instanceof JCheckBoxMenuItem) { JCheckBoxMenuItem cb = (JCheckBoxMenuItem) ev.getSource(); boolean state = cb.getState(); if (state) { ToolbarPool.getDefault().setPreferredIconSize(16); } else { ToolbarPool.getDefault().setPreferredIconSize(24); } //Rebuild toolbar panel //#43652: Find current toolbar configuration String name = ToolbarPool.getDefault().getConfiguration(); ToolbarConfiguration tbConf = findConfiguration(name); if (tbConf != null) { tbConf.rebuildPanel(); } rebuildMenu(); } } }); menu.add (cbmi); menu.add (new JPopupMenu.Separator()); // generate list of available toolbar configurations List configList = Arrays.asList (ToolbarPool.getDefault ().getConfigurations ()); // ignore when there is only one toolbar config #39906 if (configList.size() > 1) { it = configList.iterator (); ButtonGroup bg = new ButtonGroup (); final String current = ToolbarPool.getDefault ().getConfiguration (); while (it.hasNext()) { final String name = (String)it.next (); String displayName = findConfiguration(name).getDisplayName(); JRadioButtonMenuItem mi = new JRadioButtonMenuItem ( displayName, (name != null && name.equals(current)) ); mi.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent e) { ErrorManager.getDefault().getInstance(getClass().getName()).log ("Triggered a change in toolbar config from " + current + " to " + name + "."); //NOI18N WindowManagerImpl.getInstance().setToolbarConfigName (name); rebuildMenu(); } }); bg.add (mi); menu.add (mi); } menu.add (new JPopupMenu.Separator()); } JMenuItem menuItem = new JMenuItem(NbBundle.getMessage(ToolbarConfiguration.class, "CTL_DisplayToolbars")); menuItem.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent event) { //#38613 fix -start ConfigureToolbarPanel.showConfigureDialog(new ToolbarFolderNode()); // NodeOperation no = (NodeOperation)Lookup.getDefault().lookup (NodeOperation.class); // no.explore(new ToolbarFolderNode()); //#38613 fix - end } }); menu.add(menuItem); JMenuItem mi = new JMenuItem (getBundleString("PROP_saveAs")); // NOI18N mi.addActionListener (new ActionListener () { public void actionPerformed (ActionEvent e) { NotifyDescriptor.InputLine il = new NotifyDescriptor.InputLine (getBundleString("PROP_saveLabel"), // NOI18N getBundleString("PROP_saveDialog")); // NOI18N il.setInputText (getBundleString("PROP_saveName")); // NOI18N Object ok = org.openide.DialogDisplayer.getDefault ().notify (il); if (ok == NotifyDescriptor.OK_OPTION) { String s = il.getInputText(); if (s.length() != 0) { try { String newName = il.getInputText(); if (tryWriteDocument (newName)) { WindowManagerImpl.getInstance().setToolbarConfigName (newName); } } catch (IOException ioe) { // Bugfix #10779 04 Sep 2001 by Jiri Rechtacek // show a error message ErrorManager.getDefault().notify (ioe); } } } } }); menu.add (mi); } // getContextMenu /** Make toolbar visible/invisible in this configuration * @param tb toolbar * @param b true to make toolbar visible */ public void setToolbarVisible(Toolbar tb, boolean b) { ToolbarConstraints tc = getToolbarConstraints(tb.getName()); if (b) { addVisible(tc); } else { removeVisible(tc); } if (toolbarMenu != null) { //#39808 - somoewhat bruteforce approach, but works and is simple enough. // assumes the toolbar selection is always processed through the setToolbarVisible() method. //correct selection of the toolbar checkboxes in the main menu.. Component[] elements = toolbarMenu.getMenuComponents(); for (int i = 0; i < elements.length; i++) { JComponent component = (JComponent)elements[i]; String tcmenu = (String)component.getClientProperty("ToolbarName"); //NOI18N if (tcmenu != null && tcmenu.equals(tb.getName())) { ((JCheckBoxMenuItem)component).setSelected(b); break; } } } tb.setVisible(b); reflectChanges(); firePropertyChange(); } /** Returns true if the toolbar is visible in this configuration * @param tb toolbar * @return true if the toolbar is visible */ public boolean isToolbarVisible(Toolbar tb) { ToolbarConstraints tc = getToolbarConstraints(tb.getName()); return tc.isVisible(); } PropertyChangeSupport pcs; public void addPropertyChangeListener(PropertyChangeListener l) { if (pcs == null) { pcs = new PropertyChangeSupport(this); } pcs.addPropertyChangeListener(l); } public void removePropertyChangeListener(PropertyChangeListener l) { if (pcs != null) { pcs.removePropertyChangeListener(l); } } private void firePropertyChange() { if (pcs != null) { pcs.firePropertyChange("constraints", null, null); // some constraints have changed } } //// writting /** Try write document to file. It is asked for replacing if there is configuration of same name. * @param cn configuration file name * @return false if don't want replace */ boolean tryWriteDocument (String cn) throws IOException { final FileObject tbFO = NbPlaces.getDefault().toolbars().getPrimaryFile(); FileObject newFO = tbFO.getFileObject(cn, EXT_XML); // Bugfix #10779 04 Sep 2001 by Jiri Rechtacek // Windows are case-insensitive, find for a file by lower-case name if(Utilities.isWindows() && (newFO == null)) { FileObject children[] = tbFO.getChildren(); for(int i=0; i < children.length; i++) if(children[i].getExt().equals(EXT_XML) && cn.toLowerCase().equals(children[i].getName().toLowerCase())) { // there is a file with same name by lower-case newFO = children[i]; cn = children[i].getName(); } } // enf of bugfix #10779 if (newFO != null) { NotifyDescriptor replaceD = new NotifyDescriptor.Confirmation (MessageFormat.format (getBundleString("MSG_replaceConfiguration"), // NOI18N new String [] { cn }), NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.WARNING_MESSAGE); org.openide.DialogDisplayer.getDefault().notify (replaceD); if (replaceD.getValue() != DialogDescriptor.OK_OPTION) { return false; } } writeDocument (cn); return true; } /** Write actual toolbar configuration. */ public void writeDocument () throws IOException { writeDocument (configName); } /** Write toolbar configuration for specified file name to xml. * @param cn configuration file name */ private void writeDocument (final String cn) throws IOException { ERR.log ("writeDocument: " + cn); // NOI18N WritableToolbarConfiguration wtc = new WritableToolbarConfiguration (toolbarRows, invisibleToolbars); final StringBuffer sb = new StringBuffer ("\n\n"); // NOI18N sb.append ("\n\n").append (wtc.toString()); // NOI18N final FileObject tbFO = NbPlaces.getDefault().toolbars().getPrimaryFile(); final FileSystem tbFS = tbFO.getFileSystem(); Object prev = WRITE_IN_PROGRESS.get (); try { WRITE_IN_PROGRESS.set (Boolean.TRUE); tbFS.runAtomicAction (new FileSystem.AtomicAction () { public void run () throws IOException { FileLock lock = null; OutputStream os = null; FileObject xmlFO = tbFO.getFileObject(cn, EXT_XML); if (xmlFO == null) xmlFO = tbFO.createData (cn, EXT_XML); try { lock = xmlFO.lock (); os = xmlFO.getOutputStream (lock); Writer writer = new OutputStreamWriter(os, "UTF-8"); // NOI18N writer.write(sb.toString()); writer.close(); } finally { lastReload = System.currentTimeMillis (); ERR.log ("Setting last reload: " + lastReload); // NOI18N if (os != null) os.close (); if (lock != null) lock.releaseLock (); } } }); } finally { WRITE_IN_PROGRESS.set (prev); } ERR.log ("writeDocument finished"); // NOI18N } /** lazy init of toolbar panel */ private static final synchronized JPanel toolbarPanel () { if (toolbarPanel == null) { toolbarPanel = new JPanel(); toolbarPanel.setLayout(new FlowLayout (FlowLayout.LEFT)); } return toolbarPanel; } /** Listens on changes in the document. */ public void propertyChange(PropertyChangeEvent ev) { if (!XMLDataObject.PROP_DOCUMENT.equals(ev.getPropertyName ())) { // interested only in PROP_DOCUMENT properties return; } if (Boolean.TRUE.equals (WRITE_IN_PROGRESS.get ())) { return; } updateConfiguration((XMLDataObject)ev.getSource()); } /** Updates configuration and also 'configuration over'. * @see #readConfig * @see #checkConfigurationOver */ void updateConfiguration(final XMLDataObject xmlDataObject) { long mod = xmlDataObject.getPrimaryFile ().lastModified().getTime (); ERR.log ("Checking modified: " + lastReload); // NOI18N //Bugfix #10196, this condition commented to make sure that all changes //will be applied. /*if (lastReload >= mod) { // not changed since last refresh return; }*/ // [dafe] - code below demonstrates data integrity problem that occurs // in current toolbar impl. data in toolbar pool and data in toolbar // rows are not maintained centrally, and because of this invoke later, // they are inconsistent for a while (toolbar rows have older data, while // toolbar pool has already new content) // needs architecture redesign IMO SwingUtilities.invokeLater(new Runnable() { public void run () { try { initInstance (); readConfig(xmlDataObject); checkConfigurationOver (); if (configName.equals (toolbarPool ().getConfiguration())) { ERR.log ("Activating the configuration"); // NOI18N // 1st argument is true because the change is important // 2nd argument is false, because it should prevent the system // to write anything do activate (true, false); } } catch (IOException ex) { ErrorManager.getDefault().notify ( ErrorManager.INFORMATIONAL, ex ); } } }); } /** @return upper vertical location of specified row */ int getRowVertLocation (ToolbarRow row) { int index = rowIndex(row); int vertLocation = index * ToolbarLayout.VGAP; Iterator iter = toolbarRows.iterator(); for (int i = 0; i < index; i++) { vertLocation += ((ToolbarRow)iter.next()).getPreferredHeight(); } return vertLocation; } // class WritableToolbarConfiguration static class WritableToolbarConfiguration { /** List of rows. */ Vector rows; /** Create new WritableToolbarConfiguration. * @param rs list of rows * @param iv map of invisible toolbars */ public WritableToolbarConfiguration (Vector rs, Map iv) { initRows (rs); initInvisible (iv); removeEmptyRows(); } /** Init list of writable rows. * @param rs list of rows */ void initRows (Vector rs) { rows = new Vector(); Iterator it = rs.iterator(); while (it.hasNext()) { rows.addElement (new ToolbarRow.WritableToolbarRow ((ToolbarRow)it.next())); } } /** Init invisible toolbars in toolbar rows. * @param iv map of invisible toolbars */ void initInvisible (Map iv) { Iterator it = iv.keySet().iterator(); ToolbarConstraints tc; int row; while (it.hasNext()) { tc = (ToolbarConstraints)it.next(); row = ((Integer)iv.get (tc)).intValue(); for (int i = row; i < row + tc.getRowCount(); i++) { getRow (i).addToolbar (tc); } } } /** Removes empty rows. */ void removeEmptyRows () { ToolbarRow.WritableToolbarRow row; for (int i = rows.size() - 1; i >= 0; i--) { row = (ToolbarRow.WritableToolbarRow)rows.elementAt (i); if (row.isEmpty()) rows.removeElement (row); } } /** * @param r row index * @return WritableToolbarRow for specified row index */ ToolbarRow.WritableToolbarRow getRow (int r) { try { return (ToolbarRow.WritableToolbarRow)rows.elementAt (r); } catch (ArrayIndexOutOfBoundsException e) { rows.addElement (new ToolbarRow.WritableToolbarRow ()); return getRow (r); } } /** @return ToolbarConfiguration in xml format. */ public String toString () { StringBuffer sb = new StringBuffer(); sb.append ("<").append (TAG_CONFIG).append (">\n"); // NOI18N Iterator it = rows.iterator(); while (it.hasNext()) { sb.append (it.next().toString()); } sb.append ("\n"); // NOI18N return sb.toString(); } } // end of class WritableToolbarConfiguration } // end of class Configuration |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.