tmf.ui: Add (Un)check(In)active buttons to TimeGraphFilterDialog
authorChristian Mansky <christian.mansky@gmx.at>
Tue, 10 Mar 2015 18:59:12 +0000 (19:59 +0100)
committerPatrick Tasse <patrick.tasse@gmail.com>
Fri, 20 Mar 2015 22:20:00 +0000 (18:20 -0400)
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 <christian.mansky@gmx.at>
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/43648
Reviewed-by: Hudson CI
org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowCheckActiveProvider.java [new file with mode: 0644]
org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/analysis/os/linux/ui/views/controlflow/ControlFlowView.java
org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/Messages.java
org.eclipse.tracecompass.analysis.os.linux.ui/src/org/eclipse/tracecompass/internal/analysis/os/linux/ui/messages.properties
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/TimeGraphCombo.java
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/ITimeGraphEntryActiveProvider.java [new file with mode: 0644]
org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/dialogs/TimeGraphFilterDialog.java

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 (file)
index 0000000..9c930f7
--- /dev/null
@@ -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;
+    }
+
+}
index 8a80ce2f282a739acd6f4d6276a51ab910bcc588..943baeb4d4ec079ee135731673ef96c5691598da 100644 (file)
@@ -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);
index ec3a5c2f75752fef47cd615d3f37ac74c0a50e29..f0e98d513ece9a8cd6c40e107812dd4c7d202442 100644 (file)
@@ -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;
 
index a26ca88d21476790ce9ee392c848c97e044ea675..a6a7d1ed771461899cacfdec504a53d96372feac 100644 (file)
@@ -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
 
index a54372d4a52147d1884c69aa5cadc98f7f7564e6..46345a2c9661ef79a9bc5d6832db08a04f98ea30 100644 (file)
@@ -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 (file)
index 0000000..169bf37
--- /dev/null
@@ -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);
+
+}
index fc1bcd4f3fc69cfeb222bfe48a87cfd255e3eb67..76a3f3bcb192e019a0ffc0b167b5bf7820fc18e8 100644 (file)
@@ -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
This page took 0.032542 seconds and 5 git commands to generate.