From: Christian Mansky Date: Tue, 10 Mar 2015 18:59:12 +0000 (+0100) Subject: tmf.ui: Add (Un)check(In)active buttons to TimeGraphFilterDialog X-Git-Url: http://drtracing.org/?a=commitdiff_plain;h=b97d61f00854fd693ca78eb5bdfe23715ecbbc99;p=deliverable%2Ftracecompass.git tmf.ui: Add (Un)check(In)active buttons to TimeGraphFilterDialog Adds installable buttons to TimeGraphFilterDialog in order to provide view specific filtering functionality. In this case check/uncheck active/inactive buttons are added specific to the ControlFlowView. Change-Id: Ibac317385527a61df09e82f0721eff19dcfcce83 Signed-off-by: Christian Mansky Signed-off-by: Patrick Tasse Reviewed-on: https://git.eclipse.org/r/43648 Reviewed-by: Hudson CI --- diff --git a/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java new file mode 100644 index 0000000000..9c930f7a42 --- /dev/null +++ b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2015 Keba AG + * + * 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: + * Christian Mansky - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow; + +import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes; +import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelAnalysis; +import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.StateValues; +import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; +import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; +import org.eclipse.tracecompass.statesystem.core.exceptions.StateSystemDisposedException; +import org.eclipse.tracecompass.statesystem.core.interval.ITmfStateInterval; +import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; +import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceContext; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ITimeGraphEntryActiveProvider; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; + +/** + * Provides Functionality for check Active / uncheck inactive + * + * @noinstantiate This class is not intended to be instantiated by clients. + * @noextend This class is not intended to be subclassed by clients. + * @since 1.0 + */ +public class ControlFlowCheckActiveProvider implements ITimeGraphEntryActiveProvider { + + String fLabel; + String fTooltip; + + /** + * @param label + * Button label + * @param tooltip + * Button tooltip + */ + public ControlFlowCheckActiveProvider(String label, String tooltip) { + fLabel = label; + fTooltip = tooltip; + } + + @Override + public String getLabel() { + return fLabel; + } + + @Override + public String getTooltip() { + return fTooltip; + } + + @Override + public boolean isActive(ITimeGraphEntry element) { + if (element instanceof ControlFlowEntry) { + ControlFlowEntry cfe = (ControlFlowEntry) element; + + TmfTraceManager traceManager = TmfTraceManager.getInstance(); + TmfTraceContext traceContext = traceManager.getCurrentTraceContext(); + TmfTimeRange winRange = traceContext.getWindowRange(); + TmfTimeRange selRange = traceContext.getSelectionRange(); + + /* Take precedence of selection over window range. */ + long beginTS = selRange.getStartTime().getValue(); + long endTS = selRange.getEndTime().getValue(); + + /* No selection, take window range */ + if (beginTS == endTS) { + beginTS = winRange.getStartTime().getValue(); + endTS = winRange.getEndTime().getValue(); + } + + ITmfTrace trace = cfe.getTrace(); + ITmfStateSystem ssq = TmfStateSystemAnalysisModule.getStateSystem(trace, KernelAnalysis.ID); + if (ssq != null) { + beginTS = Math.max(beginTS, ssq.getStartTime()); + endTS = Math.min(endTS, ssq.getCurrentEndTime()); + if (beginTS > endTS) { + return false; + } + try { + int statusQuark = ssq.getQuarkRelative(cfe.getThreadQuark(), Attributes.STATUS); + + /* Get the initial state at beginTS */ + ITmfStateInterval currentInterval = ssq.querySingleState(beginTS, statusQuark); + if (isIntervalInStateActive(currentInterval)) { + return true; + } + + /* Get the following state changes */ + long ts = currentInterval.getEndTime(); + while (ts != -1 && ts < endTS) { + ts++; /* To "jump over" to the next state in the history */ + currentInterval = ssq.querySingleState(ts, statusQuark); + if (isIntervalInStateActive(currentInterval)) { + return true; + } + ts = currentInterval.getEndTime(); + } + } catch (AttributeNotFoundException | StateSystemDisposedException e) { + /* Ignore ... */ + } + } + } + + return false; + } + + private static boolean isIntervalInStateActive (ITmfStateInterval ival) { + int value = ival.getStateValue().unboxInt(); + /* An entry is only active when running */ + if (value == StateValues.PROCESS_STATUS_RUN_USERMODE || value == StateValues.PROCESS_STATUS_RUN_SYSCALL || + value == StateValues.PROCESS_STATUS_INTERRUPTED) { + return true; + } + + return false; + } + +} diff --git a/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java index 8a80ce2f28..943baeb4d4 100644 --- a/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java +++ b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal + * Copyright (c) 2012, 2015 Ericsson, École Polytechnique de Montréal 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 @@ -9,6 +9,7 @@ * Contributors: * Patrick Tasse - Initial API and implementation * Geneviève Bastien - Move code to provide base classes for time graph view + * Christian Mansky - Add check active / uncheck inactive buttons *******************************************************************************/ package org.eclipse.tracecompass.analysis.os.linux.ui.views.controlflow; @@ -27,6 +28,7 @@ import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.swt.widgets.Composite; import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.Attributes; import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelAnalysis; import org.eclipse.tracecompass.analysis.os.linux.core.kernelanalysis.KernelThreadInformationProvider; @@ -108,6 +110,17 @@ public class ControlFlowView extends AbstractTimeGraphView { setEntryComparator(new ControlFlowEntryComparator()); } + @Override + public void createPartControl(Composite parent) { + super.createPartControl(parent); + // add "Check active" Button to TimeGraphFilterDialog + super.getTimeGraphCombo().addTimeGraphFilterCheckActiveButton( + new ControlFlowCheckActiveProvider(Messages.ControlFlowView_checkActiveLabel, Messages.ControlFlowView_checkActiveToolTip)); + // add "Uncheck inactive" Button to TimeGraphFilterDialog + super.getTimeGraphCombo().addTimeGraphFilterUncheckInactiveButton( + new ControlFlowCheckActiveProvider(Messages.ControlFlowView_uncheckInactiveLabel, Messages.ControlFlowView_uncheckInactiveToolTip)); + } + @Override protected void fillLocalToolBar(IToolBarManager manager) { super.fillLocalToolBar(manager); diff --git a/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/Messages.java b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/Messages.java index ec3a5c2f75..f0e98d513e 100644 --- a/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/Messages.java +++ b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/Messages.java @@ -31,7 +31,10 @@ public class Messages extends NLS { public static String ControlFlowView_previousProcessActionToolTipText; public static String ControlFlowView_followCPUBwdText; public static String ControlFlowView_followCPUFwdText; - + public static String ControlFlowView_checkActiveLabel; + public static String ControlFlowView_checkActiveToolTip; + public static String ControlFlowView_uncheckInactiveLabel; + public static String ControlFlowView_uncheckInactiveToolTip; public static String ControlFlowView_attributeSyscallName; public static String ControlFlowView_attributeCpuName; diff --git a/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/messages.properties b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/messages.properties index a26ca88d21..a6a7d1ed77 100644 --- a/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/messages.properties +++ b/org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/messages.properties @@ -24,7 +24,10 @@ ControlFlowView_previousProcessActionNameText=Previous Process ControlFlowView_previousProcessActionToolTipText=Select Previous Process ControlFlowView_followCPUBwdText=Follow CPU Backward ControlFlowView_followCPUFwdText=Follow CPU Forward - +ControlFlowView_checkActiveLabel=Check Active +ControlFlowView_checkActiveToolTip=Checks all threads executing within the time frame. +ControlFlowView_uncheckInactiveLabel=Uncheck Inactive +ControlFlowView_uncheckInactiveToolTip=Unchecks all threads not executing within the time frame. ControlFlowView_attributeSyscallName=System Call ControlFlowView_attributeCpuName=CPU diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphCombo.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphCombo.java index a54372d4a5..46345a2c96 100644 --- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphCombo.java +++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphCombo.java @@ -10,6 +10,7 @@ * Patrick Tasse - Initial API and implementation * François Rajotte - Filter implementation * Geneviève Bastien - Add event links between entries + * Christian Mansky - Add check active / uncheck inactive buttons *******************************************************************************/ package org.eclipse.tracecompass.tmf.ui.widgets.timegraph; @@ -63,6 +64,7 @@ import org.eclipse.swt.widgets.TreeItem; import org.eclipse.tracecompass.internal.tmf.ui.Activator; import org.eclipse.tracecompass.internal.tmf.ui.ITmfImageConstants; import org.eclipse.tracecompass.internal.tmf.ui.Messages; +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.ITimeGraphEntryActiveProvider; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs.TimeGraphFilterDialog; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ILinkEvent; import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; @@ -759,6 +761,28 @@ public class TimeGraphCombo extends Composite { fFilterDialog.setLabelProvider(labelProvider); } + /** + * Adds a "check active" button used by the filter dialog + * + * @param activeProvider + * Additional button info specific to a certain view. + * @since 1.0 + */ + public void addTimeGraphFilterCheckActiveButton(ITimeGraphEntryActiveProvider activeProvider) { + fFilterDialog.addTimeGraphFilterCheckActiveButton(activeProvider); + } + + /** + * Adds an "uncheck inactive" button used by the filter dialog + * + * @param inactiveProvider + * Additional button info specific to a certain view. + * @since 1.0 + */ + public void addTimeGraphFilterUncheckInactiveButton(ITimeGraphEntryActiveProvider inactiveProvider) { + fFilterDialog.addTimeGraphFilterUncheckInactiveButton(inactiveProvider); + } + /** * Sets the tree columns for this time graph combo. * diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/ITimeGraphEntryActiveProvider.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/ITimeGraphEntryActiveProvider.java new file mode 100644 index 0000000000..169bf37083 --- /dev/null +++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/ITimeGraphEntryActiveProvider.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2015 Keba AG + * + * 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: + * Christian Mansky - Initial API and implementation + *******************************************************************************/ + +package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs; + +import org.eclipse.tracecompass.tmf.ui.widgets.timegraph.model.ITimeGraphEntry; + +/** + * Interface containing information for an additional view-specific active + * dependent button to be used in TimeGraphFilterDialog. + * + * @since 1.0 + */ +public interface ITimeGraphEntryActiveProvider { + + /** + * @return Name of the button label. + */ + String getLabel(); + + /** + * @return Tooltip of the button. + */ + String getTooltip(); + + /** + * @param entry + * An Element in the TimeGraphFilterDialog to check against + * selecting/ticking + * @return True if this element is active. + */ + boolean isActive(ITimeGraphEntry entry); + +} diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/TimeGraphFilterDialog.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/TimeGraphFilterDialog.java index fc1bcd4f3f..76a3f3bcb1 100644 --- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/TimeGraphFilterDialog.java +++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/TimeGraphFilterDialog.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. + * Copyright (c) 2000, 2015 IBM 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 @@ * François Rajotte - Support for multiple columns + selection control * Patrick Tasse - Fix Sonar warnings * Generoso Pagano - Add tree filter + * Christian Mansky - Add check active / uncheck inactive buttons *******************************************************************************/ package org.eclipse.tracecompass.tmf.ui.widgets.timegraph.dialogs; @@ -66,6 +67,8 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { private static final int BUTTON_UNCHECK_SELECTED_ID = IDialogConstants.CLIENT_ID + 1; private static final int BUTTON_CHECK_SUBTREE_ID = IDialogConstants.CLIENT_ID + 2; private static final int BUTTON_UNCHECK_SUBTREE_ID = IDialogConstants.CLIENT_ID + 3; + private static final int BUTTON_CHECK_ACTIVE_ID = IDialogConstants.CLIENT_ID + 4; + private static final int BUTTON_UNCHECK_INACTIVE_ID = IDialogConstants.CLIENT_ID + 5; private static final int DEFAULT_WIDTH = 60; private static final int DEFAULT_HEIGHT = 18; @@ -74,6 +77,9 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { private IBaseLabelProvider fLabelProvider; + private ITimeGraphEntryActiveProvider fCheckActiveProvider; + private ITimeGraphEntryActiveProvider fUncheckInactiveProvider; + private ITreeContentProvider fContentProvider; private String[] fColumnNames; @@ -111,6 +117,8 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { setStatusLineAboveButtons(true); setHelpAvailable(false); fExpandedElements = null; + fCheckActiveProvider = null; + fUncheckInactiveProvider = null; } /** @@ -220,6 +228,24 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { fLabelProvider = labelProvider; } + /** + * @param activeProvider + * Information about an additional view specific Button + * @since 1.0 + */ + public void addTimeGraphFilterCheckActiveButton(ITimeGraphEntryActiveProvider activeProvider) { + fCheckActiveProvider = activeProvider; + } + + /** + * @param inactiveProvider + * Information about an additional view specific Button + * @since 1.0 + */ + public void addTimeGraphFilterUncheckInactiveButton(ITimeGraphEntryActiveProvider inactiveProvider) { + fUncheckInactiveProvider = inactiveProvider; + } + /** * @param columnNames * An array of column names to display @@ -383,6 +409,17 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { Button checkAllButton = createButton(buttonComposite, IDialogConstants.SELECT_ALL_ID, Messages.TmfTimeFilterDialog_CHECK_ALL, false); + Button checkActiveButton = null; + if (fCheckActiveProvider != null) { + checkActiveButton = createButton(buttonComposite, + BUTTON_CHECK_ACTIVE_ID, fCheckActiveProvider.getLabel(), + false); + checkActiveButton.setToolTipText(fCheckActiveProvider.getTooltip()); + } else if (fUncheckInactiveProvider != null) { + // Filler label to ensure correct layout. + Label filler = new Label(buttonComposite, 0); + filler.setText(""); //$NON-NLS-1$ + } Button uncheckSelectedButton = createButton(buttonComposite, BUTTON_UNCHECK_SELECTED_ID, Messages.TmfTimeFilterDialog_UNCHECK_SELECTED, @@ -393,12 +430,22 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { Button uncheckAllButton = createButton(buttonComposite, IDialogConstants.DESELECT_ALL_ID, Messages.TmfTimeFilterDialog_UNCHECK_ALL, false); + Button uncheckInactiveButton = null; + if (fUncheckInactiveProvider != null) { + uncheckInactiveButton = createButton(buttonComposite, + BUTTON_UNCHECK_INACTIVE_ID, fUncheckInactiveProvider.getLabel(), + false); + uncheckInactiveButton.setToolTipText(fUncheckInactiveProvider.getTooltip()); + } /* * Apply the layout again after creating the buttons to override * createButton messing with the columns */ layout.numColumns = 3; + if (fCheckActiveProvider != null || fUncheckInactiveProvider != null) { + layout.numColumns++; + } buttonComposite.setLayout(layout); /* Add a listener to each button */ @@ -439,6 +486,10 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { } }); + if (checkActiveButton != null) { + checkActiveButton.addSelectionListener(new CheckActiveSelectionAdapter(true)); + } + uncheckSelectedButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -479,6 +530,10 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { } }); + if (uncheckInactiveButton != null) { + uncheckInactiveButton.addSelectionListener(new CheckActiveSelectionAdapter(false)); + } + return buttonComposite; } @@ -564,4 +619,83 @@ public class TimeGraphFilterDialog extends SelectionStatusDialog { } } + + private class CheckActiveSelectionAdapter extends SelectionAdapter { + + boolean fIsCheckActive; + ITimeGraphEntryActiveProvider fActiveProvider; + + CheckActiveSelectionAdapter(boolean isActive) { + super(); + fIsCheckActive = isActive; + if (fIsCheckActive) { + fActiveProvider = fCheckActiveProvider; + } else { + fActiveProvider = fUncheckInactiveProvider; + } + } + + @Override + public void widgetSelected(SelectionEvent e) { + /* Uncheck all elements that are not in this list */ + Object[] viewerElements = fContentProvider.getElements(fInput); + for (int j = 0; j < viewerElements.length; j++) { + if (fIsCheckActive) { + checkActive(viewerElements[j]); + } else { + uncheckInactive(viewerElements[j]); + } + } + + updateOKStatus(); + } + + private boolean checkActive(Object element) { + boolean wasChildChecked = false; + boolean isActive = false; + + for (Object child : fContentProvider.getChildren(element)) { + wasChildChecked |= checkActive(child); + } + + if (!fTree.getChecked(element)) { + /* Call isActive if none of this elements children are checked. */ + if (!wasChildChecked) { + isActive = element instanceof ITimeGraphEntry && + fActiveProvider.isActive((ITimeGraphEntry) element); + } + /* + * Check this element if its either active or if any of its + * children are checked. + */ + if (isActive || wasChildChecked) { + fTree.setChecked(element, true); + } + } + + return fTree.getChecked(element); + } + + private boolean uncheckInactive(Object element) { + boolean wasChildChecked = false; + + for (Object child : fContentProvider.getChildren(element)) { + wasChildChecked |= uncheckInactive(child); + } + + /* + * Call isActive if this element is checked and none of its children + * are checked. + */ + if (fTree.getChecked(element) && !wasChildChecked) { + /* Uncheck this element if its inactive. */ + if (element instanceof ITimeGraphEntry && + !fActiveProvider.isActive((ITimeGraphEntry) element)) { + fTree.setChecked(element, false); + } + } + + return fTree.getChecked(element); + } + } } \ No newline at end of file