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