/******************************************************************************* * 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.Collection; import java.util.Iterator; import org.eclipse.jface.action.Action; 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.TreeColumnLayout; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.resource.LocalResourceManager; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.TreeViewerColumn; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPartSite; import org.eclipse.ui.PlatformUI; import org.simantics.db.ChangeSetIdentifier; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.WriteGraph; import org.simantics.db.common.CommentMetadata; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.service.XSupport; import org.simantics.layer0.Layer0; import org.simantics.team.Activator; import org.simantics.team.internal.DebugPolicy; import org.simantics.team.internal.Images; import org.simantics.ui.SimanticsUI; import org.simantics.utils.ui.ExceptionUtils; import org.simantics.utils.ui.dialogs.ShowError; /** * @author Kalle Kondelin */ public class HistoryView extends TreeView { public HistoryView() { } private void createPopupMenu() { final MenuManager mm = new MenuManager("Graph History Popup", "#GraphHistoryPopup"); mm.setRemoveAllWhenShown(true); mm.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { manager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); } }); Menu menu = mm.createContextMenu(treeViewer.getControl()); treeViewer.getControl().setMenu(menu); IWorkbenchPartSite site = getSite(); if (null != site) site.registerContextMenu(mm.getId(), mm, treeViewer); treeViewer.getControl().addMouseListener(new GraphHistoryMouseAdapter()); getSite().setSelectionProvider(treeViewer); } @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 idColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); TreeViewerColumn dateColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); TreeViewerColumn commentColumn = new TreeViewerColumn(treeViewer, SWT.LEFT); idColumn.setLabelProvider(new IdColumnLabelProvider()); dateColumn.setLabelProvider(new DateColumnLabelProvider()); commentColumn.setLabelProvider(new CommentColumnLabelProvider()); idColumn.getColumn().setText("Id"); idColumn.getColumn().setWidth(20); ad.setColumnData(idColumn.getColumn(), new ColumnWeightData(50, 20)); dateColumn.getColumn().setText("Date"); dateColumn.getColumn().setWidth(20); ad.setColumnData(dateColumn.getColumn(), new ColumnWeightData(50, 40)); commentColumn.getColumn().setText("Comment"); commentColumn.getColumn().setWidth(20); ad.setColumnData(commentColumn.getColumn(), new ColumnWeightData(50, 50)); final HistoryContentProvider contentProvider = new HistoryContentProvider(SimanticsUI.getSession()); treeViewer.setContentProvider(contentProvider); //viewer.setSorter(new ViewerSorter()); treeViewer.setInput(this); getViewSite().getActionBars().getToolBarManager().add(new Action("Previous", Activator.PREVIOUS_ICON) { @Override public void run() { contentProvider.previous(); } }); getViewSite().getActionBars().getToolBarManager().add(new Action("Next", Activator.NEXT_ICON) { @Override public void run() { contentProvider.next(); } }); getViewSite().getActionBars().getToolBarManager().add(new Action("Get Graph History", Activator.REFRESH_ICON) { @Override public void run() { contentProvider.refresh(); } }); if (DebugPolicy.DEBUG) { getViewSite().getActionBars().getToolBarManager().add(new Action("Debug", Activator.DEBUG_ICON) { @Override public void run() { Session s = SimanticsUI.getSession(); try { s.sync(new WriteRequest() { @Override public void perform(WriteGraph graph) throws DatabaseException { for (DebugPolicy.Action da : DebugPolicy.actions) { switch (da) { default: break; case CorruptClusterAction: corruptClusterAction(graph); break; case DebugCommitAction: debugCommitAction(graph); break; } } } }); } catch (DatabaseException e) { ShowError.showError("Debug Action Failed", e.getMessage(), e); Logger.defaultLogError("Debug action failed.", e); } } }); getViewSite().getActionBars().getToolBarManager().add(new Action("Exit", Activator.EXIT_ICON) { @Override public void run() { System.out.println("exit"); PlatformUI.getWorkbench().close(); System.exit(0); } }); } new ItemDetailToolTip(treeViewer, treeViewer.getTree(), null); createPopupMenu(); } static class HistoryContentProvider extends ChangeSetProvider { class HistoryElement extends ChangeSetElement { HistoryElement(Session session, ChangeSetIdentifier cs) { super(session, cs); } } private long topChangeSet; // Identifies first displayed change set. Zero if head. private final int CS_LIMIT = 100; // Max number of change sets per page. private HistoryElement[] changeSetIds; HistoryContentProvider(Session session) { super(session); topChangeSet = 0; } @Override public void refresh() { topChangeSet = 0; super.refresh(); } @Override public Object[] getElements(Object inputElement) { try { if (0 != topChangeSet) return changeSetIds; changeSetIds = getElements(managementSupport.getHeadRevisionId()); } catch (DatabaseException e) { ExceptionUtils.logAndShowError(e); changeSetIds = new HistoryElement[0]; } return changeSetIds; } private HistoryElement[] getElements(long head) { try { if (head < 1) return new HistoryElement[0]; Collection cids; long min = Math.max(1, head - CS_LIMIT); cids = managementSupport.getChangeSetIdentifiers(min, head); if (null == cids) changeSetIds = new HistoryElement[0]; else { changeSetIds = new HistoryElement[cids.size()]; Iterator it = cids.iterator(); int i = cids.size(); while (it.hasNext()) { changeSetIds[--i] = new HistoryElement(session, it.next()); } assert(i == 0); } } catch (DatabaseException e) { ExceptionUtils.logAndShowError(e); changeSetIds = new HistoryElement[0]; } return changeSetIds; } void next() { if (0 != topChangeSet) { long head = 0; try { head = managementSupport.getHeadRevisionId(); } catch (DatabaseException e) { Logger.defaultLogError(e); } if (topChangeSet + CS_LIMIT > head) topChangeSet = 0; else topChangeSet += CS_LIMIT; changeSetIds = getElements(topChangeSet); } super.refresh(); } void previous() { long head = 0; try { head = managementSupport.getHeadRevisionId(); if (0 == topChangeSet) topChangeSet = head; if (topChangeSet > CS_LIMIT + 1) topChangeSet -= CS_LIMIT; changeSetIds = getElements(topChangeSet); } catch (DatabaseException e) { Logger.defaultLogError(e); } super.refresh(); } } static class GraphHistoryMouseAdapter extends MouseAdapter { final boolean DEBUG = false; public GraphHistoryMouseAdapter() { } protected ISelection getClickedContext(MouseEvent e) { final Tree tree = (Tree)e.getSource(); Point point = new Point(e.x, e.y); TreeItem item = tree.getItem(point); // No selectable item at point? if (item == null) return null; tree.select(item); Object data = item.getData(); if (DEBUG) System.out.println("tree item data: " + data); return null; } @Override public void mouseUp(MouseEvent e) { ISelection context = getClickedContext(e); if (context == null) return; // Tree tree = (Tree)e.getSource(); } @Override public void mouseDoubleClick(MouseEvent e) { ISelection context = getClickedContext(e); if (context == null) return; // Tree tree = (Tree)e.getSource(); } } private static void corruptClusterAction(WriteGraph graph) throws DatabaseException { XSupport xs = graph.getService(XSupport.class); // Layer0 l0 = Layer0.getInstance(graph); Resource r = graph.newResource(); String msg = "Corrupt cluster r=" + r; System.out.println(msg); CommentMetadata cm = graph.getMetadata(CommentMetadata.class); cm.add(msg); xs.corruptCluster(r); Resource rr = graph.newResource(); msg = "Corrupt cluster rr=" + rr; System.out.println(msg); cm.add(msg); xs.corruptCluster(rr); graph.addMetadata(cm); // Add comment to change set. } private static void debugCommitAction(WriteGraph graph) throws DatabaseException { Layer0 l0 = Layer0.getInstance(graph); CommentMetadata cm = graph.getMetadata(CommentMetadata.class); graph.addMetadata(cm.add("Debug commit.")); Resource root = graph.newResource(); graph.claim(root, l0.InstanceOf, l0.Entity); graph.claimLiteral(root, l0.HasName, "Debug Resource Root"); Resource project = graph.getResource("http://Projects/Development%20Project"); graph.claim(root, l0.PartOf, project); final int N = 1<<20; int count = 1; for (int i=0; i