lttng: Add Next/Previous TID event action in CFV
[deliverable/tracecompass.git] / tmf / org.eclipse.tracecompass.tmf.ui / src / org / eclipse / tracecompass / tmf / ui / widgets / timegraph / widgets / TimeGraphControl.java
index 2b949633942e5a457f02c29ccedcf5dd474c95aa..2f5c35895a97bfd14661edb75131ff0076479f36 100644 (file)
@@ -27,9 +27,11 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Queue;
 
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jface.action.IStatusLineManager;
@@ -39,6 +41,7 @@ import org.eclipse.jface.viewers.AbstractTreeViewer;
 import org.eclipse.jface.viewers.ISelection;
 import org.eclipse.jface.viewers.ISelectionChangedListener;
 import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
 import org.eclipse.jface.viewers.ViewerFilter;
 import org.eclipse.osgi.util.NLS;
 import org.eclipse.swt.SWT;
@@ -70,6 +73,7 @@ import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
 import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager;
 import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentInfo;
 import org.eclipse.tracecompass.tmf.ui.signal.TmfTimeViewAlignmentSignal;
@@ -153,6 +157,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
     private int fDragButton;
     private int fDragX0 = 0;
     private int fDragX = 0;
+    private boolean fHasNamespaceFocus = false;
     private long fDragTime0 = 0; // used to preserve accuracy of modified selection
     private int fIdealNameSpace = 0;
     private long fTime0bak;
@@ -239,6 +244,15 @@ public class TimeGraphControl extends TimeGraphBaseControl
         return fTimeGraphProvider;
     }
 
+    /**
+     * Gets the time data provider used by this viewer.
+     *
+     * @return The time data provider, or <code>null</code> if not set
+     */
+    public ITimeDataProvider getTimeDataProvider() {
+        return fTimeProvider;
+    }
+
     /**
      * Gets the color map used by this timegraph viewer.
      *
@@ -321,6 +335,12 @@ public class TimeGraphControl extends TimeGraphBaseControl
                 listener.widgetSelected(null);
             }
         }
+
+        if (null != fSelectionChangedListeners) {
+            for (ISelectionChangedListener listener : fSelectionChangedListeners) {
+                listener.selectionChanged(new SelectionChangedEvent(this, getSelection()));
+            }
+        }
     }
 
     /**
@@ -575,6 +595,108 @@ public class TimeGraphControl extends TimeGraphBaseControl
         }
     }
 
+    /**
+     * Set the expanded state of a given entry to certain relative level.
+     * It will call fireTreeEvent() for each changed entry. At the end
+     * it will call redraw().
+     *
+     * @param entry
+     *            The entry
+     * @param level
+     *            level to expand to or negative for all levels
+     * @param expanded
+     *            True if expanded, false if collapsed
+     */
+    private void setExpandedState(ITimeGraphEntry entry, int level, boolean expanded) {
+        setExpandedStateInt(entry, level, expanded);
+        redraw();
+    }
+
+    /**
+     * Set the expanded state of a given entry and its children to the first
+     * level that has one collapsed entry.
+     *
+     * @param entry
+     *            The entry
+     */
+    private void setExpandedStateLevel(ITimeGraphEntry entry) {
+        int level = findExpandedLevel(entry);
+        if (level >= 0) {
+            setExpandedStateInt(entry, level, true);
+            redraw();
+        }
+    }
+
+    /*
+     * Inner class for finding relative level with at least one
+     * collapsed entry.
+     */
+    private class SearchNode {
+        SearchNode(ITimeGraphEntry e, int l) {
+            entry = e;
+            level = l;
+        }
+        ITimeGraphEntry entry;
+        int level;
+    }
+
+    /**
+     * Finds the relative level with at least one collapsed entry.
+     *
+     * @param entry
+     *            the start entry
+     * @return the found level or -1 if all levels are already expanded.
+     */
+    private int findExpandedLevel(ITimeGraphEntry entry) {
+        Queue<SearchNode> queue = new LinkedList<>();
+        SearchNode root = new SearchNode(entry, 0);
+        SearchNode node = root;
+        queue.add(root);
+
+        while (!queue.isEmpty()) {
+            node = queue.remove();
+            if (node.entry.hasChildren() && !getExpandedState(node.entry)) {
+                return node.level;
+            }
+            for (ITimeGraphEntry e : node.entry.getChildren()) {
+                if (e.hasChildren()) {
+                    SearchNode n = new SearchNode(e, node.level + 1);
+                    queue.add(n);
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Set the expanded state of a given entry to certain relative level.
+     * It will call fireTreeEvent() for each changed entry. No redraw is done.
+     *
+     * @param entry
+     *            The entry
+     * @param level
+     *            level to expand to or negative for all levels
+     * @param expanded
+     *            True if expanded, false if collapsed
+     */
+    private void setExpandedStateInt(ITimeGraphEntry entry, int aLevel, boolean expanded) {
+        int level = aLevel;
+        if ((level > 0) || (level < 0)) {
+            level--;
+            if (entry.hasChildren()) {
+                for (ITimeGraphEntry e : entry.getChildren()) {
+                    setExpandedStateInt(e, level, expanded);
+                }
+            }
+        }
+        Item item = fItemData.findItem(entry);
+        if (item != null && item.fExpanded != expanded) {
+            item.fExpanded = expanded;
+            fItemData.updateExpandedItems();
+            fireTreeEvent(item.fEntry, item.fExpanded);
+        }
+    }
+
     /**
      * Collapses all nodes of the viewer's tree, starting with the root.
      */
@@ -712,6 +834,14 @@ public class TimeGraphControl extends TimeGraphBaseControl
         }
     }
 
+    @Override
+    public boolean setFocus() {
+        if ((fTimeProvider != null) && fTimeProvider.getNameSpace() > 0) {
+            fHasNamespaceFocus = true;
+        }
+        return super.setFocus();
+    }
+
     @Override
     public ISelection getSelection() {
         TimeGraphSelection sel = new TimeGraphSelection();
@@ -719,10 +849,9 @@ public class TimeGraphControl extends TimeGraphBaseControl
         if (null != trace && null != fTimeProvider) {
             long selectedTime = fTimeProvider.getSelectionBegin();
             ITimeEvent event = Utils.findEvent(trace, selectedTime, 0);
+            sel.add(trace);
             if (event != null) {
                 sel.add(event);
-            } else {
-                sel.add(trace);
             }
         }
         return sel;
@@ -2292,6 +2421,29 @@ public class TimeGraphControl extends TimeGraphBaseControl
             if (fVerticalZoomAlignEntry != null) {
                 setElementPosition(fVerticalZoomAlignEntry.getKey(), fVerticalZoomAlignEntry.getValue());
             }
+        } else if ((e.character == '+' || e.character == '=') && ((e.stateMask & SWT.CTRL) == 0)) {
+            if (fHasNamespaceFocus) {
+                ITimeGraphEntry entry = getSelectedTrace();
+                setExpandedState(entry, 0, true);
+            } else {
+                zoomIn();
+            }
+        } else if (e.character == '-' && ((e.stateMask & SWT.CTRL) == 0)) {
+            if (fHasNamespaceFocus) {
+                ITimeGraphEntry entry = getSelectedTrace();
+                if ((entry != null) && entry.hasChildren()) {
+                    setExpandedState(entry, -1, false);
+                }
+            } else {
+                zoomOut();
+            }
+        } else if ((e.character == '*') && ((e.stateMask & SWT.CTRL) == 0)) {
+            if (fHasNamespaceFocus) {
+                ITimeGraphEntry entry = getSelectedTrace();
+                if ((entry != null) && entry.hasChildren()) {
+                    setExpandedStateLevel(entry);
+                }
+            }
         }
         if (idx >= 0) {
             selectItem(idx, false);
@@ -2493,6 +2645,12 @@ public class TimeGraphControl extends TimeGraphBaseControl
             }
             fMouseOverSplitLine = mouseOverSplitLine;
         }
+
+        if (e.x >= fTimeProvider.getNameSpace()) {
+            fHasNamespaceFocus = false;
+        } else {
+            fHasNamespaceFocus = true;
+        }
         updateCursor(e.x, e.stateMask);
         updateStatusLine(e.x);
     }
@@ -2624,6 +2782,10 @@ public class TimeGraphControl extends TimeGraphBaseControl
                 redraw();
                 updateCursor(e.x, e.stateMask);
                 fTimeGraphScale.setDragRange(fDragX0, fDragX);
+            } else {
+              idx = getItemIndexAtY(e.y);
+              selectItem(idx, false);
+              fireSelectionChanged();
             }
         }
     }
@@ -2976,7 +3138,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
      * Returns this control's filters.
      *
      * @return an array of viewer filters
-     * @since 2.0
+     * @since 1.2
      */
     public @NonNull ViewerFilter[] getFilters() {
         return Iterables.toArray(fFilters, ViewerFilter.class);
@@ -2987,7 +3149,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
      *
      * @param filters
      *            an array of viewer filters, or null
-     * @since 2.0
+     * @since 1.2
      */
     public void setFilters(@NonNull ViewerFilter[] filters) {
         fFilters.clear();
@@ -3172,6 +3334,7 @@ public class TimeGraphControl extends TimeGraphBaseControl
         if (null == fTimeProvider) {
             return;
         }
+        Point p = toControl(e.x, e.y);
         if (e.detail == SWT.MENU_MOUSE) {
             if (fPendingMenuDetectEvent == null) {
                 /* Feature in Linux. The MenuDetectEvent is received before mouseDown.
@@ -3179,10 +3342,16 @@ public class TimeGraphControl extends TimeGraphBaseControl
                  * This allows for the method to detect if mouse is used to drag zoom.
                  */
                 fPendingMenuDetectEvent = e;
+                /*
+                 *  Prevent the platform to show the menu when returning. The
+                 *  menu will be shown (see below) when this method is called
+                 *  again during mouseup().
+                 */
+                e.doit = false;
                 return;
             }
             fPendingMenuDetectEvent = null;
-            if (fDragState != DRAG_ZOOM || fDragX != fDragX0) {
+            if ((p.x >= fTimeProvider.getNameSpace()) && (fDragState != DRAG_ZOOM || fDragX != fDragX0)) {
                 return;
             }
         } else {
@@ -3190,21 +3359,34 @@ public class TimeGraphControl extends TimeGraphBaseControl
                 return;
             }
         }
-        Point p = toControl(e.x, e.y);
         int idx = getItemIndexAtY(p.y);
         if (idx >= 0 && idx < fItemData.fExpandedItems.length) {
+            e.doit = true;
             Item item = fItemData.fExpandedItems[idx];
             ITimeGraphEntry entry = item.fEntry;
+
+            /* Send menu event for the time graph entry */
+            e.doit = true;
+            e.data = entry;
+            fireMenuEventOnTimeGraphEntry(e);
+            Menu menu = getMenu();
+            if (e.doit && (menu != null)) {
+                menu.setVisible(true);
+            }
+
+            /* Send menu event for time event */
             if (entry.hasTimeEvents()) {
                 ITimeEvent event = Utils.findEvent(entry, getTimeAtX(p.x), 2);
                 if (event != null) {
+                    e.doit = true;
                     e.data = event;
                     fireMenuEventOnTimeEvent(e);
-                    return;
+                    menu = getMenu();
+                    if (e.doit && (menu != null)) {
+                        menu.setVisible(true);
+                    }
                 }
             }
-            e.data = entry;
-            fireMenuEventOnTimeGraphEntry(e);
         }
     }
 
This page took 0.081609 seconds and 5 git commands to generate.