+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.team.ui;\r
+\r
+import java.util.Map;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.resource.LocalResourceManager;\r
+import org.eclipse.jface.viewers.TreeViewer;\r
+import org.eclipse.jface.viewers.ViewerCell;\r
+import org.eclipse.jface.viewers.ViewerFilter;\r
+import org.eclipse.jface.window.ToolTip;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Control;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.swt.widgets.Tree;\r
+import org.eclipse.ui.IMemento;\r
+import org.eclipse.ui.IViewSite;\r
+import org.eclipse.ui.PartInitException;\r
+import org.eclipse.ui.part.ViewPart;\r
+import org.simantics.browsing.ui.swt.ViewArgumentUtils;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.management.ISessionContextChangedListener;\r
+import org.simantics.db.management.ISessionContextProvider;\r
+import org.simantics.db.management.SessionContextChangedEvent;\r
+import org.simantics.utils.datastructures.disposable.DisposeState;\r
+\r
+/**\r
+ * @author Kalle Kondelin\r
+ */\r
+abstract class TreeView extends ViewPart {\r
+ protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {\r
+ @Override\r
+ public void sessionContextChanged(SessionContextChangedEvent event) {\r
+ sessionContext = event.getNewValue();\r
+ }\r
+ };\r
+ protected LocalResourceManager resourceManager;\r
+ protected Composite parent;\r
+ protected TreeViewer treeViewer;\r
+ protected IMemento memento;\r
+ private Map<String, String> args;\r
+ private ISessionContextProvider contextProvider;\r
+ private ISessionContext sessionContext;\r
+ private DisposeState disposeState = DisposeState.Alive;\r
+\r
+ public TreeView() {\r
+ }\r
+\r
+ \r
+\r
+ protected Map<String, String> getViewArguments() {\r
+ return args;\r
+ }\r
+\r
+ protected DisposeState getDisposeState() {\r
+ return disposeState;\r
+ }\r
+\r
+ public ISessionContext getSessionContext() {\r
+ return sessionContext;\r
+ }\r
+\r
+ public ISessionContextProvider getSessionContextProvider() {\r
+ return contextProvider;\r
+ }\r
+\r
+\r
+ /**\r
+ * Invoked when this viewpart is disposed. Unhooks the view from its\r
+ * ISessionContextProvider. Overriding is allowed but super.dispose() must\r
+ * be called.\r
+ * \r
+ * @see org.eclipse.ui.part.WorkbenchPart#dispose()\r
+ */\r
+ @Override\r
+ public void dispose() {\r
+ disposeState = DisposeState.Disposing;\r
+ try {\r
+ if (contextProvider != null) {\r
+ contextProvider.removeContextChangedListener(contextChangeListener);\r
+ contextProvider = null;\r
+ }\r
+ resourceManager.dispose();\r
+ resourceManager = null;\r
+ args = null;\r
+ sessionContext = null;\r
+ parent = null;\r
+ super.dispose();\r
+ } finally {\r
+ disposeState = DisposeState.Disposed;\r
+ }\r
+ }\r
+\r
+ @Override\r
+ public void setFocus() {\r
+ treeViewer.getTree().setFocus();\r
+ }\r
+\r
+ @Override\r
+ public void init(IViewSite site) throws PartInitException {\r
+ super.init(site);\r
+ this.args = ViewArgumentUtils.parseViewArguments(this);\r
+ }\r
+\r
+ @Override\r
+ public void init(IViewSite site, IMemento memento) throws PartInitException {\r
+ super.init(site, memento);\r
+ this.args = ViewArgumentUtils.parseViewArguments(this);\r
+ this.memento = memento;\r
+ }\r
+\r
+ @Override\r
+ public void saveState(IMemento memento) {\r
+ if (this.memento != null) {\r
+ memento.putMemento(this.memento);\r
+ }\r
+// if (explorer != null)\r
+// explorer.saveState(memento);\r
+ }\r
+ \r
+ protected static abstract class NameAndDescriptionToolTip extends ToolTip {\r
+ public NameAndDescriptionToolTip(Control control, int style) {\r
+ super(control, style, false);\r
+ }\r
+\r
+ protected abstract Object getModelElement(Event event);\r
+\r
+ /**\r
+ * Adds logic to only show a tooltip if a meaningful item is under the\r
+ * cursor.\r
+ */\r
+ protected boolean shouldCreateToolTip(Event event) {\r
+ if (!super.shouldCreateToolTip(event))\r
+ return false;\r
+ Object tableElement = getModelElement(event); \r
+ return tableElement != null && tableElement instanceof DisplayElement;\r
+ }\r
+\r
+ protected Composite createToolTipContentArea(Event event,\r
+ Composite parent) {\r
+ Object modelElement = getModelElement(event);\r
+\r
+ Image iconImage = null;\r
+ String nameString = "no name";\r
+\r
+ if (modelElement instanceof DisplayElement) {\r
+ iconImage = null;\r
+ nameString = ((DisplayElement)modelElement).getIdText();\r
+ }\r
+\r
+ // Create the content area\r
+ Composite composite = new Composite(parent, SWT.NONE);\r
+ composite.setBackground(parent.getDisplay().getSystemColor(\r
+ SWT.COLOR_INFO_BACKGROUND));\r
+ composite.setLayout(new GridLayout(2, false));\r
+\r
+ // The title area with the icon (if there is one) and label.\r
+ Label title = createEntry(composite, iconImage, nameString);\r
+// title.setFont(tooltipHeading);\r
+ GridDataFactory.createFrom((GridData)title.getLayoutData())\r
+ .hint(SWT.DEFAULT, SWT.DEFAULT)\r
+// .minSize(MIN_TOOLTIP_WIDTH, 1)\r
+ .applyTo(title);\r
+\r
+ // The description (if there is one)\r
+// String descriptionString = "description";\r
+// if (descriptionString != null)\r
+// createEntry(composite, null, descriptionString);\r
+\r
+ // Other Content to add\r
+ addContent(composite, modelElement);\r
+\r
+ return composite;\r
+ }\r
+\r
+ /**\r
+ * Adds a line of information to <code>parent</code>. If\r
+ * <code>icon</code> is not <code>null</code>, an icon is placed on the\r
+ * left, and then a label with <code>text</code>.\r
+ * \r
+ * @param parent\r
+ * the composite to add the entry to\r
+ * @param icon\r
+ * the icon to place next to the text. <code>null</code> for\r
+ * none.\r
+ * @param text\r
+ * the text to display\r
+ * @return the created label\r
+ */\r
+ protected Label createEntry(Composite parent, Image icon, String text) {\r
+ if (icon != null) {\r
+ Label iconLabel = new Label(parent, SWT.NONE);\r
+ iconLabel.setImage(icon);\r
+ iconLabel.setBackground(parent.getDisplay().getSystemColor(\r
+ SWT.COLOR_INFO_BACKGROUND));\r
+ iconLabel.setData(new GridData());\r
+ }\r
+\r
+ Label textLabel = new Label(parent, SWT.WRAP);\r
+ \r
+ if(icon == null) {\r
+ GridDataFactory.generate(textLabel, 2, 1);\r
+ } else {\r
+ GridDataFactory.generate(textLabel, 1, 1);\r
+ }\r
+ \r
+ textLabel.setText(text);\r
+ textLabel.setBackground(parent.getDisplay().getSystemColor(\r
+ SWT.COLOR_INFO_BACKGROUND));\r
+ return textLabel;\r
+ }\r
+\r
+ /**\r
+ * Adds a line of information to <code>parent</code>. If\r
+ * <code>icon</code> is not <code>null</code>, an icon is placed on the\r
+ * left, and then a label with <code>text</code>, which supports using\r
+ * anchor tags to creates links\r
+ * \r
+ * @param parent\r
+ * the composite to add the entry to\r
+ * @param icon\r
+ * the icon to place next to the text. <code>null</code> for\r
+ * none.\r
+ * @param text\r
+ * the text to display\r
+ * @return the created link\r
+ */\r
+ protected Text createEntryWithText(Composite parent, Image icon, String text) {\r
+ if (icon != null) {\r
+ Label iconLabel = new Label(parent, SWT.NONE);\r
+ iconLabel.setImage(icon);\r
+ iconLabel.setBackground(parent.getDisplay().getSystemColor(\r
+ SWT.COLOR_INFO_BACKGROUND));\r
+ iconLabel.setData(new GridData());\r
+ }\r
+ Text texts = new Text(parent, SWT.READ_ONLY | SWT.MULTI | SWT.V_SCROLL);\r
+ if(icon == null) {\r
+ GridDataFactory.generate(texts, 2, 1);\r
+ }\r
+ texts.setText(text);\r
+ texts.setBackground(parent.getDisplay().getSystemColor(\r
+ SWT.COLOR_INFO_BACKGROUND));\r
+ return texts;\r
+ }\r
+\r
+ protected void addContent(Composite destination, Object modelElement) {\r
+ }\r
+ }\r
+\r
+ protected static class ItemDetailToolTip extends NameAndDescriptionToolTip {\r
+// private final boolean DEBUG = false;\r
+ private TreeViewer viewer;\r
+ private Tree tree;\r
+ ItemDetailToolTip(TreeViewer viewer, Tree tree, ViewerFilter filter) {\r
+ super(tree,NO_RECREATE);\r
+ this.tree = tree;\r
+ this.viewer = viewer;\r
+ this.setHideOnMouseDown(false);\r
+ }\r
+ public Point getLocation(Point tipSize, Event event) {\r
+ // try to position the tooltip at the bottom of the cell\r
+ ViewerCell cell = viewer.getCell(new Point(event.x, event.y));\r
+ if( cell != null )\r
+ return tree.toDisplay(event.x,cell.getBounds().y+cell.getBounds().height);\r
+ return super.getLocation(tipSize, event);\r
+ }\r
+ protected Object getToolTipArea(Event event) {\r
+ // Ensure that the tooltip is hidden when the cell is left\r
+ return viewer.getCell(new Point(event.x, event.y));\r
+ }\r
+ protected void addContent(Composite destination, Object modelElement) {\r
+ final DisplayElement item = (DisplayElement)modelElement;\r
+ String text = null;\r
+ if (null != item) {\r
+ text = item.getValue();\r
+ createEntryWithText(destination, null, text.toString());\r
+ }\r
+ }\r
+ protected Object getModelElement(Event event) {\r
+ org.eclipse.swt.widgets.TreeItem treeItem = tree.getItem(new Point(event.x, event.y));\r
+ if (treeItem == null)\r
+ return null;\r
+ return treeItem.getData();\r
+ }\r
+ }\r
+}\r