blob: 45681a6b8489c29e3dc9b3487e3abcf471104f94 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2021 SAP AG and IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* SAP AG - initial API and implementation
* IBM Corporation - alignment and order of columns
*******************************************************************************/
package org.eclipse.mat.ui.util;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.mat.query.Column;
import org.eclipse.mat.query.Column.Alignment;
import org.eclipse.mat.query.IContextObject;
import org.eclipse.mat.query.IQueryContext;
import org.eclipse.mat.query.IResult;
import org.eclipse.mat.query.IResultTable;
import org.eclipse.mat.query.IResultTree;
import org.eclipse.mat.query.ISelectionProvider;
import org.eclipse.mat.query.ResultMetaData;
import org.eclipse.mat.report.IOutputter;
import org.eclipse.mat.report.RendererRegistry;
import org.eclipse.mat.ui.MemoryAnalyserPlugin;
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.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
public abstract class Copy
{
protected Control control;
protected Item[] selection;
public static void copyToClipboard(Control control)
{
Item[] selection = (control instanceof Table) ? ((Table) control).getSelection() //
: ((Tree) control).getSelection();
new CopyToClipboard(control, selection).doCopy();
}
public static void copyToClipboard(String text, Display display)
{
Clipboard clipboard = new Clipboard(display);
clipboard.setContents(new Object[] { text }, new Transfer[] { TextTransfer.getInstance() });
clipboard.dispose();
}
// //////////////////////////////////////////////////////////////
// private methods
// //////////////////////////////////////////////////////////////
private Copy(Control control, Item[] selection)
{
this.control = control;
this.selection = selection != null && selection.length > 0 ? selection : null;
}
private static class CopyToClipboard extends Copy
{
private CopyToClipboard(Control control, Item[] selection)
{
super(control, selection);
}
private void doCopy()
{
IResult t = control instanceof Table ? convert((Table)control) : convert((Tree)control);
StringWriter writer = null;
try
{
IOutputter outputter = RendererRegistry.instance().match("txt", t.getClass());//$NON-NLS-1$
writer = new StringWriter();
outputter.process(new ContextImpl(null, null), t, writer);
writer.flush();
writer.close();
copyToClipboard(writer.toString(), control.getDisplay());
}
catch (IOException e)
{
MemoryAnalyserPlugin.log(e);
return;
}
}
}
protected IResultTable convert(Table ct)
{
IResultTable t = new IResultTable() {
@Override
public Column[] getColumns()
{
TableColumn tcs[] = ct.getColumns();
int order[] = ct.getColumnOrder();
Column c[] = new Column[order.length];
for (int i = 0; i < order.length; ++i)
{
int col = order[i];
TableColumn tc = tcs[col];
c[i] = new Column(tc.getText());
switch (tc.getAlignment()) {
case SWT.RIGHT:
c[i].aligning(Alignment.RIGHT);
break;
case SWT.CENTER:
c[i].aligning(Alignment.CENTER);
break;
case SWT.LEFT:
default:
c[i].aligning(Alignment.LEFT);
break;
}
}
return c;
}
@Override
public Object getColumnValue(Object row, int columnIndex)
{
return ((TableItem)row).getText(ct.getColumnOrder()[columnIndex]);
}
@Override
public IContextObject getContext(Object row)
{
return null;
}
@Override
public ResultMetaData getResultMetaData()
{
return null;
}
@Override
public int getRowCount()
{
if (selection != null)
return selection.length;
else
return ct.getItemCount();
}
@Override
public Object getRow(int rowId)
{
if (selection != null)
return selection[rowId];
else
return ct.getItems()[rowId];
}
};
return t;
}
interface IRTS extends IResultTree, ISelectionProvider {};
protected IResultTree convert(Tree ct)
{
final Set<Item> selset = selection != null ? new HashSet<Item>(Arrays.asList(selection)) : Collections.<Item>emptySet();
IResultTree t = new IRTS() {
@Override
public Column[] getColumns()
{
TreeColumn tcs[] = ct.getColumns();
int order[] = ct.getColumnOrder();
Column c[] = new Column[tcs.length];
for (int i = 0; i < order.length; ++i)
{
int col = order[i];
TreeColumn tc = tcs[col];
c[i] = new Column(tc.getText());
switch (tc.getAlignment()) {
case SWT.RIGHT:
c[i].aligning(Alignment.RIGHT);
break;
case SWT.CENTER:
c[i].aligning(Alignment.CENTER);
break;
case SWT.LEFT:
default:
c[i].aligning(Alignment.LEFT);
break;
}
}
return c;
}
@Override
public Object getColumnValue(Object row, int columnIndex)
{
TreeItem treeitem = (TreeItem)row;
int[] order = ct.getColumnOrder();
// Special case for navigator view or other tree without columns
if (order.length == 0 || columnIndex == -1)
return treeitem.getText();
return treeitem.getText(order[columnIndex]);
}
@Override
public IContextObject getContext(Object row)
{
return null;
}
@Override
public ResultMetaData getResultMetaData()
{
return null;
}
@Override
public List<?> getElements()
{
if (selection == null)
return Arrays.asList(ct.getItems());
ArrayList<TreeItem>ret = new ArrayList<TreeItem>();
/*
* Add the selection items which do not
* have a parent in the selection - these would be missed
* as the parent would not be printed or expanded.
*/
for (Item i : selection)
{
if (i instanceof TreeItem)
{
TreeItem ti = (TreeItem)i;
TreeItem pi = ti.getParentItem();
if (!selset.contains(pi))
ret.add(ti);
}
}
return ret;
}
@Override
public boolean hasChildren(Object element)
{
int ret = ((TreeItem)element).getItemCount();
return ret > 0;
}
@Override
public List<?> getChildren(Object parent)
{
if (selection == null)
return Arrays.asList(((TreeItem)parent).getItems());
ArrayList<TreeItem>ret = new ArrayList<TreeItem>();
for (TreeItem ti : ((TreeItem)parent).getItems())
{
if (selset.contains(ti))
ret.add(ti);
}
return ret;
}
@Override
public boolean isSelected(Object row)
{
return selset.contains(row);
}
@Override
public boolean isExpanded(Object row)
{
return ((TreeItem)row).getExpanded();
}
};
return t;
}
private static class ContextImpl implements IOutputter.Context
{
private File outputDir;
private IQueryContext context;
public ContextImpl(IQueryContext context, File outputDir)
{
this.context = context;
this.outputDir = outputDir;
}
public String getId()
{
return "X"; //$NON-NLS-1$
}
public int getLimit()
{
return 0;
}
public File getOutputDirectory()
{
return outputDir;
}
public String getPathToRoot()
{
return "";//$NON-NLS-1$
}
public IQueryContext getQueryContext()
{
return context;
}
public String addIcon(URL icon)
{
return null;
}
public String addContextResult(String name, IResult result)
{
return null;
}
public boolean hasLimit()
{
return false;
}
public boolean isColumnVisible(int columnIndex)
{
return true;
}
public String param(String key, String defaultValue)
{
return defaultValue;
}
public String param(String key)
{
return null;
}
public boolean isTotalsRowVisible()
{
return true;
}
}
}