diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/api/debugger/jpda/CallStackFrame.java --- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/CallStackFrame.java Thu May 29 16:35:41 2008 +0400 +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/CallStackFrame.java Thu May 29 15:28:17 2008 +0200 @@ -66,6 +66,8 @@ * @return line number associated with this this stack frame */ public abstract int getLineNumber (String struts); + + public abstract int getFrameDepth(); /** * Returns the current operation (if any) at the location of this call stack frame. @@ -183,5 +185,12 @@ * @return thread */ public abstract JPDAThread getThread (); + + /** + * Get the list of monitors aquired in this frame + * + * @return the list of monitors aquired in this frame + */ + List getOwnedMonitors(); } \ No newline at end of file diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/api/debugger/jpda/DeadlockDetector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/DeadlockDetector.java Thu May 29 15:28:17 2008 +0200 @@ -0,0 +1,116 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.api.debugger.jpda; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Collection; +import java.util.Set; + +/** + * + * @author Martin Entlicher + */ +public abstract class DeadlockDetector { + + public static final String PROP_DEADLOCK = "deadlock"; // NOI18N + + private Set deadlocks; + private PropertyChangeSupport pcs = new PropertyChangeSupport(this); + + public final synchronized Set getDeadlocks() { + return deadlocks; + } + + protected final void setDeadlocks(Set deadlocks) { + synchronized (this) { + this.deadlocks = deadlocks; + } + firePropertyChange(PROP_DEADLOCK, null, deadlocks); + } + + protected final Deadlock createDeadlock(Collection threads) { + return new Deadlock(threads); + } + + private void firePropertyChange(String name, Object oldValue, Object newValue) { + pcs.firePropertyChange(name, oldValue, newValue); + } + + public final void addPropertyChangeListener(PropertyChangeListener l) { + pcs.addPropertyChangeListener(l); + } + + public final void removePropertyChangeListener(PropertyChangeListener l) { + pcs.removePropertyChangeListener(l); + } + + public static final class Deadlock { + + private Collection threads; + + private Deadlock(Collection threads) { + this.threads = threads; + } + + public Collection getThreads() { + return threads; + } + } + + /*public static final class ThreadInDeadlock { + + private JPDAThread thread; + private MonitorInfo monitor; + + public ThreadInDeadlock(JPDAThread thread, MonitorInfo monitor) { + this.thread = thread; + this.monitor = monitor; + } + + public JPDAThread getThread() { + return thread; + } + + public MonitorInfo getMonitor() { + return monitor; + } + }*/ +} diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDABreakpoint.java --- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDABreakpoint.java Thu May 29 16:35:41 2008 +0400 +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDABreakpoint.java Thu May 29 15:28:17 2008 +0200 @@ -80,7 +80,7 @@ /** Set of actions. */ private boolean enabled = true; private boolean hidden = false; - private int suspend = SUSPEND_ALL; + private int suspend = SUSPEND_EVENT_THREAD; private String printText; private Collection breakpointListeners = new HashSet(); diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java --- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java Thu May 29 16:35:41 2008 +0400 +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDADebugger.java Thu May 29 15:28:17 2008 +0200 @@ -88,6 +88,13 @@ /** Property name constant. */ public static final String PROP_SUSPEND = "suspend"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_STARTED = "threadStarted"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_DIED = "threadDied"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_GROUP_ADDED = "threadGroupAdded"; // NOI18N + /** Suspend property value constant. */ public static final int SUSPEND_ALL = EventRequest.SUSPEND_ALL; /** Suspend property value constant. */ @@ -315,6 +322,15 @@ public abstract void setSuspend (int s); /** + * Returns all threads that exist in the debuggee. + * + * @return all threads + */ + public List getAllThreads() { + return Collections.emptyList(); + } + + /** * Returns current thread or null. * * @return current thread or null @@ -491,5 +507,17 @@ public long[] getInstanceCounts(List classTypes) throws UnsupportedOperationException { throw new UnsupportedOperationException("Not supported."); } + + public ThreadsCollector getThreadsCollector() { + return null; + } + + /** + * Creates a deadlock detector. + * @return deadlock detector with automatic detection of deadlock among suspended threads + */ + public DeadlockDetector getDeadlockDetector() { + return new DeadlockDetector() {}; + } } diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDAThread.java --- a/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDAThread.java Thu May 29 16:35:41 2008 +0400 +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/JPDAThread.java Thu May 29 15:28:17 2008 +0200 @@ -76,10 +76,16 @@ /** Thread state constant. */ public static final int STATE_ZOMBIE = ThreadReference.THREAD_STATUS_ZOMBIE; + /** + * Suspended property of the thread. Fired when isSuspended() changes. + */ + public static final String PROP_SUSPENDED = "suspended"; /** Property name constant. */ public static final String PROP_CALLSTACK = "callStack"; /** Property name constant. */ public static final String PROP_VARIABLES = "variables"; + /** Property name constant. */ + public static final String PROP_BREAKPOINT = "currentBreakpoint"; @@ -114,6 +120,12 @@ * @see {@link CallStackFrame#getCurrentOperation} */ public abstract Operation getCurrentOperation(); + + /** + * Returns the current breakpoint hit by this thread. + * @return The current breakpoint, or null. + */ + public abstract JPDABreakpoint getCurrentBreakpoint(); /** * Returns the list of the last operations, that were performed on this thread. @@ -237,9 +249,24 @@ public abstract ObjectVariable getContendedMonitor (); /** + * Returns monitor this thread is waiting on, with the information + * about the owner of the monitor. + * + * @return monitor this thread is waiting on, with the owner. + */ + public abstract MonitorInfo getContendedMonitorAndOwner (); + + /** * Returns monitors owned by this thread. * * @return monitors owned by this thread */ public abstract ObjectVariable[] getOwnedMonitors (); + + /** + * Get the list of monitors with stack frame info owned by this thread. + * + * @return the list of monitors with stack frame info + */ + List getOwnedMonitorsAndFrames(); } diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/api/debugger/jpda/MonitorInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/MonitorInfo.java Thu May 29 15:28:17 2008 +0200 @@ -0,0 +1,85 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun + * Microsystems, Inc. All Rights Reserved. + * + * 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. + */ + +package org.netbeans.api.debugger.jpda; + +import com.sun.jdi.AbsentInformationException; +import java.beans.PropertyChangeListener; +import java.util.List; +import org.netbeans.spi.debugger.jpda.EditorContext.Operation; + + +/** + * Represents one owned monitor. + * + *
+ * Since JDI interfaces evolve from one version to another, it's strongly recommended
+ * not to implement this interface in client code. New methods can be added to
+ * this interface at any time to keep up with the JDI functionality.
+ * + * @author Martin Entlicher + */ +public interface MonitorInfo { + + /** + * Returns the acquired monitor object + * + * @return monitor object + */ + ObjectVariable getMonitor(); + + /** + * Returns the frame at which this monitor was acquired by the owning thread. + * + * @return The frame, or null when the implementation cannot + * determine the stack frame (e.g., for monitors acquired by JNI). + */ + CallStackFrame getFrame(); + + /** + * Get the owning thread. + * + * @return the thread. + */ + JPDAThread getThread(); + +} + \ No newline at end of file diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/api/debugger/jpda/ThreadsCollector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/api.debugger.jpda/src/org/netbeans/api/debugger/jpda/ThreadsCollector.java Thu May 29 15:28:17 2008 +0200 @@ -0,0 +1,91 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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 2008 Sun Microsystems, Inc. + */ + +package org.netbeans.api.debugger.jpda; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.List; + +/** + * + * @author martin + */ +public abstract class ThreadsCollector { + + private final PropertyChangeSupport pch = new PropertyChangeSupport(this); + + /** Property name constant. */ + public static final String PROP_THREAD_STARTED = "threadStarted"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_DIED = "threadDied"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_GROUP_ADDED = "threadGroupAdded"; // NOI18N + + /** Property name constant. */ + public static final String PROP_THREAD_SUSPENDED = "threadSuspended"; // NOI18N + /** Property name constant. */ + public static final String PROP_THREAD_RESUMED = "threadResumed"; // NOI18N + + + public final void addPropertyChangeListener(PropertyChangeListener l) { + pch.addPropertyChangeListener(l); + } + + public final void removePropertyChangeListener(PropertyChangeListener l) { + pch.removePropertyChangeListener(l); + } + + protected final void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pch.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Returns all threads that exist in the debuggee. + * + * @return all threads + */ + public abstract List getAllThreads(); + + /** + * Creates a deadlock detector. + * @return deadlock detector with automatic detection of deadlock among suspended threads + */ + public abstract DeadlockDetector getDeadlockDetector(); +} diff -r 56bcd6cdfc36 api.debugger.jpda/src/org/netbeans/spi/debugger/jpda/EditorContext.java --- a/api.debugger.jpda/src/org/netbeans/spi/debugger/jpda/EditorContext.java Thu May 29 16:35:41 2008 +0400 +++ b/api.debugger.jpda/src/org/netbeans/spi/debugger/jpda/EditorContext.java Thu May 29 15:28:17 2008 +0200 @@ -46,6 +46,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import org.netbeans.api.debugger.jpda.JPDAThread; import org.netbeans.api.debugger.jpda.LineBreakpoint; import org.netbeans.api.debugger.jpda.LocalVariable; import org.netbeans.api.debugger.jpda.Variable; @@ -86,6 +87,8 @@ public static final String CURRENT_EXPRESSION_SECONDARY_LINE_ANNOTATION_TYPE = "CurrentExpression"; /** Annotation type constant. */ public static final String CURRENT_EXPRESSION_CURRENT_LINE_ANNOTATION_TYPE = "CurrentExpressionLine"; + /** Annotation type constant. */ + public static final String OTHER_THREAD_ANNOTATION_TYPE = "OtherThread"; /** Property name constant. */ public static final String PROP_LINE_NUMBER = "lineNumber"; @@ -143,6 +146,16 @@ String annotationType, Object timeStamp ); + + public Object annotate ( + String url, + int lineNumber, + String annotationType, + Object timeStamp, + JPDAThread thread + ) { + return null; + } /** * Adds annotation to given url on given character range. diff -r 56bcd6cdfc36 spi.viewmodel/src/org/netbeans/spi/viewmodel/ModelEvent.java --- a/spi.viewmodel/src/org/netbeans/spi/viewmodel/ModelEvent.java Thu May 29 16:35:41 2008 +0400 +++ b/spi.viewmodel/src/org/netbeans/spi/viewmodel/ModelEvent.java Thu May 29 15:27:37 2008 +0200 @@ -156,6 +156,11 @@ * @since 1.6 */ public static final int CHILDREN_MASK = 8; + /** + * The mask for expansion change. + * @since 1.TODO + */ + public static final int EXPANSION_MASK = 16; private Object node; private int change; diff -r 56bcd6cdfc36 spi.viewmodel/src/org/netbeans/spi/viewmodel/Models.java --- a/spi.viewmodel/src/org/netbeans/spi/viewmodel/Models.java Thu May 29 16:35:41 2008 +0400 +++ b/spi.viewmodel/src/org/netbeans/spi/viewmodel/Models.java Thu May 29 15:27:37 2008 +0200 @@ -65,6 +65,7 @@ import javax.swing.SwingUtilities; import org.netbeans.modules.viewmodel.DefaultTreeExpansionManager; +import org.netbeans.modules.viewmodel.TreeModelRoot; import org.netbeans.modules.viewmodel.TreeTable; import org.netbeans.spi.viewmodel.ColumnModel; @@ -82,6 +83,7 @@ import org.netbeans.spi.viewmodel.UnknownTypeException; import org.openide.ErrorManager; +import org.openide.explorer.view.TreeView; import org.openide.nodes.Node; import org.openide.util.Exceptions; import org.openide.util.WeakSet; @@ -127,6 +129,21 @@ TreeTable tt = new TreeTable (); tt.setModel (compoundModel); return tt; + } + + /** + * Creates a root node of the nodes tree structure + * for given {@link org.netbeans.spi.viewmodel.Models.CompoundModel}. + * + * @param compoundModel a compound model instance + * + * @return new instance root node + */ + public static Node createNodes ( + CompoundModel compoundModel, + TreeView treeView + ) { + return new TreeModelRoot (compoundModel, treeView).getRootNode(); } /** @@ -184,6 +201,7 @@ List treeModels; List treeModelFilters; List treeExpansionModels; + List treeExpansionModelFilters; List nodeModels; List nodeModelFilters; List tableModels; @@ -195,7 +213,7 @@ // Either the list contains 10 lists of individual models + one list of mixed models; or the models directly boolean hasLists = false; - if (models.size() == 11) { + if (models.size() == 11 || models.size() == 12) { Iterator it = models.iterator (); while (it.hasNext ()) { if (!(it.next() instanceof List)) break; @@ -204,7 +222,7 @@ hasLists = true; } } - if (hasLists) { // We have 11 lists of individual models + if (hasLists) { // We have 11 or 12 lists of individual models treeModels = (List) models.get(0); treeModelFilters = (List) models.get(1); revertOrder(treeModelFilters); @@ -220,10 +238,12 @@ revertOrder(nodeActionsProviderFilters); columnModels = (List) models.get(9); otherModels = (List) models.get(10); + treeExpansionModelFilters = (models.size() > 11) ? (List) models.get(11) : (List) Collections.EMPTY_LIST; } else { // We have the models, need to find out what they implement treeModels = new LinkedList (); treeModelFilters = new LinkedList (); treeExpansionModels = new LinkedList (); + treeExpansionModelFilters = new LinkedList (); nodeModels = new LinkedList (); nodeModelFilters = new LinkedList (); tableModels = new LinkedList (); @@ -247,6 +267,11 @@ treeModelFilters.add(0, (TreeModelFilter) model); if (model instanceof TreeExpansionModel) treeExpansionModels.add((TreeExpansionModel) model); + if (model instanceof TreeExpansionModelFilter) + if (first) + treeExpansionModelFilters.add((TreeExpansionModelFilter) model); + else + treeExpansionModelFilters.add(0, (TreeExpansionModelFilter) model); if (model instanceof NodeModel) nodeModels.add((NodeModel) model); if (model instanceof NodeModelFilter) @@ -304,7 +329,10 @@ new DelegatingTreeModel (treeModels), treeModelFilters ), - new DelegatingTreeExpansionModel (treeExpansionModels), + createCompoundTreeExpansionModel( + new DelegatingTreeExpansionModel (treeExpansionModels), + treeExpansionModelFilters + ), createCompoundNodeModel ( new DelegatingNodeModel (nodeModels), nodeModelFilters @@ -374,7 +402,7 @@ */ public static TreeFeatures treeFeatures (JComponent view) throws UnsupportedOperationException { - return new TreeFeatures (view); + return new DefaultTreeFeatures (view); } @@ -470,6 +498,16 @@ (NodeActionsProviderFilter) nodeActionsProviderFilters.get (i) ); return nap; + } + + private static TreeExpansionModel createCompoundTreeExpansionModel ( + TreeExpansionModel expansionModel, + List filters + ) { + for (TreeExpansionModelFilter filter : filters) { + expansionModel = new CompoundTreeExpansionModel (expansionModel, filter); + } + return expansionModel; } @@ -584,7 +622,7 @@ * * @author Jan Jancura */ - final static class CompoundTreeModel implements TreeModel, ModelListener { + private final static class CompoundTreeModel implements TreeModel, ModelListener { private TreeModel model; @@ -733,7 +771,7 @@ * * @author Jan Jancura */ - final static class CompoundNodeModel implements ExtendedNodeModel, ModelListener { + private final static class CompoundNodeModel implements ExtendedNodeModel, ModelListener { private ExtendedNodeModel model; @@ -951,7 +989,7 @@ * * @author Jan Jancura */ - final static class CompoundTableModel implements TableModel, ModelListener { + private final static class CompoundTableModel implements TableModel, ModelListener { private TableModel model; @@ -1086,7 +1124,7 @@ * * @author Jan Jancura */ - final static class DelegatingTreeModel implements TreeModel { + private final static class DelegatingTreeModel implements TreeModel { private TreeModel[] models; private HashMap classNameToModel = new HashMap(); @@ -1268,7 +1306,7 @@ * * @author Jan Jancura */ - final static class CompoundNodeActionsProvider + private final static class CompoundNodeActionsProvider implements NodeActionsProvider { @@ -1329,6 +1367,75 @@ n + " " + model; } } + + private final static class CompoundTreeExpansionModel implements TreeExpansionModel, ModelListener { + + private TreeExpansionModel expansionModel; + private TreeExpansionModelFilter expansionFilter; + + private Collection modelListeners = new HashSet(); + + CompoundTreeExpansionModel(TreeExpansionModel expansionModel, TreeExpansionModelFilter expansionFilter) { + this.expansionModel = expansionModel; + this.expansionFilter = expansionFilter; + } + + public boolean isExpanded(Object node) throws UnknownTypeException { + return expansionFilter.isExpanded(expansionModel, node); + } + + public void nodeExpanded(Object node) { + expansionModel.nodeExpanded(node); + expansionFilter.nodeExpanded(node); + } + + public void nodeCollapsed(Object node) { + expansionModel.nodeCollapsed(node); + expansionFilter.nodeCollapsed(node); + } + + /** + * Registers given listener. + * + * @param l the listener to add + */ + public void addModelListener (ModelListener l) { + synchronized (modelListeners) { + if (modelListeners.size() == 0) { + expansionFilter.addModelListener (this); + //model.addModelListener (this); + } + modelListeners.add(l); + } + } + + /** + * Unregisters given listener. + * + * @param l the listener to remove + */ + public void removeModelListener (ModelListener l) { + synchronized (modelListeners) { + modelListeners.remove(l); + if (modelListeners.size() == 0) { + expansionFilter.removeModelListener (this); + //model.removeModelListener (this); + } + } + } + + public void modelChanged(ModelEvent event) { + ModelEvent newEvent = translateEvent(event, this); + Collection listeners; + synchronized (modelListeners) { + listeners = new ArrayList(modelListeners); + } + for (Iterator it = listeners.iterator(); it.hasNext(); ) { + it.next().modelChanged(newEvent); + } + } + + } /** * Creates one {@link org.netbeans.spi.viewmodel.TableModel} @@ -1337,7 +1444,7 @@ * * @author Jan Jancura */ - final static class DelegatingTableModel implements TableModel { + private final static class DelegatingTableModel implements TableModel { private TableModel[] models; private HashMap classNameToModel = new HashMap(); @@ -1521,8 +1628,7 @@ * * @author Jan Jancura */ - final static class DelegatingTreeExpansionModel - implements TreeExpansionModel { + private final static class DelegatingTreeExpansionModel implements TreeExpansionModel { private TreeExpansionModel[] models; private HashMap classNameToModel = new HashMap(); @@ -1694,7 +1800,7 @@ * * @author Jan Jancura */ - static final class DelegatingNodeModel implements ExtendedNodeModel { + private static final class DelegatingNodeModel implements ExtendedNodeModel { private NodeModel[] models; private HashMap classNameToModel = new HashMap(); @@ -2678,14 +2784,40 @@ } } + public static interface TreeFeatures { + + /** + * Returns true if given node is expanded. + * + * @param node a node to be checked + * @return true if given node is expanded + */ + public boolean isExpanded (Object node); + + /** + * Expands given list of nodes. + * + * @param node a list of nodes to be expanded + */ + public void expandNode (Object node); + + /** + * Collapses given node. + * + * @param node a node to be expanded + */ + public void collapseNode (Object node); + + } + /** * Implements set of tree view features. */ - public static final class TreeFeatures { + private static final class DefaultTreeFeatures implements TreeFeatures { private JComponent view; - private TreeFeatures (JComponent view) { + private DefaultTreeFeatures (JComponent view) { this.view = view; } @@ -3020,6 +3152,9 @@ if (tableModel != treeModel && tableModel != nodeModel) { tableModel.addModelListener (l); } + if (treeExpansionModel instanceof CompoundTreeExpansionModel) { + ((CompoundTreeExpansionModel) treeExpansionModel).addModelListener(l); + } } /** @@ -3034,6 +3169,9 @@ } if (tableModel != treeModel && tableModel != nodeModel) { tableModel.removeModelListener (l); + } + if (treeExpansionModel instanceof CompoundTreeExpansionModel) { + ((CompoundTreeExpansionModel) treeExpansionModel).removeModelListener(l); } } diff -r 56bcd6cdfc36 spi.viewmodel/src/org/netbeans/spi/viewmodel/TreeExpansionModelFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spi.viewmodel/src/org/netbeans/spi/viewmodel/TreeExpansionModelFilter.java Thu May 29 15:27:37 2008 +0200 @@ -0,0 +1,90 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved. + * + * 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun 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]" + * + * Contributor(s): + * + * The Original Software is NetBeans. The Initial Developer of the Original + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun + * Microsystems, Inc. All Rights Reserved. + * + * 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. + */ + +package org.netbeans.spi.viewmodel; + + +/** + * This model filter controlls expansion, collapsion of nodes in tree view, and + * defindes default expand state for all node in it. It may delegate to the supplied + * TreeExpansionModel. + * + * @author Martin Entlicher + */ +public interface TreeExpansionModelFilter extends Model { + + /** + * Defines default state (collapsed, expanded) of given node. + * + * @param node a node + * @return default state (collapsed, expanded) of given node + */ + public abstract boolean isExpanded (TreeExpansionModel original, Object node) + throws UnknownTypeException; + + /** + * Called when given node is expanded. + * + * @param node a expanded node + */ + public abstract void nodeExpanded (Object node); + + /** + * Called when given node is collapsed. + * + * @param node a collapsed node + */ + public abstract void nodeCollapsed (Object node); + + /** + * Registers given listener. + * + * @param l the listener to add + */ + public abstract void addModelListener (ModelListener l); + + /** + * Unregisters given listener. + * + * @param l the listener to remove + */ + public abstract void removeModelListener (ModelListener l); +}