From de790b478e041e87d1a981e8649ccdf7c908d7ba Mon Sep 17 00:00:00 2001 From: Marc Dumais Date: Mon, 6 May 2013 06:30:25 -0400 Subject: [PATCH] Bug 405390 - [Visualizer] Implement selection-based filtering of the multicore visualizer display Change-Id: I516af7e4b625add754eaa1713ddc562a33f15c79 Reviewed-on: https://git.eclipse.org/r/12138 Reviewed-by: Marc-Andre Laperle IP-Clean: Marc-Andre Laperle Tested-by: Marc-Andre Laperle --- .../resources/messages.properties | 11 +- .../ui/actions/FilterCanvasAction.java | 72 +++++ .../ui/model/IVisualizerModelObject.java | 25 ++ .../internal/ui/model/VisualizerCPU.java | 22 +- .../internal/ui/model/VisualizerCore.java | 24 +- .../internal/ui/model/VisualizerModel.java | 19 +- .../internal/ui/model/VisualizerThread.java | 29 +- .../view/IMulticoreVisualizerConstants.java | 5 +- .../internal/ui/view/MulticoreVisualizer.java | 58 +++- .../ui/view/MulticoreVisualizerCanvas.java | 147 +++++++-- .../view/MulticoreVisualizerCanvasFilter.java | 300 ++++++++++++++++++ .../MulticoreVisualizerEventListener.java | 5 +- .../ui/view/MulticoreVisualizerStatusBar.java | 60 ++++ 13 files changed, 734 insertions(+), 43 deletions(-) create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/actions/FilterCanvasAction.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/IVisualizerModelObject.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvasFilter.java create mode 100644 dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerStatusBar.java diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/resources/messages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/resources/messages.properties index 62b3b75d91f..9cee7975be6 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/resources/messages.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/resources/messages.properties @@ -1,5 +1,5 @@ # ============================================================================= -# Copyright (c) 2012 Tilera Corporation and others. +# Copyright (c) 2012, 2013 Tilera Corporation and others. # All rights reserved. This program and the accompanying materials # are made available under the terms of the Eclipse Public License v1.0 # which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ # Contributors: # William R. Swanson (Tilera Corporation) # Marc Dumais (Ericsson) - Add CPU/core load information to the multicore visualizer (Bug 396268) +# Marc Dumais (Ericsson) - Bug 405390 # ============================================================================= # ----------------------------------------------------------------------------- @@ -32,3 +33,11 @@ MulticoreVisualizer.actions.SetLoadMeterPeriod.description=Choose the refresh sp MulticoreVisualizer.actions.LoadMeterSubmenu.text=Load Meters MulticoreVisualizer.actions.LoadMetersRefreshSubSubmenu.text=Refresh Speed + +MulticoreVisualizer.actions.ClearFilter.text=Clear filter +MulticoreVisualizer.actions.SetFilter.text=Filter to selection +MulticoreVisualizer.view.CanvasFilter.Active.text=Filter Active: +MulticoreVisualizer.view.CanvasFilter.cpu.text=CPUs: +MulticoreVisualizer.view.CanvasFilter.core.text=Cores: +MulticoreVisualizer.view.CanvasFilter.thread.text=Threads: +MulticoreVisualizer.view.CanvasFilter.NotActive.text=Filter not active \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/actions/FilterCanvasAction.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/actions/FilterCanvasAction.java new file mode 100644 index 00000000000..e018bd8c642 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/actions/FilterCanvasAction.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Dumais (Ericsson) - Initial API and implementation (Bug 405390) + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.actions; + +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.MulticoreVisualizerUIPlugin; +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.view.MulticoreVisualizer; +import org.eclipse.cdt.visualizer.ui.VisualizerAction; + +/** + * @since 1.1 + */ +public class FilterCanvasAction extends VisualizerAction { + + /** Visualizer instance we're associated with. */ + MulticoreVisualizer m_visualizer = null; + boolean m_haveFilter = false; + + + /** + * @param filterType: the type of canvas object the filter applies-to. If null, reset filter + */ + public FilterCanvasAction(boolean enable) { + m_haveFilter = enable; + if (m_haveFilter) { + setText(MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.actions.SetFilter.text")); //$NON-NLS-1$ + } + else { + setText(MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.actions.ClearFilter.text")); //$NON-NLS-1$ + } + } + + /** Dispose method. */ + @Override + public void dispose() + { + m_visualizer = null; + super.dispose(); + } + + // --- init methods --- + + /** Initializes this action for the specified view. */ + public void init(MulticoreVisualizer visualizer) + { + m_visualizer = visualizer; + } + + + // --- methods --- + + /** Invoked when action is triggered. */ + @Override + public void run() { + if (m_visualizer != null) { + if (m_haveFilter) { + m_visualizer.applyCanvasFilter(); + } + else { + m_visualizer.clearCanvasFilter(); + } + } + } +} \ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/IVisualizerModelObject.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/IVisualizerModelObject.java new file mode 100644 index 00000000000..757189bb815 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/IVisualizerModelObject.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Dumais (Ericsson) - Initial API and implementation (Bug 405390) + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model; + +/** + * Common interface for visualizer model objects + */ +public interface IVisualizerModelObject { + /** Get the ID of this model object */ + public int getID(); + + /** Get the parent of this model object*/ + public IVisualizerModelObject getParent(); + + /** Compare two IVisualizerModelObject */ + public int compareTo(IVisualizerModelObject o); +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCPU.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCPU.java index c70117be4c8..3b1e056c321 100755 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCPU.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCPU.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Tilera Corporation and others. + * Copyright (c) 2012, 2013 Tilera Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,6 +8,7 @@ * Contributors: * William R. Swanson (Tilera Corporation) - initial API and implementation * Marc Dumais (Ericsson) - Add CPU/core load information to the multicore visualizer (Bug 396268) + * Marc Dumais (Ericsson) - Bug 405390 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model; @@ -23,7 +24,7 @@ import java.util.List; /** Represents single CPU. */ public class VisualizerCPU - implements Comparable + implements Comparable, IVisualizerModelObject { // --- members --- @@ -78,10 +79,17 @@ public class VisualizerCPU // --- accessors --- /** Gets ID of this CPU. */ + @Override public int getID() { return m_id; } + /** CPU has no parent - always returns null */ + @Override + public IVisualizerModelObject getParent() { + return null; + } + /** sets the load info for this CPU * @since 1.1*/ public synchronized void setLoadInfo (VisualizerLoadInfo info) { @@ -154,4 +162,14 @@ public class VisualizerCPU return result; } + /** IVisualizerModelObject version of compareTO() */ + @Override + public int compareTo(IVisualizerModelObject o) { + if (o != null) { + if (o.getClass() == this.getClass()) { + return compareTo((VisualizerCPU)o); + } + } + return 1; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCore.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCore.java index 4d2e6571d44..20a63dfacd4 100755 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCore.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerCore.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Tilera Corporation and others. + * Copyright (c) 2012, 2013 Tilera Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -8,13 +8,15 @@ * Contributors: * William R. Swanson (Tilera Corporation) - initial API and implementation * Marc Dumais (Ericsson) - Add CPU/core load information to the multicore visualizer (Bug 396268) + * Marc Dumais (Ericsson) - Bug 405390 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model; + /** Represents single core of a CPU. */ public class VisualizerCore - implements Comparable + implements Comparable, IVisualizerModelObject { // --- members --- @@ -60,10 +62,17 @@ public class VisualizerCore } /** Gets Linux CPU ID of this core. */ + @Override public int getID() { return m_id; } + /** Return CPU this core is on. */ + @Override + public IVisualizerModelObject getParent() { + return getCPU(); + } + /** sets the load info for this core * @since 1.1*/ public synchronized void setLoadInfo (VisualizerLoadInfo info) { @@ -103,5 +112,16 @@ public class VisualizerCore } return result; } + + /** IVisualizerModelObject version of compareTO() */ + @Override + public int compareTo(IVisualizerModelObject o) { + if (o != null) { + if (o.getClass() == this.getClass()) { + return compareTo((VisualizerCore)o); + } + } + return 1; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerModel.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerModel.java index bdddd3bdf25..dfc9b87d095 100755 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerModel.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerModel.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Tilera Corporation and others. + * Copyright (c) 2012, 2013 Tilera Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,7 +7,7 @@ * * Contributors: * William R. Swanson (Tilera Corporation) - initial API and implementation - * Marc Dumais (Ericsson) - Initial API and implementation (Bug 396268) + * Marc Dumais (Ericsson) - Bug 405390 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model; @@ -127,6 +127,21 @@ public class VisualizerModel return m_cpus.size(); } + /** Gets number of cores. */ + public int getCoreCount() { + int count = 0; + + for(VisualizerCPU cpu : m_cpus) { + count += cpu.getCoreCount(); + } + return count; + } + + /** Gets number of threads. */ + public int getThreadCount () { + return m_threads.size(); + } + /** Gets CPU with specified ID. */ public VisualizerCPU getCPU(int id) { return m_cpuMap.get(id); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerThread.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerThread.java index 18a8586704a..33810daf394 100755 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerThread.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/model/VisualizerThread.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Tilera Corporation and others. + * Copyright (c) 2012, 2013 Tilera Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,13 +9,15 @@ * William R. Swanson (Tilera Corporation) - initial API and implementation * Marc Khouzam (Ericsson) - Added knowledge about execution * state and os/gdb thread ids + * Marc Dumais (Ericsson) - Bug 405390 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model; + /** Represents single thread. */ public class VisualizerThread - implements Comparable + implements Comparable, IVisualizerModelObject { // --- members --- @@ -113,6 +115,18 @@ public class VisualizerThread return m_tid; } + /** Gets thread id (tid). */ + @Override + public int getID() { + return getTID(); + } + + /** Return core the thread is on */ + @Override + public IVisualizerModelObject getParent() { + return getCore(); + } + /** Gets gdb thread id. */ public int getGDBTID() { return m_gdbtid; @@ -155,4 +169,15 @@ public class VisualizerThread } return result; } + + /** IVisualizerModelObject version of compareTo() */ + @Override + public int compareTo(IVisualizerModelObject o) { + if (o != null) { + if (o.getClass() == this.getClass()) { + return compareTo((VisualizerThread)o); + } + } + return 1; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/IMulticoreVisualizerConstants.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/IMulticoreVisualizerConstants.java index 6ec0634e24f..e62511e450c 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/IMulticoreVisualizerConstants.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/IMulticoreVisualizerConstants.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Ericsson and others. + * Copyright (c) 2012, 2013 Ericsson and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -76,6 +76,9 @@ public class IMulticoreVisualizerConstants */ public static final Color COLOR_LOAD_TEXT = Colors.GREEN; + /** Color used to draw text to the status bar */ + public static final Color COLOR_STATUS_BAR_TEXT = Colors.GREEN; + // Colors for load meters /** diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizer.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizer.java index 65443da8b91..aab49363d3b 100755 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizer.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Tilera Corporation and others. + * Copyright (c) 2012, 2013 Tilera Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,6 +11,7 @@ * Marc Dumais (Ericsson) - Bug 399281 * Marc Dumais (Ericsson) - Add CPU/core load information to the multicore visualizer (Bug 396268) * Marc Dumais (Ericsson) - Bug 399419 + * Marc Dumais (Ericsson) - Bug 405390 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.view; @@ -29,6 +30,7 @@ import org.eclipse.cdt.dsf.gdb.launching.GDBProcess; import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.MulticoreVisualizerUIPlugin; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.actions.EnableLoadMetersAction; +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.actions.FilterCanvasAction; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.actions.RefreshAction; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.actions.SelectAllAction; import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.actions.SetLoadMeterPeriodAction; @@ -197,6 +199,11 @@ public class MulticoreVisualizer extends GraphicCanvasVisualizer /** Menu action */ List m_setLoadMeterPeriodActions = null; + /** Menu action */ + FilterCanvasAction m_setFilterAction = null; + + /** Menu action */ + FilterCanvasAction m_clearFilterAction = null; // --- constructors/destructors --- @@ -339,6 +346,23 @@ public class MulticoreVisualizer extends GraphicCanvasVisualizer return (MulticoreVisualizerCanvas) getCanvas(); } + /** Sets-up a canvas filter */ + public void applyCanvasFilter() { + m_canvas.applyFilter(); + refresh(); + } + + /** Removes current canvas filter */ + public void clearCanvasFilter() { + m_canvas.clearFilter(); + refresh(); + } + + /** Tells if a canvas filter is in effect */ + public boolean isCanvasFilterActive() { + return m_canvas.isFilterActive(); + } + /** Return the data model backing this multicore visualizer */ public VisualizerModel getModel() { return fDataModel; @@ -415,6 +439,16 @@ public class MulticoreVisualizer extends GraphicCanvasVisualizer defaultAction.setChecked(true); defaultAction.run(); + // canvas filter actions - they will be dynamically enabled/disabled + // according to canvas selection + m_setFilterAction = new FilterCanvasAction(true); + m_setFilterAction.init(this); + m_setFilterAction.setEnabled(false); + + m_clearFilterAction = new FilterCanvasAction(false); + m_clearFilterAction.init(this); + m_clearFilterAction.setEnabled(false); + // Note: debug view may not be initialized at startup, // so we'll pretend the actions are not yet updated, // and reinitialize them later. @@ -429,6 +463,13 @@ public class MulticoreVisualizer extends GraphicCanvasVisualizer boolean enabled = hasSelection(); m_selectAllAction.setEnabled(enabled); m_refreshAction.setEnabled(enabled); + + // enable "filter-to selection" menu item if there is a + // canvas selection + m_setFilterAction.setEnabled(m_canvas.hasSelection()); + + // enable "Clear filter" menu item if filter is active + m_clearFilterAction.setEnabled(isCanvasFilterActive()); // show the load meter refresh speed sub-menu only // if the load meters are enabled @@ -515,6 +556,16 @@ public class MulticoreVisualizer extends GraphicCanvasVisualizer m_setLoadMeterPeriodActions = null; } + if (m_setFilterAction != null) { + m_setFilterAction.dispose(); + m_setFilterAction = null; + } + + if (m_clearFilterAction != null) { + m_clearFilterAction.dispose(); + m_clearFilterAction = null; + } + m_actionsInitialized = false; } @@ -592,6 +643,11 @@ public class MulticoreVisualizer extends GraphicCanvasVisualizer m_loadMetersRefreshSubSubmenu.add(act); } + // add filtering options + menuManager.add(m_separatorAction); + menuManager.add(m_setFilterAction); + menuManager.add(m_clearFilterAction); + updateActions(); Point location = m_viewer.getContextMenuLocation(); updateContextMenuActions(location); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvas.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvas.java index 164c0eaf3c4..ffc328310ed 100755 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvas.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvas.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Tilera Corporation and others. + * Copyright (c) 2012, 2013 Tilera Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,7 @@ * Marc Dumais (Ericsson) - Add CPU/core load information to the multicore visualizer (Bug 396268) * Marc Dumais (Ericsson) - Bug 399419 * Marc Dumais (Ericsson) - Bug 404894 + * Marc Dumais (Ericsson) - Bug 405390 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.view; @@ -139,6 +140,11 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas /** Selected PIDs. */ protected HashSet m_selectedPIDs = null; + /** Display filter for the graphical objects */ + protected MulticoreVisualizerCanvasFilter m_canvasFilter = null; + + /** Canvas status bar */ + protected MulticoreVisualizerStatusBar m_statusBar = null; // --- constructors/destructors --- @@ -228,6 +234,12 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas }; m_updateTimer.setRepeating(false); // one-shot timer m_updateTimer.start(); + + // canvas filter + m_canvasFilter = new MulticoreVisualizerCanvasFilter(this); + + // status bar + m_statusBar = new MulticoreVisualizerStatusBar(); } /** Cleans up control */ @@ -276,6 +288,14 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas m_selectedPIDs.clear(); m_selectedPIDs = null; } + if (m_canvasFilter != null) { + m_canvasFilter.dispose(); + m_canvasFilter = null; + } + if (m_statusBar != null) { + m_statusBar.dispose(); + m_statusBar = null; + } } @@ -291,6 +311,8 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas public void setModel(VisualizerModel model) { m_model = model; + // TODO : Consider clearing the filter if the model changes, + // by calling clearFilter() requestRecache(); requestUpdate(); } @@ -355,6 +377,10 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas m_recacheState |= state; m_recacheSizes |= sizes; m_recacheLoadMeters |= load; + // clear status bar message + m_statusBar.setMessage(null); + // re-compute filter to reflect latest model changes + m_canvasFilter.updateFilter(); } /** Fits n square items into a rectangle of the specified size. @@ -411,13 +437,19 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas for (VisualizerCPU cpu : m_model.getCPUs()) { //if (force_cpu_count >= cpu_count) break; //cpu_count++; - MulticoreVisualizerCPU mcpu = new MulticoreVisualizerCPU(cpu.getID()); - m_cpus.add(mcpu); - m_cpuMap.put(cpu, mcpu); - for (VisualizerCore core : cpu.getCores()) { - MulticoreVisualizerCore mcore = new MulticoreVisualizerCore(mcpu, core.getID()); - m_cores.add(mcore); - m_coreMap.put(core, mcore); + // filter permits displaying this CPU? + if (m_canvasFilter.displayObject(cpu)) { + MulticoreVisualizerCPU mcpu = new MulticoreVisualizerCPU(cpu.getID()); + m_cpus.add(mcpu); + m_cpuMap.put(cpu, mcpu); + for (VisualizerCore core : cpu.getCores()) { + // filter permits displaying this core? + if (m_canvasFilter.displayObject(core)) { + MulticoreVisualizerCore mcore = new MulticoreVisualizerCore(mcpu, core.getID()); + m_cores.add(mcore); + m_coreMap.put(core, mcore); + } + } } } } @@ -442,19 +474,25 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas while (modelCpus.hasMoreElements()) { VisualizerCPU modelCpu = modelCpus.nextElement(); MulticoreVisualizerCPU visualizerCpu = m_cpuMap.get(modelCpu); - // update CPUs load meter - MulticoreVisualizerLoadMeter meter = visualizerCpu.getLoadMeter(); - meter.setEnabled(m_model.getLoadMetersEnabled()); - meter.setLoad(modelCpu.getLoad()); - meter.setHighLoadWatermark(modelCpu.getHighLoadWatermark()); - - for (VisualizerCore modelCore : modelCpu.getCores()) { - MulticoreVisualizerCore visualizerCore = m_coreMap.get(modelCore); - // update cores load meter - meter = visualizerCore.getLoadMeter(); + // when filtering is active, not all objects might be in the map + if (visualizerCpu != null) { + // update CPUs load meter + MulticoreVisualizerLoadMeter meter = visualizerCpu.getLoadMeter(); meter.setEnabled(m_model.getLoadMetersEnabled()); - meter.setLoad(modelCore.getLoad()); - meter.setHighLoadWatermark(modelCore.getHighLoadWatermark()); + meter.setLoad(modelCpu.getLoad()); + meter.setHighLoadWatermark(modelCpu.getHighLoadWatermark()); + + for (VisualizerCore modelCore : modelCpu.getCores()) { + MulticoreVisualizerCore visualizerCore = m_coreMap.get(modelCore); + // when filtering is active, not all objects might be in the map + if (visualizerCore != null) { + // update cores load meter + meter = visualizerCore.getLoadMeter(); + meter.setEnabled(m_model.getLoadMetersEnabled()); + meter.setLoad(modelCore.getLoad()); + meter.setHighLoadWatermark(modelCore.getHighLoadWatermark()); + } + } } } } @@ -474,6 +512,14 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas // General margin/spacing constants. int cpu_margin = 8; // margin around edges of CPU grid int cpu_separation = 6; // spacing between CPUS + int statusBarHeight; + // reserve space for status bar only if filter is active + if (isFilterActive()) { + statusBarHeight = 20; + } + else { + statusBarHeight = 0; + } // make room when load meters are present, else use a more compact layout int core_margin = m_model.getLoadMetersEnabled() ? 20 : 12; // margin around cores in a CPU @@ -490,13 +536,27 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas // Figure out area to allocate to each CPU box. int ncpus = m_cpus.size(); int width = bounds.width + cpu_separation; - int height = bounds.height + cpu_separation; + int height = bounds.height + cpu_separation - statusBarHeight; + + // put status bar at the bottom of the canvas area + m_statusBar.setBounds(cpu_margin, bounds.y + bounds.height - 2 * cpu_margin , width , statusBarHeight); + int cpu_edge = fitSquareItems(ncpus, width, height); int cpu_size = cpu_edge - cpu_separation; if (cpu_size < 0) cpu_size = 0; // Calculate area on each CPU for placing cores. - int ncores = m_cores.size() / ((ncpus == 0) ? 1 : ncpus); + int ncores = 0; + // find the greatest number of cores on a given CPU and use + // that number for size calculations for all CPUs - this way + // we avoid displaying cores of varying sizes, in different + // CPUs. + for (MulticoreVisualizerCPU cpu : m_cpus) { + int n = cpu.getCores().size(); + if (n > ncores) { + ncores = n; + } + } int cpu_width = cpu_size - core_margin * 2 + core_separation; int cpu_height = cpu_size - core_margin * 2 + core_separation; int core_edge = fitSquareItems(ncores, cpu_width, cpu_height); @@ -572,14 +632,17 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas // like processes and threads for (VisualizerThread thread : m_model.getThreads()) { - VisualizerCore core = thread.getCore(); - MulticoreVisualizerCore mcore = m_coreMap.get(core); - if (mcore != null) { - MulticoreVisualizerThread mthread = - new MulticoreVisualizerThread(mcore, thread); - mcore.addThread(mthread); - m_threads.add(mthread); - m_threadMap.put(thread, mthread); + // filter permits displaying this thread? + if(m_canvasFilter.displayObject(thread)) { + VisualizerCore core = thread.getCore(); + MulticoreVisualizerCore mcore = m_coreMap.get(core); + if (mcore != null) { + MulticoreVisualizerThread mthread = + new MulticoreVisualizerThread(mcore, thread); + mcore.addThread(mthread); + m_threads.add(mthread); + m_threadMap.put(thread, mthread); + } } } @@ -658,6 +721,12 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas thread.paintContent(gc); } + // paint status bar + if (m_canvasFilter.isFilterActive()) { + m_statusBar.setMessage(m_canvasFilter.toString()); + m_statusBar.paintContent(gc); + } + // paint drag-selection marquee last, so it's on top. m_marquee.paintContent(gc); } @@ -1025,4 +1094,22 @@ public class MulticoreVisualizerCanvas extends GraphicCanvas public void setSelectionEventsEnabled(boolean enabled) { m_selectionManager.setSelectionEventsEnabled(enabled); } + + + // --- canvas filter methods --- + + /** Set-up a canvas white-list filter. */ + public void applyFilter() { + m_canvasFilter.applyFilter(); + } + + /** Removes any canvas filter currently in place */ + public void clearFilter() { + m_canvasFilter.clearFilter(); + } + + /** Tells if a canvas filter is currently in place */ + public boolean isFilterActive() { + return m_canvasFilter.isFilterActive(); + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvasFilter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvasFilter.java new file mode 100644 index 00000000000..09dce2c7a5c --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerCanvasFilter.java @@ -0,0 +1,300 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Dumais (Ericsson) - Initial API and implementation (Bug 405390) + *******************************************************************************/ + +package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.view; + +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.MulticoreVisualizerUIPlugin; +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model.IVisualizerModelObject; +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model.VisualizerCPU; +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model.VisualizerCore; +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model.VisualizerModel; +import org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.model.VisualizerThread; +import org.eclipse.cdt.visualizer.ui.util.SelectionUtils; +import org.eclipse.jface.viewers.ISelection; + + +/** + * White-list Filter for the graphical objects displayed in the multicore + * visualizer canvas. + */ +public class MulticoreVisualizerCanvasFilter { + + /** The white list */ + List m_filterList = null; + /** the dynamically expanded list, containing elements in the */ + /** white list and their parents - recalculated as required */ + /** since some elements can move around and change parent */ + List m_dynamicFilterList = null; + /** reference to the canvas */ + private MulticoreVisualizerCanvas m_canvas = null; + + /** is the filter is active/set */ + private boolean m_filterActive = false; + + /** for stats */ + private int m_shownCpu = 0; + /** for stats */ + private int m_shownCore = 0; + /** for stats */ + private int m_shownThread = 0; + /** for stats */ + private int m_totalCpu = 0; + /** for stats */ + private int m_totalCore = 0; + /** for stats */ + private int m_totalThread = 0; + + /** String constant used in this class */ + private static final String STR_FILTER_NOT_ACTIVE = MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.NotActive.text"); //$NON-NLS-1$ + /** String constant used in this class */ + private static final String STR_FILTER_ACTIVE = MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.Active.text"); //$NON-NLS-1$ + /** String constant used in this class */ + private static final String STR_CPU = MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.cpu.text"); //$NON-NLS-1$ + /** String constant used in this class */ + private static final String STR_CORE = MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.core.text"); //$NON-NLS-1$ + /** String constant used in this class */ + private static final String STR_THREAD = MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.thread.text"); //$NON-NLS-1$ + + // --- constructors/destructors --- + + /** Constructor. */ + public MulticoreVisualizerCanvasFilter(MulticoreVisualizerCanvas canvas) { + m_canvas = canvas; + } + + /** Dispose method */ + public void dispose() { + clearFilter(); + m_canvas = null; + } + + + // --- filter methods --- + + /** + * Set-up a canvas white-list filter. Any applicable selected object is added to + * the filter. + */ + public void applyFilter() { + // replace current filter? Clear old one first. + if (isFilterActive()) { + clearFilter(); + } + + m_filterList = new ArrayList(); + m_dynamicFilterList = new ArrayList(); + + m_filterActive = true; + + // get list of selected objects the filter applies-for + ISelection selection = m_canvas.getSelection(); + List selectedObjects = SelectionUtils.getSelectedObjects(selection); + + for (Object obj : selectedObjects) { + if (obj instanceof IVisualizerModelObject) { + m_filterList.add((IVisualizerModelObject)obj); + } + } + } + + /** Removes any canvas filter currently in place */ + public void clearFilter() { + if (m_filterList != null) { + m_filterList.clear(); + m_filterList = null; + } + + if (m_dynamicFilterList != null) { + m_dynamicFilterList.clear(); + m_dynamicFilterList = null; + } + resetCounters(); + m_filterActive = false; + + } + + /** tells if a canvas filter is currently in place */ + public boolean isFilterActive() { + return m_filterActive; + } + + /** + * Updates the filter to contain the up-to-date parent objects, + * for all filter objects. + */ + public void updateFilter() { + if (m_filterList == null) + return; + + resetCounters(); + m_dynamicFilterList.clear(); + + for (IVisualizerModelObject elem : m_filterList) { + // element still in current model? + if (isElementInCurrentModel(elem)) { + // add element to list + addElementToFilterList(elem); + + // also add all its ancestors + IVisualizerModelObject parent = elem.getParent(); + while (parent != null) { + addElementToFilterList(parent); + parent = parent.getParent(); + } + } + } + } + + /** + * Tells if a candidate model object should be displayed, according to the + * filter in place. + */ + public boolean displayObject(final IVisualizerModelObject candidate) { + // filter not active? Let anything be displayed + if (!m_filterActive) { + return true; + } + + // Candidate is in white list? + if (isElementInFilterList(candidate)) { + return true; + } + + return false; + } + + + // --- filter list management --- + + /** + * Adds an element to the dynamic filter list, if an equivalent + * element is not already there. + */ + private void addElementToFilterList(final IVisualizerModelObject elem) { + if (!isElementInFilterList(elem)) { + m_dynamicFilterList.add(elem); + stepStatsCounter(elem); + } + } + + /** + * Checks if an element already has an equivalent in the + * dynamic filter list. + */ + private boolean isElementInFilterList(final IVisualizerModelObject candidate) { + // is the candidate in the dynamic filter list? + for (IVisualizerModelObject elem : m_dynamicFilterList) { + // Note: we are comparing the content (IDs), not references. + if (candidate.compareTo(elem) == 0) { + return true; + } + } + return false; + } + + + /** Used to check if model elements in the filter still exist in the current model. */ + private boolean isElementInCurrentModel(IVisualizerModelObject element) { + VisualizerModel model = m_canvas.getModel(); + if (model != null) { + if (element instanceof VisualizerThread) { + VisualizerThread thread = model.getThread(((VisualizerThread) element).getGDBTID()); + if (thread != null) { + // Note: we are comparing the content (IDs), not references. + if (thread.compareTo(element) == 0) { + return true; + } + } + } + else if (element instanceof VisualizerCore) { + VisualizerCore core = model.getCore(element.getID()); + if (core != null) { + // Note: we are comparing the content (IDs), not references. + if (core.compareTo(element) == 0) { + return true; + } + } + } + else if (element instanceof VisualizerCPU) { + VisualizerCPU cpu = model.getCPU(element.getID()); + if (cpu != null) { + // Note: we are comparing the content (IDs), not references. + if (cpu.compareTo(element) == 0) { + return true; + } + } + } + } + return false; + } + + // --- Stats counters --- + + /** + * Used to step the filtered counters for a given type of + * model object. + */ + private void stepStatsCounter(IVisualizerModelObject modelObj) { + if (modelObj instanceof VisualizerCPU) { + m_shownCpu++; + } + else if (modelObj instanceof VisualizerCore) { + m_shownCore++; + } + else if (modelObj instanceof VisualizerThread) { + m_shownThread++; + } + } + + /** Reset the filtering counters */ + private void resetCounters() { + m_shownCpu = 0; + m_shownCore = 0; + m_shownThread = 0; + // refresh total counts since the model can change + if (m_canvas != null) { + VisualizerModel model = m_canvas.getModel(); + if (model != null) { + m_totalCpu = model.getCPUCount(); + m_totalCore = model.getCoreCount(); + m_totalThread = model.getThreadCount(); + } + } + } + + + /** returns a String giving the current filtering stats */ + private String getStats() { + + + return STR_FILTER_ACTIVE + " " + STR_CPU + " " + m_shownCpu + "/" + m_totalCpu + ", " + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + STR_CORE + " " + m_shownCore + "/" + m_totalCore + ", " + //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$ + STR_THREAD + " " + m_shownThread + "/" + m_totalThread; //$NON-NLS-1$//$NON-NLS-2$ + } + + @Override + public String toString() { + if (isFilterActive()) { + return getStats(); + } + else { + return STR_FILTER_NOT_ACTIVE; + } + } +} + + + + + diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerEventListener.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerEventListener.java index f33b780800b..d0e71eb5eb9 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerEventListener.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerEventListener.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012 Ericsson and others. + * Copyright (c) 2012, 2013 Ericsson and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ * Marc Khouzam (Ericsson) - initial API and implementation * Marc Dumais (Ericsson) - Bug 400231 * Marc Dumais (Ericsson) - Bug 399419 + * Marc Dumais (Ericsson) - Bug 405390 *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.view; @@ -122,7 +123,7 @@ public class MulticoreVisualizerEventListener { thread.setState(newState); thread.setCore(vCore); - fVisualizer.getMulticoreVisualizerCanvas().requestUpdate(); + fVisualizer.refresh(); } } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerStatusBar.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerStatusBar.java new file mode 100644 index 00000000000..9038a1d43a4 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.multicorevisualizer.ui/src/org/eclipse/cdt/dsf/gdb/multicorevisualizer/internal/ui/view/MulticoreVisualizerStatusBar.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2013 Ericsson + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Marc Dumais (Ericsson) - Initial API and implementation (Bug 405390) + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.multicorevisualizer.internal.ui.view; + +import org.eclipse.cdt.visualizer.ui.util.GUIUtils; +import org.eclipse.swt.graphics.GC; + +public class MulticoreVisualizerStatusBar extends MulticoreVisualizerGraphicObject { + + // --- members --- + + /** message to display in status bar */ + protected String m_statusMessage = null; + + // --- constructors/destructors --- + + /** Constructor */ + public MulticoreVisualizerStatusBar() { + } + + + /** Dispose method */ + @Override + public void dispose() { + super.dispose(); + m_statusMessage = null; + } + + + // --- accessors --- + + public void setMessage (String message) { + m_statusMessage = message; + } + + // --- paint methods --- + + /** Invoked to allow element to paint itself on the viewer canvas */ + @Override + public void paintContent(GC gc) { + + if (m_statusMessage == null) + return; + + // Display message text + gc.setForeground(IMulticoreVisualizerConstants.COLOR_STATUS_BAR_TEXT); + int tx = m_bounds.x; + int ty = m_bounds.y + 15; + GUIUtils.drawTextAligned(gc, m_statusMessage, tx, ty, true, false); + } + +}