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 @@ -152,6 +152,26 @@ + + + + ViewFactory and ViewLifecycle classes added. + + + + + +

+ ViewFactory class introduced to provide GUI views + created from registered view models. + ViewLifecycle class is a support class for a custom view + based on registered view models. +

+
+ + + +
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.33 +OpenIDE-Module-Specification-Version: 2.34 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/views/CustomView.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/CustomView.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/CustomView.java @@ -0,0 +1,109 @@ +/* + * 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.views; + +import java.io.Serializable; +import org.netbeans.spi.debugger.ui.ViewLifecycle.ModelUpdateListener; + +/** + * Additional view for custom model set. + * + * @author Martin Entlicher + */ +public class CustomView extends View { + + private transient String icon; + private transient String displayName; + private transient String toolTip; + + public CustomView(String icon, String name, String helpID, String propertiesHelpID, + String displayName, String toolTip) { + super(icon, name, helpID, propertiesHelpID, null, null); + this.icon = icon; + this.displayName = displayName; + this.toolTip = toolTip; + } + + @Override + public String getName() { + return displayName; + } + + @Override + public String getToolTipText() { + return toolTip; + } + + public static ViewModelListener createViewModelService(String name, + String propertiesHelpID, + ModelUpdateListener mul) { + return new ViewModelListener(name, propertiesHelpID, mul); + } + + @Override + public Object writeReplace() { + return new ResolvableHelper(icon, name, helpID, propertiesHelpID, displayName, toolTip); + } + + /** + * The serializing class. + */ + private static final class ResolvableHelper implements Serializable { + + private String[] data; + + private static final long serialVersionUID = 1L; + + ResolvableHelper(String... data) { + this.data = data; + } + + public ResolvableHelper() { + // Just for the purpose of deserialization + } + + public Object readResolve() { + return new CustomView(data[0], data[1], data[2], data[3], data[4], data[5]); + } + } + +} diff --git a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/View.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/View.java --- a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/View.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/View.java @@ -45,6 +45,7 @@ package org.netbeans.modules.debugger.ui.views; import java.awt.BorderLayout; +import java.awt.Image; import java.io.Externalizable; import java.io.IOException; import java.io.ObjectInput; @@ -76,13 +77,13 @@ private transient JComponent contentComponent; private transient ViewModelListener viewModelListener; - private String name; // Store just the name persistently, we'll create the component from that - private transient String helpID; - private transient String propertiesHelpID; + protected String name; // Store just the name persistently, we'll create the component from that + protected transient String helpID; + protected transient String propertiesHelpID; private transient String displayNameResource; private transient String toolTipResource; - private View (String icon, String name, String helpID, String propertiesHelpID, + protected View (String icon, String name, String helpID, String propertiesHelpID, String displayNameResource, String toolTipResource) { setIcon (ImageUtilities.loadImage (icon)); // Remember the location of the component when closed. @@ -112,7 +113,9 @@ contentComponent = new javax.swing.JPanel(new BorderLayout ()); //tree = Models.createView (Models.EMPTY_MODEL); - contentComponent.setName (NbBundle.getMessage (View.class, toolTipResource)); + if (toolTipResource != null) { + contentComponent.setName (NbBundle.getMessage (View.class, toolTipResource)); + } add (contentComponent, BorderLayout.CENTER); //NOI18N JToolBar toolBar = new JToolBar(JToolBar.VERTICAL); toolBar.setFloatable(false); diff --git a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/ViewComponent.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/ViewComponent.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/ViewComponent.java @@ -0,0 +1,110 @@ +/* + * 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.views; + +import java.awt.BorderLayout; +import javax.swing.JComponent; +import javax.swing.JToolBar; +import javax.swing.UIManager; +import org.openide.util.HelpCtx; +import org.openide.util.ImageUtilities; + +/** + * + * @author Martin Entlicher + */ +public class ViewComponent extends JComponent implements org.openide.util.HelpCtx.Provider { + + private String icon; + private String name; + private String helpID; + private String propertiesHelpID; + private transient JComponent contentComponent; + private ViewModelListener viewModelListener; + + public ViewComponent(String icon, String name, String helpID, String propertiesHelpID) { + this.icon = icon; + this.name = name; + this.helpID = helpID; + this.propertiesHelpID = propertiesHelpID; + initComponents(); + } + + private void initComponents() { + setLayout (new BorderLayout ()); + contentComponent = new javax.swing.JPanel(new BorderLayout ()); + add (contentComponent, BorderLayout.CENTER); //NOI18N + JToolBar toolBar = new JToolBar(JToolBar.VERTICAL); + toolBar.setFloatable(false); + toolBar.setRollover(true); + toolBar.setBorderPainted(true); + if( "Aqua".equals(UIManager.getLookAndFeel().getID()) ) { //NOI18N + toolBar.setBackground(UIManager.getColor("NbExplorerView.background")); //NOI18N + } + toolBar.setBorder(javax.swing.BorderFactory.createCompoundBorder( + javax.swing.BorderFactory.createMatteBorder(0, 0, 0, 1, + javax.swing.UIManager.getDefaults().getColor("Separator.background")), + javax.swing.BorderFactory.createMatteBorder(0, 0, 0, 1, + javax.swing.UIManager.getDefaults().getColor("Separator.foreground")))); + add(toolBar, BorderLayout.WEST); + JComponent buttonsPane = toolBar; + viewModelListener = new ViewModelListener ( + name, + contentComponent, + buttonsPane, + propertiesHelpID, + ImageUtilities.loadImage(icon) + ); + } + + @Override + public void removeNotify() { + if (viewModelListener != null) { + viewModelListener.destroy (); + } + } + + @Override + public HelpCtx getHelpCtx() { + return new org.openide.util.HelpCtx(helpID); + } +} diff --git a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/ViewModelListener.java b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/ViewModelListener.java --- a/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/ViewModelListener.java +++ b/spi.debugger.ui/src/org/netbeans/modules/debugger/ui/views/ViewModelListener.java @@ -75,6 +75,7 @@ import org.netbeans.api.debugger.Session; import org.netbeans.spi.debugger.ContextProvider; import org.netbeans.spi.debugger.SessionProvider; +import org.netbeans.spi.debugger.ui.ViewLifecycle.ModelUpdateListener; import org.netbeans.spi.viewmodel.AsynchronousModelFilter; import org.netbeans.spi.viewmodel.CheckNodeModel; import org.netbeans.spi.viewmodel.CheckNodeModelFilter; @@ -169,6 +170,8 @@ private Preferences viewPreferences; private MessageFormat viewTreeDisplayFormat; private ViewPreferenceChangeListener prefListener = new ViewPreferenceChangeListener(); + + private ModelUpdateListener mul; private static final RequestProcessor RP = new RequestProcessor(ViewModelListener.class.getName(), 1); @@ -190,11 +193,23 @@ buttonsPane.setLayout(new GridBagLayout()); this.propertiesHelpID = propertiesHelpID; this.viewIcon = viewIcon; - viewPreferences = NbPreferences.forModule(ContextProvider.class).node(VIEW_PREFERENCES_NAME).node(viewType); + initView(); setUp(); } // + ViewModelListener(String viewType, String propertiesHelpID, ModelUpdateListener mul) { + this.viewType = viewType; + this.propertiesHelpID = propertiesHelpID; + this.mul = mul; + setUp(); + } + + private void initView() { + // To have reasonable preferred size + view.add(Models.createView(Models.EMPTY_MODEL)); + } + void setUp() { if (SwingUtilities.isEventDispatchThread()) { RP.post(new Runnable() { @@ -204,6 +219,7 @@ }); return ; } + viewPreferences = NbPreferences.forModule(ContextProvider.class).node(VIEW_PREFERENCES_NAME).node(viewType); DebuggerManager.getDebuggerManager ().addDebuggerListener ( DebuggerManager.PROP_CURRENT_ENGINE, this @@ -217,7 +233,7 @@ updateModelLazily (); } - void destroy () { + public void destroy () { if (SwingUtilities.isEventDispatchThread()) { RP.post(new Runnable() { @Override public void run() { @@ -255,7 +271,7 @@ } } final boolean haveModels = haveTreeModels || haveNodeModels || tableModels != null && tableModels.size() > 0; - if (haveModels && view.getComponentCount() > 0) { + if (haveModels && view != null && view.getComponentCount() > 0) { JComponent tree = (JComponent) view.getComponent(0); if (!(tree instanceof javax.swing.JTabbedPane)) { Models.setModelsToView(tree, null); @@ -281,22 +297,25 @@ currentSession = null; providerToDisplay = null; buttons = null; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - // Have to access UI in AWT - synchronized (destroyLock) { - if (buttons == null) { // Still destroyed. Might be re-created in between. - buttonsPane.removeAll(); - view.removeAll(); + if (view != null) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // Have to access UI in AWT + synchronized (destroyLock) { + if (buttons == null) { // Still destroyed. Might be re-created in between. + buttonsPane.removeAll(); + view.removeAll(); + } } } - } - }); + }); + } sls = new ArrayList(subListeners); subListeners.clear(); isUp = false; } + mul = null; } for (ViewModelListener l : sls) { l.destroy(); @@ -463,7 +482,7 @@ buttons = theButtons; tabbedPane = cp.lookupFirst(viewPath, javax.swing.JTabbedPane.class); - ModelsChangeRefresher mcr = new ModelsChangeRefresher(); + ModelsChangeRefresher mcr = new ModelsChangeRefresher(e); Customizer[] modelListCustomizers = new Customizer[] { //(Customizer) treeModels, //(Customizer) treeModelFilters, @@ -496,7 +515,7 @@ } } - refreshModel(); + refreshModel(e); } private static void addAsCustomizers(List modelListCustomizerLists, Object[] modelLists) { @@ -519,7 +538,7 @@ return models; } - private synchronized void refreshModel() { + private synchronized void refreshModel(DebuggerEngine e) { models.clear(); if (mm == null) { // Destroyed @@ -614,6 +633,12 @@ } else { newModel = null; } + if (mul != null) { + mul.modelUpdated(newModel, e); + } + if (view == null) { + return; + } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { @@ -882,7 +907,12 @@ private class ModelsChangeRefresher implements PropertyChangeListener, Runnable { + private DebuggerEngine e; private RequestProcessor.Task task; + + ModelsChangeRefresher(DebuggerEngine e) { + this.e = e; + } @Override public synchronized void propertyChange(PropertyChangeEvent evt) { @@ -894,7 +924,7 @@ @Override public void run() { - refreshModel(); + refreshModel(e); } } diff --git a/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/ViewFactory.java b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/ViewFactory.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/ViewFactory.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 javax.swing.JComponent; +import org.netbeans.modules.debugger.ui.views.CustomView; +import org.netbeans.modules.debugger.ui.views.ViewComponent; +import org.netbeans.modules.debugger.ui.views.ViewModelListener; +import org.openide.windows.TopComponent; + +/** + * Factory that produces debugger views created from registered view models + * (see {@link org.netbeans.spi.viewmodel.Model} and it's extension interfaces). + * + * @author Martin Entlicher + * @since 2.34 + */ +public class ViewFactory { + + private static ViewFactory vf; + + private ViewFactory() {} + + /** + * Get the default implementation of view factory. + * + * @return The view factory. + */ + public static synchronized ViewFactory getDefault() { + if (vf == null) { + vf = new ViewFactory(); + } + return vf; + } + + /** + * Create {@link TopComponent} view from models registered under 'name' path. + * @param icon The icon resource of the TopComponent + * @param name Name of the view, under which are the models registered + * @param helpID The helpID of the created TopComponent + * @param propertiesHelpID The helpID of properties displayed in the view + * @param displayName Display name of the view + * @param toolTip Tooltip of the view + * @return TopComponent containing the view created from registered models. + */ + public TopComponent createViewTC(String icon, String name, String helpID, String propertiesHelpID, + String displayName, String toolTip) { + CustomView v = new CustomView(icon, name, helpID, propertiesHelpID, displayName, toolTip); + return v; + } + + /** + * Create {@link JComponent} view from models registered under 'name' path. + * @param icon The icon resource, possibly used by the button toolbar in the view + * @param name Name of the view, under which are the models registered + * @param helpID The helpID of the created TopComponent + * @param propertiesHelpID The helpID of properties displayed in the view + * @return Component containing the view created from registered models. + */ + public JComponent createViewComponent(String icon, String name, String helpID, String propertiesHelpID) { + JComponent c = new ViewComponent(icon, name, helpID, propertiesHelpID); + return c; + } + + /** + * Create a support for a custom view based on models registered under 'name' path. + * @param name Name of the view, under which are the models registered + * @param propertiesHelpID The helpID of properties displayed in the view + * @return ViewLifecycle support object for the custom view + */ + public ViewLifecycle createAbstractView(String name, String propertiesHelpID) { + ViewLifecycle.CompoundModelUpdateListener cmul = new ViewLifecycle.CompoundModelUpdateListener(); + ViewModelListener vml = CustomView.createViewModelService(name, propertiesHelpID, cmul); + return new ViewLifecycle(vml, cmul); + } + +} diff --git a/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/ViewLifecycle.java b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/ViewLifecycle.java new file mode 100644 --- /dev/null +++ b/spi.debugger.ui/src/org/netbeans/spi/debugger/ui/ViewLifecycle.java @@ -0,0 +1,153 @@ +/* + * 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.util.LinkedList; +import java.util.List; +import org.netbeans.api.debugger.DebuggerEngine; +import org.netbeans.modules.debugger.ui.views.ViewModelListener; +import org.netbeans.spi.viewmodel.Models; +import org.netbeans.spi.viewmodel.Models.CompoundModel; + +/** + * Support class for a custom view based on registered view models. + * + * @author Martin Entlicher + * @since 2.34 + */ +public final class ViewLifecycle { + + private ViewModelListener vml; + private final CompoundModelUpdateListener cmul; + + ViewLifecycle(ViewModelListener vml, CompoundModelUpdateListener cmul) { + this.vml = vml; + this.cmul = cmul; + } + + /** + * Get the current compound model, that can be used to construct the custom + * view. + * @return The current compound model + */ + public Models.CompoundModel getModel() { + return cmul.getCurrentModel(); + } + + /** + * Add a listener, which is called with the updated compound model. + * @param mul The model update listener + */ + public void addModelUpdateListener(ModelUpdateListener mul) { + cmul.addModelUpdateListener(mul); + } + + /** + * Remove a model update listener + * @param mul The model update listener + */ + public void removeModelUpdateListener(ModelUpdateListener mul) { + cmul.removeModelUpdateListener(mul); + } + + /** + * Destroy the underlying data, call this method when the view is closed. + * Model updates will no longer be received after this method is called. + */ + public void destroy() { + vml.destroy(); + } + + + /** + * Model update listener, notified with updated compound model. + */ + public static interface ModelUpdateListener { + + /** + * Called when compound model is updated. + * + * @param compoundModel The new compound model + * @param de The associated debugger engine, whose models were used to create the + * compound model. Can be null, when no active debugger engine + * was found. + */ + public void modelUpdated(Models.CompoundModel compoundModel, DebuggerEngine de); + + } + + static class CompoundModelUpdateListener implements ModelUpdateListener { + + private final List muls = new LinkedList(); + private CompoundModel currentCompoundModel; + + public void addModelUpdateListener(ModelUpdateListener mul) { + synchronized(muls) { + muls.add(mul); + } + } + + public void removeModelUpdateListener(ModelUpdateListener mul) { + synchronized(muls) { + muls.remove(mul); + } + } + + public CompoundModel getCurrentModel() { + return currentCompoundModel; + } + + @Override + public void modelUpdated(CompoundModel compoundModel, DebuggerEngine de) { + List muls2; + synchronized(muls) { + currentCompoundModel = compoundModel; + muls2 = new LinkedList(muls); + } + for (ModelUpdateListener mul : muls2) { + mul.modelUpdated(compoundModel, de); + } + } + + } + +}