]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.team.ui/src/org/simantics/team/ui/StagingView.java
Remove usage of deprecated SimanticsUI-methods
[simantics/platform.git] / bundles / org.simantics.team.ui / src / org / simantics / team / ui / StagingView.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.team.ui;
13
14 import java.util.Map;
15 import java.util.Vector;
16
17 import org.eclipse.jface.layout.GridDataFactory;
18 import org.eclipse.jface.layout.TreeColumnLayout;
19 import org.eclipse.jface.resource.JFaceResources;
20 import org.eclipse.jface.resource.LocalResourceManager;
21 import org.eclipse.jface.viewers.ColumnLabelProvider;
22 import org.eclipse.jface.viewers.ColumnWeightData;
23 import org.eclipse.jface.viewers.ITreeContentProvider;
24 import org.eclipse.jface.viewers.LabelProvider;
25 import org.eclipse.jface.viewers.TreeViewer;
26 import org.eclipse.jface.viewers.TreeViewerColumn;
27 import org.eclipse.jface.viewers.Viewer;
28 import org.eclipse.jface.viewers.ViewerCell;
29 import org.eclipse.jface.viewers.ViewerFilter;
30 import org.eclipse.jface.window.ToolTip;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.graphics.Image;
33 import org.eclipse.swt.graphics.Point;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.widgets.Composite;
37 import org.eclipse.swt.widgets.Control;
38 import org.eclipse.swt.widgets.Event;
39 import org.eclipse.swt.widgets.Label;
40 import org.eclipse.swt.widgets.Text;
41 import org.eclipse.swt.widgets.Tree;
42 import org.eclipse.ui.IMemento;
43 import org.eclipse.ui.IViewSite;
44 import org.eclipse.ui.PartInitException;
45 import org.eclipse.ui.part.ViewPart;
46 import org.simantics.Simantics;
47 import org.simantics.browsing.ui.GraphExplorer;
48 import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;
49 import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver;
50 import org.simantics.browsing.ui.swt.GraphExplorerFactory;
51 import org.simantics.browsing.ui.swt.ViewArgumentUtils;
52 import org.simantics.db.Session;
53 import org.simantics.db.exception.DatabaseException;
54 import org.simantics.db.management.ISessionContext;
55 import org.simantics.db.management.ISessionContextChangedListener;
56 import org.simantics.db.management.ISessionContextProvider;
57 import org.simantics.db.management.SessionContextChangedEvent;
58 import org.simantics.db.service.TeamSupport;
59 import org.simantics.project.ProjectKeys;
60 import org.simantics.team.Utils;
61 import org.simantics.team.internal.Images;
62 import org.simantics.ui.SimanticsUI;
63 import org.simantics.utils.datastructures.disposable.DisposeState;
64 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
65 import org.simantics.utils.datastructures.hints.HintTracker;
66 import org.simantics.utils.datastructures.hints.IHintContext.Key;
67 import org.simantics.utils.datastructures.hints.IHintListener;
68 import org.simantics.utils.datastructures.hints.IHintObservable;
69 import org.simantics.utils.datastructures.hints.IHintTracker;
70 import org.simantics.utils.ui.LayoutUtils;
71
72 /**
73  * @author Kalle Kondelin
74  */
75 public class StagingView extends ViewPart {
76
77     public StagingView() {
78     }
79
80     public class SessionContextProjectTracker extends HintTracker {
81         public SessionContextProjectTracker() {
82             IHintListener activeProjectListener = new HintListenerAdapter() {
83                 @Override
84                 public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
85                     applySessionContext(getSessionContext());
86                 }
87             };
88             addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);
89         }
90     }
91
92     protected LocalResourceManager resourceManager;
93     protected Composite parent;
94     protected TreeViewer treeViewer;
95     private Map<String, String> args;
96     private ISessionContextProvider contextProvider;
97     private ISessionContext sessionContext;
98     protected IMemento memento;
99     private IHintTracker sessionContextTracker = new SessionContextProjectTracker();
100     private DisposeState disposeState = DisposeState.Alive;
101
102     protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {
103         @Override
104         public void sessionContextChanged(SessionContextChangedEvent event) {
105             sessionContext = event.getNewValue();
106             sessionContextTracker.track(sessionContext);
107         }
108     };
109
110     protected void setSessionContextTracker(IHintTracker tracker) {
111         this.sessionContextTracker = tracker;
112     }
113
114     protected Map<String, String> getViewArguments() {
115         return args;
116     }
117
118     protected DisposeState getDisposeState() {
119         return disposeState;
120     }
121
122     public ISessionContext getSessionContext() {
123         return sessionContext;
124     }
125
126     public ISessionContextProvider getSessionContextProvider() {
127         return contextProvider;
128     }
129
130     @Override
131     public void createPartControl(Composite parent) {
132         this.parent = parent;
133         this.treeViewer = new TreeViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION);
134         this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), treeViewer.getTree());
135         Images.getInstance(JFaceResources.getResources());
136         TreeColumnLayout ad = new TreeColumnLayout();
137         parent.setLayout(ad);
138         treeViewer.getTree().setHeaderVisible(true);
139         TreeViewerColumn nameColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);
140         nameColumn.getColumn().setText("Comment");
141         nameColumn.getColumn().setWidth(200);
142 //        TreeViewerColumn typeColumn = new TreeViewerColumn(treeViewer, SWT.LEFT);
143
144         nameColumn.setLabelProvider(new MyColumnLabelProvider());
145 //        typeColumn.setLabelProvider(new MyColumnLabelProvider());
146
147         ad.setColumnData(nameColumn.getColumn(), new ColumnWeightData(80, 100));
148 //        typeColumn.getColumn().setText("Comment");
149 //        typeColumn.getColumn().setWidth(20);
150 //        ad.setColumnData(typeColumn.getColumn(), new ColumnWeightData(20, 120));
151
152         createControls(parent);
153         attachToSession();
154
155     }
156
157     /**
158      * Invoked when this viewpart is disposed. Unhooks the view from its
159      * ISessionContextProvider. Overriding is allowed but super.dispose() must
160      * be called.
161      *
162      * @see org.eclipse.ui.part.WorkbenchPart#dispose()
163      */
164     @Override
165     public void dispose() {
166         disposeState = DisposeState.Disposing;
167         try {
168             if (contextProvider != null) {
169                 contextProvider.removeContextChangedListener(contextChangeListener);
170                 contextProvider = null;
171             }
172             sessionContextTracker.untrack();
173             resourceManager.dispose();
174             resourceManager = null;
175             args = null;
176             sessionContext = null;
177             parent = null;
178             super.dispose();
179         } finally {
180            disposeState = DisposeState.Disposed;
181         }
182     }
183
184     @Override
185     public void setFocus() {
186
187     }
188
189     @Override
190     public void init(IViewSite site) throws PartInitException {
191         super.init(site);
192         this.args = ViewArgumentUtils.parseViewArguments(this);
193     }
194
195     @Override
196     public void init(IViewSite site, IMemento memento) throws PartInitException {
197         super.init(site, memento);
198         this.args = ViewArgumentUtils.parseViewArguments(this);
199         this.memento = memento;
200     }
201
202     @Override
203     public void saveState(IMemento memento) {
204         if (this.memento != null) {
205             memento.putMemento(this.memento);
206         }
207     }
208
209     protected final void attachToSession() {
210         // Track active ISessionContext changes
211         contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());
212         contextProvider.addContextChangedListener(contextChangeListener);
213
214         // Perform first-time initialization of the explorer and its input.
215         applySessionContext(contextProvider.getSessionContext());
216     }
217
218     private abstract class NameAndDescriptionToolTip extends ToolTip {
219         public NameAndDescriptionToolTip(Control control, int style) {
220             super(control, style, false);
221         }
222
223         protected abstract Object getModelElement(Event event);
224
225         /**
226          * Adds logic to only show a tooltip if a meaningful item is under the cursor.
227          */
228         @Override
229         protected boolean shouldCreateToolTip(Event event) {
230             if (!super.shouldCreateToolTip(event))
231                 return false;
232             Object tableElement = getModelElement(event);
233             return tableElement != null && tableElement instanceof DisplayElement;
234         }
235
236         @Override
237         protected Composite createToolTipContentArea(Event event, Composite parent) {
238             Object modelElement = getModelElement(event);
239
240             Image iconImage = null;
241             String nameString = "no name";
242
243             if (modelElement instanceof DisplayElement) {
244                 iconImage = null;
245                 nameString = "name";
246             }
247
248             // Create the content area
249             Composite composite = new Composite(parent, SWT.NONE);
250             composite.setBackground(parent.getDisplay().getSystemColor(
251                     SWT.COLOR_INFO_BACKGROUND));
252             composite.setLayout(new GridLayout(2, false));
253
254             // The title area with the icon (if there is one) and label.
255             Label title = createEntry(composite, iconImage, nameString);
256 //            title.setFont(tooltipHeading);
257             GridDataFactory.createFrom((GridData)title.getLayoutData())
258                 .hint(SWT.DEFAULT, SWT.DEFAULT)
259 //                .minSize(MIN_TOOLTIP_WIDTH, 1)
260                 .applyTo(title);
261
262             // The description (if there is one)
263 //            String descriptionString = "description";
264 //            if (descriptionString != null)
265 //                createEntry(composite, null, descriptionString);
266
267             // Other Content to add
268             addContent(composite, modelElement);
269
270             return composite;
271         }
272
273         /**
274          * Adds a line of information to <code>parent</code>. If
275          * <code>icon</code> is not <code>null</code>, an icon is placed on the
276          * left, and then a label with <code>text</code>.
277          *
278          * @param parent
279          *            the composite to add the entry to
280          * @param icon
281          *            the icon to place next to the text. <code>null</code> for
282          *            none.
283          * @param text
284          *            the text to display
285          * @return the created label
286          */
287         protected Label createEntry(Composite parent, Image icon, String text) {
288             if (icon != null) {
289                 Label iconLabel = new Label(parent, SWT.NONE);
290                 iconLabel.setImage(icon);
291                 iconLabel.setBackground(parent.getDisplay().getSystemColor(
292                         SWT.COLOR_INFO_BACKGROUND));
293                 iconLabel.setData(new GridData());
294             }
295
296             Label textLabel = new Label(parent, SWT.WRAP);
297
298             if(icon == null) {
299                 GridDataFactory.generate(textLabel, 2, 1);
300             } else {
301                 GridDataFactory.generate(textLabel, 1, 1);
302             }
303
304             textLabel.setText(text);
305             textLabel.setBackground(parent.getDisplay().getSystemColor(
306                     SWT.COLOR_INFO_BACKGROUND));
307             return textLabel;
308         }
309
310         /**
311          * Adds a line of information to <code>parent</code>. If
312          * <code>icon</code> is not <code>null</code>, an icon is placed on the
313          * left, and then a label with <code>text</code>, which supports using
314          * anchor tags to creates links
315          *
316          * @param parent
317          *            the composite to add the entry to
318          * @param icon
319          *            the icon to place next to the text. <code>null</code> for
320          *            none.
321          * @param text
322          *            the text to display
323          * @return the created link
324          */
325         protected Text createEntryWithText(Composite parent, Image icon, String text) {
326             if (icon != null) {
327                 Label iconLabel = new Label(parent, SWT.NONE);
328                 iconLabel.setImage(icon);
329                 iconLabel.setBackground(parent.getDisplay().getSystemColor(
330                         SWT.COLOR_INFO_BACKGROUND));
331                 iconLabel.setData(new GridData());
332             }
333             Text texts = new Text(parent, SWT.READ_ONLY | SWT.MULTI | SWT.V_SCROLL);
334             if(icon == null) {
335                 GridDataFactory.generate(texts, 2, 1);
336             }
337             texts.setText(text);
338             texts.setBackground(parent.getDisplay().getSystemColor(
339                     SWT.COLOR_INFO_BACKGROUND));
340             return texts;
341         }
342
343         protected void addContent(Composite destination, Object modelElement) {
344         }
345     }
346
347     private class ItemDetailToolTip extends NameAndDescriptionToolTip {
348         private final boolean DEBUG = false;
349         private TreeViewer viewer;
350         private Tree tree;
351         private ItemDetailToolTip(TreeViewer viewer, Tree tree, ViewerFilter filter) {
352             super(tree,NO_RECREATE);
353             this.tree = tree;
354             this.viewer = viewer;
355             this.setHideOnMouseDown(false);
356         }
357         @Override
358         public Point getLocation(Point tipSize, Event event) {
359             // try to position the tooltip at the bottom of the cell
360             ViewerCell cell = viewer.getCell(new Point(event.x, event.y));
361             if( cell != null )
362                 return tree.toDisplay(event.x,cell.getBounds().y+cell.getBounds().height);
363             return super.getLocation(tipSize, event);
364         }
365         @Override
366         protected Object getToolTipArea(Event event) {
367             // Ensure that the tooltip is hidden when the cell is left
368             return viewer.getCell(new Point(event.x, event.y));
369         }
370         @Override
371         protected void addContent(Composite destination, Object modelElement) {
372             final DisplayElement item = (DisplayElement)modelElement;
373             if (DEBUG)
374                 System.out.println("add content");
375             String text = null;
376             if (null != item) {
377                 text = modelElement.toString();
378                 createEntryWithText(destination, null, text.toString());
379             }
380         }
381         @Override
382         protected Object getModelElement(Event event) {
383             org.eclipse.swt.widgets.TreeItem treeItem = tree.getItem(new Point(event.x, event.y));
384             if (treeItem == null)
385                 return null;
386             return treeItem.getData();
387         }
388     }
389     class MyColumnLabelProvider extends ColumnLabelProvider {
390         @Override
391         public void update(ViewerCell cell) {
392             //NodeProxy proxy = (NodeProxy) cell.getElement();
393             cell.setText("Kraa");
394             cell.setImage(Images.getInstance().OTHER_IMAGE);
395         }
396     }
397     protected void createControls(final Composite parent) {
398         parent.setLayout(LayoutUtils.createNoBorderGridLayout(1, false));
399         GridDataFactory.fillDefaults().grab(true, true).applyTo(treeViewer.getTree());
400         treeViewer.setContentProvider(new CommentContentProvider(Simantics.getSession()));
401         treeViewer.setLabelProvider(new LabelProvider() {
402             @Override
403             public Image getImage(Object element) {
404                 if (element instanceof ChangeSetElement)
405                     return Images.getInstance().CHANGE_SET_IMAGE;
406                 else if (element instanceof DisplayElement)
407                     return Images.getInstance().DISPLAY_IMAGE;
408                 else if (element instanceof ResourceElement)
409                     return Images.getInstance().RESOURCE_IMAGE;
410                 else if (element instanceof StringElement)
411                     return Images.getInstance().STRING_IMAGE;
412                 else if (element instanceof UndoCombinedElement)
413                     return Images.getInstance().COMBINED_IMAGE;
414                 else if (element instanceof RedoContextElement)
415                     return Images.getInstance().REDO_IMAGE;
416                 else if (element instanceof UndoContextElement)
417                     return Images.getInstance().UNDO_IMAGE;
418                 else
419                     return Images.getInstance().OTHER_IMAGE;
420             }
421             @Override
422             public String getText(Object element) {
423                 return element.toString();
424             }
425         });
426         //viewer.setSorter(new ViewerSorter());
427         treeViewer.setInput(this);
428 //        getViewSite().getActionBars().getToolBarManager().add(new Action("GetIncoming", Activator.DOOR_IN_ICON) {
429 //            @Override
430 //            public void run() {
431 //                treeViewer.setContentProvider(new IncomingContentProvider(Simantics.getSession(), parent.getShell()));
432 //            }
433 //        });
434         new ItemDetailToolTip(treeViewer, treeViewer.getTree(), null);
435     }
436
437     /**
438      * @param parent
439      * @return
440      */
441     protected GraphExplorer createExplorerControl(Composite parent) {
442         return GraphExplorerFactory.getInstance().selectionDataResolver(new DefaultSelectionDataResolver()).create(parent);
443     }
444
445     /**
446      * Invoke this to reinitialize the explorer and reset its input. The input
447      * will be resolved from the specified ISessionContext based on the
448      * {@link SessionContextInputSource} that is currently in use. If the input
449      * is identical to the previous input, nothing will be done.
450      *
451      * @param context
452      */
453     protected final boolean applySessionContext(ISessionContext context) {
454         // If control is not alive anymore, do nothing.
455         if (disposeState != DisposeState.Alive)
456             return false;
457
458         this.sessionContext = context;
459
460         // Start tracking the session context.
461         // This will cause IHintListeners of the sessionContextTracker to fire.
462         // For this we need the above input equality (identity) checking.
463         sessionContextTracker.track(sessionContext);
464         return true;
465     }
466 }
467 class CommentContentProvider implements ITreeContentProvider {
468     protected Viewer viewer = null;
469     private final Vector<String >comments = new Vector<String>();
470     private final Session session;
471     private final TeamSupport teamSupport;
472     CommentContentProvider(Session session) {
473         this.session = session;
474         teamSupport = this.session.getService(TeamSupport.class);
475         try {
476             teamSupport.getComments(Utils.getTeamFolder(), comments);
477         } catch (DatabaseException e) {
478             comments.add(e.getMessage());
479         }
480     }
481     protected Object[] getElements() {
482         final int SIZE = comments.size();
483         Object[] objects = new Object[SIZE];
484         for (int i=0; i<SIZE; ++i)
485             objects[i] = new StagingContextElement(i, comments.get(i));
486         return objects;
487     }
488     @Override
489     public void dispose() {
490         viewer = null;
491     }
492     @Override
493     public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
494         this.viewer = viewer;
495     }
496     @Override
497     public Object[] getElements(Object inputElement) {
498         return getElements();
499     }
500     @Override
501     public Object[] getChildren(Object parentElement) {
502         if (parentElement instanceof  TreeElement)
503             return ((TreeElement)parentElement).getChildren();
504         else
505             return null;
506     }
507     @Override
508     public Object getParent(Object childElement) {
509             return null;
510     }
511     @Override
512     public boolean hasChildren(Object element) {
513         if (element instanceof  TreeElement)
514             return ((TreeElement)element).hasChildren();
515         return false;
516     }
517 }
518
519 abstract class StagingViewElement extends TreeElement {
520     StagingViewElement() {
521     }
522     @Override
523     boolean hasChildren() {
524             return false;
525     }
526     @Override
527     Object[] getChildren() {
528         return new Object[0];
529     }
530 }
531
532 class StagingContextElement extends StagingViewElement {
533     protected String name = "Staging";
534     private final String comment;
535     StagingContextElement(int index, String comment) {
536         this.comment = comment;
537     }
538     @Override
539     protected Image getIdImage() {
540         return Images.getInstance().OTHER_IMAGE;
541     }
542     @Override
543     protected String getIdText() {
544         String s = toString();
545         return s.substring(0, Math.min(10, s.length()));
546     }
547     @Override
548     public String toString() {
549         return comment;
550     }
551 }