Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick Tasse2015-06-09 19:07:04 +0000
committerPatrick Tasse2015-06-11 19:47:46 +0000
commit9ba0a108c20342909431ee83201746e44b80916b (patch)
tree01a03a0d845a66b8775f4b20bdc938075fd55132 /org.eclipse.tracecompass.tmf.ui/src
parenta87f89437ba7f966a3a2ea75b73d3eae3a3280db (diff)
downloadorg.eclipse.tracecompass-9ba0a108c20342909431ee83201746e44b80916b.tar.gz
org.eclipse.tracecompass-9ba0a108c20342909431ee83201746e44b80916b.tar.xz
org.eclipse.tracecompass-9ba0a108c20342909431ee83201746e44b80916b.zip
tmf: Add Copy to Clipboard in TmfEventsTable
Change-Id: Ic2ca73787e294ba69fcaa4b111e5a21ff66bb9a1 Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com> Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com> Reviewed-on: https://git.eclipse.org/r/49834 Reviewed-by: Hudson CI
Diffstat (limited to 'org.eclipse.tracecompass.tmf.ui/src')
-rw-r--r--org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java5
-rw-r--r--org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/commands/CopyToClipboardOperation.java163
-rw-r--r--org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties5
-rw-r--r--org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java65
4 files changed, 229 insertions, 9 deletions
diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java
index 513534af75..177174cfca 100644
--- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java
+++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/Messages.java
@@ -41,6 +41,7 @@ public class Messages extends NLS {
public static String TmfEventsTable_ClearFiltersActionText;
public static String TmfEventsTable_CollapseFilterMenuName;
public static String TmfEventsTable_ContentColumnHeader;
+ public static String TmfEventsTable_CopyToClipboardActionText;
public static String TmfEventsTable_Export_to_text;
public static String TmfEventsTable_FilterHint;
public static String TmfEventsTable_HideRawActionText;
@@ -304,6 +305,10 @@ public class Messages extends NLS {
public static String CallStackView_ImportBinaryFileButtonTooltip;
public static String CallStackView_ImportBinaryFileDialogTitle;
+ public static String CopyToClipboardOperation_TaskName;
+ public static String CopyToClipboardOperation_OutOfMemoryErrorTitle;
+ public static String CopyToClipboardOperation_OutOfMemoryErrorMessage;
+
public static String ExportToTextJob_Export_to;
public static String ExportToTextJob_Export_trace_to;
public static String ExportToTextJob_Unable_to_export_trace;
diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/commands/CopyToClipboardOperation.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/commands/CopyToClipboardOperation.java
new file mode 100644
index 0000000000..2aca2e7efa
--- /dev/null
+++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/commands/CopyToClipboardOperation.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.tmf.ui.commands;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.tracecompass.internal.tmf.ui.Activator;
+import org.eclipse.tracecompass.internal.tmf.ui.Messages;
+import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
+import org.eclipse.tracecompass.tmf.core.filter.ITmfFilter;
+import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
+import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest.ExecutionType;
+import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
+import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
+import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
+import org.eclipse.tracecompass.tmf.ui.viewers.events.columns.TmfEventTableColumn;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * This operation copies the text of selected trace events to the clipboard.
+ */
+public class CopyToClipboardOperation implements IRunnableWithProgress {
+
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$
+ private final ITmfTrace fTrace;
+ private final ITmfFilter fFilter;
+ private final List<TmfEventTableColumn> fColumns;
+ private final long fStartRank;
+ private final long fEndRank;
+
+ /**
+ * Constructor.
+ *
+ * @param trace
+ * the trace to copy events from
+ * @param filter
+ * the filter to apply to trace events, or null
+ * @param columns
+ * the list of event table columns
+ * @param start
+ * the start rank of the selection
+ * @param end
+ * the end rank of the selection
+ */
+ public CopyToClipboardOperation(ITmfTrace trace, ITmfFilter filter, List<TmfEventTableColumn> columns, long start, long end) {
+ fTrace = trace;
+ fFilter = filter;
+ fColumns = columns;
+ fStartRank = start;
+ fEndRank = end;
+ }
+
+ @Override
+ public void run(IProgressMonitor monitor) {
+ final StringBuilder sb = new StringBuilder();
+ monitor.beginTask(Messages.CopyToClipboardOperation_TaskName, (int) (fEndRank - fStartRank + 1));
+
+ boolean needTab = false;
+ for (TmfEventTableColumn column : fColumns) {
+ if (needTab) {
+ sb.append('\t');
+ }
+ sb.append(column.getHeaderName());
+ needTab = true;
+ }
+ sb.append(LINE_SEPARATOR);
+
+ copy(sb, monitor);
+
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (sb.length() == 0) {
+ return;
+ }
+ try {
+ Clipboard clipboard = new Clipboard(Display.getDefault());
+ clipboard.setContents(new Object[] { sb.toString() },
+ new Transfer[] { TextTransfer.getInstance() });
+ } catch (OutOfMemoryError e) {
+ sb.setLength(0);
+ sb.trimToSize();
+ showErrorDialog();
+ }
+ }
+ });
+
+ monitor.done();
+ }
+
+ private IStatus copy(final StringBuilder sb, final IProgressMonitor monitor) {
+ ITmfEventRequest request = new TmfEventRequest(ITmfEvent.class, TmfTimeRange.ETERNITY, fStartRank, (int) (fEndRank - fStartRank + 1), ExecutionType.FOREGROUND) {
+ @Override
+ public void handleData(ITmfEvent event) {
+ super.handleData(event);
+ if (monitor.isCanceled()) {
+ cancel();
+ return;
+ }
+ monitor.worked(1);
+ if (fFilter == null || fFilter.matches(event)) {
+ try {
+ boolean needTab = false;
+ for (TmfEventTableColumn column : fColumns) {
+ if (needTab) {
+ sb.append('\t');
+ }
+ sb.append(column.getItemString(event));
+ needTab = true;
+ }
+ sb.append(LINE_SEPARATOR);
+ } catch (OutOfMemoryError e) {
+ sb.setLength(0);
+ sb.trimToSize();
+ showErrorDialog();
+ cancel();
+ }
+ }
+ }
+ };
+ fTrace.sendRequest(request);
+ try {
+ request.waitForCompletion();
+ } catch (InterruptedException e) {
+ Activator.getDefault().logError("Wait for completion interrupted for copy to clipboard ", e); //$NON-NLS-1$
+ }
+ return Status.OK_STATUS;
+ }
+
+ private static void showErrorDialog() {
+ Display.getDefault().syncExec(new Runnable() {
+ @Override
+ public void run() {
+ Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
+ MessageBox confirmOperation = new MessageBox(shell, SWT.ICON_ERROR | SWT.OK);
+ confirmOperation.setText(Messages.CopyToClipboardOperation_OutOfMemoryErrorTitle);
+ confirmOperation.setMessage(Messages.CopyToClipboardOperation_OutOfMemoryErrorMessage);
+ confirmOperation.open();
+ }
+ });
+ }
+}
diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties
index c1c42847fa..7d91c60fd0 100644
--- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties
+++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/internal/tmf/ui/messages.properties
@@ -34,6 +34,7 @@ TmfEventsTable_ApplyPresetFilterMenuName=Apply Preset Filter...
TmfEventsTable_ClearFiltersActionText=Clear Filters
TmfEventsTable_CollapseFilterMenuName=Collapse Events
TmfEventsTable_ContentColumnHeader=Content
+TmfEventsTable_CopyToClipboardActionText=Copy to Clipboard
TmfEventsTable_Export_to_text=Export To Text...
TmfEventsTable_FilterHint=<filter>
TmfEventsTable_HideRawActionText=Hide Raw
@@ -303,6 +304,10 @@ CallStackView_ImportBinaryFileButtonText=Import binary file...
CallStackView_ImportBinaryFileButtonTooltip=Import a binary file containing debugging symbols
CallStackView_ImportBinaryFileDialogTitle=Select Binary File
+CopyToClipboardOperation_TaskName=Copying to Clipboard
+CopyToClipboardOperation_OutOfMemoryErrorTitle=Out Of Memory Error
+CopyToClipboardOperation_OutOfMemoryErrorMessage=The full selection cannot be copied to the clipboard. Press OK to abort.
+
ExportToTextJob_Export_to=Export to {0}...
ExportToTextJob_Export_trace_to=Export trace to {0}
ExportToTextJob_Unable_to_export_trace=Unable to export trace to {0}
diff --git a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java
index 56bd95d977..10c10e1642 100644
--- a/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java
+++ b/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/events/TmfEventsTable.java
@@ -21,6 +21,7 @@ package org.eclipse.tracecompass.tmf.ui.viewers.events;
import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
import java.io.FileNotFoundException;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -63,6 +64,7 @@ import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.FontRegistry;
import org.eclipse.jface.resource.JFaceResources;
@@ -117,6 +119,7 @@ import org.eclipse.tracecompass.common.core.NonNullUtils;
import org.eclipse.tracecompass.internal.tmf.core.filter.TmfCollapseFilter;
import org.eclipse.tracecompass.internal.tmf.ui.Activator;
import org.eclipse.tracecompass.internal.tmf.ui.Messages;
+import org.eclipse.tracecompass.internal.tmf.ui.commands.CopyToClipboardOperation;
import org.eclipse.tracecompass.internal.tmf.ui.commands.ExportToTextCommandHandler;
import org.eclipse.tracecompass.internal.tmf.ui.dialogs.MultiLineInputDialog;
import org.eclipse.tracecompass.tmf.core.component.ITmfEventProvider;
@@ -292,7 +295,8 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
private ITmfTrace fTrace;
private volatile boolean fPackDone = false;
private HeaderState fHeaderState = HeaderState.SEARCH;
- private long fSelectedRank = 0;
+ private long fSelectedRank = -1;
+ private long fSelectedBeginRank = -1;
private ITmfTimestamp fSelectedBeginTimestamp = null;
private IStatusLineManager fStatusLineManager = null;
@@ -507,6 +511,11 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
if (e.item.getData(Key.RANK) instanceof Long) {
fSelectedRank = (Long) e.item.getData(Key.RANK);
fRawViewer.selectAndReveal((Long) e.item.getData(Key.RANK));
+ } else {
+ fSelectedRank = -1;
+ }
+ if (fTable.getSelectionIndices().length == 1) {
+ fSelectedBeginRank = fSelectedRank;
}
if (e.item.getData(Key.TIMESTAMP) instanceof ITmfTimestamp) {
final ITmfTimestamp ts = NonNullUtils.checkNotNull((ITmfTimestamp) e.item.getData(Key.TIMESTAMP));
@@ -808,6 +817,7 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
// +1 for header row
fTable.setSelection(index + 1);
fSelectedRank = rank;
+ fSelectedBeginRank = fSelectedRank;
updateStatusLine(null);
final TableItem[] selection = fTable.getSelection();
if ((selection != null) && (selection.length > 0)) {
@@ -918,6 +928,37 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
* Create a pop-up menu.
*/
private void createPopupMenu() {
+ final IAction copyAction = new Action(Messages.TmfEventsTable_CopyToClipboardActionText) {
+ @Override
+ public void run() {
+ ITmfTrace trace = fTrace;
+ if (trace == null || (fSelectedRank == -1 && fSelectedBeginRank == -1)) {
+ return;
+ }
+
+ List<TmfEventTableColumn> columns = new ArrayList<>();
+ for (int i : fTable.getColumnOrder()) {
+ TableColumn column = fTable.getColumns()[i];
+ // Omit the margin column and hidden columns
+ if (i >= EVENT_COLUMNS_START_INDEX && (column.getResizable() || column.getWidth() > 0)) {
+ columns.add(fColumns.get(i));
+ }
+ }
+
+ long start = Math.min(fSelectedBeginRank, fSelectedRank);
+ long end = Math.max(fSelectedBeginRank, fSelectedRank);
+ final ITmfFilter filter = (ITmfFilter) fTable.getData(Key.FILTER_OBJ);
+ IRunnableWithProgress operation = new CopyToClipboardOperation(trace, filter, columns, start, end);
+ try {
+ PlatformUI.getWorkbench().getProgressService().busyCursorWhile(operation);
+ } catch (InvocationTargetException e) {
+ Activator.getDefault().logError("Invocation target exception copying to clipboard ", e); //$NON-NLS-1$
+ } catch (InterruptedException e) {
+ /* ignored */
+ }
+ }
+ };
+
final IAction showTableAction = new Action(Messages.TmfEventsTable_ShowTableActionText) {
@Override
public void run() {
@@ -1088,8 +1129,9 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
IEvaluationContext context = handlerService.getCurrentState();
List<TmfEventTableColumn> exportColumns = new ArrayList<>();
for (int i : fTable.getColumnOrder()) {
- // Omit the margin column
- if (i >= EVENT_COLUMNS_START_INDEX) {
+ TableColumn column = fTable.getColumns()[i];
+ // Omit the margin column and hidden columns
+ if (i >= EVENT_COLUMNS_START_INDEX && (column.getResizable() || column.getWidth() > 0)) {
exportColumns.add(fColumns.get(i));
}
}
@@ -1168,7 +1210,7 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
tablePopupMenu.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(final IMenuManager manager) {
- if (fTable.getSelectionIndex() == 0) {
+ if (fTable.getSelectionIndices().length == 1 && fTable.getSelectionIndices()[0] == 0) {
// Right-click on header row
if (fHeaderState == HeaderState.FILTER) {
tablePopupMenu.add(showSearchBarAction);
@@ -1199,6 +1241,10 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
}
// Right-click on table
+ if (fSelectedRank != -1 && fSelectedBeginRank != -1) {
+ tablePopupMenu.add(copyAction);
+ tablePopupMenu.add(new Separator());
+ }
if (fTable.isVisible() && fRawViewer.isVisible()) {
tablePopupMenu.add(hideTableAction);
tablePopupMenu.add(hideRawAction);
@@ -2250,6 +2296,7 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
}
fTable.setSelection(selection);
fSelectedRank = foundRank;
+ fSelectedBeginRank = fSelectedRank;
fRawViewer.selectAndReveal(fSelectedRank);
if (foundTimestamp != null) {
broadcast(new TmfSelectionRangeUpdatedSignal(TmfEventsTable.this, foundTimestamp));
@@ -2477,13 +2524,14 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
}
fTrace = trace;
fPackDone = false;
- fSelectedRank = 0;
fDisposeOnClose = disposeOnClose;
// Perform the updates on the UI thread
fTable.getDisplay().syncExec(new Runnable() {
@Override
public void run() {
+ fSelectedRank = -1;
+ fSelectedBeginRank = -1;
fTable.removeAll();
fCache.setTrace(trace); // Clear the cache
if (trace != null) {
@@ -2768,6 +2816,7 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
fPendingGotoRank = rank;
}
fSelectedRank = rank;
+ fSelectedBeginRank = fSelectedRank;
fTable.setSelection(index + 1); // +1 for header row
updateStatusLine(null);
}
@@ -2874,7 +2923,6 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
final ITmfContext context = fTrace.seekEvent(timestamp);
final long rank = context.getRank();
context.dispose();
- fSelectedRank = rank;
fTable.getDisplay().asyncExec(new Runnable() {
@Override
@@ -2884,10 +2932,9 @@ public class TmfEventsTable extends TmfComponent implements IGotoMarker, IColorS
return;
}
+ fSelectedRank = rank;
+ fSelectedBeginRank = fSelectedRank;
int index = (int) rank;
- if (fTable.isDisposed()) {
- return;
- }
if (fTable.getData(Key.FILTER_OBJ) != null) {
/* +1 for top filter status row */
index = fCache.getFilteredEventIndex(rank) + 1;

Back to the top