/*******************************************************************************
* Copyright (c) 2007, 2010 Association for Decentralized Information Management
* in Industry THTH ry.
* 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:
* VTT Technical Research Centre of Finland - initial API and implementation
*******************************************************************************/
package org.simantics.browsing.ui.platform;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.osgi.framework.Bundle;
import org.simantics.browsing.ui.BuiltinKeys;
import org.simantics.browsing.ui.GraphExplorer;
import org.simantics.browsing.ui.NodeContext;
import org.simantics.browsing.ui.common.EvaluatorData;
import org.simantics.browsing.ui.common.EvaluatorDataImpl;
import org.simantics.browsing.ui.common.node.IDropTargetNode;
import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;
import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;
import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;
import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;
import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;
import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;
import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;
import org.simantics.browsing.ui.graph.impl.Evaluators;
import org.simantics.browsing.ui.graph.impl.GraphExplorerHints;
import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;
import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;
import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
import org.simantics.browsing.ui.swt.ComparatorSelector;
import org.simantics.browsing.ui.swt.FilterArea;
import org.simantics.browsing.ui.swt.GraphExplorerViewBase;
import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;
import org.simantics.browsing.ui.swt.TypesQueryProcessor;
import org.simantics.browsing.ui.swt.ViewpointSelector;
import org.simantics.db.AsyncReadGraph;
import org.simantics.db.ReadGraph;
import org.simantics.db.Session;
import org.simantics.db.management.ISessionContext;
import org.simantics.selectionview.StandardPropertyPage;
import org.simantics.ui.dnd.LocalObjectTransfer;
import org.simantics.ui.dnd.LocalSelectionDragSourceListener;
import org.simantics.ui.dnd.NoImageDragSourceEffect;
import org.simantics.ui.workbench.IPropertyPage;
import org.simantics.utils.datastructures.hints.HintContext;
import org.simantics.utils.datastructures.hints.IHintContext;
import org.simantics.utils.ui.ErrorLogger;
import org.simantics.utils.ui.LayoutUtils;
/**
* Override:
*
* - {@link #createAuxiliaryControls(Composite, Control)} to customize the
* creation of auxiliary controls around the graph explorer control, such as
* comparator/viewpoint selectors and filter area.
* - {@link #getUiContexts()} to specify which
*
org.eclipse.ui.context
extension point contexts should be
* activated for this view site. May be empty.
* - {@link #getBrowseContexts()} to specify how the view
* content/label/decoration production should be configured. May be empty, in
* which case the browser will show nothing.
* - {@link #getContextMenuId()} to specify the ID of the context menu to be
* create for this view part and registered with the workbench. May be
*
null
, in which case a context menu will not be created nor
* registered with the workbench.
*
*
* @author Tuukka Lehtonen
* @deprecated in favor of org.simantics.views.swt.ModelledView
*
**/
public class GraphExplorerView extends GraphExplorerViewBase {
protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
protected UserSelectedViewpointFactoryQueryProcessor userSelectedViewpointFactoryQueryProcessor;
protected FilterSelectionRequestQueryProcessor filterSelectionRequestQueryProcessor;
protected FilterArea filterArea;
protected IHintContext factoryHints = new HintContext();
protected EvaluatorData evaluatorData;
protected Set browseContexts = Collections.emptySet();
protected String contextMenuId;
protected Set uiContexts = Collections.emptySet();
protected String propertyPageContributor;
protected String propertyPageClassName;
protected Set propertyBrowseContexts = Collections.emptySet();
protected boolean hideComparatorSelector = false;
protected boolean hideViewpointSelector = false;
protected boolean hideFilter = false;
@Override
public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) {
super.setInitializationData(cfig, propertyName, data);
if (data instanceof String) {
Set browseContexts = new HashSet();
Set uiContexts = new HashSet();
Set propertyBrowseContexts = new HashSet();
String[] parameters = ((String) data).split(";");
IContextService service = (IContextService) PlatformUI.getWorkbench().getService(IContextService.class);
Set definedContexts = new HashSet();
for (Object cid : service.getDefinedContextIds())
definedContexts.add((String) cid);
for (String parameter : parameters) {
String[] keyValue = parameter.split("=");
if (keyValue.length > 2) {
ErrorLogger.defaultLogWarning("Invalid parameter '" + parameter + ". Complete view argument: " + data, null);
continue;
}
String key = keyValue[0];
String value = keyValue.length > 1 ? keyValue[1] : "";
if ("browseContext".equals(key)) {
browseContexts.add(value);
} else if ("contextMenuId".equals(key)) {
this.contextMenuId = value;
} else if ("uiContext".equals(key)) {
if (!definedContexts.contains(value)) {
ErrorLogger.defaultLogWarning("Parameter '" + parameter + "' references a non-existent Eclipse UI context '" + value + "'. Complete view argument: " + data, null);
continue;
}
uiContexts.add(value);
} else if ("propertyBrowseContext".equals(key)) {
propertyBrowseContexts.add(value);
} else if ("propertyPageClass".equals(key)) {
this.propertyPageContributor = cfig.getContributor().getName();
this.propertyPageClassName = value;
} else if ("hideComparatorSelector".equals(key)) {
this.hideComparatorSelector = true;
} else if ("hideViewpointSelector".equals(key)) {
this.hideViewpointSelector = true;
} else if ("hideFilter".equals(key)) {
this.hideFilter = true;
}
}
this.browseContexts = browseContexts;
this.uiContexts = uiContexts;
this.propertyBrowseContexts = propertyBrowseContexts;
}
}
public GraphExplorer getExplorer() {
return explorer;
}
public T getBrowseContext() {
return evaluatorData.getBrowseContext();
}
/**
* Override this to specify which browse contexts are considered active for
* this browser. This information is read only once during view
* initialization, no change listening is implemented.
*
* @return
*/
protected Set getBrowseContexts() {
return browseContexts;
}
/* (non-Javadoc)
* @see org.simantics.browsing.ui.swt.GraphExplorerViewBase#getContextMenuId()
*/
@Override
protected String getContextMenuId() {
return contextMenuId;
}
/**
* @return the set of org.eclipse.ui.context
contexts to
* activate for this view site
*/
protected Set getUiContexts() {
return uiContexts;
}
@Override
protected IPropertyPage getPropertyPage() {
if (propertyPageContributor != null && propertyPageClassName != null) {
try {
Bundle b = Platform.getBundle(propertyPageContributor);
if (b == null) {
ErrorLogger.defaultLogError("property page '" + propertyPageClassName + "' contributor bundle '"
+ propertyPageContributor + "' was not found in the platform.", null);
return null;
}
Class> clazz = b.loadClass(propertyPageClassName);
if (!IPropertyPage.class.isAssignableFrom(clazz)) {
ErrorLogger.defaultLogError("property page class '" + propertyPageClassName + "' is not assignable to "
+ IPropertyPage.class + ".", null);
return null;
}
Constructor> ctor = clazz.getConstructor(IWorkbenchPartSite.class);
return (IPropertyPage) ctor.newInstance(getSite());
} catch (Exception e) {
ErrorLogger.defaultLogError("Failed to instantiate IPropertyPage implementation '" + propertyPageClassName
+ "' from bundle '" + propertyPageContributor + "'. See exception for details.", e);
// Something failed, don't try to instantiate the property page anymore.
propertyPageClassName = null;
}
} else if (!propertyBrowseContexts.isEmpty()) {
return new StandardPropertyPage(getSite(), new HashSet(propertyBrowseContexts));
}
return null;
}
@Override
protected void createControls(Composite parent) {
super.createControls(parent);
Control control = explorer.getControl();
userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();
userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();
filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();
createAuxiliaryControls(parent, control);
setupDropTarget(control);
setWorkbenchListeners();
activateUiContexts();
}
protected void createAuxiliaryControls(Composite parent, Control explorerControl) {
if (explorerControl instanceof Tree)
parent.setLayout(LayoutUtils.createNoBorderGridLayout(3, false));
if (!hideComparatorSelector) {
ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, parent, SWT.READ_ONLY);
comparatorSelector.moveAbove(explorerControl);
}
if (!hideViewpointSelector) {
ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, parent, SWT.READ_ONLY);
viewpointSelector.moveAbove(explorerControl);
}
if (!hideFilter) {
filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, parent, SWT.READ_ONLY);
filterArea.moveAbove(explorerControl);
}
GridDataFactory.fillDefaults().grab(true, true).span(3,1).applyTo(explorerControl);
}
protected void setupDropTarget(Control control) {
DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_LINK);
target.setTransfer(getAcceptedDataTypes());
target.addDropListener(new DropTargetAdapter() {
Tree tree = (Tree) explorer.getControl();
@Override
public void dragEnter(DropTargetEvent event) {
event.detail = DND.DROP_COPY;
}
@Override
public void drop(DropTargetEvent event) {
TreeItem item = tree.getItem(tree.toControl(event.x, event.y));
if (item != null)
handleDrop(event.data, (NodeContext) item.getData());
else
handleDrop(event.data, null);
}
});
}
protected void activateUiContexts() {
Collection contexts = getUiContexts();
if (!contexts.isEmpty()) {
IContextService cs = (IContextService) getSite().getService(IContextService.class);
for (String context : contexts)
cs.activateContext(context);
}
}
@SuppressWarnings("rawtypes")
@Override
public Object getAdapter(Class adapter) {
if (adapter == IFilterAreaProvider.class)
return filterArea;
return super.getAdapter(adapter);
}
@Override
public void dispose() {
//System.out.println(this + ".GraphExplorerViewBase2.dispose()");
removeWorkbenchListeners();
userSelectedComparableFactoryQueryProcessor = null;
userSelectedViewpointFactoryQueryProcessor = null;
filterSelectionRequestQueryProcessor = null;
super.dispose();
}
@Override
protected final void initializeExplorer(GraphExplorer explorer, ISessionContext context) {
if (explorer.isDisposed())
return;
super.initializeExplorer(explorer, context);
Session session = context != null ? context.getSession() : null;
if (session != null) {
evaluatorData = createEvaluatorData(session);
factoryHints.setHint(GraphExplorerHints.KEY_SESSION_CONTEXT, context);
explorer.setDataSource(new AsyncReadGraphDataSource(session));
explorer.setDataSource(new ReadGraphDataSource(session));
}
else {
evaluatorData = new EvaluatorDataImpl();
explorer.removeDataSource(AsyncReadGraph.class);
explorer.removeDataSource(ReadGraph.class);
factoryHints.removeHint(GraphExplorerHints.KEY_SESSION_CONTEXT);
}
explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));
explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));
explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));
explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));
explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));
explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));
explorer.setPrimitiveProcessor(new TypesQueryProcessor());
explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());
explorer.setPrimitiveProcessor(new InheritsQueryProcessor());
explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());
if(!hideViewpointSelector) {
explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);
explorer.setProcessor(new ComparableSelectorQueryProcessor());
}
if(!hideComparatorSelector) {
explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);
}
explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
initializeExplorerWithEvaluator(explorer, context, evaluatorData);
}
protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {
}
protected EvaluatorData createEvaluatorData(Session session) {
return Evaluators.load(session, getBrowseContexts(), resourceManager);
}
protected Transfer[] getAcceptedDataTypes() {
return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.getInstance() };
}
protected void handleDrop(Object data, NodeContext target) {
if (target != null) {
Object input = target.getConstant(BuiltinKeys.INPUT);
//System.out.println("DROPPED " + data + " ON " + target);
if (input instanceof IDropTargetNode)
((IDropTargetNode) input).drop(data);
}
}
@Override
protected Object createDragSource(GraphExplorer explorer) {
ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
DragSourceListener listener = new LocalSelectionDragSourceListener(selectionProvider);
Control control = explorer.getControl();
DragSource source = new DragSource(control, DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);
source.setTransfer(new Transfer[] {LocalObjectTransfer.getTransfer()});
source.addDragListener(listener);
source.setDragSourceEffect(new NoImageDragSourceEffect(control));
return listener;
}
public EvaluatorData getEvaluatorData() {
return evaluatorData;
}
}