diff --git a/spi.debugger.ui/apichanges.xml b/spi.debugger.ui/apichanges.xml --- a/spi.debugger.ui/apichanges.xml +++ b/spi.debugger.ui/apichanges.xml @@ -172,6 +172,25 @@ + + + + EngineComponentsProvider interface added. + + + + + +

+ EngineComponentsProvider interface introduced + to provide GUI components that are associated with a debugger + engine. EngineComponentsProvider.ComponentInfo + provides information about the associated component. +

+
+ + +
diff --git a/spi.debugger.ui/manifest.mf b/spi.debugger.ui/manifest.mf --- a/spi.debugger.ui/manifest.mf +++ b/spi.debugger.ui/manifest.mf @@ -2,6 +2,6 @@ OpenIDE-Module: org.netbeans.spi.debugger.ui/1 OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/debugger/ui/Bundle.properties OpenIDE-Module-Layer: org/netbeans/modules/debugger/resources/mf-layer.xml -OpenIDE-Module-Specification-Version: 2.34 +OpenIDE-Module-Specification-Version: 2.35 OpenIDE-Module-Provides: org.netbeans.spi.debugger.ui OpenIDE-Module-Install: org/netbeans/modules/debugger/ui/DebuggerModule.class diff --git a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/ComponentInfoFromBeanContext.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/ComponentInfoFromBeanContext.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/ComponentInfoFromBeanContext.java @@ -0,0 +1,133 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.debugger.ui; + +import java.awt.Component; +import java.beans.DesignMode; +import java.beans.beancontext.BeanContextChildComponentProxy; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import javax.swing.SwingUtilities; +import org.netbeans.api.debugger.Properties; +import org.netbeans.spi.debugger.ui.EngineComponentsProvider.ComponentInfo; +import org.openide.util.Exceptions; +import org.openide.windows.TopComponent; + +/** + * A helper class, which transforms the old providing of associated GUI components + * via BeanContextChildComponentProxy to the new API {@link ComponentInfo}. + * + * @author Martin Entlicher + */ +public class ComponentInfoFromBeanContext { + + private static final String PROPERTY_CLOSED_TC = "closedTopComponents"; // NOI18N + + public static Transform TRANSFORM; // Initialized from EngineComponentsProvider + + static List transform(List componentProxies) { + ComponentInfo.class.getName(); // Initializes TRANSFORM + List cinfos = new ArrayList(componentProxies.size()); + for (final BeanContextChildComponentProxy cp : componentProxies) { + final Component[] c = new Component[] { null }; + final boolean[] doOpen = new boolean[] { false }; + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + c[0] = cp.getComponent(); + doOpen[0] = (cp instanceof DesignMode) ? ((DesignMode) cp).isDesignTime() : true; + } + }); + if (c[0] == null) { + //throw new NullPointerException("No component from "+cp); + continue; + } + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + continue; + } + //cs.add(c[0]); + boolean open = doOpen[0]; + if (c[0] instanceof TopComponent) { + final TopComponent tc = (TopComponent) c[0]; + boolean wasClosed = Properties.getDefault().getProperties(DebuggerManagerListener.class.getName()). + getProperties(PROPERTY_CLOSED_TC).getBoolean(tc.getName(), false); + boolean wasOpened = !Properties.getDefault().getProperties(DebuggerManagerListener.class.getName()). + getProperties(PROPERTY_CLOSED_TC).getBoolean(tc.getName(), true); + open = (doOpen[0] && !wasClosed || !doOpen[0] && wasOpened); + } + ComponentInfo ci = TRANSFORM.transform(c[0], open); + cinfos.add(ci); + } + + return cinfos; + } + + static void closing(List components) { + for (ComponentInfo ci : components) { + Component c = ci.getComponent(); + if (c instanceof TopComponent) { + TopComponent tc = (TopComponent) c; + /* To check which components we're closing: + try { + Method pid = TopComponent.class.getDeclaredMethod("preferredID"); + pid.setAccessible(true); + System.err.println("ComponentInfoFromBeanContext.closing("+pid.invoke(tc)+")"); + } catch (Exception ex) { + ex.printStackTrace(); + }*/ + boolean isOpened = tc.isOpened(); + Properties.getDefault().getProperties(DebuggerManagerListener.class.getName()). + getProperties(PROPERTY_CLOSED_TC).setBoolean(tc.getName(), !isOpened); + } + } + + } + + public static interface Transform { + + ComponentInfo transform(Component c, boolean opened);//BeanContextChildComponentProxy componentProxy); + + } +} diff --git a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/DebuggerManagerListener.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/DebuggerManagerListener.java --- a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/DebuggerManagerListener.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/DebuggerManagerListener.java @@ -52,9 +52,12 @@ import java.beans.beancontext.BeanContextChildComponentProxy; import java.lang.ref.Reference; import java.lang.ref.WeakReference; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -71,6 +74,8 @@ import org.netbeans.api.debugger.Properties; import org.netbeans.modules.debugger.ui.actions.DebuggerAction; import org.netbeans.spi.debugger.ActionsProvider; +import org.netbeans.spi.debugger.ui.EngineComponentsProvider; +import org.netbeans.spi.debugger.ui.EngineComponentsProvider.ComponentInfo; import org.openide.awt.Toolbar; import org.openide.awt.ToolbarPool; import org.openide.util.Exceptions; @@ -92,8 +97,10 @@ private static final String PROPERTY_CLOSED_TC = "closedTopComponents"; // NOI18N private List openedGroups = new LinkedList(); - private final Map> openedComponents = new HashMap>(); - private Set> componentsInitiallyOpened = new HashSet>(); + //private final Map> openedComponents = new HashMap>(); + private final Map>> openedComponents = + new HashMap>>(); + private static final Set> componentsInitiallyOpened = new HashSet>(); private final Map> closedToolbarButtons = new HashMap>(); private final Map> usedToolbarButtons = new HashMap>(); private final Map toolbarButtonsPrefferedSize = new HashMap(); @@ -101,7 +108,7 @@ private ToolbarContainerListener toolbarContainerListener; private static final RequestProcessor RP = new RequestProcessor("Debugger Engine Setup", 1); // NOI18N - private static final List OPENED_COMPONENTS = new LinkedList(); + private static final List OPENED_COMPONENTS = new LinkedList(); @Override public void engineAdded (DebuggerEngine engine) { @@ -116,10 +123,12 @@ } final List componentProxies = engine.lookup(null, BeanContextChildComponentProxy.class); + final List componentsProvidersL = engine.lookup(null, EngineComponentsProvider.class); //final List windowsToOpen = engine.lookup(null, TopComponent.class); - if (componentProxies != null && !componentProxies.isEmpty()) { - final List componentsToOpen = new ArrayList(componentProxies.size()); - componentsToOpen.add(new java.awt.Label("EMPTY")); + if (!componentProxies.isEmpty() || !componentsProvidersL.isEmpty()) { + final Map> componentsToOpen = + new LinkedHashMap>(); + componentsToOpen.put(null, null); // Going to initialize... if (openedComponents.isEmpty() && openedGroups.isEmpty()) { fillOpenedDebuggerComponents(componentsInitiallyOpened); } @@ -130,48 +139,49 @@ rp.post (new Runnable () { @Override public void run () { - List cs = new ArrayList(componentProxies.size()); + final Map> ecs = + new LinkedHashMap>(); + final List cs = new ArrayList(); try { - final List topComponentsToOpen = new ArrayList(componentProxies.size()); - for (final BeanContextChildComponentProxy cp : componentProxies) { - final Component[] c = new Component[] { null }; - final boolean[] doOpen = new boolean[] { false }; - try { - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - c[0] = cp.getComponent(); - doOpen[0] = (cp instanceof DesignMode) ? ((DesignMode) cp).isDesignTime() : true; + final List componentsProviders; + if (!componentProxies.isEmpty()) { + BeanContextComponentProvider bccp = new BeanContextComponentProvider(componentProxies); + if (componentsProvidersL.isEmpty()) { + componentsProviders = Collections.singletonList(bccp); + } else { + List cps = new ArrayList(componentsProvidersL.size() + 1); + cps.addAll(componentsProvidersL); + cps.add(bccp); + componentsProviders = Collections.unmodifiableList(cps); + } + } else { + componentsProviders = componentsProvidersL; + } + final Map topComponentsToOpen = new LinkedHashMap(); + for (EngineComponentsProvider ecp : componentsProviders) { + List cis = ecp.getComponents(); + for (final ComponentInfo ci : cis) { + if (ci.isOpened()) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + Component c = ci.getComponent(); + if (c instanceof TopComponent) { + topComponentsToOpen.put((TopComponent) c, ci); + } else { + c.setVisible(true); + } + } + }); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + continue; } - }); - if (c[0] == null) { - //throw new NullPointerException("No component from "+cp); - continue; } - } catch (Exception ex) { - Exceptions.printStackTrace(ex); - continue; + cs.add(ci); } - cs.add(c[0]); - if (c[0] instanceof TopComponent) { - final TopComponent tc = (TopComponent) c[0]; - boolean wasClosed = Properties.getDefault().getProperties(DebuggerManagerListener.class.getName()). - getProperties(PROPERTY_CLOSED_TC).getBoolean(tc.getName(), false); - boolean wasOpened = !Properties.getDefault().getProperties(DebuggerManagerListener.class.getName()). - getProperties(PROPERTY_CLOSED_TC).getBoolean(tc.getName(), true); - if (doOpen[0] && !wasClosed || !doOpen[0] && wasOpened) { - topComponentsToOpen.add(tc); - } - } else { - if (doOpen[0]) { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - c[0].setVisible(true); - } - }); - } - } + ecs.put(ecp, cis); } if (topComponentsToOpen.size() > 0) { SwingUtilities.invokeLater(new Runnable() { @@ -184,19 +194,23 @@ } finally { synchronized (openedComponents) { componentsToOpen.clear(); - componentsToOpen.addAll(cs); + componentsToOpen.putAll(ecs); openedComponents.notifyAll(); } synchronized (OPENED_COMPONENTS) { + OPENED_COMPONENTS.addAll(cs); + /* consider componentsInitiallyOpened when closing components from OPENED_COMPONENTS + * instead of this: if (componentsInitiallyOpened.isEmpty()) { OPENED_COMPONENTS.addAll(cs); } else { - List ocs = new ArrayList(cs); + List ocs = new ArrayList(cs); for (Reference cref : componentsInitiallyOpened) { ocs.remove(cref.get()); } OPENED_COMPONENTS.addAll(ocs); } + */ } } } @@ -231,11 +245,16 @@ } } - private void openTopComponents(List components) { + private void openTopComponents(Map components) { assert SwingUtilities.isEventDispatchThread(); Set modesWithVisibleTC = new HashSet(); - for (TopComponent tc : components) { + for (Map.Entry tci : components.entrySet()) { + TopComponent tc = tci.getKey(); + ComponentInfo ci = tci.getValue(); tc.open(); + if (ci.isMinimized()) { + WindowManager.getDefault().setTopComponentMinimized(tc, true); + } Mode mode = WindowManager.getDefault().findMode(tc); if (modesWithVisibleTC.add(mode)) { TopComponent tcSel = mode.getSelectedTopComponent(); @@ -375,30 +394,63 @@ public void engineRemoved (DebuggerEngine engine) { //boolean doCloseToolbar = false; synchronized (openedComponents) { - List openedWindows = openedComponents.remove(engine); - if (openedWindows != null) { + final Map> openedWindowsByProvider = openedComponents.remove(engine); + if (openedWindowsByProvider != null) { // If it's not filled yet by AWT, wait... - if (openedWindows.size() == 1 && openedWindows.get(0) instanceof java.awt.Label) { + if (openedWindowsByProvider.size() == 1 && openedWindowsByProvider.get(0) == null) { try { openedComponents.wait(); } catch (InterruptedException iex) {} } + List openedWindows = new ArrayList(); + for (List lci : openedWindowsByProvider.values()) { + openedWindows.addAll(lci); + } // Check whether the component is opened by some other engine... - final List retainOpened = new ArrayList(); - for (List ltc : openedComponents.values()) { - retainOpened.addAll(ltc); + final List retainOpened = new ArrayList(); + for (Map> meci : openedComponents.values()) { + for (List lci : meci.values()){ + retainOpened.addAll(lci); + } } - final List windowsToClose = new ArrayList(openedWindows); - windowsToClose.removeAll(retainOpened); + final List initiallyOpened = new ArrayList(); for (Reference cref : componentsInitiallyOpened) { - windowsToClose.remove(cref.get()); + Component c = cref.get(); + if (c != null) { + initiallyOpened.add(c); + } } - if (!windowsToClose.isEmpty()) { - SwingUtilities.invokeLater (new Runnable () { + final List windowsToClose = new ArrayList(openedWindows); + //windowsToClose.removeAll(retainOpened); + try { + SwingUtilities.invokeAndWait(new Runnable() { @Override - public void run () { + public void run() { + List retainOpenedComponents = new ArrayList(retainOpened.size()); + for (ComponentInfo ci : retainOpened) { + retainOpenedComponents.add(ci.getComponent()); + } + for (Component c : initiallyOpened) { + if (c != null) { + retainOpenedComponents.add(c); + } + } + List windowsToCloseCopy = (ArrayList) ((ArrayList) windowsToClose).clone(); + for (ComponentInfo ci : windowsToCloseCopy) { + Component c = ci.getComponent(); + if (retainOpenedComponents.contains(c)) { + windowsToClose.remove(ci); + } + } + for (EngineComponentsProvider ecp : openedWindowsByProvider.keySet()) { + List cis = openedWindowsByProvider.get(ecp); + List closing = new ArrayList(cis); + closing.retainAll(windowsToClose); + ecp.willCloseNotify(closing); + } final List topComponentsToClose = new ArrayList(windowsToClose.size()); - for (Component c : windowsToClose) { + for (ComponentInfo ci : windowsToClose) { + Component c = ci.getComponent(); if (c instanceof TopComponent) { TopComponent tc = (TopComponent) c; boolean isOpened = tc.isOpened(); @@ -414,6 +466,8 @@ closeTopComponentsList(topComponentsToClose); } }); + } catch (Exception exc) { + Exceptions.printStackTrace(exc); } synchronized (OPENED_COMPONENTS) { OPENED_COMPONENTS.removeAll(windowsToClose); @@ -435,6 +489,9 @@ } if (openedComponents.isEmpty() && openedGroups.isEmpty()) { componentsInitiallyOpened.clear(); + synchronized (OPENED_COMPONENTS) { + OPENED_COMPONENTS.clear(); + } /*doCloseToolbar = true; SwingUtilities.invokeLater (new Runnable () { public void run () { @@ -568,14 +625,40 @@ group.close (); } synchronized (OPENED_COMPONENTS) { - for (Component c : OPENED_COMPONENTS) { + final List initiallyOpened; + if (componentsInitiallyOpened.isEmpty()) { + initiallyOpened = Collections.EMPTY_LIST; + } else { + initiallyOpened = new ArrayList(); + for (Reference cref : componentsInitiallyOpened) { + Component c = cref.get(); + if (c != null) { + initiallyOpened.add(c); + } + } + } + for (ComponentInfo ci : OPENED_COMPONENTS) { + Component c = ci.getComponent(); + if (initiallyOpened.contains(c)) { + continue; + } if (c instanceof TopComponent) { + /* To check which components we're closing: + try { + Method pid = TopComponent.class.getDeclaredMethod("preferredID"); + pid.setAccessible(true); + System.err.println("doCloseDebuggerUI("+pid.invoke(c)+")"); + } catch (Exception ex) { + ex.printStackTrace(); + } + */ ((TopComponent) c).close(); } else { c.setVisible(false); } } OPENED_COMPONENTS.clear(); + componentsInitiallyOpened.clear(); } ToolbarPool.getDefault().waitFinished(); if (ToolbarPool.getDefault().getConfiguration().equals("Debugging")) { // NOI18N @@ -672,5 +755,25 @@ } } + + private static class BeanContextComponentProvider implements EngineComponentsProvider { + + private final List componentProxies; + + public BeanContextComponentProvider(List componentProxies) { + this.componentProxies = componentProxies; + } + + @Override + public List getComponents() { + return ComponentInfoFromBeanContext.transform(componentProxies); + } + + @Override + public void willCloseNotify(List components) { + ComponentInfoFromBeanContext.closing(components); + } + + } } diff --git a/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/EngineComponentsProvider.java b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/EngineComponentsProvider.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/EngineComponentsProvider.java @@ -0,0 +1,220 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.spi.debugger.ui; + +import java.awt.Component; +import java.util.List; +import org.netbeans.modules.debugger.ui.ComponentInfoFromBeanContext; +import org.netbeans.spi.debugger.DebuggerServiceRegistration; +import org.openide.windows.TopComponent; +import org.openide.windows.WindowManager; + +/** + * Provider of components associated with a debugger engine. + * An instance of this class needs to be registered under the appropriate session/engine + * ID path by {@link DebuggerServiceRegistration}. + *

+ * The provided components are checked when the appropriate debugger engine is started + * and opened if necessary. After the debugger engine is finished, + * {@link EngineComponentsProvider#willCloseNotify(java.util.List)} is called + * with components that are not used by other running engines and which are subsequently + * closed. + * + * @author Martin Entlicher + * @since 2.35 + */ +public interface EngineComponentsProvider { + + /** + * Provide a list of components associated with the debugger engine. + * The components are opened when the debugger engine starts and closed + * when the debugger engine finishes. + * + * @return The list of components associated with the debugger engine. + */ + List getComponents(); + + /** + * This method is called when the debugger engine finishes with the list + * of components that are about to be closed. + * The implementation might test them for opened state to decide if they + * should be opened the next time when {@link #getComponents()} is called. + * @param components The components that are to be closed. It's guaranteed + * that only components returned by {@link #getComponents()} are passed in + * and only those, that are not needed by another running engine. + */ + void willCloseNotify(List components); + + /** + * Information about a component associated with a debugger engine. + */ + public static final class ComponentInfo { + + static { + initHelperTransform(); + } + + private final ComponentProvider provider; + private final boolean opened; + private final boolean minimized; + //private int order = Integer.MAX_VALUE; + + private ComponentInfo(ComponentProvider provider, boolean opened, boolean minimized) { + this.provider = provider; + this.opened = opened; + this.minimized = minimized; + } + + /** + * Get the component. + * @return The component + */ + public Component getComponent() { + return provider.getComponent(); + } + + /** + * Test if the component is to be opened when the debugger engine starts. + * @return true when this component is to be opened on engine start, + * false otherwise. + */ + public boolean isOpened() { + return opened; + } + + /** + * Test if the component is to be opened in a minimized state when the + * debugger engine starts. + * @return true when this component is to be opened in a minimized state, + * false otherwise. + */ + public boolean isMinimized() { + return minimized; + } + + /* can be added when needed + public void setOrder(int order) { + this.order = order; + } + + public int getOrder() { + return order; + } + */ + + /* When generic Component support is required + public static ComponentInfo create(ComponentProvider componentProvider) { + return new ComponentInfo(componentProvider); + } + */ + + /** + * Create a component information about a {@link TopComponent}, + * which is opened by default. + * @param tcName The ID of the {@link TopComponent} + * @return A component information. + */ + public static ComponentInfo create(String tcId) { + return create(tcId, true); + } + + /** + * Create a component information about a {@link TopComponent}. + * @param tcName The ID of the {@link TopComponent} + * @param opened true if the component should be opened, + * false otherwise. + * @return A component information. + */ + public static ComponentInfo create(String tcId, boolean opened) { + return create(tcId, opened, false); + } + + /** + * Create a component information about a {@link TopComponent}. + * @param tcName The ID of the {@link TopComponent} + * @param opened true if the component should be opened, + * false otherwise. + * @param minimized true if the component should be opened in a minimized state, + * false otherwise. + * @return A component information. + */ + public static ComponentInfo create(String tcId, boolean opened, boolean minimized) { + return new ComponentInfo(new TopComponentProvider(tcId), opened, minimized); + } + + private static void initHelperTransform() { + ComponentInfoFromBeanContext.TRANSFORM = new ComponentInfoFromBeanContext.Transform() { + @Override + public ComponentInfo transform(final Component c, boolean opened) { + return new ComponentInfo(new ComponentProvider() { + @Override + public Component getComponent() { + return c; + } + }, opened, false); + } + }; + } + + } + + /*public - when generic Component suport is required. */ + static interface ComponentProvider { + + Component getComponent(); + } + + static class TopComponentProvider implements ComponentProvider { + + private final String tcId; + + private TopComponentProvider(String tcId) { + this.tcId = tcId; + } + + @Override + public java.awt.Component getComponent() { + return WindowManager.getDefault().findTopComponent(tcId); + } + } + +} diff --git a/spi.debugger.ui/test/unit/src/org/netbeans/spi/debugger/ui/EngineComponentsProviderTest.java b/spi.debugger.ui/test/unit/src/org/netbeans/spi/debugger/ui/EngineComponentsProviderTest.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/test/unit/src/org/netbeans/spi/debugger/ui/EngineComponentsProviderTest.java @@ -0,0 +1,116 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.spi.debugger.ui; + +import java.awt.Component; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import javax.swing.SwingUtilities; +import junit.framework.Test; +import junit.framework.TestCase; +import org.netbeans.api.debugger.DebuggerApiTestBase; +import org.netbeans.junit.NbModuleSuite; +import org.netbeans.spi.debugger.ui.EngineComponentsProvider.ComponentInfo; +import org.openide.windows.TopComponent; + +/** + * + * @author Martin + */ +public class EngineComponentsProviderTest extends DebuggerApiTestBase { + + public EngineComponentsProviderTest(String s) { + super(s); + } + + public static Test suite() { + return EngineComponentsProviderTest.createTestSuite(EngineComponentsProviderTest.class); + } + + public void testCreateTC() throws Throwable { + ComponentInfo ciVar = EngineComponentsProvider.ComponentInfo.create("localsView"); + checkComponentInfo(ciVar, true, false, "org.netbeans.modules.debugger.ui.views.LocalsView"); + + ComponentInfo ciWatch = EngineComponentsProvider.ComponentInfo.create("watchesView", false); + checkComponentInfo(ciWatch, false, false, "org.netbeans.modules.debugger.ui.views.WatchesView"); + + ComponentInfo ciCS = EngineComponentsProvider.ComponentInfo.create("callstackView", false, true); + checkComponentInfo(ciCS, false, true, "org.netbeans.modules.debugger.ui.views.CallStackView"); + } + + private void checkComponentInfo(final ComponentInfo ci, + boolean opened, boolean minimized, + final String ID) throws Throwable { + assertEquals("Opened", opened, ci.isOpened()); + assertEquals("Minimized", minimized, ci.isMinimized()); + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + Component c = ci.getComponent(); + assertTrue("Is TopComponent:", c instanceof TopComponent); + TopComponent tc = (TopComponent) c; + try { + Method pid = TopComponent.class.getDeclaredMethod("preferredID"); + pid.setAccessible(true); + String tcId = (String) pid.invoke(tc); + //System.err.println("tcId = "+tcId); + assertEquals("TopComponent preferredID:", ID, tcId); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + }); + } catch (InvocationTargetException itex) { + Thread.dumpStack(); + throw itex.getTargetException(); + } + } + + public static Test createTestSuite(Class clazz) { + NbModuleSuite.Configuration suiteConfiguration = NbModuleSuite.createConfiguration(clazz); + suiteConfiguration = suiteConfiguration.gui(false); + //suiteConfiguration = suiteConfiguration.reuseUserDir(false); + return NbModuleSuite.create(suiteConfiguration); + } + +} diff --git a/web.javascript.debugger/src/org/netbeans/modules/web/javascript/debugger/EngineComponentsProviderImpl.java b/web.javascript.debugger/src/org/netbeans/modules/web/javascript/debugger/EngineComponentsProviderImpl.java new file mode 100644 --- /dev/null +++ b/web.javascript.debugger/src/org/netbeans/modules/web/javascript/debugger/EngineComponentsProviderImpl.java @@ -0,0 +1,123 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 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 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.web.javascript.debugger; + +import java.awt.Component; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.prefs.Preferences; +import org.netbeans.api.debugger.Properties; +import org.netbeans.spi.debugger.ContextProvider; +import org.netbeans.spi.debugger.DebuggerServiceRegistration; +import org.netbeans.spi.debugger.ui.EngineComponentsProvider; +import org.openide.util.NbPreferences; +import org.openide.windows.TopComponent; + +/** + * Provider of debugger GUI components needed for JavaScript Debugger, + * minimized initially. + * + * @author Martin Entlicher + */ +@DebuggerServiceRegistration(path="javascript-debuggerengine", types=EngineComponentsProvider.class) +public class EngineComponentsProviderImpl implements EngineComponentsProvider { + + private static final String PROPERTY_CLOSED_TC = "closedTopComponents"; // NOI18N + private static final String PROPERTY_BASE_NAME = "javascript-debuggerengine.EngineComponentsProvider"; // NOI18N + + private static final String[] DBG_COMPONENTS_OPENED = { + "localsView", "watchesView", "callstackView", "breakpointsView", + }; + private static final String[] DBG_COMPONENTS_CLOSED = { + "evaluator", "resultsView", "sessionsView", + }; + + @Override + public List getComponents() { + List components = new ArrayList(DBG_COMPONENTS_OPENED.length + DBG_COMPONENTS_CLOSED.length); + for (String cid : DBG_COMPONENTS_OPENED) { + components.add(EngineComponentsProvider.ComponentInfo.create( + cid, isOpened(cid, true), true)); + } + for (String cid : DBG_COMPONENTS_CLOSED) { + components.add(EngineComponentsProvider.ComponentInfo.create( + cid, isOpened(cid, false), true)); + } + return components; + } + + private static boolean isOpened(String cid, boolean open) { + if (cid.equals("watchesView")) { + Preferences preferences = NbPreferences.forModule(ContextProvider.class).node("variables_view"); // NOI18N + open = !preferences.getBoolean("show_watches", true); // NOI18N + } + boolean wasClosed = Properties.getDefault().getProperties(PROPERTY_BASE_NAME). + getProperties(PROPERTY_CLOSED_TC).getBoolean(cid, false); + boolean wasOpened = !Properties.getDefault().getProperties(PROPERTY_BASE_NAME). + getProperties(PROPERTY_CLOSED_TC).getBoolean(cid, true); + open = (open && !wasClosed || !open && wasOpened); + return open; + } + + @Override + public void willCloseNotify(List components) { + for (ComponentInfo ci : components) { + Component c = ci.getComponent(); + if (c instanceof TopComponent) { + TopComponent tc = (TopComponent) c; + /* + try { + Method pid = TopComponent.class.getDeclaredMethod("preferredID"); + pid.setAccessible(true); + System.err.println("JS EngineComponentsProviderImpl.closing("+pid.invoke(tc)+") name = "+tc.getName()); + } catch (Exception ex) { + ex.printStackTrace(); + }*/ + boolean isOpened = tc.isOpened(); + Properties.getDefault().getProperties(PROPERTY_BASE_NAME). + getProperties(PROPERTY_CLOSED_TC).setBoolean(tc.getName(), !isOpened); + } + } + } + +}