]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.linking.ui/src/org/simantics/document/linking/views/SourceView.java
e3b1c55d3ab4f0961f02383ad6a018b2a2bde025
[simantics/platform.git] / bundles / org.simantics.document.linking.ui / src / org / simantics / document / linking / views / SourceView.java
1 package org.simantics.document.linking.views;
2
3
4 import org.eclipse.jface.action.Action;
5 import org.eclipse.jface.action.IMenuManager;
6 import org.eclipse.jface.action.IToolBarManager;
7 import org.eclipse.jface.layout.GridDataFactory;
8 import org.eclipse.jface.viewers.ISelection;
9 import org.eclipse.jface.viewers.StructuredSelection;
10 import org.eclipse.swt.SWT;
11 import org.eclipse.swt.custom.CCombo;
12 import org.eclipse.swt.events.SelectionAdapter;
13 import org.eclipse.swt.events.SelectionEvent;
14 import org.eclipse.swt.graphics.Rectangle;
15 import org.eclipse.swt.layout.FillLayout;
16 import org.eclipse.swt.layout.FormAttachment;
17 import org.eclipse.swt.layout.FormData;
18 import org.eclipse.swt.layout.FormLayout;
19 import org.eclipse.swt.layout.GridLayout;
20 import org.eclipse.swt.widgets.Button;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Display;
23 import org.eclipse.swt.widgets.Event;
24 import org.eclipse.swt.widgets.Listener;
25 import org.eclipse.swt.widgets.Sash;
26 import org.eclipse.swt.widgets.TabFolder;
27 import org.eclipse.swt.widgets.TabItem;
28 import org.eclipse.swt.widgets.Tree;
29 import org.eclipse.ui.IActionBars;
30 import org.eclipse.ui.IEditorPart;
31 import org.eclipse.ui.IPartListener;
32 import org.eclipse.ui.ISelectionListener;
33 import org.eclipse.ui.IWorkbenchPart;
34 import org.eclipse.ui.part.ViewPart;
35 import org.simantics.Simantics;
36 import org.simantics.browsing.ui.GraphExplorer;
37 import org.simantics.browsing.ui.swt.SingleSelectionInputSource;
38 import org.simantics.browsing.ui.swt.widgets.GraphExplorerComposite;
39 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
40 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;
41 import org.simantics.db.ReadGraph;
42 import org.simantics.db.Resource;
43 import org.simantics.db.common.request.ReadRequest;
44 import org.simantics.db.common.request.ResourceRead;
45 import org.simantics.db.common.utils.NameUtils;
46 import org.simantics.db.exception.AdaptionException;
47 import org.simantics.db.exception.DatabaseException;
48 import org.simantics.db.request.Read;
49 import org.simantics.document.DocumentResource;
50 import org.simantics.document.linking.Activator;
51 import org.simantics.document.linking.adapters.SourceObjectAdapter;
52 import org.simantics.document.linking.ge.Constants;
53 import org.simantics.document.linking.ge.MultiSelectionProvider;
54 import org.simantics.document.linking.ge.SourceLinkExplorerComposite;
55 import org.simantics.document.linking.ontology.DocumentLink;
56 import org.simantics.ui.SimanticsUI;
57 import org.simantics.utils.datastructures.ArrayMap;
58 import org.simantics.utils.ui.AdaptionUtils;
59
60
61 public class SourceView extends ViewPart implements ISelectionListener, IPartListener{
62
63         
64         public enum AcceptedObject{ALL,DOCUMENT};
65         /**
66          * The ID of the view as specified by the extension.
67          */
68         public static final String ID = "org.simantics.document.linking.views.SourceView";
69
70         private Composite composite;
71
72         private Action pinSelectionAction;
73         private Action linkAllAction;
74         private Action linkDocumentsAction;
75
76         private WidgetSupport support;
77         private GraphExplorerComposite objectExplorer;
78         private GraphExplorerComposite propertyExplorer;
79         private MultiSelectionProvider selectionProvider;
80         
81         private GraphExplorerComposite browseExplorer;
82         
83         
84         private TabFolder tabFolder;
85         
86         Composite linkComposite;
87         Composite browseComposite;
88         
89         private boolean pinSelection = false;
90         
91         Resource currentModel;
92         private ModelToComboListener modelToComboListener;
93         private CCombo modelCombo;
94
95         private AcceptedObject acceptedObject = AcceptedObject.DOCUMENT;
96         /**
97          * The constructor.
98          */
99         public SourceView() {
100                 support = new WidgetSupportImpl();
101         }
102
103         /**
104          * This is a callback that will allow us
105          * to create the viewer and initialize it.
106          */
107         public void createPartControl(Composite parent) {
108                  parent.setLayout(new FillLayout());
109                 composite = new Composite(parent, SWT.NONE);
110                 composite.setLayout(new FillLayout());
111                 tabFolder = new TabFolder(composite, SWT.NONE);
112                 TabItem link = new TabItem(tabFolder, SWT.NONE);
113                 link.setText("Linking");
114                 
115                 TabItem browse = new TabItem(tabFolder, SWT.NONE);
116                 browse.setText("Browsing");
117                 
118                 linkComposite = new Composite(tabFolder, SWT.NONE);
119                 link.setControl(linkComposite);
120                 
121                 browseComposite = new Composite(tabFolder, SWT.NONE);
122                 browse.setControl(browseComposite);
123                 
124                 selectionProvider = new MultiSelectionProvider();
125                 
126                 createLinkTab(linkComposite);
127         createBrowseTab(browseComposite);
128         
129         getSite().getPage().addPostSelectionListener(this);
130         getSite().getPage().addPartListener(this);
131                 makeActions();
132
133                 contributeToActionBars();
134                 
135                 getSite().setSelectionProvider(selectionProvider);
136                 
137                 
138         }
139         
140         @Override
141         public void dispose() {
142                  getSite().getPage().removePostSelectionListener(this);
143              getSite().getPage().removePartListener(this);
144         }
145         
146         private void createBrowseTab(final Composite browseComposite) {
147                 browseComposite.setLayout(new GridLayout(2,false));
148                 modelCombo = new CCombo(browseComposite, SWT.BORDER|SWT.READ_ONLY);
149                 final WidgetSupport support = new WidgetSupportImpl();
150                 Simantics.getSession().asyncRequest(new ReadRequest() {
151                         
152                         @Override
153                         public void run(ReadGraph graph) throws DatabaseException {
154                                 Resource project = Simantics.getProject().get();
155                                 modelToComboListener = new ModelToComboListener(modelCombo) {
156                                         @Override
157                                         public Resource getCurrentModel() {
158                                                 return currentModel;
159                                         }
160                                 };
161                                 graph.syncRequest(new ModelRead(project),modelToComboListener);
162                                 
163                         }
164                 });
165                 Button checkingButton = new Button(browseComposite, SWT.TOGGLE);
166                 checkingButton.setText("All");
167                 checkingButton.addSelectionListener(new SelectionAdapter() {
168                         @Override
169                         public void widgetSelected(SelectionEvent e) {
170                                 Button button = ((Button)e.widget);
171                                 boolean checked = button.getSelection();
172                                 browseExplorer.dispose();
173                                 createModelExplorer(checked,support,browseComposite);
174                                 button.setText(checked ? "Old/Removed" : "All");
175                                 if (currentModel != null)
176                                         setModel(currentModel, true);
177                                 browseComposite.getParent().layout(true, true);
178                         }
179                 });
180                 
181                 createModelExplorer(false,support,browseComposite);
182                 
183         
184         modelCombo.addSelectionListener(new SelectionAdapter() {
185                         @Override
186                         public void widgetSelected(SelectionEvent e) {
187                                 int index = modelCombo.getSelectionIndex();
188                                 if (index == -1)
189                                         return;
190                                 Resource model = (Resource)modelCombo.getData(Integer.toString(index));
191                                 if (model != null)
192                                         setModel(model);
193                         }
194                 });
195         
196         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).applyTo(modelCombo);
197        
198         }
199         
200         private void createModelExplorer(boolean onlyCheckable,WidgetSupport support,Composite browseComposite) {
201                 browseExplorer = new SourceLinkExplorerComposite(ArrayMap.keys("displaySelectors", "displayFilter","treeView").values(false, false, true), selectionProvider,getSite(), browseComposite, support,false, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
202                 if(!onlyCheckable)
203                         browseExplorer.setBrowseContexts(DocumentLink.URIs.ModelViewpointBrowseContext, DocumentLink.URIs.ModelViewpointActionContext);
204                 else
205                         browseExplorer.setBrowseContexts(DocumentLink.URIs.ModelViewpointBrowseContext2, DocumentLink.URIs.ModelViewpointActionContext);
206                 browseExplorer.setColumns(Constants.SOURCE_OBJECT_COLUMNS);
207                 browseExplorer.setInputSource(new SingleSelectionInputSource(Resource.class));
208                 browseExplorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning
209                 browseExplorer.setColumnsVisible(true);
210                 browseExplorer.setContextMenuId("#SourceModelViewPopup");
211                 browseExplorer.finish();
212         ((Tree)browseExplorer.getExplorer().getControl()).setLinesVisible(true);
213         
214         GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).span(2, 1).applyTo(browseExplorer);
215         }
216         
217         private void createLinkTab(final Composite linkComposite) {
218                 objectExplorer = new SourceLinkExplorerComposite(ArrayMap.keys("displaySelectors", "displayFilter","treeView").values(false, false,true), selectionProvider,getSite(), linkComposite, support, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
219                 objectExplorer.setBrowseContexts(DocumentLink.URIs.SourceObjectViewpointBrowseContext, DocumentLink.URIs.SourceObjectViewpointActionContext);
220                 objectExplorer.setColumns(Constants.SOURCE_OBJECT_COLUMNS);
221                 objectExplorer.setInputSource(new SingleSelectionInputSource(Resource.class));
222                 objectExplorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning
223                 objectExplorer.setColumnsVisible(true);
224                 objectExplorer.setContextMenuId("#SourceObjectViewPopup");
225                 objectExplorer.finish();
226         ((Tree)objectExplorer.getExplorer().getControl()).setLinesVisible(true);
227         
228         final Sash sash = new Sash (linkComposite, SWT.HORIZONTAL);
229         
230                 propertyExplorer = new SourceLinkExplorerComposite(ArrayMap.keys("displaySelectors", "displayFilter","treeView").values(false, false,true), selectionProvider,getSite(), linkComposite, support, SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
231                 propertyExplorer.setBrowseContexts(DocumentLink.URIs.SourcePropertyViewpointBrowseContext, DocumentLink.URIs.SourcePropertyViewpointActionContext);
232                 propertyExplorer.setColumns(Constants.SOURCE_COLUMNS);
233                 propertyExplorer.setInputSource(new SingleSelectionInputSource(Resource.class));
234                 propertyExplorer.getExplorer().setAutoExpandLevel(2); // Expand everything in the beginning
235                 propertyExplorer.setColumnsVisible(true);
236                 propertyExplorer.setContextMenuId("#SourcePropertyViewPopup");
237         propertyExplorer.finish();
238         ((Tree)propertyExplorer.getExplorer().getControl()).setLinesVisible(true);
239         
240        
241         final FormLayout form = new FormLayout ();
242         linkComposite.setLayout (form);
243         
244         FormData button1Data = new FormData ();
245         button1Data.left = new FormAttachment (0, 0);
246         button1Data.right = new FormAttachment (100, 0);
247         button1Data.top = new FormAttachment (0, 0);
248         button1Data.bottom = new FormAttachment (sash, 0);
249         objectExplorer.setLayoutData (button1Data);
250
251         final int limit = 40, percent = 20;
252         final FormData sashData = new FormData ();
253         sashData.left = new FormAttachment (0, 0);
254         sashData.right = new FormAttachment (100, 0);
255         sashData.top = new FormAttachment (percent, 0);
256         
257         sash.setLayoutData (sashData);
258         sash.addListener (SWT.Selection, new Listener () {
259                 public void handleEvent (Event e) {
260                         Rectangle sashRect = sash.getBounds ();
261                         Rectangle shellRect = linkComposite.getClientArea ();
262                         int top = shellRect.height - sashRect.height - limit;
263                         e.y = Math.max (Math.min (e.y, top), limit);
264                         if (e.y != sashRect.y)  {
265                                 sashData.top = new FormAttachment (0, e.y);
266                                 linkComposite.layout ();
267                         }
268                 }
269         });
270         
271         FormData button2Data = new FormData ();
272         button2Data.left = new FormAttachment (0, 0);
273         button2Data.right = new FormAttachment (100, 0);
274         button2Data.top = new FormAttachment (sash, 0);
275         button2Data.bottom = new FormAttachment (100, 0);
276         propertyExplorer.setLayoutData (button2Data);
277         }
278         
279
280         
281         @Override
282         public void partActivated(IWorkbenchPart part) {
283                 if (!(part instanceof IEditorPart))
284                         selectionEventFilter = part;
285         }
286         
287         @Override
288         public void partBroughtToTop(IWorkbenchPart part) {}
289         
290         @Override
291         public void partClosed(IWorkbenchPart part) {}
292         
293         @Override
294         public void partDeactivated(IWorkbenchPart part) {}
295         
296         @Override
297         public void partOpened(IWorkbenchPart part) {}
298         
299         IWorkbenchPart selectionEventFilter = null;
300         
301         @Override
302         public void selectionChanged(IWorkbenchPart part, ISelection selection) {
303                 if (part == this)
304                         return;
305                 if (pinSelection)
306                         return;
307                 // dnd event may start from different part than the target object is selected.
308                 // activating an part sends not only partActivated event, but also selectioChanged event to match the part's selection
309                 // since that would interrupt intended dnd operation, we filter selection events send by part activation.
310                 if (part == selectionEventFilter) {
311                         selectionEventFilter = null;
312                         return;
313                 }
314                 selectionEventFilter = null;
315                 
316                 final Resource res = AdaptionUtils.adaptToSingle(selection, Resource.class);
317                 if (res == null)
318                         return;
319                 try {
320                         final Resource selected  = Simantics.getSession().syncRequest(new Read<Resource>() {
321                                 @Override
322                                 public Resource perform(ReadGraph graph) throws DatabaseException {
323                                         try {
324                                                 SourceObjectAdapter adapter = graph.adapt(res, SourceObjectAdapter.class);
325                                                 return adapter.getDocumentableResource(graph, res);
326                                         } catch (AdaptionException e) {
327                                                 return res;
328                                         }
329                                 }
330                         });
331                         if (selected == null)
332                                 return;
333                         if (acceptedObject == AcceptedObject.DOCUMENT) {
334                                 if (Simantics.getSession().syncRequest(new IsDocumentRead(selected)))
335                                         return;
336                         }
337                         ISelection realSelection = new StructuredSelection(selected);
338                         objectExplorer.setInput(Simantics.getSessionContext(), realSelection);
339                         propertyExplorer.setInput(Simantics.getSessionContext(), realSelection);
340                         Simantics.getSession().asyncRequest(new ReadRequest() {
341                                 
342                                 @Override
343                                 public void run(ReadGraph graph) throws DatabaseException {
344                                         String name = NameUtils.getSafeLabel(graph, selected);
345                                         if (name.length() == 0)
346                                                 name = NameUtils.getSafeName(graph, selected);
347                                         final String title = name;
348                                         Display.getDefault().asyncExec(new Runnable() {
349                                                 @Override
350                                                 public void run() {
351                                                         setPartName(title);
352                                                         
353                                                 }
354                                         }) ;
355                                 }
356                         });
357                 } catch (Exception e) {
358                         
359                 }
360         }
361         
362         private class IsDocumentRead extends ResourceRead<Boolean> {
363                 public IsDocumentRead(Resource resource) {
364                         super(resource);
365                 }
366
367                 @Override
368                 public Boolean perform(ReadGraph graph) throws DatabaseException {
369                         DocumentResource doc = DocumentResource.getInstance(graph);
370                         return graph.isInstanceOf(resource, doc.Document);
371                 }
372         }
373
374
375         private void contributeToActionBars() {
376                 IActionBars bars = getViewSite().getActionBars();
377                 fillLocalPullDown(bars.getMenuManager());
378                 fillLocalToolBar(bars.getToolBarManager());
379         }
380
381         private void fillLocalPullDown(IMenuManager manager) {
382                 manager.add(linkAllAction);
383                 manager.add(linkDocumentsAction);
384         }
385
386         
387         private void fillLocalToolBar(IToolBarManager manager) {
388                 manager.add(pinSelectionAction);
389
390         }
391
392         private void makeActions() {
393                 pinSelectionAction = new Action("Pin selection", Action.AS_CHECK_BOX) {
394                         public void run() {
395                                 pinSelection = isChecked();
396                         }
397                 };
398 //              action1.setToolTipText("Action 1 tooltip");
399                 pinSelectionAction.setImageDescriptor(Activator.imageDescriptorFromPlugin("com.famfamfam.silk", "icons/lock.png"));
400                 
401                 
402                 linkAllAction = new Action("Link All", Action.AS_RADIO_BUTTON) {
403                         @Override
404                         public void run() {
405                                 setAcceptedObject(AcceptedObject.ALL);
406                                 
407                         }
408                 };
409                 
410                 linkDocumentsAction = new Action("Link Documents", Action.AS_RADIO_BUTTON) {
411                         @Override
412                         public void run() {
413                                 setAcceptedObject(AcceptedObject.DOCUMENT);
414
415                         }
416                 };
417                 setAcceptedObject(AcceptedObject.DOCUMENT);
418
419         }
420         
421         public void setAcceptedObject(AcceptedObject acceptedObject) {
422                 this.acceptedObject = acceptedObject;
423                 if (acceptedObject == AcceptedObject.ALL) {
424                         linkAllAction.setChecked(true);
425                         linkDocumentsAction.setChecked(false);
426                 } else {
427                         linkAllAction.setChecked(false);
428                         linkDocumentsAction.setChecked(true);
429                 }
430         }
431
432
433
434
435         /**
436          * Passing the focus request to the viewer's control.
437          */
438         public void setFocus() {
439                 composite.setFocus();
440         }
441         
442         public void setModel(Resource model) {
443                 setModel(model, false);
444         }
445         
446         public void setModel(Resource model, boolean force) {
447                 if (!force && model.equals(currentModel))
448                         return;
449                 
450                 currentModel = model;
451                 for (int i = 0; i < modelCombo.getItemCount(); i++) {
452                         Resource r = (Resource)modelCombo.getData(Integer.toString(i));
453                         if (model.equals(r)) {
454                                 modelCombo.select(i);
455                                 ISelection realSelection = new StructuredSelection(currentModel);
456                                 browseExplorer.setInput(Simantics.getSessionContext(), realSelection);
457                                 return;
458                         }
459                 }
460                 modelCombo.select(-1);
461                 ISelection realSelection = new StructuredSelection();
462                 browseExplorer.setInput(Simantics.getSessionContext(), realSelection);
463         }
464         
465         @SuppressWarnings("rawtypes")
466         @Override
467         public Object getAdapter(Class adapter) {
468                 if (adapter == GraphExplorer.class) {
469                         return browseExplorer.getExplorer();
470                 }
471                 return super.getAdapter(adapter);
472         }
473 }