From 210d92598718b9f13ed65ffb9840f8cbb2bb48ca Mon Sep 17 00:00:00 2001 From: Eyck Jentzsch Date: Sat, 21 Mar 2020 06:28:28 +0100 Subject: [PATCH] add initial implementation of TX hover --- .../META-INF/MANIFEST.MF | 2 +- com.minres.scviewer.database.ui.swt/pom.xml | 2 +- .../scviewer/database/swt/Constants.java | 8 +- .../database/swt/ToolTipHelpTextProvider.java | 12 + .../swt/ToolTipTableContentProvider.java | 21 ++ .../swt/internal/RelSelectionDialog.java | 73 ++++++ .../database/swt/internal/ToolTipHandler.java | 244 ++++++++++++++++++ .../database/swt/internal/WaveformCanvas.java | 2 +- .../database/swt/internal/WaveformViewer.java | 61 +++-- .../scviewer/database/ui/IWaveformViewer.java | 3 + .../META-INF/MANIFEST.MF | 2 +- com.minres.scviewer.e4.application/pom.xml | 2 +- .../application/parts/TransactionDetails.java | 65 ++--- .../e4/application/parts/WaveformViewer.java | 49 ++++ 14 files changed, 492 insertions(+), 54 deletions(-) create mode 100644 com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipHelpTextProvider.java create mode 100644 com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipTableContentProvider.java create mode 100644 com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/RelSelectionDialog.java create mode 100644 com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/ToolTipHandler.java diff --git a/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF b/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF index 1e8ad75..a11ba7f 100644 --- a/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.database.ui.swt/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: SWT widget Bundle-SymbolicName: com.minres.scviewer.database.ui.swt -Bundle-Version: 2.1.0.qualifier +Bundle-Version: 2.2.0.qualifier Bundle-Vendor: MINRES Technologies GmbH Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Require-Bundle: org.eclipse.swt;bundle-version="3.103.1", diff --git a/com.minres.scviewer.database.ui.swt/pom.xml b/com.minres.scviewer.database.ui.swt/pom.xml index 95ddd22..34b8a4f 100644 --- a/com.minres.scviewer.database.ui.swt/pom.xml +++ b/com.minres.scviewer.database.ui.swt/pom.xml @@ -8,5 +8,5 @@ 2.0.0-SNAPSHOT ../com.minres.scviewer.parent - 2.1.0-SNAPSHOT + 2.2.0-SNAPSHOT \ No newline at end of file diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/Constants.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/Constants.java index 679fc92..f2142fc 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/Constants.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/Constants.java @@ -2,8 +2,12 @@ package com.minres.scviewer.database.swt; public class Constants { - public final static String[] unitString={"fs", "ps", "ns", "us", "ms"};//, "s"}; + public static final String[] unitString={"fs", "ps", "ns", "us", "ms"};//, "s"}; - public final static int[] unitMultiplier={1, 3, 10, 30, 100, 300}; + public static final int[] unitMultiplier={1, 3, 10, 30, 100, 300}; + + public static final String CONTENT_PROVIDER_TAG = "TOOLTIP_CONTENT_PROVIDER"; + public static final String TEXT_PROVIDER_TAG = "TOOLTIP_TEXT_PROVIDER"; + public static final String HELP_PROVIDER_TAG = "TOOLTIP_HELP_PROVIDER"; } diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipHelpTextProvider.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipHelpTextProvider.java new file mode 100644 index 0000000..8892b80 --- /dev/null +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipHelpTextProvider.java @@ -0,0 +1,12 @@ +package com.minres.scviewer.database.swt; + +import org.eclipse.swt.widgets.Widget; + +public interface ToolTipHelpTextProvider { + /** + * Get help text + * @param widget the widget that is under help + * @return a help text string + */ + public String getHelpText(Widget widget); +} \ No newline at end of file diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipTableContentProvider.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipTableContentProvider.java new file mode 100644 index 0000000..8a9daee --- /dev/null +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/ToolTipTableContentProvider.java @@ -0,0 +1,21 @@ +package com.minres.scviewer.database.swt; + +import java.util.List; + +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Widget; + +public interface ToolTipTableContentProvider { + + public ToolTipTableContentProvider initialize(Widget widget, Point pt); + + public String getTableTitle(); + /** + * Get tool tip table content + * @param widget the widget that is under help + * @oaram pt the point where the mouse cursor is located + * @return a list of string arrays of size 2 (content & value) + */ + public List getTableContent(); + +} \ No newline at end of file diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/RelSelectionDialog.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/RelSelectionDialog.java new file mode 100644 index 0000000..fc53660 --- /dev/null +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/RelSelectionDialog.java @@ -0,0 +1,73 @@ +package com.minres.scviewer.database.swt.internal; + +import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter; + +import java.util.ArrayList; +import java.util.stream.Collectors; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.RowLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Dialog; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.List; +import org.eclipse.swt.widgets.Shell; + +import com.minres.scviewer.database.ITx; +import com.minres.scviewer.database.ITxRelation; + +class RelSelectionDialog extends Dialog { + private java.util.List entries; + + private java.util.List entryTx; + + private ITxRelation selected = null; + + public RelSelectionDialog(Shell shell, ArrayList candidates, boolean target) { + super(shell); + entries = candidates; + entryTx = entries.stream().map(r->target?r.getTarget():r.getSource()).collect(Collectors.toCollection(ArrayList::new)); + } + +public ITxRelation open() { + Shell parent = getParent(); + Shell dialog = new Shell(parent, SWT.SHEET | SWT.APPLICATION_MODAL); + dialog.setMinimumSize(10, 10); + + RowLayout rowLayout = new RowLayout(SWT.VERTICAL); + //rowLayout.fill = true; // Overriding default values. + rowLayout.marginWidth=3; + rowLayout.marginHeight=0; + rowLayout.marginLeft = 3; + rowLayout.marginTop = 0; + rowLayout.marginRight = 3; + rowLayout.marginBottom = 0; + dialog.setLayout(rowLayout); + final Label lbl = new Label(dialog,SWT.NONE); + lbl.setText("Select one:"); + final List list = new List (dialog, SWT.NONE); + for (ITx iTx : entryTx) { + list.add ("#tx" + iTx.getId()+" ("+iTx.getStream().getFullName()+")"); + } + list.addListener (SWT.Selection, e -> { + int selection = list.getSelectionIndex(); + if(selection>=0) { + selected=entries.get(selection); + dialog.close(); + } + }); + final Button bt = new Button(dialog, SWT.PUSH | SWT.RIGHT); + bt.setText("Dismiss"); + bt.setAlignment(SWT.CENTER); + bt.addSelectionListener(widgetSelectedAdapter(e -> dialog.close())); + dialog.pack(); + dialog.open(); + Display display = parent.getDisplay(); + while (!dialog.isDisposed()) { + if (!display.readAndDispatch()) + display.sleep(); + } + return selected; + } +} \ No newline at end of file diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/ToolTipHandler.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/ToolTipHandler.java new file mode 100644 index 0000000..f95173b --- /dev/null +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/ToolTipHandler.java @@ -0,0 +1,244 @@ +package com.minres.scviewer.database.swt.internal; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseListener; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.MouseTrackAdapter; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.ToolBar; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.Widget; + +import com.minres.scviewer.database.swt.Constants; +import com.minres.scviewer.database.swt.ToolTipHelpTextProvider; +import com.minres.scviewer.database.swt.ToolTipTableContentProvider; + +class ToolTipHandler { + + private Shell parentShell; + private Shell tipShell; + private Label tipLabelText; + private Table tipTable; + private Widget tipWidget; // widget this tooltip is hovering over + private Point tipPosition; // the position being hovered over + + private final TableColumn[] columns; + + private static final int hoverYOffset = 1; + + private static final String[] COLUMN_NAMES = { "Name", "Value"}; + + + private static final int MAX_CHARS = 48; + // The names of the first 32 characters + private Color[] colors = new Color[MAX_CHARS]; + + /** + * Creates a new tooltip handler + * + * @param parent the parent Shell + */ + public ToolTipHandler(Shell parent) { + final Display display = parent.getDisplay(); + this.parentShell = parent; + + tipShell = new Shell(parent, SWT.ON_TOP | SWT.TOOL); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + gridLayout.marginWidth = 2; + gridLayout.marginHeight = 2; + tipShell.setLayout(gridLayout); + + tipShell.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + + tipLabelText = new Label(tipShell, SWT.NONE); + tipLabelText.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); + tipLabelText.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); + tipLabelText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL |GridData.VERTICAL_ALIGN_CENTER)); + + final Font font = new Font(Display.getCurrent(), "Terminal", 10, SWT.NORMAL); + tipTable = new Table(tipShell, SWT.NONE); + tipTable.setHeaderVisible(true); + tipTable.setLinesVisible(true); + tipTable.setFont(font); + + columns = createColumns(tipTable); + + tipTable.setRedraw(false); + for (int i = 0; i < MAX_CHARS; i++) { + // Create a background color for this row + colors[i] = new Color(tipTable.getDisplay(), 255 - i, 127 + i, i); + + // Create the row in the table by creating + // a TableItem and setting text for each + // column + int c = 0; + TableItem item = new TableItem(tipTable, SWT.NONE); + item.setText(c++, String.valueOf((char) i)); + item.setText(c++, String.valueOf(i)); + item.setBackground(colors[i]); + } + // Now that we've set the text into the columns, + // we call pack() on each one to size it to the + // contents. + for (int i = 0, n = columns.length; i < n; i++) + columns[i].pack(); + // Set redraw back to true so that the table + // will paint appropriately + tipTable.setRedraw(true); + + } + + private TableColumn[] createColumns(Table table) { + TableColumn[] columns = new TableColumn[COLUMN_NAMES.length]; + for (int i = 0, n = columns.length; i < n; i++) { + columns[i] = new TableColumn(table, SWT.LEFT); + columns[i].setText(COLUMN_NAMES[i]); + } + return columns; + } + + /** + * Enables customized hover help for a specified control + * + * @control the control on which to enable hoverhelp + */ + public void activateHoverHelp(final Control control) { + /* + * Get out of the way if we attempt to activate the control underneath the tooltip + */ + control.addMouseListener(MouseListener.mouseDownAdapter(e -> { + if (tipShell.isVisible()) + tipShell.setVisible(false); + })); + /* + * get out of the way if we move the mouse + */ + control.addMouseMoveListener(new MouseMoveListener() { + @Override + public void mouseMove(MouseEvent e) { + if (tipShell.isVisible()) + tipShell.setVisible(false); + } + + }); + /* + * Trap hover events to pop-up tooltip + */ + control.addMouseTrackListener(new MouseTrackAdapter () { + @Override + public void mouseExit(MouseEvent e) { + if (tipShell.isVisible()) tipShell.setVisible(false); + tipWidget = null; + } + @Override + public void mouseHover (MouseEvent event) { + Point pt = new Point (event.x, event.y); + Widget widget = event.widget; + if (widget instanceof ToolBar) { + ToolBar w = (ToolBar) widget; + widget = w.getItem (pt); + } + if (widget instanceof Table) { + Table w = (Table) widget; + widget = w.getItem (pt); + } + if (widget instanceof Tree) { + Tree w = (Tree) widget; + widget = w.getItem (pt); + } + if (widget == null) { + tipShell.setVisible(false); + tipWidget = null; + return; + } + if (widget == tipWidget && tipShell.isVisible()) return; + tipWidget = widget; + tipPosition = control.toDisplay(pt); + boolean showDialog = false; + Object o = widget.getData(Constants.CONTENT_PROVIDER_TAG); + if(o != null) { + ToolTipTableContentProvider provider = ((ToolTipTableContentProvider)o).initialize(widget, pt); + tipLabelText.setText(provider.getTableTitle()); + tipTable.setRedraw(false); + tipTable.removeAll(); + for (String[] strings : provider.getTableContent()) { + if(strings.length>0) { + showDialog=true; + TableItem item = new TableItem(tipTable, SWT.NONE); + item.setText(0, strings[0]); + if(strings.length>1) + item.setText(1, strings[1]); + } + } + for (int i = 0, n = columns.length; i < n; i++) + columns[i].pack(); + tipTable.setRedraw(true); + tipTable.setVisible(true); + } else { + tipTable.setVisible(false); + } + String text = (String) widget.getData(Constants.TEXT_PROVIDER_TAG); + if(text != null) { + tipLabelText.setText(text != null ? text : "Hover test should go here"); + showDialog=true; + } + if(showDialog) { + tipShell.pack(); + setHoverLocation(tipShell, tipPosition); + tipShell.setVisible(true); + } + } + }); + + /* + * Trap F1 Help to pop up a custom help box + */ + control.addHelpListener(event -> { + if (tipWidget == null) return; + ToolTipHelpTextProvider handler = (ToolTipHelpTextProvider)tipWidget.getData(Constants.HELP_PROVIDER_TAG); + if (handler == null) return; + String text = handler.getHelpText(tipWidget); + if (text == null) return; + + if (tipShell.isVisible()) { + tipShell.setVisible(false); + Shell helpShell = new Shell(parentShell, SWT.SHELL_TRIM); + helpShell.setLayout(new FillLayout()); + Label label = new Label(helpShell, SWT.NONE); + label.setText(text); + helpShell.pack(); + setHoverLocation(helpShell, tipPosition); + helpShell.open(); + } + }); + } + + /** + * Sets the location for a hovering shell + * @param shell the object that is to hover + * @param position the position of a widget to hover over + * @return the top-left location for a hovering box + */ + private void setHoverLocation(Shell shell, Point position) { + Rectangle displayBounds = shell.getDisplay().getBounds(); + Rectangle shellBounds = shell.getBounds(); + shellBounds.x = Math.max(Math.min(position.x, displayBounds.width - shellBounds.width), 0); + shellBounds.y = Math.max(Math.min(position.y + hoverYOffset, displayBounds.height - shellBounds.height), 0); + shell.setBounds(shellBounds); + } +} \ No newline at end of file diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java index 06687bc..dd29137 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformCanvas.java @@ -426,7 +426,7 @@ public class WaveformCanvas extends Canvas{ } } - public List getClicked(Point point) { + public List getElementsAt(Point point) { LinkedList result=new LinkedList<>(); for (IPainter p : Lists.reverse(painterList)) { if (p instanceof TrackAreaPainter) { diff --git a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java index 7f0654f..7cc3267 100644 --- a/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java +++ b/com.minres.scviewer.database.ui.swt/src/com/minres/scviewer/database/swt/internal/WaveformViewer.java @@ -15,6 +15,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.text.DecimalFormat; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -24,6 +25,7 @@ import java.util.Map.Entry; import java.util.NavigableMap; import java.util.NoSuchElementException; import java.util.TreeMap; +import java.util.stream.Collectors; import org.eclipse.core.runtime.ListenerList; import org.eclipse.jface.util.LocalSelectionTransfer; @@ -97,7 +99,7 @@ public class WaveformViewer implements IWaveformViewer { private PropertyChangeSupport pcs; - static final DecimalFormat df = new DecimalFormat("#.00####"); + static final DecimalFormat df = new DecimalFormat("#0.00####"); private ITx currentTxSelection; @@ -115,6 +117,8 @@ public class WaveformViewer implements IWaveformViewer { final WaveformCanvas waveformCanvas; + final ToolTipHandler toolTipHandler; + private boolean revealSelected=false; private Composite top; @@ -159,7 +163,7 @@ public class WaveformViewer implements IWaveformViewer { down=true; if((e.stateMask&SWT.MODIFIER_MASK)!=0) return; //don't react on modifier if (e.button == 1) { - initialSelected = waveformCanvas.getClicked(start); + initialSelected = waveformCanvas.getElementsAt(start); } else if (e.button == 3) { Menu topMenu= top.getMenu(); if(topMenu!=null) topMenu.setVisible(true); @@ -248,7 +252,7 @@ public class WaveformViewer implements IWaveformViewer { protected long snapOffsetToEvent(Point p) { long time= waveformCanvas.getTimeForOffset(p.x); long scaling=5*waveformCanvas.getScaleFactor(); - for(Object o:waveformCanvas.getClicked(p)){ + for(Object o:waveformCanvas.getElementsAt(p)){ Entry floorEntry=null, ceilEntry=null; if(o instanceof TrackEntry){ TrackEntry entry = (TrackEntry) o; @@ -417,6 +421,9 @@ public class WaveformViewer implements IWaveformViewer { createStreamDropTarget(valueList); createWaveformDragSource(waveformCanvas); createWaveformDropTarget(waveformCanvas); + + toolTipHandler = new ToolTipHandler(parent.getShell()); + toolTipHandler.activateHoverHelp(waveformCanvas); } private Composite createTextPane(SashForm leftSash, String text) { @@ -809,25 +816,41 @@ public class WaveformViewer implements IWaveformViewer { } else { if (direction == GotoDirection.NEXT) { Collection outRel=currentTxSelection.getOutgoingRelations(); - for(ITxRelation rel:outRel){ - if(relationType.equals(rel.getRelationType())){ - setSelection(new StructuredSelection(rel.getTarget()), true); - return; - } - } + ITxRelation tx = selectTxToNavigateTo(outRel, relationType, true); + if(tx!=null) setSelection(new StructuredSelection(tx.getTarget()), true); } else if (direction == GotoDirection.PREV) { Collection inRel=currentTxSelection.getIncomingRelations(); - for(ITxRelation rel:inRel){ - if(relationType.equals(rel.getRelationType())){ - setSelection(new StructuredSelection(rel.getSource()), true); - return; - } - } + ITxRelation tx = selectTxToNavigateTo(inRel, relationType, false); + if(tx!=null) setSelection(new StructuredSelection(tx.getSource()), true); } } } } + private ITxRelation selectTxToNavigateTo(Collection rel, RelationType relationType, boolean target) { + ArrayList candidates = rel.stream().filter(r -> relationType.equals(r.getRelationType())).collect(Collectors.toCollection(ArrayList::new)); + //new RelSelectionDialog(waveformCanvas.getShell(), candidates, target).open(); + switch (candidates.size()) { + case 0: return null; + case 1: return candidates.get(0); + default: + ArrayList visibleCandidates = candidates.stream().filter(r -> streamsVisible(r)).collect(Collectors.toCollection(ArrayList::new)); + if(visibleCandidates.size()==0) { + return new RelSelectionDialog(waveformCanvas.getShell(), candidates, target).open(); + } else if(visibleCandidates.size()==1) { + return visibleCandidates.size()==1?visibleCandidates.get(0):null; + } else { + return new RelSelectionDialog(waveformCanvas.getShell(), visibleCandidates, target).open(); + } + } + } + + private boolean streamsVisible(ITxRelation relation) { + final ITxStream src = relation.getSource().getStream(); + final ITxStream tgt = relation.getTarget().getStream(); + return streams.stream().anyMatch(x -> x.waveform == src) && streams.stream().anyMatch(x -> x.waveform == tgt); + } + /* (non-Javadoc) * @see com.minres.scviewer.database.swt.IWaveformPanel#moveCursor(com.minres.scviewer.database.swt.GotoDirection) */ @@ -1130,6 +1153,10 @@ public class WaveformViewer implements IWaveformViewer { return null; } + public List getElementsAt(Point pt){ + return waveformCanvas.getElementsAt(pt); + } + private void createWaveformDragSource(final Canvas canvas) { Transfer[] types = new Transfer[] { LocalSelectionTransfer.getTransfer() }; DragSource dragSource = new DragSource(canvas, DND.DROP_MOVE); @@ -1137,7 +1164,7 @@ public class WaveformViewer implements IWaveformViewer { dragSource.addDragListener(new DragSourceAdapter() { public void dragStart(DragSourceEvent event) { event.doit = false; - List clicked = waveformCanvas.getClicked(new Point(event.x, event.y)); + List clicked = waveformCanvas.getElementsAt(new Point(event.x, event.y)); for(Object o:clicked){ if(o instanceof CursorPainter){ LocalSelectionTransfer.getTransfer().setSelection(new StructuredSelection(o)); @@ -1150,7 +1177,7 @@ public class WaveformViewer implements IWaveformViewer { public void dragSetData(DragSourceEvent event) { if (LocalSelectionTransfer.getTransfer().isSupportedType(event.dataType)) { - event.data=waveformCanvas.getClicked(new Point(event.x, event.y)); + event.data=waveformCanvas.getElementsAt(new Point(event.x, event.y)); } } }); diff --git a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java index 6575cfc..77ced9b 100644 --- a/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java +++ b/com.minres.scviewer.database.ui/src/com/minres/scviewer/database/ui/IWaveformViewer.java @@ -18,6 +18,7 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Control; @@ -62,6 +63,8 @@ public interface IWaveformViewer extends PropertyChangeListener, ISelectionProvi public TrackEntry getEntryForStream(IWaveform source); + public List getElementsAt(Point pt); + public void moveSelectedTrack(int i); public void setHighliteRelation(RelationType relationType); diff --git a/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF b/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF index 3fee919..2018fcc 100644 --- a/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF +++ b/com.minres.scviewer.e4.application/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: com.minres.scviewer.e4.application;singleton:=true -Bundle-Version: 2.3.0.qualifier +Bundle-Version: 2.4.0.qualifier Bundle-Vendor: %Bundle-Vendor Require-Bundle: javax.inject;bundle-version="1.0.0", org.eclipse.core.runtime;bundle-version="3.11.1", diff --git a/com.minres.scviewer.e4.application/pom.xml b/com.minres.scviewer.e4.application/pom.xml index a0c8e84..2fb3288 100644 --- a/com.minres.scviewer.e4.application/pom.xml +++ b/com.minres.scviewer.e4.application/pom.xml @@ -1,7 +1,7 @@ 4.0.0 com.minres.scviewer.e4.application - 2.3.0-SNAPSHOT + 2.4.0-SNAPSHOT com.minres.scviewer com.minres.scviewer.parent diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/TransactionDetails.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/TransactionDetails.java index bb39838..a562c1e 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/TransactionDetails.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/TransactionDetails.java @@ -97,7 +97,7 @@ public class TransactionDetails { /** The attribute filter. */ TxAttributeFilter attributeFilter; - + /** The view sorter. */ TxAttributeViewerSorter viewSorter; @@ -124,12 +124,12 @@ public class TransactionDetails { treeViewer.expandAll(true); } }); - + nameFilter.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); attributeFilter = new TxAttributeFilter(); viewSorter = new TxAttributeViewerSorter(); - + treeViewer = new TreeViewer(parent); treeViewer.setContentProvider(new TransactionTreeContentProvider()); treeViewer.setLabelProvider(new TxPropertiesLabelProvider()); @@ -148,7 +148,7 @@ public class TransactionDetails { public void treeExpanded(TreeExpansionEvent event) { treeViewer.getSelection(); } - + }); // Set up the table @@ -188,14 +188,14 @@ public class TransactionDetails { } }); // Pack the columns -// for (int i = 0, n = table.getColumnCount(); i < n; i++) { -// table.getColumn(i).pack(); -// } + // for (int i = 0, n = table.getColumnCount(); i < n; i++) { + // table.getColumn(i).pack(); + // } // Turn on the header and the lines tree.setHeaderVisible(true); tree.setLinesVisible(true); - + treeViewer.addDoubleClickListener(new IDoubleClickListener(){ @Override @@ -213,7 +213,7 @@ public class TransactionDetails { } } } - + }); parent.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { @@ -279,7 +279,7 @@ public class TransactionDetails { } else { treeViewer.setInput(null); } - + } private void setExpandedState(TreeItem[] treeItems, ArrayList states) { @@ -294,7 +294,7 @@ public class TransactionDetails { ret.add(treeItem.getItemCount()>0?treeItem.getExpanded():true); return ret; } - + private int getTopItemHier(ArrayList names){ int indexInParent=-1; TreeItem obj = treeViewer.getTree().getTopItem(); @@ -314,7 +314,7 @@ public class TransactionDetails { } return indexInParent; } - + private void setTopItemFromHier(ArrayList names, int indexInParent) { if(indexInParent<0 || names.size()==0 ) return; TreeItem selItem=null; @@ -375,16 +375,16 @@ public class TransactionDetails { */ String txToString(ITx tx){ StringBuilder sb = new StringBuilder(); - sb.append("tx#").append(tx.getId()).append("[").append(timeToString(tx.getBeginTime())). //$NON-NLS-1$ //$NON-NLS-2$ - append(" - ").append(timeToString(tx.getEndTime())).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ + sb.append("tx#").append(tx.getId()).append("[").append(timeToString(tx.getBeginTime())); //$NON-NLS-1$ //$NON-NLS-2$ + sb.append(" - ").append(timeToString(tx.getEndTime())).append("]"); //$NON-NLS-1$ //$NON-NLS-2$ return sb.toString(); } - + /** * The Class TxAttributeViewerSorter. */ class TxAttributeViewerSorter extends ViewerComparator { - + /** The Constant ASCENDING. */ private static final int ASCENDING = 0; @@ -469,7 +469,7 @@ public class TransactionDetails { */ @Override public boolean select(Viewer viewer, Object parentElement, Object element) { - + if (searchString == null || searchString.length() == 0) { return true; } @@ -482,7 +482,7 @@ public class TransactionDetails { if(element instanceof Object[]) { return (((Object[])element)[0]).toString().toLowerCase().matches(searchString.toLowerCase()); } - + return false; } } @@ -491,19 +491,19 @@ public class TransactionDetails { * The Enum Type. */ enum Type {/** The props. */ -PROPS, /** The attrs. */ - ATTRS, /** The in rel. */ - IN_REL, /** The out rel. */ - OUT_REL} + PROPS, /** The attrs. */ + ATTRS, /** The in rel. */ + IN_REL, /** The out rel. */ + OUT_REL} /** * The Class TreeNode. */ class TreeNode{ - + /** The type. */ public Type type; - + /** The element. */ public ITx element; @@ -624,16 +624,16 @@ PROPS, /** The attrs. */ * The Class AttributeLabelProvider. */ class AttributeLabelProvider extends LabelProvider implements IStyledLabelProvider { - + /** The field. */ final int field; - + /** The Constant NAME. */ public static final int NAME=0; - + /** The Constant TYPE. */ public static final int TYPE=1; - + /** The Constant VALUE. */ public static final int VALUE=2; @@ -678,13 +678,18 @@ PROPS, /** The attrs. */ String value = attribute.getValue().toString(); if((DataType.UNSIGNED == attribute.getDataType() || DataType.INTEGER==attribute.getDataType()) && !"0".equals(value)) { try { - value = attribute.getValue().toString() + " [0x"+Long.toHexString(Long.parseLong(attribute.getValue().toString()))+"]"; + value += " [0x"+Long.toHexString(Long.parseLong(attribute.getValue().toString()))+"]"; } catch(NumberFormatException e) { } } return new StyledString(value); }else if(element instanceof Object[]){ Object[] elements = (Object[]) element; - return new StyledString(elements[field].toString()); + Object o = elements[field]; + if(o instanceof ITx) { + ITx tx = (ITx)o; + return new StyledString(txToString(tx)+" ("+tx.getStream().getFullName()+")"); + } else + return new StyledString(o.toString()); } else if(element instanceof ITx){ return new StyledString(txToString((ITx) element)); }else diff --git a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java index 5495e59..ef059fa 100644 --- a/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java +++ b/com.minres.scviewer.e4.application/src/com/minres/scviewer/e4/application/parts/WaveformViewer.java @@ -65,14 +65,18 @@ import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Rectangle; 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.Widget; +import com.minres.scviewer.database.DataType; import com.minres.scviewer.database.ITx; +import com.minres.scviewer.database.ITxAttribute; import com.minres.scviewer.database.ITxEvent; import com.minres.scviewer.database.ITxRelation; import com.minres.scviewer.database.IWaveform; @@ -80,6 +84,7 @@ import com.minres.scviewer.database.IWaveformDb; import com.minres.scviewer.database.IWaveformDbFactory; import com.minres.scviewer.database.RelationType; import com.minres.scviewer.database.swt.Constants; +import com.minres.scviewer.database.swt.ToolTipTableContentProvider; import com.minres.scviewer.database.swt.WaveformViewerFactory; import com.minres.scviewer.database.ui.GotoDirection; import com.minres.scviewer.database.ui.ICursor; @@ -366,6 +371,50 @@ public class WaveformViewer implements IFileChangeListener, IPreferenceChangeLis prefs.addPreferenceChangeListener(this); waveformPane.addDisposeListener(this); + + waveformPane.getWaveformControl().setData(Constants.CONTENT_PROVIDER_TAG, new ToolTipTableContentProvider() { + private List res; + + @Override + public ToolTipTableContentProvider initialize(Widget widget, Point pt) { + res = waveformPane.getElementsAt(pt); + return this; + } + + @Override + public String getTableTitle() { + if(res.size()>0) { + Object o = res.get(0); + if(o instanceof ITx) { + ITx tx = (ITx)o; + return tx.toString(); + } + } + return ""; + } + + @Override + public List getTableContent() { + final ArrayList ret = new ArrayList<>(); + if(res.size()>0){ + Object o = res.get(0); + if(o instanceof ITx) { + ITx tx = (ITx)o; + ret.add(new String[]{"type", tx.getGenerator().getName()}); + for (ITxAttribute iTxAttribute : tx.getAttributes()) { + String value = iTxAttribute.getValue().toString(); + if((DataType.UNSIGNED == iTxAttribute.getDataType() || DataType.INTEGER==iTxAttribute.getDataType()) && !"0".equals(value)) { + try { + value += " [0x"+Long.toHexString(Long.parseLong(iTxAttribute.getValue().toString()))+"]"; + } catch(NumberFormatException e) { } + } + ret.add(new String[]{iTxAttribute.getName(), value}); + } + } + } + return ret; + } + }); } /* (non-Javadoc)