package org.simantics.document.linking.views; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.CCombo; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Sash; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.TabItem; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IPartListener; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.part.ViewPart; import org.simantics.Simantics; import org.simantics.browsing.ui.GraphExplorer; import org.simantics.browsing.ui.swt.SingleSelectionInputSource; import org.simantics.browsing.ui.swt.widgets.GraphExplorerComposite; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport; import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.request.ResourceRead; import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.AdaptionException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.request.Read; import org.simantics.document.DocumentResource; import org.simantics.document.linking.Activator; import org.simantics.document.linking.adapters.SourceObjectAdapter; import org.simantics.document.linking.ge.Constants; import org.simantics.document.linking.ge.MultiSelectionProvider; import org.simantics.document.linking.ge.SourceLinkExplorerComposite; import org.simantics.document.linking.ontology.DocumentLink; import org.simantics.ui.SimanticsUI; import org.simantics.utils.datastructures.ArrayMap; import org.simantics.utils.ui.AdaptionUtils; public class SourceView extends ViewPart implements ISelectionListener, IPartListener{ public enum AcceptedObject{ALL,DOCUMENT}; /** * The ID of the view as specified by the extension. */ public static final String ID = "org.simantics.document.linking.views.SourceView"; //$NON-NLS-1$ private Composite composite; private Action pinSelectionAction; private Action linkAllAction; private Action linkDocumentsAction; private WidgetSupport support; private GraphExplorerComposite objectExplorer; private GraphExplorerComposite propertyExplorer; private MultiSelectionProvider selectionProvider; private GraphExplorerComposite browseExplorer; private TabFolder tabFolder; Composite linkComposite; Composite browseComposite; private boolean pinSelection = false; Resource currentModel; private ModelToComboListener modelToComboListener; private CCombo modelCombo; private AcceptedObject acceptedObject = AcceptedObject.DOCUMENT; /** * The constructor. */ public SourceView() { support = new WidgetSupportImpl(); } /** * This is a callback that will allow us * to create the viewer and initialize it. */ public void createPartControl(Composite parent) { parent.setLayout(new FillLayout()); composite = new Composite(parent, SWT.NONE); composite.setLayout(new FillLayout()); tabFolder = new TabFolder(composite, SWT.NONE); TabItem link = new TabItem(tabFolder, SWT.NONE); link.setText(Messages.SourceView_Linking); TabItem browse = new TabItem(tabFolder, SWT.NONE); browse.setText(Messages.SourceView_Browsing); linkComposite = new Composite(tabFolder, SWT.NONE); link.setControl(linkComposite); browseComposite = new Composite(tabFolder, SWT.NONE); browse.setControl(browseComposite); selectionProvider = new MultiSelectionProvider(); createLinkTab(linkComposite); createBrowseTab(browseComposite); getSite().getPage().addPostSelectionListener(this); getSite().getPage().addPartListener(this); makeActions(); contributeToActionBars(); getSite().setSelectionProvider(selectionProvider); } @Override public void dispose() { getSite().getPage().removePostSelectionListener(this); getSite().getPage().removePartListener(this); } private void createBrowseTab(final Composite browseComposite) { browseComposite.setLayout(new GridLayout(2,false)); modelCombo = new CCombo(browseComposite, SWT.BORDER|SWT.READ_ONLY); final WidgetSupport support = new WidgetSupportImpl(); Simantics.getSession().asyncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { Resource project = Simantics.getProject().get(); modelToComboListener = new ModelToComboListener(modelCombo) { @Override public Resource getCurrentModel() { return currentModel; } }; graph.syncRequest(new ModelRead(project),modelToComboListener); } }); Button checkingButton = new Button(browseComposite, SWT.TOGGLE); checkingButton.setText(Messages.SourceView_All); checkingButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { Button button = ((Button)e.widget); boolean checked = button.getSelection(); browseExplorer.dispose(); createModelExplorer(checked,support,browseComposite); button.setText(checked ? Messages.SourceView_OldRemoved : Messages.SourceView_All); if (currentModel != null) setModel(currentModel, true); browseComposite.getParent().layout(true, true); } }); createModelExplorer(false,support,browseComposite); modelCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { int index = modelCombo.getSelectionIndex(); if (index == -1) return; Resource model = (Resource)modelCombo.getData(Integer.toString(index)); if (model != null) setModel(model); } }); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).applyTo(modelCombo); } private void createModelExplorer(boolean onlyCheckable,WidgetSupport support,Composite browseComposite) { browseExplorer = new SourceLinkExplorerComposite(ArrayMap.keys("displaySelectors", "displayFilter","treeView").values(false, false, true), selectionProvider,getSite(), browseComposite, support,false, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if(!onlyCheckable) browseExplorer.setBrowseContexts(DocumentLink.URIs.ModelViewpointBrowseContext, DocumentLink.URIs.ModelViewpointActionContext); else browseExplorer.setBrowseContexts(DocumentLink.URIs.ModelViewpointBrowseContext2, DocumentLink.URIs.ModelViewpointActionContext); browseExplorer.setColumns(Constants.SOURCE_OBJECT_COLUMNS); browseExplorer.setInputSource(new SingleSelectionInputSource(Resource.class)); browseExplorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning browseExplorer.setColumnsVisible(true); browseExplorer.setContextMenuId("#SourceModelViewPopup"); //$NON-NLS-1$ browseExplorer.finish(); ((Tree)browseExplorer.getExplorer().getControl()).setLinesVisible(true); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).span(2, 1).applyTo(browseExplorer); } private void createLinkTab(final Composite linkComposite) { objectExplorer = new SourceLinkExplorerComposite(ArrayMap.keys("displaySelectors", "displayFilter","treeView").values(false, false,true), selectionProvider,getSite(), linkComposite, support, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ objectExplorer.setBrowseContexts(DocumentLink.URIs.SourceObjectViewpointBrowseContext, DocumentLink.URIs.SourceObjectViewpointActionContext); objectExplorer.setColumns(Constants.SOURCE_OBJECT_COLUMNS); objectExplorer.setInputSource(new SingleSelectionInputSource(Resource.class)); objectExplorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning objectExplorer.setColumnsVisible(true); objectExplorer.setContextMenuId("#SourceObjectViewPopup"); //$NON-NLS-1$ objectExplorer.finish(); ((Tree)objectExplorer.getExplorer().getControl()).setLinesVisible(true); final Sash sash = new Sash (linkComposite, SWT.HORIZONTAL); propertyExplorer = new SourceLinkExplorerComposite(ArrayMap.keys("displaySelectors", "displayFilter","treeView").values(false, false,true), selectionProvider,getSite(), linkComposite, support, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ propertyExplorer.setBrowseContexts(DocumentLink.URIs.SourcePropertyViewpointBrowseContext, DocumentLink.URIs.SourcePropertyViewpointActionContext); propertyExplorer.setColumns(Constants.SOURCE_COLUMNS); propertyExplorer.setInputSource(new SingleSelectionInputSource(Resource.class)); propertyExplorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning propertyExplorer.setColumnsVisible(true); propertyExplorer.setContextMenuId("#SourcePropertyViewPopup"); //$NON-NLS-1$ propertyExplorer.finish(); ((Tree)propertyExplorer.getExplorer().getControl()).setLinesVisible(true); final FormLayout form = new FormLayout (); linkComposite.setLayout (form); FormData button1Data = new FormData (); button1Data.left = new FormAttachment (0, 0); button1Data.right = new FormAttachment (100, 0); button1Data.top = new FormAttachment (0, 0); button1Data.bottom = new FormAttachment (sash, 0); objectExplorer.setLayoutData (button1Data); final int limit = 40, percent = 20; final FormData sashData = new FormData (); sashData.left = new FormAttachment (0, 0); sashData.right = new FormAttachment (100, 0); sashData.top = new FormAttachment (percent, 0); sash.setLayoutData (sashData); sash.addListener (SWT.Selection, new Listener () { public void handleEvent (Event e) { Rectangle sashRect = sash.getBounds (); Rectangle shellRect = linkComposite.getClientArea (); int top = shellRect.height - sashRect.height - limit; e.y = Math.max (Math.min (e.y, top), limit); if (e.y != sashRect.y) { sashData.top = new FormAttachment (0, e.y); linkComposite.layout (); } } }); FormData button2Data = new FormData (); button2Data.left = new FormAttachment (0, 0); button2Data.right = new FormAttachment (100, 0); button2Data.top = new FormAttachment (sash, 0); button2Data.bottom = new FormAttachment (100, 0); propertyExplorer.setLayoutData (button2Data); } @Override public void partActivated(IWorkbenchPart part) { if (!(part instanceof IEditorPart)) selectionEventFilter = part; } @Override public void partBroughtToTop(IWorkbenchPart part) {} @Override public void partClosed(IWorkbenchPart part) {} @Override public void partDeactivated(IWorkbenchPart part) {} @Override public void partOpened(IWorkbenchPart part) {} IWorkbenchPart selectionEventFilter = null; @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (part == this) return; if (pinSelection) return; // dnd event may start from different part than the target object is selected. // activating an part sends not only partActivated event, but also selectioChanged event to match the part's selection // since that would interrupt intended dnd operation, we filter selection events send by part activation. if (part == selectionEventFilter) { selectionEventFilter = null; return; } selectionEventFilter = null; final Resource res = AdaptionUtils.adaptToSingle(selection, Resource.class); if (res == null) return; try { final Resource selected = Simantics.getSession().syncRequest(new Read() { @Override public Resource perform(ReadGraph graph) throws DatabaseException { try { SourceObjectAdapter adapter = graph.adapt(res, SourceObjectAdapter.class); return adapter.getDocumentableResource(graph, res); } catch (AdaptionException e) { return res; } } }); if (selected == null) return; if (acceptedObject == AcceptedObject.DOCUMENT) { if (Simantics.getSession().syncRequest(new IsDocumentRead(selected))) return; } ISelection realSelection = new StructuredSelection(selected); objectExplorer.setInput(Simantics.getSessionContext(), realSelection); propertyExplorer.setInput(Simantics.getSessionContext(), realSelection); Simantics.getSession().asyncRequest(new ReadRequest() { @Override public void run(ReadGraph graph) throws DatabaseException { String name = NameUtils.getSafeLabel(graph, selected); if (name.length() == 0) name = NameUtils.getSafeName(graph, selected); final String title = name; Display.getDefault().asyncExec(new Runnable() { @Override public void run() { setPartName(title); } }) ; } }); } catch (Exception e) { } } private class IsDocumentRead extends ResourceRead { public IsDocumentRead(Resource resource) { super(resource); } @Override public Boolean perform(ReadGraph graph) throws DatabaseException { DocumentResource doc = DocumentResource.getInstance(graph); return graph.isInstanceOf(resource, doc.Document); } } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); fillLocalToolBar(bars.getToolBarManager()); } private void fillLocalPullDown(IMenuManager manager) { manager.add(linkAllAction); manager.add(linkDocumentsAction); } private void fillLocalToolBar(IToolBarManager manager) { manager.add(pinSelectionAction); } private void makeActions() { pinSelectionAction = new Action(Messages.SourceView_PinSelection, Action.AS_CHECK_BOX) { public void run() { pinSelection = isChecked(); } }; // action1.setToolTipText("Action 1 tooltip"); pinSelectionAction.setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/lock.png")); //$NON-NLS-1$ //$NON-NLS-2$ linkAllAction = new Action(Messages.SourceView_LinkAll, Action.AS_RADIO_BUTTON) { @Override public void run() { setAcceptedObject(AcceptedObject.ALL); } }; linkDocumentsAction = new Action(Messages.SourceView_LinkDocuments, Action.AS_RADIO_BUTTON) { @Override public void run() { setAcceptedObject(AcceptedObject.DOCUMENT); } }; setAcceptedObject(AcceptedObject.DOCUMENT); } public void setAcceptedObject(AcceptedObject acceptedObject) { this.acceptedObject = acceptedObject; if (acceptedObject == AcceptedObject.ALL) { linkAllAction.setChecked(true); linkDocumentsAction.setChecked(false); } else { linkAllAction.setChecked(false); linkDocumentsAction.setChecked(true); } } /** * Passing the focus request to the viewer's control. */ public void setFocus() { composite.setFocus(); } public void setModel(Resource model) { setModel(model, false); } public void setModel(Resource model, boolean force) { if (!force && model.equals(currentModel)) return; currentModel = model; for (int i = 0; i < modelCombo.getItemCount(); i++) { Resource r = (Resource)modelCombo.getData(Integer.toString(i)); if (model.equals(r)) { modelCombo.select(i); ISelection realSelection = new StructuredSelection(currentModel); browseExplorer.setInput(Simantics.getSessionContext(), realSelection); return; } } modelCombo.select(-1); ISelection realSelection = new StructuredSelection(); browseExplorer.setInput(Simantics.getSessionContext(), realSelection); } @SuppressWarnings("rawtypes") @Override public Object getAdapter(Class adapter) { if (adapter == GraphExplorer.class) { return browseExplorer.getExplorer(); } return super.getAdapter(adapter); } }