| /******************************************************************************* |
| * Copyright (c) 2008-2011 Chair for Applied Software Engineering, |
| * Technische Universitaet Muenchen. |
| * 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: |
| ******************************************************************************/ |
| package org.eclipse.emf.emfstore.internal.client.ui.views.historybrowserview; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.LinkedHashSet; |
| import java.util.List; |
| import java.util.Set; |
| import java.util.concurrent.Callable; |
| |
| import org.apache.commons.lang.StringUtils; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.edit.provider.ComposedAdapterFactory; |
| import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; |
| import org.eclipse.emf.emfstore.client.ESLocalProject; |
| import org.eclipse.emf.emfstore.client.util.ESVoidCallable; |
| import org.eclipse.emf.emfstore.internal.client.common.UnknownEMFStoreWorkloadCommand; |
| import org.eclipse.emf.emfstore.internal.client.model.ESWorkspaceProviderImpl; |
| import org.eclipse.emf.emfstore.internal.client.model.ProjectSpace; |
| import org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ServerCall; |
| import org.eclipse.emf.emfstore.internal.client.model.impl.api.ESWorkspaceImpl; |
| import org.eclipse.emf.emfstore.internal.client.model.util.ProjectSpaceContainer; |
| import org.eclipse.emf.emfstore.internal.client.observers.DeleteProjectSpaceObserver; |
| import org.eclipse.emf.emfstore.internal.client.ui.Activator; |
| import org.eclipse.emf.emfstore.internal.client.ui.common.RunInUI; |
| import org.eclipse.emf.emfstore.internal.client.ui.controller.AbstractEMFStoreUIController; |
| import org.eclipse.emf.emfstore.internal.client.ui.dialogs.EMFStoreMessageDialog; |
| import org.eclipse.emf.emfstore.internal.client.ui.views.changes.ChangePackageVisualizationHelper; |
| import org.eclipse.emf.emfstore.internal.client.ui.views.historybrowserview.graph.IPlotCommit; |
| import org.eclipse.emf.emfstore.internal.client.ui.views.historybrowserview.graph.PlotCommitProvider; |
| import org.eclipse.emf.emfstore.internal.client.ui.views.historybrowserview.graph.PlotLane; |
| import org.eclipse.emf.emfstore.internal.client.ui.views.historybrowserview.graph.SWTPlotRenderer; |
| import org.eclipse.emf.emfstore.internal.client.ui.views.scm.SCMContentProvider; |
| import org.eclipse.emf.emfstore.internal.common.model.ModelElementId; |
| import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil; |
| import org.eclipse.emf.emfstore.internal.server.conflictDetection.ModelElementIdToEObjectMappingImpl; |
| import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESHistoryInfoImpl; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.HistoryInfo; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.ModelElementQuery; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.PrimaryVersionSpec; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.RangeQuery; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.VersionSpec; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.VersioningFactory; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.Versions; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.AbstractOperation; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.CompositeOperation; |
| import org.eclipse.emf.emfstore.internal.server.model.versioning.util.HistoryQueryBuilder; |
| import org.eclipse.emf.emfstore.server.ESCloseableIterable; |
| import org.eclipse.emf.emfstore.server.exceptions.ESException; |
| import org.eclipse.emf.emfstore.server.model.ESHistoryInfo; |
| import org.eclipse.emf.emfstore.server.model.query.ESHistoryQuery; |
| import org.eclipse.emf.emfstore.server.model.query.ESModelElementQuery; |
| import org.eclipse.emf.emfstore.server.model.versionspec.ESVersionSpec; |
| import org.eclipse.jface.action.Action; |
| import org.eclipse.jface.action.IToolBarManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.dialogs.InputDialog; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.layout.GridDataFactory; |
| import org.eclipse.jface.layout.GridLayoutFactory; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.viewers.TreeViewerColumn; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Link; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Tree; |
| import org.eclipse.swt.widgets.TreeItem; |
| import org.eclipse.swt.widgets.Widget; |
| import org.eclipse.ui.IActionBars; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.dialogs.ElementListSelectionDialog; |
| import org.eclipse.ui.part.ViewPart; |
| |
| /** |
| * This eclipse views displays the version history of EMFStore. |
| * |
| * @author wesendon |
| * @author Aumann |
| * @author Hodaie |
| * @author Shterev |
| * |
| */ |
| // TODO: review setInput methods |
| public class HistoryBrowserView extends ViewPart implements ProjectSpaceContainer { |
| |
| // icons |
| private static final String EXPAND_ALL_GIF = "icons/expandall.gif"; //$NON-NLS-1$ |
| private static final String COLLAPSE_ALL_GIF = "icons/collapseall.gif"; //$NON-NLS-1$ |
| |
| // Config |
| private static final int UPPER_LIMIT = 10; |
| private static final int LOWER_LIMIT = 20; |
| |
| // model state |
| private ProjectSpace projectSpace; |
| private EObject modelElement; |
| |
| private List<HistoryInfo> infos; |
| private PrimaryVersionSpec centerVersion; |
| private boolean showAllVersions; |
| |
| // viewer |
| private TreeViewerWithModelElementSelectionProvider viewer; |
| private SWTPlotRenderer renderer; |
| private Link noProjectHint; |
| |
| // Columns |
| private TreeViewerColumn changeColumn; |
| private TreeViewerColumn branchColumn; |
| private TreeViewerColumn commitColumn; |
| private TreeViewerColumn authorColumn; |
| private static final int BRANCH_COLUMN = 1; |
| |
| // content/label provider |
| private SCMContentProvider contentProvider; |
| private PlotCommitProvider commitProvider; |
| private AdapterFactoryLabelProvider adapterFactoryLabelProvider; |
| private HistorySCMLabelProvider changeLabel; |
| private LogMessageColumnLabelProvider commitLabel; |
| |
| // actions |
| private ExpandCollapseAction expandAndCollapse; |
| private boolean isUnlinkedFromNavigator; |
| private Action showAllBranches; |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ProjectSpace getProjectSpace() { |
| return projectSpace; |
| } |
| |
| @Override |
| public void createPartControl(Composite parent) { |
| GridLayoutFactory.fillDefaults().applyTo(parent); |
| |
| initNoProjectHint(parent); |
| |
| // init viewer |
| viewer = new TreeViewerWithModelElementSelectionProvider(parent); |
| GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getControl()); |
| final Tree tree = viewer.getTree(); |
| tree.setHeaderVisible(true); |
| ColumnViewerToolTipSupport.enableFor(viewer); |
| getSite().setSelectionProvider(viewer); |
| |
| initMenuManager(); |
| |
| changeColumn = createColumn(Messages.HistoryBrowserView_Changes, 250); |
| branchColumn = createColumn(Messages.HistoryBrowserView_Branches, 150); |
| commitColumn = createColumn(Messages.HistoryBrowserView_CommitMessage, 250); |
| authorColumn = createColumn(Messages.HistoryBrowserView_AuthorAndDate, 250); |
| |
| initContentAndLabelProvider(); |
| initGraphRenderer(); |
| initToolBar(); |
| initProjectDeleteListener(); |
| } |
| |
| private void initContentAndLabelProvider() { |
| contentProvider = new SCMContentProvider(); |
| commitProvider = new PlotCommitProvider(); |
| viewer.setContentProvider(contentProvider); |
| |
| changeLabel = new HistorySCMLabelProvider(); |
| changeColumn.setLabelProvider(changeLabel); |
| branchColumn.setLabelProvider(new BranchGraphLabelProvider()); |
| commitLabel = new LogMessageColumnLabelProvider(); |
| commitColumn.setLabelProvider(commitLabel); |
| authorColumn.setLabelProvider(new CommitInfoColumnLabelProvider()); |
| |
| adapterFactoryLabelProvider = new AdapterFactoryLabelProvider(new ComposedAdapterFactory( |
| ComposedAdapterFactory.Descriptor.Registry.INSTANCE)); |
| } |
| |
| private void initGraphRenderer() { |
| renderer = new SWTPlotRenderer(viewer.getTree().getDisplay()); |
| // XXX SWT.PaintItem is not available in RAP, so we are using the numerical constant here |
| viewer.getTree().addListener(/* SWT.PaintItem */42, new Listener() { |
| public void handleEvent(Event event) { |
| doPaint(event); |
| } |
| |
| }); |
| } |
| |
| private void doPaint(Event event) { |
| if (event.index != BRANCH_COLUMN) { |
| return; |
| } |
| |
| Object data; |
| TreeItem currItem = (TreeItem) event.item; |
| data = currItem.getData(); |
| boolean isCommitItem = true; |
| |
| while (!(data instanceof HistoryInfo)) { |
| isCommitItem = false; |
| currItem = currItem.getParentItem(); |
| if (currItem == null) { |
| // no history info in parent hierarchy, do not draw. |
| // Happens e.g. if the user deactivates showing the commits |
| return; |
| } |
| data = currItem.getData(); |
| } |
| |
| final IPlotCommit c = commitProvider.getCommitFor((HistoryInfo) data, !isCommitItem); |
| final PlotLane lane = c.getLane(); |
| if (lane != null && lane.getSaturatedColor().isDisposed()) { |
| return; |
| } |
| // if (highlight != null && c.has(highlight)) |
| // event.gc.setFont(hFont); |
| // else |
| event.gc.setFont(PlatformUI.getWorkbench().getDisplay().getSystemFont()); |
| |
| renderer.paint(event, c); |
| } |
| |
| private TreeViewerColumn createColumn(String label, int width) { |
| final TreeViewerColumn column = new TreeViewerColumn(viewer, SWT.MULTI); |
| column.getColumn().setText(label); |
| column.getColumn().setWidth(width); |
| return column; |
| } |
| |
| // TODO review this stuff |
| private void initMenuManager() { |
| final MenuManager menuMgr = new MenuManager(); |
| menuMgr.add(new Separator("additions")); //$NON-NLS-1$ |
| getSite().registerContextMenu(menuMgr, viewer); |
| final Control control = viewer.getControl(); |
| final Menu menu = menuMgr.createContextMenu(control); |
| control.setMenu(menu); |
| getSite().registerContextMenu(menuMgr, viewer); |
| } |
| |
| /** |
| * Reloads the view with the current parameters. |
| */ |
| public void refresh() { |
| RunInUI.run(new Callable<Void>() { |
| public Void call() throws Exception { |
| setDescription(); |
| return null; |
| } |
| }); |
| resetExpandCollapse(); |
| if (projectSpace == null || modelElement == null) { |
| RunInUI.run(new ESVoidCallable() { |
| @Override |
| public void run() { |
| viewer.setInput(Collections.EMPTY_LIST); |
| } |
| }); |
| return; |
| } |
| infos = getHistoryInfos(); |
| addBaseVersionTag(infos); |
| resetProviders(infos); |
| viewer.setInput(infos); |
| } |
| |
| private void addBaseVersionTag(List<HistoryInfo> infos) { |
| final HistoryInfo historyInfo = getHistoryInfo(projectSpace.getBaseVersion()); |
| if (historyInfo != null) { |
| historyInfo.getTagSpecs().add(Versions.createTAG( |
| ESVersionSpec.BASE, ESVersionSpec.GLOBAL)); |
| } |
| } |
| |
| private void resetExpandCollapse() { |
| expandAndCollapse.setChecked(false); |
| expandAndCollapse.setImage(true); |
| } |
| |
| private void setDescription() { |
| if (projectSpace == null) { |
| setContentDescription(Messages.HistoryBrowserView_NoSelection); |
| showNoProjectHint(true); |
| return; |
| } |
| String label = Messages.HistoryBrowserView_HistoryFor; |
| if (modelElement == projectSpace) { |
| label += projectSpace.getProjectName() + " [" + projectSpace.getBaseVersion().getBranch() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ |
| } else { |
| label += adapterFactoryLabelProvider.getText(modelElement); |
| } |
| showNoProjectHint(false); |
| setContentDescription(label); |
| } |
| |
| private List<HistoryInfo> getHistoryInfos() { |
| final Shell shell = getViewSite().getShell(); |
| |
| final List<HistoryInfo> result = new AbstractEMFStoreUIController<List<HistoryInfo>>(shell, true, |
| false) { |
| @Override |
| public List<HistoryInfo> doRun(final IProgressMonitor monitor) throws ESException { |
| return new UnknownEMFStoreWorkloadCommand<List<HistoryInfo>>(monitor) { |
| @Override |
| public List<HistoryInfo> run(final IProgressMonitor monitor) throws ESException { |
| final List<HistoryInfo> historyInfosFromServer = getHistoryInfosFromServer(monitor); |
| return historyInfosFromServer; |
| } |
| }.execute(); // UnknownEMFStoreWorkloadCommand |
| } |
| }.execute(); // AbstractEMFStoreUIController |
| |
| return result != null ? result : new ArrayList<HistoryInfo>(); |
| } |
| |
| private List<HistoryInfo> getHistoryInfosFromServer(final IProgressMonitor monitor) |
| throws ESException { |
| |
| return new ServerCall<List<HistoryInfo>>(projectSpace) { |
| @Override |
| protected List<HistoryInfo> run() throws ESException { |
| monitor.beginTask(Messages.HistoryBrowserView_FetchingHistory, 100); |
| final List<HistoryInfo> historyInfos = getLocalChanges(); |
| monitor.worked(10); |
| if (projectSpace != modelElement) { |
| final List<ESHistoryInfo> infos = modelElementQuery(); |
| for (final ESHistoryInfo info : infos) { |
| historyInfos.add(((ESHistoryInfoImpl) info).toInternalAPI()); |
| } |
| } else { |
| // TODO monitor |
| final List<ESHistoryInfo> infos = rangeQuery(); |
| for (final ESHistoryInfo info : infos) { |
| historyInfos.add(((ESHistoryInfoImpl) info).toInternalAPI()); |
| } |
| } |
| monitor.worked(90); |
| return historyInfos; |
| } |
| |
| }.execute(); // ServerCall |
| |
| } |
| |
| private List<ESHistoryInfo> modelElementQuery() throws ESException { |
| final ModelElementQuery query = HistoryQueryBuilder.modelelementQuery( |
| centerVersion, |
| Arrays.asList(ModelUtil.getModelElementId(modelElement)), |
| UPPER_LIMIT, |
| LOWER_LIMIT, |
| showAllVersions, |
| true); |
| // TODO: proivde util method |
| final ESHistoryQuery<ESModelElementQuery> api = query.toAPI(); |
| final List<ESHistoryInfo> infos = projectSpace.toAPI().getHistoryInfos(api, new NullProgressMonitor()); |
| return infos; |
| } |
| |
| private List<ESHistoryInfo> rangeQuery() throws ESException { |
| final RangeQuery<?> rangeQuery = HistoryQueryBuilder |
| .rangeQuery( |
| centerVersion, |
| UPPER_LIMIT, |
| LOWER_LIMIT, |
| showAllVersions, true, true, true); |
| final List<ESHistoryInfo> infos = projectSpace.toAPI().getHistoryInfos( |
| rangeQuery.toAPI(), |
| new NullProgressMonitor()); |
| return infos; |
| } |
| |
| private List<HistoryInfo> getLocalChanges() { |
| |
| final ArrayList<HistoryInfo> revisions = new ArrayList<HistoryInfo>(); |
| if (projectSpace != null) { |
| // TODO: add a feature "hide local revision" |
| final HistoryInfo localHistoryInfo = VersioningFactory.eINSTANCE.createHistoryInfo(); |
| final AbstractChangePackage changePackage = projectSpace.getLocalChangePackage(false); |
| // filter for modelelement, do additional sanity check as the |
| // project space could've been also selected |
| if (modelElement != null && projectSpace.getProject().contains(modelElement)) { |
| final Set<AbstractOperation> operationsToRemove = new LinkedHashSet<AbstractOperation>(); |
| final ESCloseableIterable<AbstractOperation> operations = changePackage.operations(); |
| try { |
| for (final AbstractOperation operation : operations.iterable()) { |
| |
| if (!operation.getAllInvolvedModelElements().contains( |
| ModelUtil.getProject(modelElement).getModelElementId(modelElement))) { |
| operationsToRemove.add(operation); |
| } |
| } |
| } finally { |
| operations.close(); |
| } |
| // TODO: LCP - bummer.. |
| // changePackage.getOperations().removeAll(operationsToRemove); |
| } |
| // TODO: LCP |
| // localHistoryInfo.setChangePackage(changePackage); |
| final PrimaryVersionSpec versionSpec = VersioningFactory.eINSTANCE.createPrimaryVersionSpec(); |
| versionSpec.setIdentifier(-1); |
| localHistoryInfo.setPrimarySpec(versionSpec); |
| localHistoryInfo.setPreviousSpec(ModelUtil.clone(projectSpace.getBaseVersion())); |
| revisions.add(localHistoryInfo); |
| } |
| return revisions; |
| } |
| |
| private void resetProviders(List<HistoryInfo> infos) { |
| // TODO: LCP |
| final ArrayList<AbstractChangePackage> cps = new ArrayList<AbstractChangePackage>(); |
| for (final HistoryInfo info : infos) { |
| if (info.getChangePackage() != null) { |
| cps.add(info.getChangePackage()); |
| } |
| } |
| |
| final ChangePackageVisualizationHelper newHelper = new ChangePackageVisualizationHelper( |
| new ModelElementIdToEObjectMappingImpl(projectSpace.getProject(), cps)); |
| changeLabel.setProject(projectSpace.getProject()); |
| changeLabel.setChangePackageVisualizationHelper(newHelper); |
| commitLabel.setProject(projectSpace.getProject()); |
| commitLabel.setChangePackageVisualizationHelper(newHelper); |
| commitProvider.reset(infos); |
| } |
| |
| /** |
| * Displays the history for the given input. |
| * |
| * @param input eobject in projectspace or projectspace itself |
| */ |
| public void setInput(EObject input) { |
| try { |
| if (input instanceof ProjectSpace) { |
| projectSpace = (ProjectSpace) input; |
| } else if (input != null) { |
| final ESWorkspaceImpl workspace = ESWorkspaceProviderImpl.getInstance().getWorkspace(); |
| projectSpace = workspace.toInternalAPI().getProjectSpace(ModelUtil.getProject(input)); |
| } else { |
| projectSpace = null; |
| } |
| modelElement = input; |
| |
| showAll(true); |
| setCenterVersion(); |
| refresh(); |
| } catch (final ESException e) { |
| } |
| } |
| |
| /** |
| * Sets a {@link ESLocalProject} as an input for the view. The history for the input will be shown. |
| * |
| * @param localProject the project to show the history for. |
| */ |
| public void setInput(ESLocalProject localProject) { |
| setInput((EObject) localProject); |
| } |
| |
| private void showAll(boolean show) { |
| showAllVersions = show; |
| showAllBranches.setChecked(show); |
| } |
| |
| private void setCenterVersion() { |
| if (projectSpace != null) { |
| centerVersion = projectSpace.getBaseVersion(); |
| } else { |
| centerVersion = null; |
| } |
| } |
| |
| private void showNoProjectHint(boolean b) { |
| noProjectHint.setVisible(b); |
| noProjectHint.getParent().layout(); |
| } |
| |
| private void initNoProjectHint(final Composite parent) { |
| noProjectHint = new Link(parent, SWT.WRAP); |
| GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER).grab(true, false).applyTo(noProjectHint); |
| |
| noProjectHint |
| .setText(Messages.HistoryBrowserView_SelectProjectOrCallHistory); |
| noProjectHint.addSelectionListener(new SelectionListener() { |
| public void widgetSelected(SelectionEvent e) { |
| final ElementListSelectionDialog elsd = new ElementListSelectionDialog(parent.getShell(), |
| new ESBrowserLabelProvider()); |
| final List<ProjectSpace> relevantProjectSpaces = new ArrayList<ProjectSpace>(); |
| final ESWorkspaceImpl workspace = ESWorkspaceProviderImpl.getInstance().getWorkspace(); |
| for (final ProjectSpace ps : workspace.toInternalAPI().getProjectSpaces()) { |
| if (ps.getUsersession() != null) { |
| relevantProjectSpaces.add(ps); |
| } |
| } |
| elsd.setElements(relevantProjectSpaces.toArray()); |
| elsd.setMultipleSelection(false); |
| elsd.setTitle(Messages.HistoryBrowserView_SelectProjectTitle); |
| elsd.setMessage(Messages.HistoryBrowserView_SelectProjectMsg); |
| if (Window.OK == elsd.open()) { |
| for (final Object o : elsd.getResult()) { |
| final ProjectSpace resultSelection = (ProjectSpace) o; |
| if (resultSelection != null) { |
| setInput(resultSelection); |
| } |
| break; |
| } |
| } |
| } |
| |
| public void widgetDefaultSelected(SelectionEvent e) { |
| widgetSelected(e); |
| } |
| }); |
| } |
| |
| private void initProjectDeleteListener() { |
| ESWorkspaceProviderImpl.getObserverBus().register(new DeleteProjectSpaceObserver() { |
| public void projectSpaceDeleted(ProjectSpace projectSpace) { |
| if (HistoryBrowserView.this.projectSpace == projectSpace) { |
| setInput((EObject) null); |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public void dispose() { |
| adapterFactoryLabelProvider.dispose(); |
| changeLabel.dispose(); |
| commitLabel.dispose(); |
| super.dispose(); |
| } |
| |
| @Override |
| public void setFocus() { |
| viewer.getControl().setFocus(); |
| } |
| |
| /** |
| * ==================================================================== |
| * |
| * TOOLBAR. |
| * |
| * ==================================================================== |
| */ |
| |
| private void initToolBar() { |
| final IActionBars bars = getViewSite().getActionBars(); |
| final IToolBarManager menuManager = bars.getToolBarManager(); |
| |
| addRefreshAction(menuManager); |
| addShowAllBranchesAction(menuManager); |
| addExpandAllAndCollapseAllAction(menuManager); |
| addNextAndPreviousAction(menuManager); |
| addJumpToRevisionAction(menuManager); |
| addLinkWithNavigatorAction(menuManager); |
| } |
| |
| private void addRefreshAction(IToolBarManager menuManager) { |
| final Action refresh = new Action() { |
| @Override |
| public void run() { |
| refresh(); |
| } |
| |
| }; |
| refresh.setImageDescriptor(Activator.getImageDescriptor("/icons/refresh.png")); //$NON-NLS-1$ |
| refresh.setToolTipText(Messages.HistoryBrowserView_Refresh); |
| menuManager.add(refresh); |
| } |
| |
| private void addNextAndPreviousAction(IToolBarManager menuManager) { |
| final Action prev = new Action() { |
| @Override |
| public void run() { |
| centerVersion = prevNextCenter(false); |
| refresh(); |
| } |
| |
| }; |
| prev.setImageDescriptor(Activator.getImageDescriptor("/icons/prev.png")); //$NON-NLS-1$ |
| prev.setToolTipText(Messages.HistoryBrowserView_PreviousItems); |
| menuManager.add(prev); |
| |
| final Action next = new Action() { |
| @Override |
| public void run() { |
| centerVersion = prevNextCenter(true); |
| refresh(); |
| } |
| |
| }; |
| next.setImageDescriptor(Activator.getImageDescriptor("/icons/next.png")); //$NON-NLS-1$ |
| next.setToolTipText(Messages.HistoryBrowserView_NextItems); |
| menuManager.add(next); |
| } |
| |
| private PrimaryVersionSpec prevNextCenter(boolean next) { |
| if (projectSpace == null || centerVersion == null) { |
| return null; |
| } |
| // all versions pages only based on version numbers |
| if (showAllVersions) { |
| return biggestOrSmallesInfo(next); |
| } |
| // if center is not on the selected branch (base version of ps) jump to base before paging |
| if (!projectSpace.getBaseVersion().getBranch().equals(centerVersion.getBranch())) { |
| return projectSpace.getBaseVersion(); |
| } |
| |
| // search next or prev version on given branch |
| HistoryInfo current = getHistoryInfo(centerVersion); |
| while (current != null) { |
| if (next) { |
| if (current.getNextSpec().size() > 0) { |
| final HistoryInfo nextInfo = getHistoryInfo(current.getNextSpec().get(0)); |
| if (nextInfo == null) { |
| return current.getPrimarySpec(); |
| } |
| current = nextInfo; |
| } else { |
| break; |
| } |
| } else { |
| if (current.getPreviousSpec() != null |
| && current.getPreviousSpec().getBranch().equals(projectSpace.getBaseVersion().getBranch())) { |
| final HistoryInfo prevInfo = getHistoryInfo(current.getPreviousSpec()); |
| if (prevInfo == null) { |
| return current.getPrimarySpec(); |
| } |
| current = prevInfo; |
| } else { |
| break; |
| } |
| } |
| } |
| |
| if (current == null) { |
| return centerVersion; |
| } |
| return current.getPrimarySpec(); |
| } |
| |
| private HistoryInfo getHistoryInfo(PrimaryVersionSpec version) { |
| if (version == null) { |
| return null; |
| } |
| for (final HistoryInfo info : infos) { |
| if (version.equals(info.getPrimarySpec())) { |
| return info; |
| } |
| } |
| return null; |
| } |
| |
| private PrimaryVersionSpec biggestOrSmallesInfo(boolean biggest) { |
| @SuppressWarnings("unchecked") |
| final List<HistoryInfo> input = (List<HistoryInfo>) viewer.getInput(); |
| if (input == null) { |
| return centerVersion; |
| } |
| final ArrayList<HistoryInfo> resultCandidates = new ArrayList<HistoryInfo>(input); |
| PrimaryVersionSpec result = centerVersion; |
| for (final HistoryInfo info : resultCandidates) { |
| if (info.getPrimarySpec().getIdentifier() != -1 |
| && (biggest && info.getPrimarySpec().compareTo(result) == 1 || !biggest && info.getPrimarySpec() |
| .compareTo(result) == -1)) { |
| result = info.getPrimarySpec(); |
| } |
| } |
| return result; |
| } |
| |
| private void addLinkWithNavigatorAction(IToolBarManager menuManager) { |
| isUnlinkedFromNavigator = Activator.getDefault().getDialogSettings().getBoolean("LinkWithNavigator"); //$NON-NLS-1$ |
| final Action linkWithNavigator = new Action(Messages.HistoryBrowserView_LinkWithNavigator, SWT.TOGGLE) { |
| |
| @Override |
| public void run() { |
| Activator.getDefault().getDialogSettings().put("LinkWithNavigator", !isChecked()); //$NON-NLS-1$ |
| isUnlinkedFromNavigator = !isChecked(); |
| } |
| |
| }; |
| linkWithNavigator.setImageDescriptor(Activator.getImageDescriptor("icons/link_with_editor.gif")); //$NON-NLS-1$ |
| linkWithNavigator.setToolTipText("Link with Navigator"); //$NON-NLS-1$ |
| linkWithNavigator.setChecked(!isUnlinkedFromNavigator); |
| menuManager.add(linkWithNavigator); |
| } |
| |
| private void addShowAllBranchesAction(IToolBarManager menuManager) { |
| showAllBranches = new Action("", SWT.TOGGLE) { //$NON-NLS-1$ |
| @Override |
| public void run() { |
| showAllVersions = isChecked(); |
| refresh(); |
| } |
| |
| }; |
| showAllBranches.setImageDescriptor(Activator.getImageDescriptor("icons/arrow_branch.png")); //$NON-NLS-1$ |
| showAllBranches.setToolTipText(Messages.HistoryBrowserView_ShowAllBranches); |
| showAllBranches.setChecked(true); |
| menuManager.add(showAllBranches); |
| } |
| |
| private void addJumpToRevisionAction(IToolBarManager menuManager) { |
| final Action jumpTo = new Action() { |
| @Override |
| public void run() { |
| final InputDialog inputDialog = new InputDialog(getSite().getShell(), |
| Messages.HistoryBrowserView_GoToRevision, |
| Messages.HistoryBrowserView_Revision, |
| StringUtils.EMPTY, |
| null); |
| if (inputDialog.open() == Window.OK) { |
| if (projectSpace != null) { |
| final PrimaryVersionSpec versionSpec = resolveVersion(inputDialog.getValue()); |
| if (versionSpec != null) { |
| showAll(true); |
| centerVersion = versionSpec; |
| refresh(); |
| } |
| } |
| } |
| } |
| |
| }; |
| jumpTo.setImageDescriptor(Activator.getImageDescriptor("/icons/magnifier.png")); //$NON-NLS-1$ |
| jumpTo.setToolTipText(Messages.HistoryBrowserView_GoToRevisionToolTip); |
| menuManager.add(jumpTo); |
| } |
| |
| private PrimaryVersionSpec resolveVersion(final String value) { |
| return new AbstractEMFStoreUIController<PrimaryVersionSpec>(getViewSite().getShell()) { |
| @Override |
| public PrimaryVersionSpec doRun(IProgressMonitor monitor) throws ESException { |
| return new UnknownEMFStoreWorkloadCommand<PrimaryVersionSpec>(monitor) { |
| @Override |
| public PrimaryVersionSpec run(IProgressMonitor monitor) throws ESException { |
| try { |
| return projectSpace.resolveVersionSpec(Versions.createPRIMARY( |
| VersionSpec.GLOBAL, Integer.parseInt(value)), new NullProgressMonitor()); |
| } catch (final ESException e) { |
| EMFStoreMessageDialog.showExceptionDialog( |
| Messages.HistoryBrowserView_VersionDoesNotExist, e); |
| } catch (final NumberFormatException e) { |
| MessageDialog.openError(getSite().getShell(), Messages.HistoryBrowserView_Error, |
| Messages.HistoryBrowserView_NumericValueExpected); |
| } |
| return null; |
| } |
| }.execute(); |
| } |
| }.execute(); |
| } |
| |
| private void addExpandAllAndCollapseAllAction(IToolBarManager menuManager) { |
| final ImageDescriptor expandImg = Activator.getImageDescriptor(EXPAND_ALL_GIF); |
| final ImageDescriptor collapseImg = Activator.getImageDescriptor(COLLAPSE_ALL_GIF); |
| |
| expandAndCollapse = new ExpandCollapseAction(StringUtils.EMPTY, SWT.TOGGLE, expandImg, collapseImg); |
| expandAndCollapse.setImageDescriptor(expandImg); |
| expandAndCollapse.setToolTipText(Messages.HistoryBrowserView_ExpandCollapseToggle); |
| menuManager.add(expandAndCollapse); |
| } |
| |
| /** |
| * Expand/Collapse action. |
| * |
| * @author wesendon |
| */ |
| private final class ExpandCollapseAction extends Action { |
| private final ImageDescriptor expandImg; |
| private final ImageDescriptor collapseImg; |
| |
| private ExpandCollapseAction(String text, int style, ImageDescriptor expandImg, ImageDescriptor collapseImg) { |
| super(text, style); |
| this.expandImg = expandImg; |
| this.collapseImg = collapseImg; |
| } |
| |
| @Override |
| public void run() { |
| if (!isChecked()) { |
| setImage(true); |
| viewer.collapseAll(); |
| } else { |
| setImage(false); |
| viewer.expandToLevel(2); |
| } |
| } |
| |
| public void setImage(boolean expand) { |
| setImageDescriptor(expand ? expandImg : collapseImg); |
| } |
| } |
| |
| /** |
| * Treeviewer that provides a model element selection for selected |
| * operations and mode element ids. |
| * |
| * @author koegel |
| */ |
| private final class TreeViewerWithModelElementSelectionProvider extends TreeViewer { |
| private TreeViewerWithModelElementSelectionProvider(Composite parent) { |
| super(parent, SWT.MULTI); |
| } |
| |
| @Override |
| protected Widget internalExpand(Object elementOrPath, boolean expand) { |
| // TODO Auto-generated method stub |
| return super.internalExpand(elementOrPath, expand); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * @see org.eclipse.jface.viewers.AbstractTreeViewer#getSelection() |
| */ |
| @Override |
| public ISelection getSelection() { |
| final Control control = getControl(); |
| |
| if (control == null || control.isDisposed()) { |
| return super.getSelection(); |
| } |
| |
| final Widget[] items = getSelection(getControl()); |
| if (items.length != 1) { |
| return super.getSelection(); |
| } |
| |
| final Widget item = items[0]; |
| final Object data = item.getData(); |
| if (data == null) { |
| return super.getSelection(); |
| } |
| |
| // TODO: remove assignment |
| final Object element = data; |
| EObject selectedModelElement = null; |
| |
| if (element instanceof CompositeOperation) { |
| selectedModelElement = handleCompositeOperation((CompositeOperation) element); |
| } else if (element instanceof AbstractOperation) { |
| selectedModelElement = handleAbstractOperation((AbstractOperation) element); |
| } else if (element instanceof ProjectSpace) { |
| selectedModelElement = ((ProjectSpace) element).getProject(); |
| } else if (element instanceof ModelElementId |
| && projectSpace.getProject().contains((ModelElementId) element)) { |
| selectedModelElement = projectSpace.getProject().getModelElement((ModelElementId) element); |
| } else if (projectSpace.getProject().contains((EObject) element)) { |
| selectedModelElement = (EObject) element; |
| } |
| |
| if (selectedModelElement != null) { |
| return new StructuredSelection(selectedModelElement); |
| } |
| |
| return super.getSelection(); |
| } |
| |
| private EObject handleCompositeOperation(CompositeOperation op) { |
| final AbstractOperation mainOperation = op.getMainOperation(); |
| if (mainOperation != null) { |
| final ModelElementId modelElementId = mainOperation.getModelElementId(); |
| final EObject modelElement = projectSpace.getProject().getModelElement(modelElementId); |
| return modelElement; |
| } |
| |
| return null; |
| } |
| |
| private EObject handleAbstractOperation(AbstractOperation op) { |
| final ModelElementId modelElementId = op.getModelElementId(); |
| final EObject modelElement = projectSpace.getProject().getModelElement(modelElementId); |
| return modelElement; |
| } |
| } |
| |
| } |