PageRenderTime 23ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/netbeans-7.3/openide.loaders/src/org/openide/awt/ToolbarPool.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 658 lines | 371 code | 83 blank | 204 comment | 54 complexity | 53d0ddc02c0e3f3f077e1db5590e2050 MD5 | raw file
  1. /*
  2. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  3. *
  4. * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
  5. *
  6. * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
  7. * Other names may be trademarks of their respective owners.
  8. *
  9. * The contents of this file are subject to the terms of either the GNU
  10. * General Public License Version 2 only ("GPL") or the Common
  11. * Development and Distribution License("CDDL") (collectively, the
  12. * "License"). You may not use this file except in compliance with the
  13. * License. You can obtain a copy of the License at
  14. * http://www.netbeans.org/cddl-gplv2.html
  15. * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
  16. * specific language governing permissions and limitations under the
  17. * License. When distributing the software, include this License Header
  18. * Notice in each file and include the License file at
  19. * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
  20. * particular file as subject to the "Classpath" exception as provided
  21. * by Oracle in the GPL Version 2 section of the License file that
  22. * accompanied this code. If applicable, add the following below the
  23. * License Header, with the fields enclosed by brackets [] replaced by
  24. * your own identifying information:
  25. * "Portions Copyrighted [year] [name of copyright owner]"
  26. *
  27. * Contributor(s):
  28. *
  29. * The Original Software is NetBeans. The Initial Developer of the Original
  30. * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
  31. * Microsystems, Inc. All Rights Reserved.
  32. *
  33. * If you wish your version of this file to be governed by only the CDDL
  34. * or only the GPL Version 2, indicate your decision by adding
  35. * "[Contributor] elects to include this software in this distribution
  36. * under the [CDDL or GPL Version 2] license." If you do not indicate a
  37. * single choice of license, a recipient has the option to distribute
  38. * your version of this file under either the CDDL, the GPL Version 2 or
  39. * to extend the choice of license to its licensees as provided above.
  40. * However, if you add GPL Version 2 code and therefore, elected the GPL
  41. * Version 2 license, then the option applies only if the new code is
  42. * made subject to such option by the copyright holder.
  43. */
  44. package org.openide.awt;
  45. import java.awt.BorderLayout;
  46. import java.awt.Component;
  47. import java.awt.EventQueue;
  48. import java.awt.FlowLayout;
  49. import java.awt.event.ActionEvent;
  50. import java.awt.event.ActionListener;
  51. import java.awt.event.MouseEvent;
  52. import java.io.IOException;
  53. import java.util.ArrayList;
  54. import java.util.Collections;
  55. import java.util.Map;
  56. import java.util.TreeMap;
  57. import java.util.logging.Level;
  58. import java.util.logging.Logger;
  59. import javax.accessibility.Accessible;
  60. import javax.accessibility.AccessibleContext;
  61. import javax.accessibility.AccessibleRole;
  62. import javax.swing.ButtonGroup;
  63. import javax.swing.JComponent;
  64. import javax.swing.JComponent.AccessibleJComponent;
  65. import javax.swing.JPanel;
  66. import javax.swing.JPopupMenu;
  67. import javax.swing.JRadioButtonMenuItem;
  68. import org.netbeans.modules.openide.loaders.AWTTask;
  69. import org.netbeans.modules.openide.loaders.DataObjectAccessor;
  70. import org.openide.cookies.InstanceCookie;
  71. import org.openide.filesystems.FileObject;
  72. import org.openide.filesystems.FileUtil;
  73. import org.openide.loaders.DataFolder;
  74. import org.openide.loaders.FolderInstance;
  75. import org.openide.util.Task;
  76. import org.openide.util.TaskListener;
  77. /**
  78. * This class keeps track of the current toolbars and their names.
  79. * @author David Peroutka, Libor Kramolis
  80. */
  81. public final class ToolbarPool extends JComponent implements Accessible {
  82. /** Default ToolbarPool */
  83. private static ToolbarPool defaultPool;
  84. /** objects responsible for creation of the window */
  85. private Folder instance;
  86. /** DataFolder from which the pool was created */
  87. private DataFolder folder;
  88. /** Maps name to <code>Toolbar</code>s */
  89. private Map<String, Toolbar> toolbars;
  90. private ArrayList<String> toolbarNames;
  91. /** Maps name to <code>ToolbarPool.Configuration</code>s */
  92. private Map<String, ToolbarPool.Configuration> toolbarConfigs;
  93. /** Current name of selected configuration */
  94. private String name = ""; // NOI18N
  95. /** Center component */
  96. private Component center;
  97. /** Popup menu listener */
  98. private PopupListener listener;
  99. /** Accessible context */
  100. private AccessibleContext toolbarAccessibleContext;
  101. /** Name of default toolbar configuration. */
  102. public static final String DEFAULT_CONFIGURATION = "Standard"; // NOI18N
  103. /** when it is not wise to wait for full initialization */
  104. private static final ThreadLocal<Boolean> DONT_WAIT = new ThreadLocal<Boolean>();
  105. private TPTaskListener taskListener;
  106. /** Preferred icon size. 2 sizes are supported now: 16 and 24. */
  107. private int preferredIconSize = 24;
  108. /**
  109. * Returns default toolbar pool.
  110. * @return default system pool
  111. */
  112. public static synchronized ToolbarPool getDefault () {
  113. if (defaultPool == null) {
  114. FileObject root = FileUtil.getConfigRoot();
  115. FileObject fo = null;
  116. try {
  117. fo = FileUtil.createFolder(root, "Toolbars"); // NOI18N
  118. } catch (IOException ex) {
  119. Logger.getLogger(ToolbarPool.class.getName()).log(Level.CONFIG, "Cannot create Toolbars folder.", ex);
  120. }
  121. if (fo == null)
  122. throw new IllegalStateException("No Toolbars/"); // NOI18N
  123. DataFolder folder = DataFolder.findFolder(fo);
  124. defaultPool = new ToolbarPool(folder);
  125. // we mustn't do this in constructor to prevent from
  126. // nevereding recursive calls to this method.
  127. defaultPool.instance.recreate();
  128. }
  129. return defaultPool;
  130. }
  131. static final long serialVersionUID =3420915387298484008L;
  132. /**
  133. * Creates a new <code>ToolbarPool</code>. Useful for modules that need they
  134. * own toolbars.
  135. *
  136. * @param df the data folder to read toolbar definitions and configurations from
  137. * @since 1.5
  138. */
  139. public ToolbarPool (DataFolder df) {
  140. folder = df;
  141. setLayout (new BorderLayout ());
  142. listener = new PopupListener();
  143. toolbars = new TreeMap<String, Toolbar>();
  144. toolbarNames = new ArrayList<String>(20);
  145. toolbarConfigs = new TreeMap<String, ToolbarPool.Configuration>();
  146. instance = new Folder (df);
  147. getAccessibleContext().setAccessibleName(instance.instanceName());
  148. getAccessibleContext().setAccessibleDescription(instance.instanceName());
  149. }
  150. /**
  151. * Gets preferred size of icons used by toolbar buttons. Default icon size
  152. * is 24x24. Icon size 16x16 is also supported.
  153. * @return preferred size of toolbar icons in pixels
  154. * @since 4.15
  155. */
  156. public int getPreferredIconSize () {
  157. return preferredIconSize;
  158. }
  159. /**
  160. * Sets preferred size of icons used by toolbar buttons.
  161. * @param preferredIconSize size of toolbar icons in pixels; currently one of 16 or 24
  162. * @throws IllegalArgumentException if an unsupported size is given
  163. * @since 4.15
  164. */
  165. public void setPreferredIconSize (int preferredIconSize) throws IllegalArgumentException {
  166. if ((preferredIconSize != 16) && (preferredIconSize != 24)) {
  167. throw new IllegalArgumentException("Unsupported argument value:" + preferredIconSize); //NOI18N
  168. }
  169. this.preferredIconSize = preferredIconSize;
  170. }
  171. /** Allows to wait till the content of the pool is initialized. */
  172. public final void waitFinished () {
  173. instance.waitFinished();
  174. }
  175. /** Check whether all data needed for the toolbar are read from disk.
  176. *
  177. * @return true if {@link #waitFinished} and other getters will return immediately
  178. * @since 7.30
  179. */
  180. public final boolean isFinished() {
  181. return instance.isFinished();
  182. }
  183. /** Initialization of new values.
  184. * @param toolbars map (String, Toolbar) of toolbars
  185. * @param conf map (String, Configuration) of configs
  186. */
  187. void update (Map<String, Toolbar> toolbars, Map<String, ToolbarPool.Configuration> conf,
  188. ArrayList<String> toolbarNames) {
  189. this.toolbars = toolbars;
  190. this.toolbarNames = new ArrayList<String>( toolbarNames );
  191. this.toolbarConfigs = conf;
  192. if (!"".equals(name)) {
  193. setConfiguration (name);
  194. }
  195. }
  196. /** Updates the default configuration. */
  197. private synchronized void updateDefault () {
  198. Toolbar[] bars = getToolbarsNow ();
  199. name = ""; // NOI18N
  200. if (bars.length == 1) {
  201. revalidate(bars[0]);
  202. } else {
  203. JPanel tp = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 0));
  204. for (int i = 0; i < bars.length; i++) {
  205. tp.add(bars[i]);
  206. }
  207. revalidate(tp);
  208. }
  209. }
  210. /** Activates a configuration.
  211. * @param c configuration
  212. */
  213. private synchronized void activate (Configuration c) {
  214. Component comp = c.activate ();
  215. name = c.getName();
  216. revalidate (comp);
  217. }
  218. /** Sets DnDListener to all Toolbars.
  219. * @deprecated
  220. */
  221. @Deprecated
  222. public void setToolbarsListener (Toolbar.DnDListener l) {
  223. for (Toolbar t: toolbars.values()) {
  224. t.setDnDListener (l);
  225. }
  226. }
  227. /** Uses new component as a cental one. */
  228. private void revalidate (Component c) {
  229. if (c != center) {
  230. // exchange
  231. if (center != null) {
  232. remove (center);
  233. center.removeMouseListener (listener);
  234. }
  235. add (center = c, BorderLayout.CENTER);
  236. center.addMouseListener (listener);
  237. invalidate();
  238. revalidate();
  239. repaint();
  240. }
  241. }
  242. /**
  243. * Returns a <code>Toolbar</code> to which this pool maps the given name.
  244. * @param name a <code>String</code> that is to be a toolbar's name
  245. * @return a <code>Toolbar</code> to which this pool maps the name
  246. */
  247. public final Toolbar findToolbar (String name) {
  248. return toolbars.get (name);
  249. }
  250. /**
  251. * Getter for the name of current configuration.
  252. * @return the name of current configuration
  253. */
  254. public final String getConfiguration () {
  255. return name;
  256. }
  257. /**
  258. * Switch to toolbar configuration by specific config name
  259. * @param n toolbar configuration name
  260. */
  261. public final void setConfiguration (String n) {
  262. Boolean prev = DONT_WAIT.get();
  263. try {
  264. DONT_WAIT.set(true);
  265. setConfigurationNow(n);
  266. } finally {
  267. DONT_WAIT.set(prev);
  268. }
  269. }
  270. private void setConfigurationNow (String n) {
  271. String old = name;
  272. // should be 'instance.waitFinished();' but some bug in isFinished ...
  273. if (!instance.isFinished()) {
  274. if (taskListener == null) {
  275. taskListener = new TPTaskListener();
  276. instance.addTaskListener(taskListener);
  277. }
  278. taskListener.setConfiguration(n);
  279. return;
  280. }
  281. if (taskListener != null) {
  282. instance.removeTaskListener(taskListener);
  283. taskListener = null;
  284. }
  285. Configuration config = null;
  286. if (n != null) {
  287. config = toolbarConfigs.get (n);
  288. }
  289. if (config != null) { // if configuration found
  290. activate (config);
  291. } else if (toolbarConfigs.isEmpty()) { // if no toolbar configuration
  292. updateDefault ();
  293. } else {
  294. // line below commented - bugfix, we need default configuration always when unknown config name is used:
  295. // if (center == null) { // bad config name (n) and no configuration activated yet
  296. config = toolbarConfigs.get (DEFAULT_CONFIGURATION);
  297. if (config == null) {
  298. config = toolbarConfigs.values().iterator().next();
  299. }
  300. activate (config);
  301. }
  302. firePropertyChange("configuration", old, name); //NOI18N
  303. }
  304. /**
  305. * @return the <code>DataFolder</code> from which the pool was created.
  306. */
  307. public final DataFolder getFolder() {
  308. return folder;
  309. }
  310. /**
  311. * Returns the toolbars contained in this pool.
  312. * @return the toolbars contained in this pool
  313. */
  314. public final Toolbar[] getToolbars() {
  315. if (!Boolean.TRUE.equals(DONT_WAIT.get())) {
  316. waitFinished();
  317. }
  318. return getToolbarsNow();
  319. }
  320. final synchronized Toolbar[] getToolbarsNow() {
  321. Toolbar[] arr = new Toolbar[toolbarNames.size ()];
  322. int index = 0;
  323. for( String tn : toolbarNames ) {
  324. arr[index++] = findToolbar(tn);
  325. }
  326. return arr;
  327. }
  328. /**
  329. * @return the names of toolbar configurations contained in this pool
  330. */
  331. public final String[] getConfigurations () {
  332. if (!Boolean.TRUE.equals(DONT_WAIT.get())) {
  333. waitFinished();
  334. }
  335. return getConfigurationsNow();
  336. }
  337. final synchronized String[] getConfigurationsNow () {
  338. ArrayList<String> list = new ArrayList<String>( toolbarConfigs.keySet() );
  339. Collections.sort( list );
  340. String[] arr = new String[ list.size() ];
  341. return list.toArray( arr );
  342. }
  343. /** Read accessible context
  344. * @return - accessible context
  345. */
  346. @Override
  347. public AccessibleContext getAccessibleContext () {
  348. if(toolbarAccessibleContext == null) {
  349. toolbarAccessibleContext = new AccessibleJComponent() {
  350. @Override
  351. public AccessibleRole getAccessibleRole() {
  352. return AccessibleRole.TOOL_BAR;
  353. }
  354. };
  355. }
  356. return toolbarAccessibleContext;
  357. }
  358. /**
  359. * This class is used for delayed setting of configuration after instance
  360. * creation is finished. It may happen during IDE start that
  361. * ToolbarPool.setConfiguration is called before instance is created.
  362. */
  363. private class TPTaskListener implements TaskListener {
  364. private String conf;
  365. TPTaskListener() {}
  366. public void taskFinished(Task task) {
  367. ToolbarPool.this.setConfiguration(conf);
  368. conf = null;
  369. }
  370. void setConfiguration(String conf) {
  371. // #23619: Don't reset already pending configuration to be set.
  372. if(this.conf == null) {
  373. this.conf = conf;
  374. }
  375. }
  376. }
  377. /**
  378. * This class can be used to produce a <code>ToolbarPool</code> instance
  379. * from the given <code>DataFolder</code>.
  380. */
  381. private class Folder extends FolderInstance {
  382. public Folder (DataFolder f) {
  383. super (f);
  384. DataObjectAccessor.DEFAULT.precreateInstances(this);
  385. }
  386. /**
  387. * Full name of the data folder's primary file separated by dots.
  388. * @return the name
  389. */
  390. @Override
  391. public String instanceName () {
  392. return instanceClass().getName();
  393. }
  394. /**
  395. * Returns the root class of all objects.
  396. * @return Object.class
  397. */
  398. @Override
  399. public Class instanceClass () {
  400. return ToolbarPool.class;
  401. }
  402. /**
  403. * Accepts only cookies that can provide <code>Configuration</code>.
  404. * @param cookie the instance cookie to test
  405. * @return true if the cookie can provide <code>Configuration</code>
  406. */
  407. @Override
  408. protected InstanceCookie acceptCookie (InstanceCookie cookie)
  409. throws java.io.IOException, ClassNotFoundException {
  410. Class cls = cookie.instanceClass();
  411. if (ToolbarPool.Configuration.class.isAssignableFrom (cls)) {
  412. return cookie;
  413. }
  414. if (Component.class.isAssignableFrom (cls)) {
  415. return cookie;
  416. }
  417. return null;
  418. }
  419. /**
  420. * Returns a <code>Toolbar.Folder</code> cookie for the specified
  421. * <code>DataFolder</code>.
  422. * @param df a <code>DataFolder</code> to create the cookie for
  423. * @return a <code>Toolbar.Folder</code> for the specified folder
  424. */
  425. @Override
  426. protected InstanceCookie acceptFolder (DataFolder df) {
  427. Toolbar res = new Toolbar(df);
  428. //#223266
  429. FileObject fo = df.getPrimaryFile();
  430. Object disable = fo.getAttribute("nb.toolbar.overflow.disable"); //NOI18N
  431. if (Boolean.TRUE.equals(disable)) {
  432. res.putClientProperty("nb.toolbar.overflow.disable", Boolean.TRUE); //NOI18N
  433. }
  434. return res.waitFinished();
  435. }
  436. /**
  437. * Updates the <code>ToolbarPool</code> represented by this folder.
  438. *
  439. * @param cookies array of instance cookies for the folder
  440. * @return the updated <code>ToolbarPool</code> representee
  441. */
  442. protected Object createInstance (InstanceCookie[] cookies)
  443. throws java.io.IOException, ClassNotFoundException {
  444. assert EventQueue.isDispatchThread() : Thread.currentThread().getName();
  445. final int length = cookies.length;
  446. final Map<String, Toolbar> toolbars = new TreeMap<String, Toolbar> ();
  447. final ArrayList<String> toolbarNames = new ArrayList<String>();
  448. final Map<String, Configuration> conf = new TreeMap<String, Configuration> ();
  449. for (int i = 0; i < length; i++) {
  450. try {
  451. Object obj = cookies[i].instanceCreate();
  452. if (obj instanceof Toolbar) {
  453. Toolbar toolbar = (Toolbar) obj;
  454. // should be done by ToolbarPanel in add method
  455. toolbar.removeMouseListener(listener);
  456. toolbar.addMouseListener(listener);
  457. toolbars.put(toolbar.getName(), toolbar);
  458. toolbarNames.add(toolbar.getName());
  459. continue;
  460. }
  461. if (obj instanceof ToolbarPool.Configuration) {
  462. ToolbarPool.Configuration config = (ToolbarPool.Configuration) obj;
  463. java.lang.String name = config.getName();
  464. if (name == null) {
  465. name = cookies[i].instanceName();
  466. }
  467. conf.put(name, config);
  468. continue;
  469. }
  470. if (obj instanceof Component) {
  471. Component comp = (Component) obj;
  472. String name = comp.getName();
  473. if (name == null) {
  474. name = cookies[i].instanceName();
  475. }
  476. conf.put(name, new ToolbarPool.ComponentConfiguration(comp));
  477. continue;
  478. }
  479. } catch (IOException ex) {
  480. Logger.getLogger(ToolbarPool.class.getName()).log(Level.INFO, "Error while creating toolbars.", ex);
  481. } catch (ClassNotFoundException ex) {
  482. Logger.getLogger(ToolbarPool.class.getName()).log(Level.INFO, "Error while creating toolbars.", ex);
  483. }
  484. }
  485. update (toolbars, conf, toolbarNames);
  486. return ToolbarPool.this;
  487. }
  488. /** Recreate the instance in AWT thread.
  489. */
  490. @Override
  491. protected Task postCreationTask (Runnable run) {
  492. return new AWTTask (run, this);
  493. }
  494. } // end of Folder
  495. /**
  496. * Class to showing popup menu
  497. */
  498. private class PopupListener extends MouseUtils.PopupMouseAdapter {
  499. PopupListener() {}
  500. /**
  501. * Called when the sequence of mouse events should lead to actual showing popup menu
  502. */
  503. protected void showPopup (MouseEvent e) {
  504. Configuration conf = toolbarConfigs.get (name);
  505. if (conf != null) {
  506. JPopupMenu pop = conf.getContextMenu();
  507. pop.show (e.getComponent (), e.getX (), e.getY ());
  508. }
  509. }
  510. } // end of PopupListener
  511. /**
  512. * Abstract class for toolbar configuration
  513. */
  514. public static interface Configuration {
  515. /** Activates the configuration and returns right
  516. * component that can display the configuration.
  517. * @return representation component
  518. */
  519. public abstract Component activate ();
  520. /** Name of the configuration.
  521. * @return the name
  522. */
  523. public abstract String getName ();
  524. /** Popup menu that should be displayed when the users presses
  525. * right mouse button on the panel. This menu can contain
  526. * contains list of possible configurations, additional actions, etc.
  527. *
  528. * @return popup menu to be displayed
  529. */
  530. public abstract JPopupMenu getContextMenu ();
  531. }
  532. /** Implementation of configuration that reacts to one
  533. * component */
  534. private static final class ComponentConfiguration extends JPopupMenu
  535. implements Configuration, ActionListener {
  536. private Component comp;
  537. ComponentConfiguration() {
  538. }
  539. static final long serialVersionUID =-409474484612485719L;
  540. /** @param comp component that represents this configuration */
  541. public ComponentConfiguration (Component comp) {
  542. this.comp = comp;
  543. }
  544. /** Simply returns the representation component */
  545. public Component activate () {
  546. return comp;
  547. }
  548. /** @return name of the component
  549. */
  550. @Override
  551. public String getName () {
  552. return comp.getName ();
  553. }
  554. /** Updates items in popup menu and returns itself.
  555. */
  556. public JPopupMenu getContextMenu () {
  557. removeAll ();
  558. // generate list of available toolbar panels
  559. ButtonGroup bg = new ButtonGroup ();
  560. String current = ToolbarPool.getDefault ().getConfiguration ();
  561. for( String name : ToolbarPool.getDefault().getConfigurationsNow() ) {
  562. JRadioButtonMenuItem mi = new JRadioButtonMenuItem (name, (name.compareTo (current) == 0));
  563. mi.addActionListener (this);
  564. bg.add (mi);
  565. this.add (mi);
  566. }
  567. return this;
  568. }
  569. /** Reacts to action in popup menu. Switches the configuration.
  570. */
  571. public void actionPerformed (ActionEvent evt) {
  572. ToolbarPool.getDefault().setConfiguration (evt.getActionCommand ());
  573. }
  574. }
  575. } // end of ToolbarPool