--- /dev/null
+package org.simantics.document.ui.contribution;\r
+\r
+import java.util.Collection;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.dnd.DND;\r
+import org.eclipse.swt.dnd.DropTarget;\r
+import org.eclipse.swt.dnd.DropTargetAdapter;\r
+import org.eclipse.swt.dnd.DropTargetEvent;\r
+import org.eclipse.swt.dnd.TextTransfer;\r
+import org.eclipse.swt.dnd.Transfer;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.IWorkbenchSite;\r
+import org.simantics.Simantics;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyFactory;\r
+import org.simantics.browsing.ui.swt.widgets.StringPropertyModifier;\r
+import org.simantics.browsing.ui.swt.widgets.TrackedText;\r
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
+import org.simantics.db.AsyncReadGraph;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.NamedResource;\r
+import org.simantics.db.common.ResourceArray;\r
+import org.simantics.db.common.procedure.adapter.AsyncListenerAdapter;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.management.ISessionContext;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.db.service.SerialisationSupport;\r
+import org.simantics.document.DocumentResource;\r
+import org.simantics.document.ui.graphfile.DocumentVersionUtils;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.selectionview.AbstractResourceTabContribution;\r
+import org.simantics.selectionview.ComparableTabContributor;\r
+import org.simantics.selectionview.PropertyTabContributorImpl;\r
+import org.simantics.ui.dnd.LocalObjectTransfer;\r
+import org.simantics.ui.dnd.ResourceReferenceTransfer;\r
+import org.simantics.ui.dnd.ResourceTransferUtils;\r
+import org.simantics.ui.utils.ResourceAdaptionUtils;\r
+import org.simantics.ui.workbench.editor.EditorAdapter;\r
+import org.simantics.ui.workbench.editor.EditorRegistry;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+import org.simantics.utils.ui.ExceptionUtils;\r
+\r
+/**\r
+ * PropertyTab for documents.\r
+ * \r
+ * \r
+ * @author Marko Luukkainen <marko.luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class DocumentTabContribution extends AbstractResourceTabContribution{\r
+ \r
+ \r
+ public DocumentTabContribution(ReadGraph graph, Resource r) throws DatabaseException{\r
+ super(graph,r);\r
+ }\r
+ \r
+ @Override\r
+ public void getContributors(ReadGraph graph, Resource resource,\r
+ Integer priority, String label,\r
+ Collection<ComparableTabContributor> result)\r
+ throws DatabaseException {\r
+ DocumentResource doc = DocumentResource.getInstance(graph);\r
+ if (!graph.isInstanceOf(resource, doc.Document))\r
+ return;\r
+ result.add(new ComparableTabContributor(new DocumentPropertyTabContributor(), 1, resource, "Document"));\r
+ }\r
+ \r
+ private class DocumentPropertyTabContributor extends PropertyTabContributorImpl {\r
+ \r
+ @Override\r
+ public void createControls(Composite body, IWorkbenchSite site, ISessionContext context, final WidgetSupport support) {\r
+ \r
+ Composite composite = new Composite(body, SWT.NONE);\r
+ GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);\r
+ GridLayoutFactory.fillDefaults().margins(3,3).spacing(1, 1).numColumns(4).applyTo(composite);\r
+\r
+ Label label = new Label(composite, SWT.NONE);\r
+ label.setText("Name");\r
+\r
+ TrackedText name = new TrackedText(composite, support, SWT.BORDER);\r
+ name.setTextFactory(new StringPropertyFactory(Layer0.URIs.HasName));\r
+ name.addModifyListener(new StringPropertyModifier(context, Layer0.URIs.HasName));\r
+ NameInputValidator validator = new NameInputValidator();\r
+ name.setInputValidator(validator);\r
+ support.register(validator);\r
+ \r
+ Button showButton = new Button(composite, SWT.PUSH);\r
+ showButton.setText("Show");\r
+ showButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ openResource(AdaptionUtils.adaptToSingle(support.getInput(),Resource.class));\r
+ }\r
+ });\r
+ DocumentResource doc;\r
+ try {\r
+ doc = DocumentResource.getInstance(context.getSession());\r
+ new DocumentRevisionWidget(composite, support, doc.HasOlderVersion, "Old");\r
+ new DocumentRevisionWidget(composite, support, doc.HasNewerVersion, "New");\r
+ } catch (DatabaseException e1) {\r
+ ExceptionUtils.logAndShowError("Cannot create documen version UI", e1);\r
+ }\r
+ \r
+\r
+ GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(name.getWidget());\r
+ GridDataFactory.fillDefaults().span(2, 1).applyTo(showButton);\r
+ }\r
+ \r
+ @Override\r
+ public Read<String> getPartNameReadRequest(final ISelection forSelection) {\r
+ \r
+ return new Read<String>() {\r
+ @Override\r
+ public String perform(ReadGraph graph) throws DatabaseException {\r
+ Resource res = AdaptionUtils.adaptToSingle(forSelection, Resource.class);\r
+ if (res == null)\r
+ return "N/A";\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ return graph.getPossibleRelatedValue(res, l0.HasName);\r
+ }\r
+ };\r
+ }\r
+ }\r
+ \r
+ private static void openResource(final Resource resource) {\r
+ Simantics.getSession().asyncRequest(new ReadRequest() {\r
+ \r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ openResource(graph, resource); \r
+ }\r
+ });\r
+ }\r
+ \r
+ private static void openResource(ReadGraph graph, final Resource resource) throws DatabaseException{\r
+ EditorAdapter[] adapters = EditorRegistry.getInstance().getAdaptersFor(graph, resource);\r
+ if (adapters.length == 0)\r
+ return;\r
+ EditorAdapter highPri = null;\r
+ int pri = Integer.MIN_VALUE;\r
+ for (EditorAdapter a : adapters) {\r
+ int p = a.getPriority();\r
+ if (highPri == null || p > pri) {\r
+ highPri = a;\r
+ pri = p;\r
+ } \r
+ }\r
+ final EditorAdapter adapter = highPri;\r
+ \r
+ Display.getDefault().asyncExec(new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ try {\r
+ adapter.openEditor(resource);\r
+ } catch (Exception e) {\r
+ ExceptionUtils.logAndShowError("Cannot open editor", e);\r
+ }\r
+ }\r
+ });\r
+ }\r
+ \r
+ private static class DocumentRevisionWidget implements Widget {\r
+ ISessionContext context;\r
+ \r
+ Resource document;\r
+ Resource revisionRel;\r
+ NamedResource revisionDoc;\r
+ \r
+ Button showButton;\r
+ Button removeButton;\r
+ Text text;\r
+ \r
+ public DocumentRevisionWidget(Composite parent, WidgetSupport support, Resource rel, String name) {\r
+ support.register(this);\r
+ this.revisionRel = rel;\r
+ \r
+ Label label = new Label(parent, SWT.NONE);\r
+ label.setText(name);\r
+ text = new Text(parent, SWT.SINGLE|SWT.BORDER|SWT.READ_ONLY);\r
+ showButton = new Button(parent, SWT.PUSH);\r
+ showButton.setText("Show");\r
+ showButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ if (revisionDoc != null)\r
+ openResource(revisionDoc.getResource());\r
+ }\r
+ });\r
+ removeButton = new Button(parent, SWT.PUSH);\r
+ removeButton.setText("Unset");\r
+ removeButton.addSelectionListener(new SelectionAdapter() {\r
+ @Override\r
+ public void widgetSelected(SelectionEvent e) {\r
+ if (revisionDoc == null)\r
+ return;\r
+ try {\r
+ context.getSession().syncRequest(new WriteRequest() {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ DocumentVersionUtils.unsetVersion(graph, document, revisionDoc.getResource(), revisionRel);\r
+ }\r
+ });\r
+ revisionDoc = null;\r
+ } catch (DatabaseException e1) {\r
+ ExceptionUtils.logAndShowError("Cannot remove document revision", e1);\r
+ }\r
+ updateUI();\r
+ }\r
+ });\r
+ \r
+ DropTarget dropTarget = new DropTarget(text, DND.DROP_COPY|DND.DROP_LINK);\r
+ dropTarget.setTransfer(new Transfer[] { TextTransfer.getInstance(),ResourceReferenceTransfer.getInstance(), LocalObjectTransfer.getTransfer() });\r
+ dropTarget.addDropListener(new DropTargetAdapter() {\r
+ \r
+ @Override\r
+ public void dragEnter(DropTargetEvent event) {\r
+ // drop data is null, so we cannot to validate drop.\r
+ event.detail = DND.DROP_LINK;\r
+ }\r
+ \r
+ @Override\r
+ public void drop(DropTargetEvent event) {\r
+ ResourceArray[] data = parseEventData(event);\r
+ if (data.length != 1)\r
+ return;\r
+ if (data[0].resources ==null || data[0].resources.length != 1)\r
+ return;\r
+ setRevisionDoc(data[0].resources[0]);\r
+ }\r
+ \r
+ private ResourceArray[] parseEventData(DropTargetEvent event) {\r
+ if (event.data instanceof String) {\r
+ try {\r
+ SerialisationSupport support = context.getSession().getService(SerialisationSupport.class);\r
+ return ResourceTransferUtils.readStringTransferable(support, (String) event.data).toResourceArrayArray();\r
+ } catch (IllegalArgumentException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ } catch (DatabaseException e) {\r
+ ErrorLogger.defaultLogError(e);\r
+ }\r
+ }\r
+ ResourceArray[] ret = ResourceAdaptionUtils.toResourceArrays(event.data);\r
+ if (ret.length > 0)\r
+ return ret;\r
+ return null;\r
+ }\r
+ });\r
+ \r
+ GridDataFactory.fillDefaults().grab(true, false).align(SWT.FILL, SWT.CENTER).applyTo(text);\r
+ \r
+ }\r
+ \r
+ @Override\r
+ public void setInput(ISessionContext context, Object input) {\r
+ this.context = context;\r
+ document = AdaptionUtils.adaptToSingle(input, Resource.class);\r
+ \r
+ context.getSession().asyncRequest(new Read<NamedResource>() {\r
+ @Override\r
+ public NamedResource perform(ReadGraph graph)\r
+ throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(graph);\r
+ Resource revisionDoc = graph.getPossibleObject(document, revisionRel);\r
+ if (revisionDoc == null)\r
+ return null;\r
+ return new NamedResource((String)graph.getRelatedValue(revisionDoc, l0.HasName), revisionDoc);\r
+ }\r
+ },new AsyncListenerAdapter<NamedResource>(){\r
+ @Override\r
+ public void execute(AsyncReadGraph graph,final NamedResource result) {\r
+ Display.getDefault().asyncExec(new Runnable() {\r
+ \r
+ @Override\r
+ public void run() {\r
+ revisionDoc = result;\r
+ updateUI();\r
+ }\r
+ });\r
+ }\r
+ \r
+ @Override\r
+ public void exception(AsyncReadGraph graph, Throwable t) {\r
+ ExceptionUtils.logAndShowError("Cannot show document revision", t);\r
+ }\r
+ \r
+ @Override\r
+ public boolean isDisposed() {\r
+ return showButton.isDisposed();\r
+ }\r
+ });\r
+ \r
+ \r
+ updateUI();\r
+ }\r
+ \r
+ private void updateUI() {\r
+ if (showButton.isDisposed())\r
+ return;\r
+ showButton.setEnabled(revisionDoc != null);\r
+ removeButton.setEnabled(revisionDoc != null);\r
+ if (revisionDoc != null)\r
+ text.setText(revisionDoc.getName());\r
+ else\r
+ text.setText("");\r
+ }\r
+ \r
+ private void setRevisionDoc(final Resource toSet) {\r
+ context.getSession().asyncRequest(new WriteRequest() {\r
+ \r
+ @Override\r
+ public void perform(WriteGraph graph) throws DatabaseException {\r
+ DocumentVersionUtils.setVersion(graph, document, toSet, revisionRel);\r
+ }\r
+ });\r
+ }\r
+ \r
+ }\r
+\r
+\r
+}\r