/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* 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:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.eclipse.ui.viewers;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import com.windowtester.eclipse.ui.UiPlugin;
import com.windowtester.eclipse.ui.session.ISessionMonitor;
import com.windowtester.recorder.ui.IEventSequenceModel;
import com.windowtester.runtime.IAdaptable;
import com.windowtester.ui.core.model.IEventGroup;
import com.windowtester.ui.core.model.IEventSequence;
import com.windowtester.ui.core.model.ISemanticEvent;
import com.windowtester.ui.internal.corel.model.Event;
import com.windowtester.ui.internal.corel.model.EventSequenceContentProvider;
/**
* A tree viewer for displaying sequences of semantic events.
*/
public class EventSequenceTreeViewer {
private class EventSequenceTreeCellModifier implements ICellModifier {
private boolean _enabled;
public void setEnabled(boolean enabled) {
_enabled = enabled;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object,
* java.lang.String)
*/
public boolean canModify(Object element, String property) {
return _enabled;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object,
* java.lang.String)
*/
public Object getValue(Object element, String property) {
return ((IEventGroup)element).getName();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ICellModifier#modify(java.lang.Object,
* java.lang.String, java.lang.Object)
*/
public void modify(Object element, String property, Object value) {
TreeItem item = (TreeItem) element;
((IEventGroup) item.getData()).setName((String)value);
getTreeViewer().update(item.getData(), null);
}
}
private static final int DEFAULT_STYLE_BITS = SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL;
private TreeViewer treeViewer;
private EventSequenceContentProvider contentProvider;
private IEventSequenceModel sequenceModel;
private final int treeStyleBits;
private com.windowtester.eclipse.ui.viewers.EventSequenceTreeViewer.EventSequenceTreeCellModifier cellModifier;
public EventSequenceTreeViewer(ISessionMonitor sessionMonitor, Composite parent, IEventSequenceModel sequenceModel, int treeStyleBits) {
this.treeStyleBits = treeStyleBits;
initializeContentProvider(sessionMonitor, sequenceModel);
initializeTree(parent);
}
public EventSequenceTreeViewer(ISessionMonitor sessionMonitor, Composite parent, IEventSequenceModel sequenceModel) {
this(sessionMonitor, parent, sequenceModel, DEFAULT_STYLE_BITS);
}
public EventSequenceTreeViewer(Composite parent, IEventSequenceModel sequenceModel) {
this(UiPlugin.getDefault().getSessionMonitor(), parent, sequenceModel);
}
private void initializeContentProvider(ISessionMonitor sessionMonitor, IEventSequenceModel sequenceModel) {
this.sequenceModel = sequenceModel;
this.contentProvider = new EventSequenceContentProvider(sessionMonitor, sequenceModel);
}
private void initializeTree(Composite parent) {
Tree tree = new Tree(parent, getTreeStyle());
treeViewer = new TreeViewer(tree);
treeViewer.setContentProvider(getContentProvider());
treeViewer.setLabelProvider(getLabelProvider());
treeViewer.setInput(getInitalInput());
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
getSequenceModel().select(getEvents(event));
}
});
EventSequenceDNDSupport.addTo(this);
setUpCellEditors(treeViewer);
}
private void setUpCellEditors(TreeViewer treeViewer) {
cellModifier = new EventSequenceTreeCellModifier();
treeViewer.setCellModifier(cellModifier);
treeViewer.setColumnProperties(new String[] { "column" });
treeViewer.setCellEditors(new CellEditor[] { new TextCellEditor(treeViewer.getTree()) });
}
private int getTreeStyle() {
return treeStyleBits;
}
protected ISemanticEvent[] getEvents(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
return adapt(selection.toArray());
}
private ISemanticEvent[] adapt(Object[] elems) {
ISemanticEvent[] events = new ISemanticEvent[elems.length];
for (int i = 0; i < elems.length; i++) {
events[i] = adaptToSemanticEvent(elems[i]);
}
return events;
}
private ISemanticEvent adaptToSemanticEvent(Object object) {
if (object instanceof ISemanticEvent)
return (ISemanticEvent)object;
if (object instanceof IAdaptable) {
IAdaptable adapted = (IAdaptable)object;
return (ISemanticEvent) adapted.getAdapter(ISemanticEvent.class);
}
return null; //shouldn't get here!
}
protected final IEventSequenceModel getSequenceModel() {
return sequenceModel;
}
public final ISemanticEvent[] getSelection() {
return getSequenceModel().getSelection();
}
private ILabelProvider getLabelProvider() {
return getContentProvider();
}
private Object getInitalInput() {
return getContentProvider().getCachedSequence();
}
private EventSequenceContentProvider getContentProvider() {
return contentProvider;
}
public final TreeViewer getTreeViewer() {
return treeViewer;
}
public IEventSequence getSequence() {
return getContentProvider().getCachedSequence();
}
// private boolean _updating;
public void refresh() {
Display.getDefault().asyncExec(new Runnable() {
public void run() {
// if (_updating) //avoid infinite regress!
// return;
// _updating = true;
// updateSelection();
getTreeViewer().refresh();
updateSelection();
// _updating = false;
}
});
}
public void setExpandedState(IEventGroup group, boolean b) {
getTreeViewer().setExpandedState(group, true);
}
public void setGroupedState(IEventGroup group) {
refresh();
setExpandedState(group, true);
getCellModifier().setEnabled(true);
getTreeViewer().editElement(group, 0);
getCellModifier().setEnabled(false);
}
private EventSequenceTreeCellModifier getCellModifier() {
return cellModifier;
}
public void updateSelection() {
ISemanticEvent[] modelSelection = getSelection();
List<TreeItem> toSelect = new ArrayList<TreeItem>();
Tree tree = getTreeViewer().getTree();
TreeItem[] items = tree.getItems();
if (items.length == 0)
return;
for (int i=0; i < items.length; ++i) {
TreeItem item = items[i];
Event event = (Event) item.getData();
for (int j = 0; j < modelSelection.length; j++) {
if (modelSelection[j] == event)
toSelect.add(item);
}
}
if (toSelect.isEmpty())
return;
tree.setSelection(toSelect.toArray(new TreeItem[]{}));
}
}