/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.team.ui; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.TreeColumnLayout; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IMemento; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.IWorkbenchSite; import org.eclipse.ui.PartInitException; import org.eclipse.ui.part.IPageSite; import org.eclipse.ui.part.ViewPart; import org.simantics.browsing.ui.GraphExplorer; import org.simantics.browsing.ui.graph.impl.SessionContextInputSource; import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver; import org.simantics.browsing.ui.swt.GraphExplorerFactory; import org.simantics.browsing.ui.swt.ViewArgumentUtils; import org.simantics.databoard.Bindings; import org.simantics.db.ChangeSetIdentifier; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.exception.DatabaseException; import org.simantics.db.management.ISessionContext; import org.simantics.db.management.ISessionContextChangedListener; import org.simantics.db.management.ISessionContextProvider; import org.simantics.db.management.SessionContextChangedEvent; import org.simantics.db.request.Read; import org.simantics.layer0.Layer0; import org.simantics.project.ProjectKeys; import org.simantics.team.internal.Images; import org.simantics.ui.SimanticsUI; import org.simantics.utils.datastructures.disposable.DisposeState; import org.simantics.utils.datastructures.hints.HintListenerAdapter; import org.simantics.utils.datastructures.hints.HintTracker; import org.simantics.utils.datastructures.hints.IHintContext.Key; import org.simantics.utils.datastructures.hints.IHintListener; import org.simantics.utils.datastructures.hints.IHintObservable; import org.simantics.utils.datastructures.hints.IHintTracker; import org.simantics.utils.ui.LayoutUtils; /** * @author Kalle Kondelin */ public class SynchroniseView extends ViewPart { public SynchroniseView() { } public class SessionContextProjectTracker extends HintTracker { public SessionContextProjectTracker() { IHintListener activeProjectListener = new HintListenerAdapter() { @Override public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) { applySessionContext(getSessionContext()); } }; addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener); } } protected LocalResourceManager resourceManager; protected Composite parent; protected TreeViewer treeViewer; private Map args; private ISessionContextProvider contextProvider; private ISessionContext sessionContext; protected IMemento memento; private IHintTracker sessionContextTracker = new SessionContextProjectTracker(); private DisposeState disposeState = DisposeState.Alive; protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() { @Override public void sessionContextChanged(SessionContextChangedEvent event) { sessionContext = event.getNewValue(); sessionContextTracker.track(sessionContext); } }; protected void setSessionContextTracker(IHintTracker tracker) { this.sessionContextTracker = tracker; } protected Map getViewArguments() { return args; } protected DisposeState getDisposeState() { return disposeState; } public ISessionContext getSessionContext() { return sessionContext; } public ISessionContextProvider getSessionContextProvider() { return contextProvider; } @Override public void createPartControl(Composite parent) { this.parent = parent; this.treeViewer = new TreeViewer(parent, SWT.SINGLE | SWT.FULL_SELECTION); this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), treeViewer.getTree()); Images.getInstance(JFaceResources.getResources()); TreeColumnLayout ad = new TreeColumnLayout(); parent.setLayout(ad); treeViewer.getTree().setHeaderVisible(true); //treeViewer.getTree().setLinesVisible(true); //treeViewer.setUseHashlookup(true); //treeViewer.setAutoExpandLevel(3); TreeViewerColumn nameColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); TreeViewerColumn typeColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); // TreeViewerColumn idColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); // TreeViewerColumn lookupIdColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); // TreeViewerColumn zColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); nameColumn.setLabelProvider(new MyColumnLabelProvider()); typeColumn.setLabelProvider(new MyColumnLabelProvider()); // idColumn.setLabelProvider(new MyColumnLabelProvider()); // lookupIdColumn.setLabelProvider(new MyColumnLabelProvider()); // zColumn.setLabelProvider(new MyColumnLabelProvider()); nameColumn.getColumn().setText("Name"); nameColumn.getColumn().setWidth(20); ad.setColumnData(nameColumn.getColumn(), new ColumnWeightData(80, 100)); typeColumn.getColumn().setText("Type"); typeColumn.getColumn().setWidth(20); ad.setColumnData(typeColumn.getColumn(), new ColumnWeightData(20, 120)); // idColumn.getColumn().setText("ID"); // idColumn.getColumn().setWidth(20); // ad.setColumnData(idColumn.getColumn(), new ColumnWeightData(10, 50)); // lookupIdColumn.getColumn().setText("Lookup ID"); // lookupIdColumn.getColumn().setWidth(20); // ad.setColumnData(lookupIdColumn.getColumn(), new ColumnWeightData(50, 100)); // zColumn.getColumn().setText("Z"); // zColumn.getColumn().setWidth(70); // ad.setColumnData(zColumn.getColumn(), new ColumnWeightData(10, 70)); createControls(parent); attachToSession(); } /** * Invoked when this viewpart is disposed. Unhooks the view from its * ISessionContextProvider. Overriding is allowed but super.dispose() must * be called. * * @see org.eclipse.ui.part.WorkbenchPart#dispose() */ @Override public void dispose() { disposeState = DisposeState.Disposing; try { if (contextProvider != null) { contextProvider.removeContextChangedListener(contextChangeListener); contextProvider = null; } sessionContextTracker.untrack(); resourceManager.dispose(); resourceManager = null; args = null; sessionContext = null; parent = null; super.dispose(); } finally { disposeState = DisposeState.Disposed; } } @Override public void setFocus() { } @Override public void init(IViewSite site) throws PartInitException { super.init(site); this.args = ViewArgumentUtils.parseViewArguments(this); } @Override public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); this.args = ViewArgumentUtils.parseViewArguments(this); this.memento = memento; } @Override public void saveState(IMemento memento) { if (this.memento != null) { memento.putMemento(this.memento); } // if (explorer != null) // explorer.saveState(memento); } protected final void attachToSession() { // Track active ISessionContext changes contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow()); contextProvider.addContextChangedListener(contextChangeListener); // Perform first-time initialization of the explorer and its input. applySessionContext(contextProvider.getSessionContext()); } // private abstract class NameAndDescriptionToolTip extends ToolTip { // public NameAndDescriptionToolTip(Control control, int style) { // super(control, style, false); // } // // protected abstract Object getModelElement(Event event); // // /** // * Adds logic to only show a tooltip if a meaningful item is under the // * cursor. // */ // protected boolean shouldCreateToolTip(Event event) { // if (!super.shouldCreateToolTip(event)) // return false; // Object tableElement = getModelElement(event); // return tableElement != null && tableElement instanceof DisplayElement; // } // // protected Composite createToolTipContentArea(Event event, // Composite parent) { // Object modelElement = getModelElement(event); // // Image iconImage = null; // String nameString = "no name"; // // if (modelElement instanceof DisplayElement) { // iconImage = null; // nameString = "name"; // } // // // Create the content area // Composite composite = new Composite(parent, SWT.NONE); // composite.setBackground(parent.getDisplay().getSystemColor( // SWT.COLOR_INFO_BACKGROUND)); // composite.setLayout(new GridLayout(2, false)); // // // The title area with the icon (if there is one) and label. // Label title = createEntry(composite, iconImage, nameString); //// title.setFont(tooltipHeading); // GridDataFactory.createFrom((GridData)title.getLayoutData()) // .hint(SWT.DEFAULT, SWT.DEFAULT) //// .minSize(MIN_TOOLTIP_WIDTH, 1) // .applyTo(title); // // // The description (if there is one) //// String descriptionString = "description"; //// if (descriptionString != null) //// createEntry(composite, null, descriptionString); // // // Other Content to add // addContent(composite, modelElement); // // return composite; // } // // /** // * Adds a line of information to parent. If // * icon is not null, an icon is placed on the // * left, and then a label with text. // * // * @param parent // * the composite to add the entry to // * @param icon // * the icon to place next to the text. null for // * none. // * @param text // * the text to display // * @return the created label // */ // protected Label createEntry(Composite parent, Image icon, String text) { // if (icon != null) { // Label iconLabel = new Label(parent, SWT.NONE); // iconLabel.setImage(icon); // iconLabel.setBackground(parent.getDisplay().getSystemColor( // SWT.COLOR_INFO_BACKGROUND)); // iconLabel.setData(new GridData()); // } // // Label textLabel = new Label(parent, SWT.WRAP); // // if(icon == null) { // GridDataFactory.generate(textLabel, 2, 1); // } else { // GridDataFactory.generate(textLabel, 1, 1); // } // // textLabel.setText(text); // textLabel.setBackground(parent.getDisplay().getSystemColor( // SWT.COLOR_INFO_BACKGROUND)); // return textLabel; // } // // /** // * Adds a line of information to parent. If // * icon is not null, an icon is placed on the // * left, and then a label with text, which supports using // * anchor tags to creates links // * // * @param parent // * the composite to add the entry to // * @param icon // * the icon to place next to the text. null for // * none. // * @param text // * the text to display // * @return the created link // */ // protected Text createEntryWithText(Composite parent, Image icon, String text) { // if (icon != null) { // Label iconLabel = new Label(parent, SWT.NONE); // iconLabel.setImage(icon); // iconLabel.setBackground(parent.getDisplay().getSystemColor( // SWT.COLOR_INFO_BACKGROUND)); // iconLabel.setData(new GridData()); // } // Text texts = new Text(parent, SWT.READ_ONLY | SWT.MULTI | SWT.V_SCROLL); // if(icon == null) { // GridDataFactory.generate(texts, 2, 1); // } // texts.setText(text); // texts.setBackground(parent.getDisplay().getSystemColor( // SWT.COLOR_INFO_BACKGROUND)); // return texts; // } // // protected void addContent(Composite destination, Object modelElement) { // } // } /* private class ItemDetailToolTip extends NameAndDescriptionToolTip { private final boolean DEBUG = false; private TreeViewer viewer; private Tree tree; private ItemDetailToolTip(TreeViewer viewer, Tree tree, ViewerFilter filter) { super(tree,NO_RECREATE); this.tree = tree; this.viewer = viewer; this.setHideOnMouseDown(false); } public Point getLocation(Point tipSize, Event event) { // try to position the tooltip at the bottom of the cell ViewerCell cell = viewer.getCell(new Point(event.x, event.y)); if( cell != null ) return tree.toDisplay(event.x,cell.getBounds().y+cell.getBounds().height); return super.getLocation(tipSize, event); } protected Object getToolTipArea(Event event) { // Ensure that the tooltip is hidden when the cell is left return viewer.getCell(new Point(event.x, event.y)); } protected void addContent(Composite destination, Object modelElement) { final DisplayElement item = (DisplayElement)modelElement; if (DEBUG) System.out.println("add content"); String text = null; if (null != item) { text = modelElement.toString(); createEntryWithText(destination, null, text.toString()); } } protected Object getModelElement(Event event) { org.eclipse.swt.widgets.TreeItem treeItem = tree.getItem(new Point(event.x, event.y)); if (treeItem == null) return null; return treeItem.getData(); } }*/ class MyColumnLabelProvider extends ColumnLabelProvider { @Override public void update(ViewerCell cell) { //NodeProxy proxy = (NodeProxy) cell.getElement(); cell.setText("Kraa"); cell.setImage(Images.getInstance().OTHER_IMAGE); } } protected void createControls(final Composite parent) { parent.setLayout(LayoutUtils.createNoBorderGridLayout(1, false)); GridDataFactory.fillDefaults().grab(true, true).applyTo(treeViewer.getTree()); treeViewer.setContentProvider(new UndoContentProvider(SimanticsUI.getSession())); treeViewer.setLabelProvider(new LabelProvider() { @Override public Image getImage(Object element) { if (element instanceof ChangeSetElement) return Images.getInstance().CHANGE_SET_IMAGE; else if (element instanceof DisplayElement) return Images.getInstance().DISPLAY_IMAGE; else if (element instanceof ResourceElement) return Images.getInstance().RESOURCE_IMAGE; else if (element instanceof StringElement) return Images.getInstance().STRING_IMAGE; else if (element instanceof UndoCombinedElement) return Images.getInstance().COMBINED_IMAGE; else if (element instanceof RedoContextElement) return Images.getInstance().REDO_IMAGE; else if (element instanceof UndoContextElement) return Images.getInstance().UNDO_IMAGE; else return Images.getInstance().OTHER_IMAGE; } @Override public String getText(Object element) { return element.toString(); } }); //viewer.setSorter(new ViewerSorter()); treeViewer.setInput(this); Control control = treeViewer.getControl(); // ISelectionProvider selectionProvider = new ISelectionProvider() { // @Override // public void addSelectionChangedListener(ISelectionChangedListener listener) { // } // @Override // public ISelection getSelection() { // return null; // } // @Override // public void removeSelectionChangedListener(ISelectionChangedListener listener) { // } // @Override // public void setSelection(ISelection selection) { // } // }; createContextMenu(control, getSite()); // ImageDescriptor desc = BundleUtils.getImageDescriptorFromPlugin("com.famfamfam.silk", "icons/arrow_undo.png"); // getViewSite().getActionBars().getToolBarManager().add(new Action("GetUndoHistory", desc) { // @Override // public void run() { // treeViewer.setContentProvider(new UndoContentProvider(SimanticsUI.getSession())); // } // }); // getViewSite().getActionBars().getToolBarManager().add(new Action("DumpSelectedRevision", Activator.BIN_CLOSED_ICON) { // @Override // public void run() { // IStructuredSelection is = (IStructuredSelection)viewer.getSelection(); // Object o = is.getFirstElement(); // if (o instanceof ChangeSetElement) { // ChangeSetElement ce = (ChangeSetElement)o; // long csid = ce.getChangeSetIdentifier().getId(); // ManagementSupport ms = SimanticsUI.getSession().getService(ManagementSupport.class); // try { // ms.dumpRevision(csid); // ShowMessage.showInformation("DumpSelectedRevision", "Operation was successful."); // } catch (DatabaseException e) { // ExceptionUtils.logAndShowError(e); // } // } // } // }); } public IMenuManager createContextMenu(Control control, IWorkbenchSite site) { final MenuManager mm = new MenuManager("#TeamViewPopup", "#TeamViewPopup"); mm.setRemoveAllWhenShown(true); mm.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { mm.add(new GroupMarker(IWorkbenchActionConstants.WB_START)); } }); Menu menu = mm.createContextMenu(control); control.setMenu(menu); if (site != null) { if (site instanceof IWorkbenchPartSite) { ((IWorkbenchPartSite) site).registerContextMenu(mm.getId(), mm, site.getSelectionProvider()); } else if (site instanceof IPageSite) { ((IPageSite) site).registerContextMenu(mm.getId(), mm, site.getSelectionProvider()); } } return mm; } /** * @param parent * @return */ protected GraphExplorer createExplorerControl(Composite parent) { return GraphExplorerFactory.getInstance().selectionDataResolver(new DefaultSelectionDataResolver()).create(parent); } // Needed for preventing unnecessary re-initialization of the explorer with the same input. // private Object currentInput; /** * Invoke this to reinitialize the explorer and reset its input. The input * will be resolved from the specified ISessionContext based on the * {@link SessionContextInputSource} that is currently in use. If the input * is identical to the previous input, nothing will be done. * * @param context */ protected final boolean applySessionContext(ISessionContext context) { // If control is not alive anymore, do nothing. if (disposeState != DisposeState.Alive) return false; this.sessionContext = context; // Start tracking the session context. // This will cause IHintListeners of the sessionContextTracker to fire. // For this we need the above input equality (identity) checking. sessionContextTracker.track(sessionContext); return true; } } class IncomingContentProvider implements ITreeContentProvider { class IncomingElement extends ChangeSetElement { IncomingElement(Session session, ChangeSetIdentifier cs) { super(session, cs); } } IncomingElement[] changeSetIds; IncomingContentProvider(Session session, Shell parent) { //this.session = session; // PublishSynchroniseSupport ps = session.getService(PublishSynchroniseSupport.class); // try { Collection cids = new ArrayList(); /*if (null == cids) changeSetIds = new IncomingElement[0]; else */{ changeSetIds = new IncomingElement[cids.size()]; Iterator it = cids.iterator(); int i = 0; while (it.hasNext()) { changeSetIds[i++] = new IncomingElement(session, it.next()); } assert(i == cids.size()); } // } catch (DatabaseException e) { // changeSetIds = new IncomingElement[0]; // ExceptionUtils.logAndShowError(e); // } } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } @Override public void dispose() { } @Override public Object[] getElements(Object inputElement) { return changeSetIds; } @Override public boolean hasChildren(Object element) { return changeSetIds.length > 0; } @Override public Object getParent(Object element) { return null; } @Override public Object[] getChildren(Object parentElement) { return null; } } class OutgoingContentProvider implements ITreeContentProvider { class OutgoingElement extends ChangeSetElement { OutgoingElement(Session session, ChangeSetIdentifier cs) { super(session, cs); } } OutgoingElement[] changeSetIds; OutgoingContentProvider(Session session) { // PublishSynchroniseSupport ps = session.getService(PublishSynchroniseSupport.class); // try { Collection cids = new ArrayList(); /*if (null == cids) changeSetIds = new OutgoingElement[0]; else */{ changeSetIds = new OutgoingElement[cids.size()]; Iterator it = cids.iterator(); int i = 0; while (it.hasNext()) { changeSetIds[i++] = new OutgoingElement(session, it.next()); } assert(i == cids.size()); } // } catch (DatabaseException e) { // ExceptionUtils.logAndShowError(e); // changeSetIds = new OutgoingElement[0]; // } } @Override public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } @Override public void dispose() { } @Override public Object[] getElements(Object inputElement) { return changeSetIds; } @Override public boolean hasChildren(Object element) { if (element instanceof TreeElement) return ((TreeElement)element).hasChildren(); return false; } @Override public Object getParent(Object element) { return null; } @Override public Object[] getChildren(Object parentElement) { if (parentElement instanceof TreeElement) return ((TreeElement)parentElement).getChildren(); else return null; } } class ResourceElement extends TreeElement { private Session session; private String resourceUri; private String resourceName; private Resource resource; ResourceElement(Session session, String resource) { this.session = session; this.resourceUri = resource; } ResourceElement(Session session, Resource resource) { this.session = session; this.resource = resource; } @Override protected Image getIdImage() { return Images.getInstance().RESOURCE_IMAGE; } @Override protected String getIdText() { String s = resource.toString(); return s.substring(0, Math.min(10, s.length())); } private String getNameByUri() { try { String t = session.syncRequest(new Read() { @Override public String perform(ReadGraph g) throws DatabaseException { resource = g.getResource(resourceUri); Layer0 l0 = Layer0.getInstance(g); resourceName = g.getPossibleRelatedValue(resource, l0.HasName, Bindings.STRING); if (null == resourceName) { Set types = g.getTypes(resource); if (types.size() > 0) { Iterator i = types.iterator(); Resource r = i.next(); resourceName = g.getPossibleRelatedValue(r, l0.HasName, Bindings.STRING); } } if (null == resourceName) resourceName = resourceUri; return resourceName; } }); return t; } catch (DatabaseException e) { } return null; } private String getName() { try { String t = session.syncRequest(new Read() { @Override public String perform(ReadGraph g) throws DatabaseException { Layer0 l0 = Layer0.getInstance(g); resourceName = g.getPossibleRelatedValue(resource, l0.HasName, Bindings.STRING); if (null == resourceName) { Set types = g.getTypes(resource); if (types.size() > 0) { Iterator i = types.iterator(); Resource r = i.next(); resourceName = g.getPossibleRelatedValue(r, l0.HasName, Bindings.STRING); } } if (null == resourceName) resourceName = resourceUri; return resourceName; } }); return t; } catch (DatabaseException e) { } return null; } private Resource getParent() { try { Resource parent = session.syncRequest(new Read() { @Override public Resource perform(ReadGraph g) throws DatabaseException { Layer0 l0 = Layer0.getInstance(g); return g.getPossibleObject(resource, l0.PartOf); } }); return parent; } catch (DatabaseException e) { } return null; } public String toString() { if (null == resourceName && null != resourceUri) return getNameByUri(); else if (null != resource && null == resourceUri) return getName(); return resourceName; } @Override boolean hasChildren() { Resource p = getParent(); if (null != p) return true; else return false; } @Override Object[] getChildren() { Resource p = getParent(); if (null == p) return new Object[0]; Object[] objects = new Object[1]; objects[0] = new ResourceElement(session, p); return objects; } }