/******************************************************************************* * Copyright (c) 2007, 2012 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.swt; import java.util.Collections; import java.util.Map; import java.util.Set; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.resource.LocalResourceManager; 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.Transfer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IMemento; import org.eclipse.ui.ISelectionListener; import org.simantics.Simantics; import org.simantics.browsing.ui.BuiltinKeys; import org.simantics.browsing.ui.GraphExplorer; import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.common.ColumnKeys; import org.simantics.browsing.ui.common.node.IDropTargetNode; import org.simantics.browsing.ui.graph.impl.GraphInputSources; import org.simantics.browsing.ui.graph.impl.SessionContextInputSource; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl; import org.simantics.db.management.ISessionContext; import org.simantics.project.ProjectKeys; import org.simantics.ui.dnd.LocalObjectTransfer; import org.simantics.ui.dnd.LocalSelectionDragSourceListener; import org.simantics.ui.dnd.NoImageDragSourceEffect; import org.simantics.utils.ObjectUtils; import org.simantics.utils.datastructures.Function; import org.simantics.utils.datastructures.disposable.DisposeState; import org.simantics.utils.datastructures.hints.HintContext; import org.simantics.utils.datastructures.hints.HintListenerAdapter; import org.simantics.utils.datastructures.hints.HintTracker; import org.simantics.utils.datastructures.hints.IHintContext; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintListener; import org.simantics.utils.datastructures.hints.IHintObservable; import org.simantics.utils.datastructures.hints.IHintTracker; public abstract class SimanticsDialog extends Dialog { private final WidgetSupportImpl widgetSupport = new WidgetSupportImpl(); protected IHintContext factoryHints = new HintContext(); protected LocalResourceManager resourceManager; protected ISelectionListener workbenchSelectionListener; protected Composite parent; private Map args; // private ISessionContextProvider contextProvider; private ISessionContext sessionContext; protected IMemento memento; //private IHintTracker sessionContextTracker = new SessionContextProjectTracker(); private SessionContextInputSource inputSource = GraphInputSources.projectSource(); private DisposeState disposeState = DisposeState.Alive; private final String title; // protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() { // @Override // public void sessionContextChanged(SessionContextChangedEvent event) { // sessionContext = event.getNewValue(); // sessionContextTracker.track(sessionContext); // } // }; abstract protected void createControls(Composite body, ISessionContext context, WidgetSupport support); public SimanticsDialog(Shell shell, String title) { super(shell); this.title = title; } @Override protected void configureShell(Shell shell) { super.configureShell(shell); if (title != null) { shell.setText(title); } } protected Transfer[] getAcceptedDataTypes() { return new Transfer[] { LocalObjectTransfer.getTransfer() }; } 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); } } 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; } /** * @return the set of org.eclipse.ui.context contexts to * activate for this view site */ protected Set getUiContexts() { return Collections.emptySet(); } /** * The default hint tracker that will be active if * {@link SimanticsViewBase#setSessionContextTracker(IHintTracker) is * not called. */ public class SessionContextProjectTracker extends HintTracker { public SessionContextProjectTracker() { IHintListener activeProjectListener = new HintListenerAdapter() { @Override public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { applySessionContext(getSessionContext()); } }; addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener); } } // protected void setSessionContextTracker(IHintTracker tracker) { // this.sessionContextTracker = tracker; // } protected void setInputSource(SessionContextInputSource source) { this.inputSource = source; } protected SessionContextInputSource getInputSource() { return inputSource; } protected Map getViewArguments() { return args; } protected DisposeState getDisposeState() { return disposeState; } public ISessionContext getSessionContext() { return Simantics.getSessionContext(); } // public ISessionContextProvider getSessionContextProvider() { // return contextProvider; // } protected final void attachToSession() { // Track active ISessionContext changes //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow()); // contextProvider.addContextChangedListener(contextChangeListener); // Start tracking the current session context for input changes. // This will/must cause applySessionContext to get called. // Doing the applySessionContext initialization this way // instead of directly calling it will also make sure that // applySessionContext is only called once when first initialized, // and not twice like with the direct invocation. this.sessionContext = getSessionContext(); applySessionContext(this.sessionContext); // sessionContextTracker.track(sessionContext); } // ///////////////////////////////////////////////////////////////////////// // Override / implement these: /** * Override this method and provide a proper context menu initializer if you * want to have this base class initialize one for you. * * @return the initializer to be used by {@link #createControls(Composite)} */ protected IContextMenuInitializer getContextMenuInitializer() { String contextMenuId = getContextMenuId(); if(contextMenuId != null) { return new ContextMenuInitializer(contextMenuId); } else { return null; } } protected String getContextMenuId() { return null; } protected int getStyle() { return SWT.NONE; } /** * @param parent * @return */ protected GraphExplorer createExplorerControl(Composite parent) { return GraphExplorerFactory.getInstance() .selectionDataResolver(new DefaultSelectionDataResolver()) .create(parent, getStyle()); } /** * Override to customize the addition of listeners a newly created * GraphExplorer. * * @param explorer */ protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) { addSelectionInputListeners(explorer, menuManager); } protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) { // Consider ENTER presses to simulate mouse left button double clicks explorer.addListener(new DefaultKeyListener(Simantics.getSessionContextProvider(), explorer, new Function() { @Override public String[] execute(Object... obj) { return new String[] { getEditingColumn((NodeContext) obj[0]) }; } })); // Default double click handling explorer.addListener(new DefaultMouseListener(explorer)); } protected String getEditingColumn(NodeContext context) { return ColumnKeys.SINGLE; } // Needed for preventing unnecessary re-initialization of the explorer with the same input. private Object currentInput; protected boolean isImportantInput(Object previousInput, Object input) { return !ObjectUtils.objectEquals(previousInput, input); } /** * Invoke this to reinitialize the explorer and reset its input. The input * will be resolved from the specified ISessionContext based on the * {@link SessionContextInputSource} that is currently in use. If the input * is identical to the previous input, nothing will be done. * * @param context */ protected final boolean applySessionContext(ISessionContext context) { // If control is not alive anymore, do nothing. // System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer); if (disposeState != DisposeState.Alive) return false; this.sessionContext = context; Object input = getInputSource().get(context); // System.out.println("SimanticsView applySessionContext: " + input); if (!isImportantInput(currentInput, input)) return false; // System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")"); // initializeExplorer(explorer, context); // System.out.println(this + ": setRoot(" + input + ")"); // explorer.setRoot(input); currentInput = input; // System.out.println("SimanticsView new input: " + currentInput); widgetSupport.fireInput(context, input); // Start tracking the session context. // // If this is not the same session that is currently tracked, it will // cause IHintListeners of the sessionContextTracker to fire. // For this we need the above input equality (identity) checking. // This is here just to make sure that we are tracking the correct // session context. //sessionContextTracker.track(sessionContext); applySessionContext(context); return true; } protected Control createDialogArea(Composite parent) { // parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_GREEN)); this.parent = parent; Composite composite = (Composite)super.createDialogArea(parent); // parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_BLUE)); createControls(composite, sessionContext, widgetSupport); attachToSession(); return composite; } @Override protected Control createContents(Composite parent) { // parent.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_RED)); return super.createContents(parent); } protected Object getSelection() { return null; } }