001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.ruby.debugger.model;
043:
044: import java.util.List;
045: import java.util.concurrent.CopyOnWriteArrayList;
046: import javax.swing.Action;
047: import org.netbeans.modules.ruby.debugger.ContextProviderWrapper;
048: import org.netbeans.modules.ruby.debugger.RubySession;
049: import org.netbeans.spi.debugger.ContextProvider;
050: import org.netbeans.spi.viewmodel.ModelEvent;
051: import org.netbeans.spi.viewmodel.ModelListener;
052: import org.netbeans.spi.viewmodel.NodeActionsProvider;
053: import org.netbeans.spi.viewmodel.NodeModel;
054: import org.netbeans.spi.viewmodel.TableModel;
055: import org.netbeans.spi.viewmodel.TreeModel;
056: import org.netbeans.spi.viewmodel.UnknownTypeException;
057: import org.openide.util.NbBundle;
058: import org.rubyforge.debugcommons.model.RubyThreadInfo;
059: import static org.netbeans.spi.debugger.ui.Constants.THREAD_STATE_COLUMN_ID;
060:
061: public final class ThreadsModel implements TreeModel, TableModel,
062: NodeModel, NodeActionsProvider {
063:
064: private static final String CURRENT = "org/netbeans/modules/debugger/resources/threadsView/CurrentThread"; // NOI18N
065: private static final String RUNNING = "org/netbeans/modules/debugger/resources/threadsView/RunningThread"; // NOI18N
066: private static final String SUSPENDED = "org/netbeans/modules/debugger/resources/threadsView/SuspendedThread"; // NOI18N
067:
068: private ContextProviderWrapper contextProvider;
069: private final RubySession rubySession;
070: private final List<ModelListener> listeners;
071:
072: public ThreadsModel(ContextProvider contextProvider) {
073: this .contextProvider = new ContextProviderWrapper(
074: contextProvider);
075: rubySession = this .contextProvider.getRubySession();
076: listeners = new CopyOnWriteArrayList<ModelListener>();
077: }
078:
079: // TreeModel implementation ................................................
080:
081: public Object getRoot() {
082: return ROOT;
083: }
084:
085: public Object[] getChildren(Object parent, int from, int to)
086: throws UnknownTypeException {
087: if (parent == ROOT) {
088: return rubySession.getThreadInfos();
089: } else {
090: throw new UnknownTypeException(parent);
091: }
092: }
093:
094: public boolean isLeaf(Object node) throws UnknownTypeException {
095: if (node == ROOT) {
096: return false;
097: } else if (node instanceof RubyThreadInfo) {
098: // TODO - consider subthreads?
099: return true;
100: } else {
101: throw new UnknownTypeException(node);
102: }
103: }
104:
105: public int getChildrenCount(Object node)
106: throws UnknownTypeException {
107: if (node == ROOT) {
108: return rubySession.getThreadInfos().length;
109: } else {
110: throw new UnknownTypeException(node);
111: }
112: }
113:
114: public void addModelListener(ModelListener l) {
115: listeners.add(l);
116: }
117:
118: public void removeModelListener(ModelListener l) {
119: listeners.remove(l);
120: }
121:
122: public void fireChanges() {
123: for (ModelListener listener : listeners) {
124: listener.modelChanged(new ModelEvent.TreeChanged(this ));
125: }
126: }
127:
128: // NodeModel implementation ................................................
129:
130: public String getDisplayName(Object node)
131: throws UnknownTypeException {
132: if (node == ROOT) {
133: return NbBundle.getMessage(ThreadsModel.class,
134: "CTL_ThreadsModel.Column.Name.Name");
135: } else if (node instanceof RubyThreadInfo) {
136: RubyThreadInfo ti = (RubyThreadInfo) node;
137: String threadName = getThreadName(ti);
138: return rubySession.isActiveThread(ti.getId()) ? "<html><b>"
139: + threadName + "</b></html>" : threadName; // NOI18N
140: } else {
141: throw new UnknownTypeException(node);
142: }
143: }
144:
145: public String getIconBase(Object node) throws UnknownTypeException {
146: if (node == ROOT || node instanceof RubyThreadInfo) {
147: RubyThreadInfo ti = (RubyThreadInfo) node;
148: if (rubySession.isActiveThread(ti.getId())) {
149: return CURRENT;
150: } else if (rubySession.isSuspended(ti)) {
151: return SUSPENDED;
152: } else {
153: return RUNNING;
154: }
155: } else {
156: throw new UnknownTypeException(node);
157: }
158: }
159:
160: public String getShortDescription(Object node)
161: throws UnknownTypeException {
162: if (node == ROOT) {
163: return NbBundle.getMessage(ThreadsModel.class,
164: "CTL_ThreadsModel.Column.Name.Desc");
165: } else if (node instanceof RubyThreadInfo) {
166: return getThreadName((RubyThreadInfo) node);
167: } else {
168: throw new UnknownTypeException(node);
169: }
170: }
171:
172: // TableModel implementation ...............................................
173:
174: public Object getValueAt(Object node, String columnID)
175: throws UnknownTypeException {
176: if (node instanceof RubyThreadInfo
177: && THREAD_STATE_COLUMN_ID.equals(columnID)) {
178: return ((RubyThreadInfo) node).getStatus();
179: } else {
180: throw new UnknownTypeException(node);
181: }
182: }
183:
184: public boolean isReadOnly(Object node, String columnID)
185: throws UnknownTypeException {
186: if (node instanceof RubyThreadInfo
187: && THREAD_STATE_COLUMN_ID.equals(columnID)) {
188: return true;
189: } else {
190: throw new UnknownTypeException(node);
191: }
192: }
193:
194: public void setValueAt(Object node, String columnID, Object value)
195: throws UnknownTypeException {
196: throw new UnknownTypeException(node);
197: }
198:
199: // NodeActionsProvider implementation ......................................
200:
201: public void performDefaultAction(Object node)
202: throws UnknownTypeException {
203: if (node instanceof RubyThreadInfo) {
204: RubyThreadInfo ti = (RubyThreadInfo) node;
205: rubySession.switchThread(ti.getId(), contextProvider);
206: } else {
207: throw new UnknownTypeException(node);
208: }
209: }
210:
211: public Action[] getActions(Object node) throws UnknownTypeException {
212: return new Action[] {};
213: }
214:
215: private String getThreadName(final RubyThreadInfo ti) {
216: return "RubyThread - " + ti.getId();
217: }
218: }
|