# This patch file was generated by NetBeans IDE # Following Index: paths are relative to: C:\_r\hg\jet-main # This patch can be applied using context Tools: Patch action on respective folder. # It uses platform neutral UTF-8 encoding and \n newlines. # Above lines and this line are ignored by the patching process. Index: spi.navigator/src/org/netbeans/modules/navigator/NavigatorController.java --- spi.navigator/src/org/netbeans/modules/navigator/NavigatorController.java Base (BASE) +++ spi.navigator/src/org/netbeans/modules/navigator/NavigatorController.java Locally Modified (Based On LOCAL) @@ -47,7 +47,6 @@ import java.awt.Component; import java.awt.EventQueue; import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; @@ -65,11 +64,10 @@ import javax.swing.JComponent; import javax.swing.KeyStroke; import javax.swing.SwingUtilities; +import org.netbeans.spi.navigator.NavigatorDisplayer; import org.netbeans.spi.navigator.NavigatorLookupHint; import org.netbeans.spi.navigator.NavigatorLookupPanelsPolicy; import org.netbeans.spi.navigator.NavigatorPanel; -import org.netbeans.spi.navigator.NavigatorPanelWithUndo; -import org.openide.awt.UndoRedo; import org.openide.filesystems.FileObject; import org.openide.loaders.DataShadow; import org.openide.nodes.Node; @@ -99,7 +97,7 @@ * * @author Dafe Simonek */ -public final class NavigatorController implements LookupListener, ActionListener, +public final class NavigatorController implements LookupListener, PropertyChangeListener, NodeListener, Runnable { /** Time in ms to wait before propagating current node changes further @@ -108,8 +106,10 @@ static final int COALESCE_TIME = 100; /** Asociation with navigator UI, which we control */ - private NavigatorTC navigatorTC; + private NavigatorDisplayer navigatorTC; + private List currentPanels; + /** holds currently scheduled/running task for set data context of selected node */ private RequestProcessor.Task nodeSetterTask; private final Object NODE_SETTER_LOCK = new Object(); @@ -151,22 +151,26 @@ private static final Logger LOG = Logger.getLogger(NavigatorController.class.getName()); /** Creates a new instance of NavigatorController */ - public NavigatorController(NavigatorTC navigatorTC) { + public NavigatorController(NavigatorDisplayer navigatorTC) { this.navigatorTC = navigatorTC; clientsLookup = new ClientsLookup(); panelLookup = Lookups.proxy(new PanelLookupWrapper()); panelLookupListener = new PanelLookupListener(); + navigatorTC.addPropertyChangeListener(this); + TopComponent.getRegistry().addPropertyChangeListener(this); + installActions(); } /** Starts listening to selected nodes and active component */ - public void navigatorTCOpened() { + private void navigatorTCOpened() { + if (panelLookupNodesResult != null) { + return; + } LOG.fine("Entering navigatorTCOpened"); curNodesRes = Utilities.actionsGlobalContext().lookup(CUR_NODES); curNodesRes.addLookupListener(this); curHintsRes = Utilities.actionsGlobalContext().lookup(CUR_HINTS); curHintsRes.addLookupListener(this); - navigatorTC.getPanelSelector().addActionListener(this); - TopComponent.getRegistry().addPropertyChangeListener(this); panelLookupNodesResult = panelLookup.lookup(CUR_NODES); panelLookupNodesResult.addLookupListener(panelLookupListener); @@ -174,12 +178,13 @@ } /** Stops listening to selected nodes and active component */ - public void navigatorTCClosed() { + private void navigatorTCClosed() { + if (panelLookupNodesResult == null) { + return; + } LOG.fine("Entering navigatorTCClosed"); curNodesRes.removeLookupListener(this); curHintsRes.removeLookupListener(this); - navigatorTC.getPanelSelector().removeActionListener(this); - TopComponent.getRegistry().removePropertyChangeListener(this); panelLookupNodesResult.removeLookupListener(panelLookupListener); curNodesRes = null; curHintsRes = null; @@ -195,12 +200,13 @@ selPanel.panelDeactivated(); } lastActivatedRef = null; + currentPanels = null; navigatorTC.setPanels(null, null); panelLookupNodesResult = null; - LOG.fine("navigatorTCClosed: activated nodes: " + navigatorTC.getActivatedNodes()); - if (navigatorTC.getActivatedNodes() != null) { + LOG.fine("navigatorTCClosed: activated nodes: " + navigatorTC.getTopComponent().getActivatedNodes()); + if (navigatorTC.getTopComponent().getActivatedNodes() != null) { LOG.fine("navigatorTCClosed: clearing act nodes..."); - navigatorTC.setActivatedNodes(new Node[0]); + navigatorTC.getTopComponent().setActivatedNodes(new Node[0]); } } @@ -211,24 +217,11 @@ return panelLookup; } - /** Reacts on user selecting some new Navigator panel in panel selector - * combo box - shows the panel user has selected. - */ - public void actionPerformed (ActionEvent e) { - int index = navigatorTC.getPanelSelector().getSelectedIndex(); - if (index == -1) { - // combo box cleared, nothing to activate - return; - } - NavigatorPanel newPanel = navigatorTC.getPanels().get(index); - activatePanel(newPanel); - } - /** Activates given panel. Throws IllegalArgumentException if panel is * not available for activation. */ public void activatePanel (NavigatorPanel panel) { - if (!navigatorTC.getPanels().contains(panel)) { + if (currentPanels == null || !currentPanels.contains(panel)) { throw new IllegalArgumentException("Panel is not available for activation: " + panel); //NOI18N } NavigatorPanel oldPanel = navigatorTC.getSelectedPanel(); @@ -248,11 +241,13 @@ * current navigator hints change, * performs coalescing of fast coming changes. */ + @Override public void resultChanged(LookupEvent ev) { - if (!navigatorTC.equals(WindowManager.getDefault().getRegistry().getActivated()) + if (!navigatorTC.getTopComponent().equals(WindowManager.getDefault().getRegistry().getActivated()) // #117089: allow node change when we are empty || (curNodes == null || curNodes.isEmpty())) { ActNodeSetter nodeSetter = new ActNodeSetter(); + if (navigatorTC.allowAsyncUpdate()) { synchronized (NODE_SETTER_LOCK) { if (nodeSetterTask != null) { nodeSetterTask.cancel(); @@ -261,16 +256,20 @@ nodeSetterTask = RequestProcessor.getDefault().post(nodeSetter, COALESCE_TIME); nodeSetterTask.addTaskListener(nodeSetter); } + } else { + nodeSetter.run(); } } + } /** @return True when update show be performed, false otherwise. Update * isn't needed when current nodes are null and no navigator lookup hints * in lookup. */ private boolean shouldUpdate () { - return TopComponent.getRegistry().getCurrentNodes() != null || - Utilities.actionsGlobalContext().lookup(NavigatorLookupHint.class) != null; + Node[] nodes = TopComponent.getRegistry().getCurrentNodes(); + return (nodes != null && nodes.length > 0) + || Utilities.actionsGlobalContext().lookup(NavigatorLookupHint.class) != null; } private void updateContext () { @@ -292,10 +291,10 @@ } inUpdate = true; + try { // #67599,108066: Some updates runs delayed, so it's possible that // navigator was already closed, that's why the check if (curNodesRes == null) { - inUpdate = false; LOG.fine("Exit because curNodesRes is null, force: " + force); return; } @@ -304,7 +303,6 @@ // which don't define activated nodes Collection nodes = curNodesRes.allInstances(); if (nodes.isEmpty() && !shouldUpdate() && !force) { - inUpdate = false; LOG.fine("Exit because act nodes empty, force: " + force); return; } @@ -332,13 +330,12 @@ } List providers = obtainProviders(nodes); - List oldProviders = navigatorTC.getPanels(); + List oldProviders = currentPanels; final boolean areNewProviders = providers != null && !providers.isEmpty(); // navigator remains empty, do nothing if (oldProviders == null && providers == null) { - inUpdate = false; LOG.fine("Exit because nav remain empty, force: " + force); return; } @@ -354,25 +351,20 @@ clientsLookup.lookup(Node.class); // #93123: refresh providers list if needed if (!oldProviders.equals(providers)) { - // we must disable combo-box listener to not receive unwanted events - // during combo box content change - navigatorTC.getPanelSelector().removeActionListener(this); + currentPanels = providers; navigatorTC.setPanels(providers, null); navigatorTC.setSelectedPanel(selPanel); - navigatorTC.getPanelSelector().addActionListener(this); } // #100122: update activated nodes of Navigator TC updateActNodesAndTitle(); LOG.fine("Exit because same provider and panel, notified. Force: " + force); - inUpdate = false; return; } if (selPanel != null) { // #61334: don't deactivate previous providers if there are no new ones if (!areNewProviders && !force && null != providers) { - inUpdate = false; LOG.fine("Exit because no new providers, force: " + force); return; } @@ -390,26 +382,24 @@ } newSel.panelActivated(clientsLookup); } - // we must disable combo-box listener to not receive unwanted events - // during combo box content change - navigatorTC.getPanelSelector().removeActionListener(this); + currentPanels = providers; navigatorTC.setPanels(providers, newSel); // selected panel changed, update selPanelLookup to listen correctly panelLookup.lookup(Object.class); - navigatorTC.getPanelSelector().addActionListener(this); updateActNodesAndTitle(); LOG.fine("Normal exit, change to new provider, force: " + force); + } finally { inUpdate = false; } + } /** Updates activated nodes of Navigator TopComponent and updates its * display name to reflect activated nodes */ private void updateActNodesAndTitle () { LOG.fine("updateActNodesAndTitle called..."); Node[] actNodes = obtainActivatedNodes(); - navigatorTC.setActivatedNodes(actNodes); updateTCTitle(actNodes); } @@ -522,24 +512,13 @@ } } - /** Retrieves and returns UndoRedo support from selected panel if panel - * offers UndoRedo (implements NavigatorPanelWithUndo). - */ - UndoRedo getUndoRedo () { - NavigatorPanel panel = navigatorTC.getSelectedPanel(); - if (panel == null || !(panel instanceof NavigatorPanelWithUndo)) { - return UndoRedo.NONE; - } - return ((NavigatorPanelWithUndo)panel).getUndoRedo(); - } - /** Installs user actions handling for NavigatorTC top component */ public void installActions () { // ESC key handling - return focus to previous focus owner KeyStroke returnKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true); //JComponent contentArea = navigatorTC.getContentArea(); - navigatorTC.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(returnKey, "return"); //NOI18N - navigatorTC.getActionMap().put("return", new ESCHandler()); //NOI18N + navigatorTC.getTopComponent().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(returnKey, "return"); //NOI18N + navigatorTC.getTopComponent().getActionMap().put("return", new ESCHandler()); //NOI18N } /***** PropertyChangeListener implementation *******/ @@ -555,27 +534,37 @@ if (tc != null && tc != navigatorTC) { lastActivatedRef = new WeakReference(tc); } + } else if (TopComponent.Registry.PROP_TC_OPENED.equals(evt.getPropertyName())) { + if (evt.getNewValue() == navigatorTC.getTopComponent()) { + navigatorTCOpened(); + } } else if (TopComponent.Registry.PROP_TC_CLOSED.equals(evt.getPropertyName())) { + if (evt.getNewValue() == navigatorTC.getTopComponent()) { + navigatorTCClosed(); + } else if (panelLookupNodesResult != null) { // force update context if some tc was closed // invokeLater to let node change perform before calling update LOG.fine("Component closed, invoking update through invokeLater..."); // #124061 - force navigator cleanup in special situation TopComponent tc = TopComponent.getRegistry().getActivated(); - if (tc == navigatorTC) { + if (tc == navigatorTC.getTopComponent()) { LOG.fine("navigator active, clearing its activated nodes"); - navigatorTC.setActivatedNodes(new Node[0]); + navigatorTC.getTopComponent().setActivatedNodes(new Node[0]); } EventQueue.invokeLater(this); } + } else if (NavigatorDisplayer.PROP_PANEL_SELECTION.equals(evt.getPropertyName())) { + activatePanel((NavigatorPanel) evt.getNewValue()); } + } /****** NodeListener implementation *****/ public void nodeDestroyed(NodeEvent ev) { LOG.fine("Node destroyed reaction..."); // #121944: don't react on node destroy when we are active - if (navigatorTC.equals(WindowManager.getDefault().getRegistry().getActivated())) { + if (navigatorTC.getTopComponent().equals(WindowManager.getDefault().getRegistry().getActivated())) { LOG.fine("NavigatorTC active, skipping node destroyed reaction."); return; } @@ -657,7 +646,7 @@ // but not combo box to preserve its ESC functionality if (lastActivatedRef == null || focusOwner == null || - !SwingUtilities.isDescendingFrom(focusOwner, navigatorTC) || + !SwingUtilities.isDescendingFrom(focusOwner, navigatorTC.getTopComponent()) || focusOwner instanceof JComboBox) { return; } Index: spi.navigator/src/org/netbeans/modules/navigator/NavigatorTC.java --- spi.navigator/src/org/netbeans/modules/navigator/NavigatorTC.java Base (BASE) +++ spi.navigator/src/org/netbeans/modules/navigator/NavigatorTC.java Locally Modified (Based On LOCAL) @@ -46,6 +46,8 @@ import java.awt.BorderLayout; import java.awt.Color; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.util.List; import java.util.logging.Logger; import javax.swing.BorderFactory; @@ -55,7 +57,9 @@ import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIManager; +import org.netbeans.spi.navigator.NavigatorDisplayer; import org.netbeans.spi.navigator.NavigatorPanel; +import org.netbeans.spi.navigator.NavigatorPanelWithUndo; import org.openide.ErrorManager; import org.openide.awt.UndoRedo; import org.openide.util.HelpCtx; @@ -72,7 +76,7 @@ * * @author Dafe Simonek */ -public final class NavigatorTC extends TopComponent { +public final class NavigatorTC extends TopComponent implements NavigatorDisplayer { /** singleton instance */ private static NavigatorTC instance; @@ -80,12 +84,14 @@ /** Currently active panel in navigator (or null if empty) */ private NavigatorPanel selectedPanel; /** A list of panels currently available (or null if empty) */ - private List panels; + private List panels; /** Controller, controls behaviour and reacts to user actions */ private NavigatorController controller; /** label signalizing no available providers */ private final JLabel notAvailLbl = new JLabel( NbBundle.getMessage(NavigatorTC.class, "MSG_NotAvailable")); //NOI18N + /** Listener for the panel selector combobox */ + private ActionListener panelSelectionListener; /** Creates new NavigatorTC, singleton */ private NavigatorTC() { @@ -110,7 +116,18 @@ holderPanel.setOpaque(false); - getController().installActions(); + panelSelectionListener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + int idx = panelSelector.getSelectedIndex(); + if (panels != null && idx >= 0 && idx < panels.size() + && panels.get(idx) != selectedPanel) { + NavigatorTC.this.firePropertyChange(PROP_PANEL_SELECTION, + selectedPanel, panels.get(idx)); + } + } + }; + panelSelector.addActionListener(panelSelectionListener); associateLookup( new ProxyLookup( @@ -158,8 +175,19 @@ return instance; } + @Override + public boolean allowAsyncUpdate() { + return true; + } + + @Override + public TopComponent getTopComponent() { + return this; + } + /** Shows given navigator panel's component */ + @Override public void setSelectedPanel (NavigatorPanel panel) { int panelIdx = panels.indexOf(panel); assert panelIdx != -1 : "Panel to select is not available"; //NOI18N @@ -184,21 +212,24 @@ revalidate(); repaint(); } + panelSelector.removeActionListener(panelSelectionListener); // #93123: follow-up, synchronizing combo selection with content area selection panelSelector.setSelectedIndex(panelIdx); + panelSelector.addActionListener(panelSelectionListener); } /** Returns panel currently selected. * @return Panel currently selected or null if navigator is empty */ + @Override public NavigatorPanel getSelectedPanel () { return selectedPanel; } - /** List of panels currently contained in navigator component. + /** Only for tests. List of panels currently contained in navigator component. * @return List of NavigatorPanel instances or null if navigator is empty */ - public List getPanels () { + public List getPanels () { return panels; } @@ -206,7 +237,8 @@ * @param panels List of panels * @param select Panel to be selected, shown */ - public void setPanels (List panels, NavigatorPanel select) { + @Override + public void setPanels (List panels, NavigatorPanel select) { this.panels = panels; int panelsCount = panels == null ? -1 : panels.size(); selectedPanel = null; @@ -215,6 +247,7 @@ setToEmpty(); } else { // clear regular content + panelSelector.removeActionListener(panelSelectionListener); contentArea.removeAll(); panelSelector.removeAllItems(); // #63777: hide panel selector when only one panel available @@ -228,6 +261,7 @@ } i++; } + panelSelector.addActionListener(panelSelectionListener); if (selectFound) { setSelectedPanel(select); } else { @@ -238,8 +272,8 @@ } } - /** Returns combo box, UI for selecting proper panels */ - public JComboBox getPanelSelector () { + /** Returns combo box, UI for selecting proper panels. For tests only. */ + JComboBox getPanelSelector () { return panelSelector; } @@ -281,24 +315,15 @@ return new HelpCtx("navigator.java"); } - /** Just delegates to controller */ - @Override - public void componentOpened () { - getController().navigatorTCOpened(); - } - - /** Just delegates to controller */ - @Override - public void componentClosed () { - getController().navigatorTCClosed(); - } - // << Window system @Override public UndoRedo getUndoRedo() { - return getController().getUndoRedo(); + if (selectedPanel == null || !(selectedPanel instanceof NavigatorPanelWithUndo)) { + return UndoRedo.NONE; } + return ((NavigatorPanelWithUndo)selectedPanel).getUndoRedo(); + } /** Accessor for controller which controls UI behaviour */ public NavigatorController getController () { Index: spi.navigator/src/org/netbeans/spi/navigator/NavigatorDisplayer.java --- spi.navigator/src/org/netbeans/spi/navigator/NavigatorDisplayer.java Base (BASE) +++ spi.navigator/src/org/netbeans/spi/navigator/NavigatorDisplayer.java Locally New @@ -0,0 +1,117 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ + +package org.netbeans.spi.navigator; + +import java.beans.PropertyChangeListener; +import java.util.List; +import org.openide.windows.TopComponent; + +/** + * Abstraction of displaying the Navigator UI. Implement only if you need to + * display the navigator differently from the standard Navigator window. + *

+ * By default the standard Navigator TopComponent is provided which manages the + * navigator panels. An alternative visualization/placement can be specified by + * implementing this interface and registering it in META-INF/services. The + * methods of the interface get call by the navigator module based on what it + * needs at the moment. + * + * @author Tomas Pavek + */ +public interface NavigatorDisplayer { + /** + * Property name to be fired when the selected panel changes in the UI. + */ + String PROP_PANEL_SELECTION = "navigatorPanelSelection"; // NOI18N + + /** + * Called with the display name of currently selected objects (nodes). + * It should appear e.g. in the title of the enclosing window. + * @param name The name of selected object(s) + */ + void setDisplayName(String name); + + /** + * Called to set all the panels to display, plus which one should be selected. + * @param panels The panels to display + * @param select The panel to select (can be null) + */ + void setPanels(List panels, NavigatorPanel select); + + /** + * Called to select given panel in the UI. + * @param panel The panel to select + */ + void setSelectedPanel(NavigatorPanel panel); + + /** + * @return The currently selected panel in the UI (can be null) + */ + NavigatorPanel getSelectedPanel(); + + /** + * Tells the navigator whether it can postpone reaction to context changes + * (possibly coalesce frequent changes) when computing the panels. In other + * words, whether it can be behind the global context sometimes. (It may + * cause problems in some situations.) + * @return false if navigator should react synchronously + */ + boolean allowAsyncUpdate(); + + /** + * @return The enclosing TopComponent of the navigator UI + */ + TopComponent getTopComponent(); + + /** + * Add a listener for PROP_PANEL_SELECTION property change. + * @param l the listener + */ + void addPropertyChangeListener(PropertyChangeListener l); + + /** + * Remove a listener for PROP_PANEL_SELECTION property change. + * @param l the listener + */ + void removePropertyChangeListener(PropertyChangeListener l); +} Index: spi.navigator/src/org/netbeans/spi/navigator/NavigatorHandler.java --- spi.navigator/src/org/netbeans/spi/navigator/NavigatorHandler.java Base (BASE) +++ spi.navigator/src/org/netbeans/spi/navigator/NavigatorHandler.java Locally Modified (Based On LOCAL) @@ -44,7 +44,9 @@ package org.netbeans.spi.navigator; +import org.netbeans.modules.navigator.NavigatorController; import org.netbeans.modules.navigator.NavigatorTC; +import org.openide.util.Lookup; /** * Set of methods for driving navigator behaviour. @@ -53,6 +55,8 @@ */ public final class NavigatorHandler { + private static NavigatorController controller; + /** No external instantiation allowed. */ private NavigatorHandler () { @@ -74,7 +78,34 @@ * @throws IllegalArgumentException if given panel is not available */ public static void activatePanel (NavigatorPanel panel) { - NavigatorTC.getInstance().getController().activatePanel(panel); + getController().activatePanel(panel); } + /** + * If there is a custom NavigatorDisplayer implementation, it should call + * this method just before its UI shows up (before the enclosing + * TopComponent is opened) to actually initialize the navigator. From this + * point the navigator observes the TopComponent and once it is opened, it + * starts collecting panels from the providers and passing them to the + * displayer. + *

+ * If there is no custom NavigatorDisplayer registered, the navigator's own + * (default) TopComponent will be used and it also takes care of + * initializing the navigator automatically. No need to call this method then. + */ + public static void activateNavigator() { + getController(); } + + private static NavigatorController getController() { + if (controller == null) { + NavigatorDisplayer display = Lookup.getDefault().lookup(NavigatorDisplayer.class); + if (display != null) { + controller = new NavigatorController(display); + } else { // use the navigator's own TopComponent + controller = NavigatorTC.getInstance().getController(); + } + } + return controller; + } +} Index: spi.navigator/test/unit/src/org/netbeans/modules/navigator/NavigatorControllerTest.java --- spi.navigator/test/unit/src/org/netbeans/modules/navigator/NavigatorControllerTest.java Base (BASE) +++ spi.navigator/test/unit/src/org/netbeans/modules/navigator/NavigatorControllerTest.java Locally Modified (Based On LOCAL) @@ -98,7 +98,6 @@ URL url = NavigatorControllerTest.class.getResource("resources/sample_folder/subfolder1/subfolder2"); assertNotNull("url not found.", url); - FileUtil.setMIMEType("my_extension", "NavigatorControllerTest/TestMimeType"); FileObject fo = URLMapper.findFileObject(url); FileObject[] fos = fo.getChildren(); fo = fo.getFileObject("Nic.my_extension"); @@ -115,7 +114,7 @@ System.out.println("Testing DataShadow resolvement..."); // not really valid, uses impl fact that during obtainProviders, // NavigatorTC parameter will not be needed. - NavigatorController nc = new NavigatorController(null); + NavigatorController nc = NavigatorTC.getInstance().getController(); ArrayList shadow1Node = new ArrayList(1); shadow1Node.add(shadow1.getNodeDelegate()); List result = nc.obtainProviders(shadow1Node); Index: spi.navigator/test/unit/src/org/netbeans/modules/navigator/NavigatorTCTest.java --- spi.navigator/test/unit/src/org/netbeans/modules/navigator/NavigatorTCTest.java Base (BASE) +++ spi.navigator/test/unit/src/org/netbeans/modules/navigator/NavigatorTCTest.java Locally Modified (Based On LOCAL) @@ -44,6 +44,7 @@ package org.netbeans.modules.navigator; +import java.beans.PropertyChangeEvent; import java.lang.ref.WeakReference; import java.net.URL; import java.util.ArrayList; @@ -72,9 +73,12 @@ import org.openide.nodes.Node; import org.openide.util.ContextGlobalProvider; import org.openide.util.Lookup; +import org.openide.util.Mutex; import org.openide.util.lookup.AbstractLookup; import org.openide.util.lookup.InstanceContent; import org.openide.util.lookup.Lookups; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; /** @@ -94,9 +98,12 @@ TestLookupHint ostravskiHint = new TestLookupHint("ostravski/gyzd"); //nodesLkp.setNodes(new Node[]{ostravskiNode}); ic.add(ostravskiHint); + TestLookupHint prazskyHint = new TestLookupHint("prazsky/pepik"); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); + try { + navTCH.open(); NavigatorPanel selPanel = navTC.getSelectedPanel(); @@ -107,7 +114,6 @@ 1, ostravak.getPanelActivatedCallsCount()); assertEquals(0, ostravak.getPanelDeactivatedCallsCount()); - TestLookupHint prazskyHint = new TestLookupHint("prazsky/pepik"); ic.add(prazskyHint); ic.remove(ostravskiHint); @@ -142,15 +148,18 @@ assertFalse(prazak.wasActCalledOnActive()); assertFalse(prazak.wasDeactCalledOnInactive()); - navTC.componentClosed(); + navTCH.close(); selPanel = navTC.getSelectedPanel(); assertNull("Selected panel should be null", selPanel); assertNull("Set of panels should be null", navTC.getPanels()); - + } finally { // clean + navTCH.close(); ic.remove(ostravskiHint); + ic.remove(prazskyHint); } + } public void testBugfix104145_DeactivatedNotCalled () throws Exception { System.out.println("Testing bugfix 104145..."); @@ -158,16 +167,17 @@ TestLookupHint ostravskiHint = new TestLookupHint("ostravski/gyzd"); ic.add(ostravskiHint); + NavigatorTC navTC = NavigatorTC.getInstance(); + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); try { - NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + navTCH.open(); NavigatorPanel selPanel = navTC.getSelectedPanel(); OstravskiGyzdProvider ostravak = (OstravskiGyzdProvider) selPanel; ostravak.resetDeactCalls(); - navTC.componentClosed(); + navTCH.close(); int deact = ostravak.getPanelDeactivatedCallsCount(); assertEquals("panelDeactivated expected to be called once but called " + deact + " times.", @@ -175,6 +185,7 @@ } finally { // clean in finally block so that test doesn't affect others + navTCH.close(); ic.remove(ostravskiHint); } @@ -188,7 +199,9 @@ ic.add(ostravskiHint); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); + try { + navTCH.open(); NavigatorPanel selPanel = navTC.getSelectedPanel(); @@ -205,10 +218,12 @@ selPanel = navTC.getSelectedPanel(); assertNotNull("Selected panel is null", selPanel); assertTrue("Panel class not expected", selPanel instanceof OstravskiGyzdProvider); - + } finally { // cleanup - navTC.componentClosed(); + navTCH.close(); + ic.remove(ostravskiHint); } + } public void testBugfix93123_RefreshCombo () throws Exception { System.out.println("Testing bugfix 93123, correct refreshing of combo box with providers list..."); @@ -219,23 +234,32 @@ ic.add(ostravskiHint); TestLookupHint prazskyHint = new TestLookupHint("prazsky/pepik"); ic.add(prazskyHint); + TestLookupHint prazskyHint2 = new TestLookupHint("moravsky/honza"); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); + try { + navTCH.open(); - List panels = navTC.getPanels(); + List panels = navTC.getPanels(); assertNotNull("Selected panel should not be null", navTC.getSelectedPanel()); assertTrue("Expected 2 provider panels, but got " + panels.size(), panels.size() == 2); - NavigatorHandler.activatePanel(panels.get(1)); + final NavigatorPanel panel = panels.get(1); + Mutex.EVENT.readAccess(new Mutex.ExceptionAction() { + @Override + public Object run() throws Exception { + NavigatorHandler.activatePanel(panel); + return null; + } + }); NavigatorPanel selPanel = navTC.getSelectedPanel(); int selIdx = panels.indexOf(selPanel); assertTrue("Expected selected provider #2, but got #1", selIdx == 1); - TestLookupHint prazskyHint2 = new TestLookupHint("moravsky/honza"); ic.add(prazskyHint2); // wait for selected node change to be applied, because changes are @@ -254,13 +278,14 @@ assertTrue("Expected the same selection in combo, sel panel index: " + selIdx + ", sel in combo index: " + combo.getSelectedIndex(), selIdx == combo.getSelectedIndex()); - + } finally { // cleanup + navTCH.close(); ic.remove(ostravskiHint); ic.remove(prazskyHint); ic.remove(prazskyHint2); - navTC.componentClosed(); } + } /** Test for IZ feature #93711. It tests ability of NavigatorPanel implementors * to provide activated nodes for whole navigator panel TopComponent. @@ -277,11 +302,11 @@ ic.add(actNodesHint); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); - + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); try { + navTCH.open(); - List panels = navTC.getPanels(); + List panels = navTC.getPanels(); assertNotNull("Selected panel should not be null", navTC.getSelectedPanel()); assertTrue("Expected 1 provider panel, but got " + panels.size(), panels != null && panels.size() == 1); assertTrue("Panel class not expected", panels.get(0) instanceof ActNodeLookupProvider); @@ -294,13 +319,16 @@ // test if lookup content from provider propagated correctly to the // activated nodes of navigator TopComponent Node[] actNodes = navTC.getActivatedNodes(); + Collection lookupNodes = navTC.getLookup().lookupAll(Node.class); Node realContent = provider.getCurLookupContent(); String tcDisplayName = navTC.getDisplayName(); String providerDisplayName = provider.getDisplayName(); assertNotNull("Activated nodes musn't be null", actNodes); assertTrue("Expected 1 activated node, but got " + actNodes.length, actNodes.length == 1); + assertTrue("Expected 1 node in lookup, but got " + lookupNodes.size(), lookupNodes.size() == 1); assertTrue("Incorrect instance of activated node " + actNodes[0].getName(), actNodes[0] == realContent); + assertTrue("Different node in lookup than the activated node", realContent == lookupNodes.iterator().next()); assertTrue("Expected display name starting with '" + providerDisplayName + "', but got '" + tcDisplayName + "'", (tcDisplayName != null) && tcDisplayName.startsWith(providerDisplayName)); @@ -323,7 +351,7 @@ (tcDisplayName != null) && tcDisplayName.startsWith(providerDisplayName)); } finally { // cleanup - navTC.componentClosed(); + navTCH.close(); ic.remove(actNodesHint); } } @@ -341,7 +369,9 @@ ic.add(undoHint); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); + try { + navTCH.open(); NavigatorPanel selPanel = navTC.getSelectedPanel(); assertNotNull("Selected panel should not be null", navTC.getSelectedPanel()); @@ -352,12 +382,12 @@ UndoRedo tcUndo = navTC.getUndoRedo(); assertTrue("Expected undo manager " + panelUndo + ", but got " + tcUndo, panelUndo == tcUndo); - + } finally { // cleanup + navTCH.close(); ic.remove(undoHint); - navTC.componentClosed(); - } + } /** Test for IZ issue #113764. Checks that after closing navigator window, clientsLookup * in NavigatorController is updated properly and does not hold Node instance through @@ -377,7 +407,9 @@ ic.add(actNode); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); + try { + navTCH.open(); // wait for selected node change to be applied, because changes are // reflected with little delay @@ -396,16 +428,18 @@ // erase, close and check, lookup should be freed lkpArray = null; - navTC.componentClosed(); + navTCH.close(); for (WeakReference wLkp : wLkps) { assertGC("Lookup instance NavigatorController.getLookup() still not GCed", wLkp); } - + } finally { // cleanup + navTCH.close(); ic.remove(actNodesHint); ic.remove(actNode); } + } /** */ @@ -418,9 +452,11 @@ ic.add(explorerHint); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); + try { + navTCH.open(); - List panels = navTC.getPanels(); + List panels = navTC.getPanels(); assertNotNull("Selected panel should not be null", navTC.getSelectedPanel()); assertTrue("Expected 1 provider panel, but got " + panels.size(), panels != null && panels.size() == 1); assertTrue("Panel class not expected", panels.get(0) instanceof ListViewNavigatorPanel); @@ -454,11 +490,12 @@ } } assertTrue("Action " + DefaultEditorKit.copyAction + " not found in action map", found); - + } finally { // cleanup + navTCH.close(); ic.remove(explorerHint); - navTC.componentClosed(); } + } public void test_112954_LastSelected () throws Exception { System.out.println("Testing feature #112954, remembering last selected panel for context type..."); @@ -468,7 +505,6 @@ URL url = NavigatorControllerTest.class.getResource("resources/lastsel/file.lastsel_mime1"); assertNotNull("url not found.", url); - FileUtil.setMIMEType("lastsel_mime1", "lastsel/mime1"); FileObject fo = URLMapper.findFileObject(url); assertNotNull("File object for test node not found.", fo); DataObject dObj = DataObject.find(fo); @@ -480,10 +516,11 @@ ic.add(mime1Node); NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); - + NavigatorTCHandle navTCH = new NavigatorTCHandle(navTC); try { - List panels = navTC.getPanels(); + navTCH.open(); + + List panels = navTC.getPanels(); assertNotNull("Selected panel should not be null", navTC.getSelectedPanel()); assertTrue("Expected 3 provider panels, but got " + panels.size(), panels != null && panels.size() == 3); assertTrue("Panel class not expected", panels.get(0) instanceof LastSelMime1Panel1); @@ -491,7 +528,14 @@ assertTrue("Panel class not expected", panels.get(2) instanceof LastSelMime1Panel3); // selecting 3rd panel, this should be remembered - navTC.getController().activatePanel(panels.get(2)); + final NavigatorPanel p3 = panels.get(2); + Mutex.EVENT.readAccess(new Mutex.ExceptionAction() { + @Override + public Object run() throws Exception { + NavigatorHandler.activatePanel(p3); + return null; + } + }); ic.remove(mime1Node); ic.add(mime2Hint); @@ -508,7 +552,14 @@ assertTrue("Panel class not expected", panels.get(2) instanceof LastSelMime2Panel3); // selecting 2nd panel, this should be remembered - navTC.getController().activatePanel(panels.get(1)); + final NavigatorPanel p2 = panels.get(1); + Mutex.EVENT.readAccess(new Mutex.ExceptionAction() { + @Override + public Object run() throws Exception { + NavigatorHandler.activatePanel(p2); + return null; + } + }); ic.remove(mime2Hint); ic.add(mime1Node); @@ -538,7 +589,8 @@ assertTrue("Expected LastSelMime2Panel2 panel to be selected, but selected is " + navTC.getSelectedPanel().getClass().getSimpleName(), navTC.getSelectedPanel() instanceof LastSelMime2Panel2); } finally { - navTC.componentClosed(); + navTCH.close(); + ic.remove(mime1Node); ic.remove(mime2Hint); } } @@ -569,6 +621,32 @@ } } + private static class NavigatorTCHandle { + private NavigatorTC navTC; + NavigatorTCHandle(NavigatorTC navTC) { + this.navTC = navTC; + } + void open() throws Exception { + Mutex.EVENT.readAccess(new Mutex.ExceptionAction() { + @Override + public Object run() throws Exception { + navTC.getController().propertyChange( + new PropertyChangeEvent(navTC, TopComponent.Registry.PROP_TC_OPENED, null, navTC)); + return null; + } + }); + } + void close() throws Exception { +// Mutex.EVENT.readAccess(new Mutex.ExceptionAction() { +// @Override +// public Object run() throws Exception { + navTC.getController().propertyChange( + new PropertyChangeEvent(navTC, TopComponent.Registry.PROP_TC_CLOSED, null, navTC)); +// return null; +// } +// }); + } + } /** Test provider base, to test that infrastucture calls correct * methods in correct order. Index: spi.navigator/test/unit/src/org/netbeans/modules/navigator/resources/NavigatorControllerTestProvider.xml --- spi.navigator/test/unit/src/org/netbeans/modules/navigator/resources/NavigatorControllerTestProvider.xml Base (BASE) +++ spi.navigator/test/unit/src/org/netbeans/modules/navigator/resources/NavigatorControllerTestProvider.xml Locally Modified (Based On LOCAL) @@ -64,6 +64,20 @@ + + + + + + + + + + +]]> + + + Index: spi.navigator/test/unit/src/org/netbeans/modules/navigator/resources/testCorrectCallsOfNavigatorPanelMethodsLayer.xml --- spi.navigator/test/unit/src/org/netbeans/modules/navigator/resources/testCorrectCallsOfNavigatorPanelMethodsLayer.xml Base (BASE) +++ spi.navigator/test/unit/src/org/netbeans/modules/navigator/resources/testCorrectCallsOfNavigatorPanelMethodsLayer.xml Locally Modified (Based On LOCAL) @@ -132,6 +132,20 @@ + + + + + + + + + + +]]> + + + Index: spi.navigator/test/unit/src/org/netbeans/spi/navigator/NavigatorHandlerTest.java --- spi.navigator/test/unit/src/org/netbeans/spi/navigator/NavigatorHandlerTest.java Base (BASE) +++ spi.navigator/test/unit/src/org/netbeans/spi/navigator/NavigatorHandlerTest.java Locally Modified (Based On LOCAL) @@ -44,6 +44,7 @@ package org.netbeans.spi.navigator; +import java.beans.PropertyChangeEvent; import java.util.List; import javax.swing.JComponent; import javax.swing.JPanel; @@ -52,9 +53,11 @@ import org.netbeans.modules.navigator.UnitTestUtils; import org.openide.util.ContextGlobalProvider; import org.openide.util.Lookup; +import org.openide.util.Mutex; import org.openide.util.lookup.AbstractLookup; import org.openide.util.lookup.InstanceContent; import org.openide.util.lookup.Lookups; +import org.openide.windows.TopComponent; /** @@ -80,13 +83,21 @@ TestLookupHint hint = new TestLookupHint("NavigatorHandlerTest/TestMimeType"); ic.add(hint); - NavigatorTC navTC = NavigatorTC.getInstance(); - navTC.componentOpened(); + final NavigatorTC navTC = NavigatorTC.getInstance(); + try { + Mutex.EVENT.readAccess(new Mutex.ExceptionAction() { + @Override + public Object run() throws Exception { + navTC.getController().propertyChange( + new PropertyChangeEvent(navTC, TopComponent.Registry.PROP_TC_OPENED, null, navTC)); + return null; + } + }); NavigatorPanel selPanel = navTC.getSelectedPanel(); assertNotNull("Selected panel is null", selPanel); - List panels = navTC.getPanels(); + List panels = navTC.getPanels(); assertEquals(2, panels.size()); int selIndex = panels.indexOf(selPanel); @@ -94,17 +105,23 @@ System.out.println("selected panel before: " + navTC.getSelectedPanel().getDisplayName()); - if (selIndex == 0) { - NavigatorHandler.activatePanel(panels.get(1)); - } else { - NavigatorHandler.activatePanel(panels.get(0)); + final NavigatorPanel panel = panels.get(selIndex == 0 ? 1:0); + Mutex.EVENT.readAccess(new Mutex.ExceptionAction() { + @Override + public Object run() throws Exception { + NavigatorHandler.activatePanel(panel); + return null; } + }); assertTrue(selPanel != navTC.getSelectedPanel()); System.out.println("selected panel after: " + navTC.getSelectedPanel().getDisplayName()); - + } finally { + navTC.getController().propertyChange( + new PropertyChangeEvent(navTC, TopComponent.Registry.PROP_TC_CLOSED, null, navTC)); } + } /** Panel implementation 1 */