/*******************************************************************************
* Copyright (c) 2013, 2014 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marc Dumais (Ericsson) - Initial API and implementation (Bug 405390)
* Marc Dumais (Ericsson) - Bug 407673
*******************************************************************************/
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 {
/** white list of objects on which the filter is based */
List<IVisualizerModelObject> 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<IVisualizerModelObject> m_dynamicFilterList = null;
/** reference to the canvas */
private MulticoreVisualizerCanvas m_canvas = null;
/** whether the filter is active */
private boolean m_filterActive = false;
/** counter that reflects the number of CPUs shown once the filter is applied */
private int m_shownCpu = 0;
/** counter that reflects the number of cores shown once the filter is applied */
private int m_shownCore = 0;
/** counter that reflects the number of threads shown once the filter is applied */
private int m_shownThread = 0;
/** total number of CPUs in the current MV model */
private int m_totalCpu = 0;
/** total number of cores in the current MV model */
private int m_totalCore = 0;
/** total number of threads in the current MV model */
private int m_totalThread = 0;
/** String constant used to denote that the filter is not active */
private static final String STR_FILTER_NOT_ACTIVE =
MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.NotActive.text"); //$NON-NLS-1$
/** String constant used to denote that the filter is active */
private static final String STR_FILTER_ACTIVE =
MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.Active.text"); //$NON-NLS-1$
/** String constant used to represent CPUs */
private static final String STR_CPU =
MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.cpu.text"); //$NON-NLS-1$
/** String constant used to represent cores */
private static final String STR_CORE =
MulticoreVisualizerUIPlugin.getString("MulticoreVisualizer.view.CanvasFilter.core.text"); //$NON-NLS-1$
/** String constant used to represent threads */
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 ---
/**
* Sets-up a canvas white-list filter from the current canvas selection.
* Any applicable selected objects are added to the filter.
*/
public void applyFilter() {
// replace current filter? Clear old one first.
if (isFilterActive()) {
clearFilter();
}
m_filterList = new ArrayList<IVisualizerModelObject>();
m_dynamicFilterList = new ArrayList<IVisualizerModelObject>();
m_filterActive = true;
// get list of selected objects the filter applies-for
ISelection selection = m_canvas.getSelection();
List<Object> 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;
}
/** returns whether a canvas filter is currently in place */
public boolean isFilterActive() {
return m_filterActive;
}
/**
* Updates the dynamic filter so it contains the up-to-date parent objects
*/
public void updateFilter() {
if (m_filterList == null || m_canvas == null)
return;
VisualizerModel model = m_canvas.getModel();
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;
// Bug 407673 - if element is a thread, lookup the parent (core)
// from the current model, to be sure it's up-to-date
if (elem instanceof VisualizerThread && model != null) {
parent = model.getThread(((VisualizerThread) elem).getGDBTID()).getParent();
}
else {
parent = elem.getParent();
}
while (parent != null) {
addElementToFilterList(parent);
parent = parent.getParent();
}
}
}
}
/**
* returns whether a candidate model object should be displayed,
* according to the current filter.
*/
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 in there.
*/
private void addElementToFilterList(final IVisualizerModelObject elem) {
if (!isElementInFilterList(elem)) {
m_dynamicFilterList.add(elem);
stepStatsCounter(elem);
}
}
/**
* Returns whether 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;
}
/** returns whether a model object currently in the filter still exists 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 ---
/**
* Steps the filter 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++;
}
}
/** Resets the filter 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;
}
}
}