X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=tmf%2Forg.eclipse.tracecompass.tmf.ui%2Fsrc%2Forg%2Feclipse%2Ftracecompass%2Ftmf%2Fui%2Fwidgets%2Ftimegraph%2Fwidgets%2FTimeGraphControl.java;h=2f5c35895a97bfd14661edb75131ff0076479f36;hb=refs%2Fheads%2Fnext-previous-event;hp=2b949633942e5a457f02c29ccedcf5dd474c95aa;hpb=25033fefb1d755a3fdedf3eeafaa4fbc951fba69;p=deliverable%2Ftracecompass.git diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java index 2b94963394..2f5c35895a 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/widgets/timegraph/widgets/TimeGraphControl.java @@ -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 null 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 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); } }