From 37b7faba6f4b597d03a6fd982bfc49dd1b199080 Mon Sep 17 00:00:00 2001 From: Matthew Khouzam Date: Wed, 28 Sep 2016 13:55:51 -0400 Subject: [PATCH] timing.ui: add Export to TSV to tables and statistics This allows exporting to tsv files. Testing is done with reflection to avoid native dialog issues. Some issues are present: * In Linux, an invisible column is added at the end, while this seems ok, it makes the output inconsistent between Windows and Linux. * SWTBot cannot test native windows, therefore, the user actual actions are untested. All possible logic has been moved elsewhere to accomodate. * Tree and Table have no common parents, this will incur code duplication due to their similarities. * In Linux, tooltips are not well handled in menu items. Change-Id: I506d0e7e50bd5ce8ecbd44675a0c404ab2dda431 Signed-off-by: Matthew Khouzam Reviewed-on: https://git.eclipse.org/r/82111 Reviewed-by: Hudson CI Reviewed-by: Genevieve Bastien --- ...allLatencyStatisticsTableAnalysisTest.java | 45 +++++++++- .../SystemCallLatencyTableAnalysisTest.java | 60 ++++++++++++- .../AbstractSegmentStoreStatisticsView.java | 78 ++++++++++++++++- .../table/AbstractSegmentStoreTableView.java | 72 ++++++++++++++++ .../views/segmentstore/ExportToTsvAction.java | 85 +++++++++++++++++++ .../ui/views/segmentstore/Messages.java | 37 ++++++++ .../ui/views/segmentstore/messages.properties | 11 +++ .../viewers/tree/AbstractTmfTreeViewer.java | 4 +- 8 files changed, 387 insertions(+), 5 deletions(-) create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/ExportToTsvAction.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java create mode 100644 analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyStatisticsTableAnalysisTest.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyStatisticsTableAnalysisTest.java index 1e41b80c44..03b6c2827c 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyStatisticsTableAnalysisTest.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyStatisticsTableAnalysisTest.java @@ -14,15 +14,21 @@ package org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests.latency; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.List; import org.apache.log4j.ConsoleAppender; import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; import org.eclipse.core.runtime.FileLocator; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.swtbot.eclipse.finder.SWTWorkbenchBot; import org.eclipse.swtbot.eclipse.finder.widgets.SWTBotView; import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable; @@ -30,8 +36,10 @@ import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.eclipse.swtbot.swt.finder.results.BoolResult; import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; +import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics.AbstractSegmentStoreStatisticsView; import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.statistics.SystemCallLatencyStatisticsView; import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers; @@ -159,9 +167,15 @@ public class SystemCallLatencyStatisticsTableAnalysisTest { * * @throws IOException * trace not found? + * @throws SecurityException + * Reflection error + * @throws NoSuchMethodException + * Reflection error + * @throws IllegalArgumentException + * Reflection error */ @Test - public void testWithTrace() throws IOException { + public void testWithTrace() throws IOException, NoSuchMethodException, SecurityException, IllegalArgumentException { String tracePath; tracePath = FileLocator.toFileURL(CtfTestTrace.ARM_64_BIT_HEADER.getTraceURL()).getPath(); SWTWorkbenchBot bot = new SWTWorkbenchBot(); @@ -185,11 +199,40 @@ public class SystemCallLatencyStatisticsTableAnalysisTest { validate(treeItem.getNode(3), "poll", "6.300 µs", "6.800 µs", "6.550 µs", "---", "2"); validate(treeItem.getNode(5), "set_tid_address", "2.300 µs", "2.300 µs", "2.300 µs", "---", "1"); validate(treeItem.getNode(7), "pipe", "27.900 µs", "29.700 µs", "28.800 µs", "---", "2"); + testToTsv(view); + SWTBotMenu menuBot = view.viewMenu().menu("Export to TSV"); + assertTrue(menuBot.isEnabled()); + assertTrue(menuBot.isVisible()); bot.closeAllEditors(); SWTBotUtils.deleteProject(PROJECT_NAME, bot); } + private static void testToTsv(SWTBotView view) throws NoSuchMethodException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + assertNotNull(os); + IViewPart viewPart = view.getReference().getView(true); + assertTrue(viewPart instanceof SystemCallLatencyStatisticsView); + Class<@NonNull AbstractSegmentStoreStatisticsView> clazz = AbstractSegmentStoreStatisticsView.class; + Method method = clazz.getDeclaredMethod("exportToTsv", java.io.OutputStream.class); + method.setAccessible(true); + final Exception[] except = new Exception[1]; + UIThreadRunnable.syncExec(() -> { + try { + method.invoke((SystemCallLatencyStatisticsView) viewPart, os); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + except[0] = e; + } + }); + assertNull(except[0]); + @SuppressWarnings("null") + String[] lines = String.valueOf(os).split(System.getProperty("line.separator")); + assertNotNull(lines); + assertEquals("header", "Level\tMinimum\tMaximum\tAverage\tStandard Deviation\tCount\tTotal", lines[0]); + assertEquals("line 1", "Total\t1.000 µs\t5.904 s\t15.628 ms\t175.875 ms\t1801\t28.146 s", lines[1]); + + } + private static void validate(SWTBotTreeItem treeItem, final String nodeName, final String min, final String max, final String avg, final String stdev, final String count) { assertEquals(nodeName, treeItem.cell(0)); assertEquals(min, treeItem.cell(MIN_COL)); diff --git a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java index f952178b4d..a5b312f328 100644 --- a/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java +++ b/analysis/org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests/src/org/eclipse/tracecompass/analysis/os/linux/ui/swtbot/tests/latency/SystemCallLatencyTableAnalysisTest.java @@ -12,10 +12,12 @@ package org.eclipse.tracecompass.analysis.os.linux.ui.swtbot.tests.latency; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -33,7 +35,9 @@ import org.eclipse.swtbot.swt.finder.junit.SWTBotJunit4ClassRunner; import org.eclipse.swtbot.swt.finder.results.BoolResult; import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; +import org.eclipse.swtbot.swt.finder.widgets.SWTBotMenu; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTable; +import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableView; import org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table.AbstractSegmentStoreTableViewer; import org.eclipse.tracecompass.internal.analysis.os.linux.ui.views.latency.SystemCallLatencyView; import org.eclipse.tracecompass.segmentstore.core.BasicSegment; @@ -285,6 +289,58 @@ public class SystemCallLatencyTableAnalysisTest { bot.waitUntil(ConditionHelpers.isTableCellFilled(tableBot, "998,001", 0, 2)); } + /** + * Test creating a tsv + * + * @throws NoSuchMethodException + * Error creating the tsv + */ + @Test + public void testWriteToTsv() throws NoSuchMethodException { + List<@NonNull BasicSegment> fixture = new ArrayList<>(); + for (int i = 1; i <= 20; i++) { + int start = i; + final int delta = i; + int end = start + delta * delta; + fixture.add(new BasicSegment(start, end)); + } + assertNotNull(fTable); + fTable.updateModel(fixture); + SWTBotTable tableBot = new SWTBotTable(fTable.getTableViewer().getTable()); + SWTBot bot = new SWTBot(); + bot.waitUntil(ConditionHelpers.isTableCellFilled(tableBot, "1", 0, 2)); + SWTWorkbenchBot swtWorkbenchBot = new SWTWorkbenchBot(); + SWTBotView viewBot = swtWorkbenchBot.viewById(VIEW_ID); + testToTsv(viewBot); + SWTBotMenu menuBot = viewBot.viewMenu().menu("Export to TSV"); + assertTrue(menuBot.isEnabled()); + assertTrue(menuBot.isVisible()); + } + + private void testToTsv(SWTBotView view) throws NoSuchMethodException { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + assertNotNull(os); + Class<@NonNull AbstractSegmentStoreTableView> clazz = AbstractSegmentStoreTableView.class; + Method method = clazz.getDeclaredMethod("exportToTsv", java.io.OutputStream.class); + method.setAccessible(true); + final Exception[] except = new Exception[1]; + UIThreadRunnable.syncExec(() -> { + try { + method.invoke(fLatencyView, os); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + except[0] = e; + } + }); + assertNull(except[0]); + @SuppressWarnings("null") + String[] lines = String.valueOf(os).split(System.getProperty("line.separator")); + assertNotNull(lines); + assertEquals("number of lines", 21, lines.length); + assertEquals("header", "Start Time\tEnd Time\tDuration", lines[0]); + // not a straight up string compare due to time zones. Kathmandu and Eucla have 15 minute time zones. + assertTrue("line 1", lines[1].matches("\\d\\d:\\d\\d:00\\.000\\s000\\s001\\t\\d\\d:\\d\\d:00.000 000 002\\t1")); + } + /** * Test with an actual trace, this is more of an integration test than a * unit test. This test is a slow one too. If some analyses are not well diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentStoreStatisticsView.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentStoreStatisticsView.java index 069c67442f..0a18e3977a 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentStoreStatisticsView.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/statistics/AbstractSegmentStoreStatisticsView.java @@ -11,13 +11,26 @@ *******************************************************************************/ package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.statistics; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.action.Action; import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; import org.eclipse.tracecompass.common.core.NonNullUtils; +import org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.ExportToTsvAction; import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; import org.eclipse.tracecompass.tmf.ui.views.TmfView; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; + /** * Abstract view to to be extended to display segment store statistics. * @@ -26,7 +39,20 @@ import org.eclipse.tracecompass.tmf.ui.views.TmfView; */ public abstract class AbstractSegmentStoreStatisticsView extends TmfView { - @Nullable private AbstractSegmentStoreStatisticsViewer fStatsViewer = null; + private final Action fExportAction = new ExportToTsvAction() { + @Override + protected void exportToTsv(@Nullable OutputStream stream) { + AbstractSegmentStoreStatisticsView.this.exportToTsv(stream); + } + + @Override + protected @Nullable Shell getShell() { + return getViewSite().getShell(); + } + + }; + + private @Nullable AbstractSegmentStoreStatisticsViewer fStatsViewer = null; /** * Constructor @@ -44,6 +70,7 @@ public abstract class AbstractSegmentStoreStatisticsView extends TmfView { statsViewer.loadTrace(trace); } fStatsViewer = statsViewer; + getViewSite().getActionBars().getMenuManager().add(fExportAction); } @Override @@ -72,4 +99,53 @@ public abstract class AbstractSegmentStoreStatisticsView extends TmfView { */ protected abstract AbstractSegmentStoreStatisticsViewer createSegmentStoreStatisticsViewer(Composite parent); + /** + * Export a given items's TSV + * + * @param stream + * an output stream to write the TSV to + * @since 1.2 + */ + @VisibleForTesting + protected void exportToTsv(@Nullable OutputStream stream) { + try (PrintWriter pw = new PrintWriter(stream)) { + AbstractSegmentStoreStatisticsViewer statsViewer = fStatsViewer; + if (statsViewer == null) { + return; + } + Tree tree = statsViewer.getTreeViewer().getTree(); + int size = tree.getItemCount(); + List columns = new ArrayList<>(); + for (int i = 0; i < tree.getColumnCount(); i++) { + String valueOf = String.valueOf(tree.getColumn(i).getText()); + if (valueOf.isEmpty() && i == tree.getColumnCount() - 1) { + // Linux "feature", an invisible column is added at the end + // with gtk2 + break; + } + columns.add(valueOf); + } + String join = Joiner.on('\t').skipNulls().join(columns); + pw.println(join); + for (int i = 0; i < size; i++) { + TreeItem item = tree.getItem(i); + printItem(pw, columns, item); + } + } + } + + private void printItem(PrintWriter pw, List columns, @Nullable TreeItem item) { + if (item == null) { + return; + } + List data = new ArrayList<>(); + for (int col = 0; col < columns.size(); col++) { + data.add(String.valueOf(item.getText(col))); + } + pw.println(Joiner.on('\t').join(data)); + for (TreeItem child : item.getItems()) { + printItem(pw, columns, child); + } + } + } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/table/AbstractSegmentStoreTableView.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/table/AbstractSegmentStoreTableView.java index 4a1460d198..8b6fd47875 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/table/AbstractSegmentStoreTableView.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/analysis/timing/ui/views/segmentstore/table/AbstractSegmentStoreTableView.java @@ -13,13 +13,27 @@ package org.eclipse.tracecompass.analysis.timing.ui.views.segmentstore.table; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.action.Action; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.widgets.Composite; +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.tracecompass.internal.analysis.timing.ui.views.segmentstore.ExportToTsvAction; import org.eclipse.tracecompass.tmf.ui.views.TmfView; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; + /** * View for displaying a segment store analysis in a table. * @@ -32,6 +46,19 @@ public abstract class AbstractSegmentStoreTableView extends TmfView { // Attributes // ------------------------------------------------------------------------ + private final Action fExportAction = new ExportToTsvAction() { + @Override + protected void exportToTsv(@Nullable OutputStream stream) { + AbstractSegmentStoreTableView.this.exportToTsv(stream); + + } + + @Override + protected @Nullable Shell getShell() { + return getViewSite().getShell(); + } + }; + private @Nullable AbstractSegmentStoreTableViewer fSegmentStoreViewer; // ------------------------------------------------------------------------ @@ -54,6 +81,7 @@ public abstract class AbstractSegmentStoreTableView extends TmfView { SashForm sf = new SashForm(parent, SWT.NONE); TableViewer tableViewer = new TableViewer(sf, SWT.FULL_SELECTION | SWT.VIRTUAL); fSegmentStoreViewer = createSegmentStoreViewer(tableViewer); + getViewSite().getActionBars().getMenuManager().add(fExportAction); setInitialData(); } @@ -103,4 +131,48 @@ public abstract class AbstractSegmentStoreTableView extends TmfView { fSegmentStoreViewer.setData(fSegmentStoreViewer.getSegmentProvider()); } } + + /** + * Export a given items's TSV + * + * @param stream + * an output stream to write the TSV to + * @since 1.2 + */ + @VisibleForTesting + protected void exportToTsv(@Nullable OutputStream stream) { + try (PrintWriter pw = new PrintWriter(stream)) { + AbstractSegmentStoreTableViewer segmentStoreViewer = getSegmentStoreViewer(); + if (segmentStoreViewer == null) { + return; + } + Table table = segmentStoreViewer.getTableViewer().getTable(); + int size = table.getItemCount(); + List columns = new ArrayList<>(); + for (int i = 0; i < table.getColumnCount(); i++) { + TableColumn column = table.getColumn(i); + if (column == null) { + return; + } + String columnName = String.valueOf(column.getText()); + if (columnName.isEmpty() && i == table.getColumnCount() - 1) { + // Linux GTK2 undocumented feature + break; + } + columns.add(columnName); + } + pw.println(Joiner.on('\t').join(columns)); + for (int i = 0; i < size; i++) { + TableItem item = table.getItem(i); + if (item == null) { + continue; + } + List data = new ArrayList<>(); + for (int col = 0; col < columns.size(); col++) { + data.add(String.valueOf(item.getText(col))); + } + pw.println(Joiner.on('\t').join(data)); + } + } + } } diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/ExportToTsvAction.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/ExportToTsvAction.java new file mode 100644 index 0000000000..1f5eb40b96 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/ExportToTsvAction.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.action.Action; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.tracecompass.internal.analysis.timing.ui.Activator; + +/** + * The export to TSV abstract action + * + * TODO: improve testing when there is a way to test native widgets + * + * @author Matthew Khouzam + */ +public abstract class ExportToTsvAction extends Action { + + private static final String[] EXTENSTIONS = { "*.tsv", "*.*" };//$NON-NLS-1$//$NON-NLS-2$ + + /** + * Gets the extension of TSV + * + * @return the extension of TSV + */ + protected String[] getExtension() { + return EXTENSTIONS; + } + + @Override + public String getText() { + return String.valueOf(Messages.AbstractSegmentStoreTableView_exportToTsv); + } + + @Override + public String getToolTipText() { + return String.valueOf(Messages.ExportToTsvAction_exportToTsvToolTip); + } + + @Override + public void run() { + Shell shell = getShell(); + if (shell == null) { + return; + } + FileDialog fd = new FileDialog(shell); + fd.setFilterExtensions(getExtension()); + String fileName = fd.open(); + if (fileName == null) { + return; + } + try (FileOutputStream fos = new FileOutputStream(fileName)) { + exportToTsv(fos); + } catch (IOException e) { + Activator.getDefault().logError("IO Error " + fileName, e); //$NON-NLS-1$ + } + } + + /** + * Get the shell to open the file dialog + * + * @return the shell + */ + protected abstract @Nullable Shell getShell(); + + /** + * Export a given items's TSV + * + * @param stream + * an output stream to write the TSV to + */ + protected abstract void exportToTsv(OutputStream stream); +} diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java new file mode 100644 index 0000000000..0b0ebda500 --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/Messages.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + *******************************************************************************/ + +package org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.osgi.util.NLS; + +/** + * Messages for segment store views + * + * @author Matthew Khouzam + */ +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.analysis.timing.ui.views.segmentstore.messages"; //$NON-NLS-1$ + /** + * Export to TSV message + */ + public static @Nullable String AbstractSegmentStoreTableView_exportToTsv; + /** + * Export to TSV tooltip + */ + public static @Nullable String ExportToTsvAction_exportToTsvToolTip; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties new file mode 100644 index 0000000000..d41d46119c --- /dev/null +++ b/analysis/org.eclipse.tracecompass.analysis.timing.ui/src/org/eclipse/tracecompass/internal/analysis/timing/ui/views/segmentstore/messages.properties @@ -0,0 +1,11 @@ +############################################################################### +# Copyright (c) 2016 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 +############################################################################### + +AbstractSegmentStoreTableView_exportToTsv=Export to TSV +ExportToTsvAction_exportToTsvToolTip=Output the content of this view in a tab separated value text file. This can then be imported into any spreadsheet software. diff --git a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/tree/AbstractTmfTreeViewer.java b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/tree/AbstractTmfTreeViewer.java index c44108b21b..3c78e7951b 100644 --- a/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/tree/AbstractTmfTreeViewer.java +++ b/tmf/org.eclipse.tracecompass.tmf.ui/src/org/eclipse/tracecompass/tmf/ui/viewers/tree/AbstractTmfTreeViewer.java @@ -192,6 +192,7 @@ public abstract class AbstractTmfTreeViewer extends TmfTimeViewer { fTreeViewer.setLabelProvider(new TreeLabelProvider()); List columns = getColumnDataProvider().getColumnData(); this.setTreeColumns(columns); + } /** @@ -277,8 +278,9 @@ public abstract class AbstractTmfTreeViewer extends TmfTimeViewer { * Get the tree viewer object * * @return The tree viewer object displayed by this viewer + * @since 2.2 */ - protected TreeViewer getTreeViewer() { + public TreeViewer getTreeViewer() { return fTreeViewer; } -- 2.34.1