/*
* Copyright (c) 2012 Data Harmonisation Panel
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution. If not, see <http://www.gnu.org/licenses/>.
*
* Contributors:
* HUMBOLDT EU Integrated Project #030962
* Data Harmonisation Panel <http://www.dhpanel.eu>
*/
package eu.esdihumboldt.hale.ui.views.data.internal.explore;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.viewers.ColumnViewerToolTipSupport;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.TreeColumnViewerLabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerCell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.TreeEditor;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
import com.google.common.collect.Iterables;
import eu.esdihumboldt.hale.common.instance.model.Instance;
import eu.esdihumboldt.hale.common.schema.SchemaSpaceID;
import eu.esdihumboldt.hale.common.schema.model.TypeDefinition;
import eu.esdihumboldt.hale.ui.util.viewer.PairLabelProvider;
import eu.esdihumboldt.hale.ui.views.data.InstanceViewer;
import eu.esdihumboldt.hale.ui.views.data.internal.MetadataActionProvider;
import eu.esdihumboldt.hale.ui.views.data.internal.SimpleInstanceSelectionProvider;
import eu.esdihumboldt.util.Pair;
/**
* Instance explorer
*
* @author Simon Templer
*/
public class InstanceExplorer implements InstanceViewer {
private final SimpleInstanceSelectionProvider selectionProvider = new SimpleInstanceSelectionProvider();
private Composite selectorComposite;
private Composite main;
private TreeViewer viewer;
private TreeEditor editor;
private List<Instance> instances = new ArrayList<Instance>();
private final List<Control> selectButtons = new ArrayList<Control>();
private int selectedIndex = 0;
// private static ALogger _log =
// ALoggerFactory.getLogger(InstanceExplorer.class);
private final SelectionListener selectListener = new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
int index = 0;
for (Control button : selectButtons) {
if (button instanceof Button && ((Button) button).getSelection()) {
selectedIndex = index;
updateSelection();
return;
}
index++;
}
}
};
/**
* @see InstanceViewer#createControls(Composite, SchemaSpaceID)
*/
@Override
public void createControls(Composite parent, SchemaSpaceID schemaSpace) {
main = new Composite(parent, SWT.NONE);
main.setLayout(GridLayoutFactory.fillDefaults().numColumns(1).create());
// selector composite
selectorComposite = new Composite(main, SWT.NONE);
selectorComposite.setLayoutData(GridDataFactory.swtDefaults().create());
selectorComposite.setLayout(GridLayoutFactory.fillDefaults().create());
// viewer composite
Composite viewerComposite = new Composite(main, SWT.NONE);
viewerComposite.setLayoutData(GridDataFactory.fillDefaults().grab(true, true).create());
TreeColumnLayout layout = new TreeColumnLayout();
viewerComposite.setLayout(layout);
viewer = new TreeViewer(viewerComposite, SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
viewer.getTree().setLinesVisible(true);
// set content provider
viewer.setContentProvider(new InstanceContentProvider());
viewer.setAutoExpandLevel(TreeViewer.ALL_LEVELS);
// TODO set label provider?
// add definition columns
TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.LEFT);
column.getColumn().setText("Definition");
column.setLabelProvider(new TreeColumnViewerLabelProvider(new PairLabelProvider(true,
new DefinitionMetaLabelProvider(viewer, false, true))));
layout.setColumnData(column.getColumn(), new ColumnWeightData(1));
// add value column
column = new TreeViewerColumn(viewer, SWT.LEFT);
column.getColumn().setText("Value");
final InstanceValueLabelProvider instanceLabelProvider = new InstanceValueLabelProvider();
column.setLabelProvider(instanceLabelProvider);
// new PairLabelProvider(false, new LabelProvider())));
ColumnViewerToolTipSupport.enableFor(viewer);
layout.setColumnData(column.getColumn(), new ColumnWeightData(1));
MetadataActionProvider maep = new MetadataExploreActionProvider(viewer);
maep.setup();
// Add an editor for copying instance values
editor = new TreeEditor(viewer.getTree());
editor.horizontalAlignment = SWT.RIGHT;
viewer.getTree().addMouseMoveListener(new MouseMoveListener() {
@Override
public void mouseMove(MouseEvent e) {
final ViewerCell cell = viewer.getCell(new Point(e.x, e.y));
// Selected cell changed?
if (cell == null || editor.getItem() != cell.getItem()
|| editor.getColumn() != cell.getColumnIndex()) {
// Clean up any previous editor control
Control oldEditor = editor.getEditor();
if (oldEditor != null) {
oldEditor.dispose();
editor.setEditor(null, null, 0);
}
}
// No valid selected cell
if (cell == null || cell.getColumnIndex() == 0) {
return;
}
// cell didn't change
if ((editor.getItem() == cell.getItem() && editor.getColumn() == cell
.getColumnIndex())) {
return;
}
// determine instance value
Object value = ((Pair<?, ?>) cell.getViewerRow().getTreePath().getLastSegment())
.getSecond();
if (value instanceof Instance) {
value = ((Instance) value).getValue();
}
// copy button
if (value != null) {
final String textValue = value.toString();
if (!textValue.isEmpty()) { // empty string invalid for
// clipboard
Button button = new Button(viewer.getTree(), SWT.PUSH | SWT.FLAT);
button.setImage(PlatformUI.getWorkbench().getSharedImages()
.getImage(ISharedImages.IMG_TOOL_COPY));
button.setToolTipText("Copy string value");
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
// copy content to clipboard
Clipboard clipBoard = new Clipboard(Display.getCurrent());
clipBoard.setContents(new Object[] { textValue },
new Transfer[] { TextTransfer.getInstance() });
clipBoard.dispose();
}
});
// calculate editor size
Point size = button.computeSize(SWT.DEFAULT, SWT.DEFAULT);
editor.minimumHeight = size.y;
editor.minimumWidth = size.x;
editor.setEditor(button, (TreeItem) cell.getItem(), cell.getColumnIndex());
}
}
}
});
update();
}
/**
* Update the controls.
*/
private void update() {
// dispose old selector buttons
for (Control button : selectButtons) {
button.dispose();
}
selectButtons.clear();
selectorComposite.setLayout(GridLayoutFactory.swtDefaults()
.numColumns((instances.isEmpty()) ? (1) : (instances.size())).margins(3, 0)
.create());
// create new buttons for each instance
for (int index = 0; index < instances.size(); index++) {
Button button = new Button(selectorComposite, SWT.RADIO);
button.setText("#" + (index + 1));
button.setSelection(selectedIndex == index);
button.addSelectionListener(selectListener);
selectButtons.add(button);
}
if (selectButtons.isEmpty()) {
Label none = new Label(selectorComposite, SWT.NONE);
none.setText("No matching instances available");
selectButtons.add(none);
}
if (selectedIndex >= selectButtons.size()) {
selectedIndex = 0;
if (!selectButtons.isEmpty()) {
Control c1 = selectButtons.get(0);
if (c1 instanceof Button) {
((Button) c1).setSelection(true);
}
}
}
// both layout steps needed
selectorComposite.layout();
selectorComposite.getParent().layout();
updateSelection();
}
/**
* Update the viewer according to the current selection.
*/
private void updateSelection() {
if (selectedIndex < instances.size()) {
Instance instance = instances.get(selectedIndex);
viewer.setInput(instance);
selectionProvider.updateSelection(Collections.singleton(instance));
}
else {
viewer.setInput(null);
selectionProvider.updateSelection(null);
}
}
/**
* @see InstanceViewer#setInput(TypeDefinition, Iterable)
*/
@Override
public void setInput(TypeDefinition type, Iterable<Instance> instances) {
List<Instance> instanceList = new ArrayList<Instance>();
if (instances != null) {
Iterables.addAll(instanceList, instances);
}
this.instances = instanceList;
update();
}
/**
* @see InstanceViewer#getViewer()
*/
@Override
public Viewer getViewer() {
return viewer;
}
/**
* @see InstanceViewer#getControl()
*/
@Override
public Control getControl() {
return main;
}
/**
* @see InstanceViewer#getInstanceSelectionProvider()
*/
@Override
public ISelectionProvider getInstanceSelectionProvider() {
return selectionProvider;
}
}