Java tutorial
/******************************************************************************* * Copyright (c) 2003 Jan Karstens, Andr Langhorst. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * Jan Karstens <jan.karstens@web.de> - initial implementation * Andr Langhorst <andre@masse.de> - extensions * Dmitry Mitskevich <dmitskevich@gmail.com> - support (migrate to Eclipse 3.4.1) *******************************************************************************/ package net.sf.versiontree.views; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import net.sf.versiontree.VersionTreePlugin; import net.sf.versiontree.data.BranchTree; import net.sf.versiontree.data.ITreeElement; import net.sf.versiontree.data.algo.ILayout; import net.sf.versiontree.layout.drawer.DrawerDispatcher; import net.sf.versiontree.layout.drawer.IDrawMethod; import net.sf.versiontree.popup.actions.CopyTagAction; import net.sf.versiontree.popup.actions.ShowEmptyBranchesAction; import net.sf.versiontree.popup.actions.ShowNABranchesAction; import net.sf.versiontree.ui.DetailTableProvider; import net.sf.versiontree.ui.LogEntrySelectionListener; import net.sf.versiontree.ui.TreeView; import net.sf.versiontree.ui.TreeViewConfig; import net.sf.versiontree.ui.VersionTreeImages; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRunnable; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.TextViewer; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableFontProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.Text; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.TeamException; import org.eclipse.team.internal.ccvs.core.CVSException; import org.eclipse.team.internal.ccvs.core.CVSProviderPlugin; import org.eclipse.team.internal.ccvs.core.CVSTag; import org.eclipse.team.internal.ccvs.core.CVSTeamProvider; import org.eclipse.team.internal.ccvs.core.ICVSFile; import org.eclipse.team.internal.ccvs.core.ICVSFolder; import org.eclipse.team.internal.ccvs.core.ICVSRemoteFile; import org.eclipse.team.internal.ccvs.core.ICVSResource; import org.eclipse.team.internal.ccvs.core.ILogEntry; import org.eclipse.team.internal.ccvs.core.client.Session; import org.eclipse.team.internal.ccvs.core.connection.CVSRepositoryLocation; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.resources.RemoteFile; import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin; import org.eclipse.team.internal.ccvs.ui.ICVSUIConstants; import org.eclipse.team.internal.ccvs.ui.IHelpContextIds; import org.eclipse.team.internal.ccvs.ui.SimpleContentProvider; import org.eclipse.team.internal.ccvs.ui.TextViewerAction; import org.eclipse.team.internal.ccvs.ui.actions.CVSAction; import org.eclipse.team.internal.ccvs.ui.actions.MoveRemoteTagAction; import org.eclipse.team.internal.ccvs.ui.actions.OpenLogEntryAction; import org.eclipse.team.internal.ccvs.ui.actions.TagAction; import org.eclipse.team.internal.ui.Utils; import org.eclipse.team.internal.ui.synchronize.SyncInfoModelElement; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IActionDelegate; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IPartListener2; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchPartReference; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.help.WorkbenchHelp; import org.eclipse.ui.ide.ResourceUtil; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.texteditor.ITextEditorActionConstants; /** * This ViewPart displays a version tree based on revision information * obtained for a CVS managed resource. */ public class VersionTreeView extends ViewPart implements LogEntrySelectionListener { public static final String VIEW_ID = "net.sf.versiontree.views.VersionTreeView"; //$NON-NLS-1$ private SashForm sashForm; private SashForm innerSashForm; private TreeView treeView; private TableViewer tableViewer; private DetailTableProvider detailProvider; private TextViewer commentViewer; private Text searchField; private TableViewer tagViewer; private Action refreshAction; private Action deepLayoutAction; private Action wideLayoutAction; private Action showEmptyBranchesAction; private Action showNABranchesAction; private Action getRevisionAction; private Action getContentsAction; private Action toggleHorVerDisplayAction; private Action linkWithEditorAction; private Action tagWithExistingAction; private Action copyTagAction; private TextViewerAction copyCommentAction; private TextViewerAction selectAllAction; private OpenLogEntryAction openActionDelegate; private Image branchImage; private Image versionImage; private Image lockedImage; private Image requestImage; private Image mergeToImage; private Image mergeFromImage; private Image closedImage; private ILogEntry[] entries; private ILogEntry currentEntry; private ILogEntry currentSelection; private String[][] tableData = new String[][] { { VersionTreePlugin.getResourceString("VersionTreeView.File"), "" }, { VersionTreePlugin.getResourceString("VersionTreeView.Revision"), "" }, { VersionTreePlugin.getResourceString("VersionTreeView.Date"), "" }, { VersionTreePlugin.getResourceString("VersionTreeView.Author"), "" }, { VersionTreePlugin.getResourceString("VersionTreeView.State"), "" }, }; private IFile file; private boolean linkingEnabled; private boolean shutdown; /** * The tree holding the revision structure. */ private BranchTree branchTree; private FetchLogEntriesJob fetchLogEntriesJob; private IPreferenceStore prefs; private final class TagLabelProvider extends LabelProvider implements ITableFontProvider { @Override public Image getImage(Object element) { if (element == null) { return null; } IPreferenceStore prefs = VersionTreePlugin.getDefault().getPreferenceStore(); CVSTag tag = (CVSTag) element; switch (tag.getType()) { case CVSTag.BRANCH: case CVSTag.HEAD: return branchImage; case CVSTag.VERSION: if (tag.getName().matches(prefs.getString(VersionTreePlugin.PREF_REGEX_LOCKED))) { return lockedImage; } if (tag.getName().matches(prefs.getString(VersionTreePlugin.PREF_REGEX_REQUEST))) { return requestImage; } if (tag.getName().matches(prefs.getString(VersionTreePlugin.PREF_REGEX_CLOSED))) { return closedImage; } if (tag.getName().matches(prefs.getString(VersionTreePlugin.PREF_REGEX_MERGE_TO))) { return mergeToImage; } if (tag.getName().matches(prefs.getString(VersionTreePlugin.PREF_REGEX_MERGE_FROM))) { return mergeFromImage; } return versionImage; } return null; } @Override public String getText(Object element) { return ((CVSTag) element).getName(); } public Font getFont(Object element, int columnIndex) { String branchFilter = treeView.getTreeViewConfig().getBranchFilter(); if (!branchFilter.isEmpty() && getText(element).contains(branchFilter)) { return JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT); } return null; } } /** * Content provider for the table in the detail view */ class ViewContentProvider implements IStructuredContentProvider { public void inputChanged(Viewer v, Object oldInput, Object newInput) { } public void dispose() { } public Object[] getElements(Object parent) { return tableData; } } private IPartListener partListener = new IPartListener() { public void partActivated(IWorkbenchPart part) { if (part instanceof IEditorPart) { editorActivated((IEditorPart) part); } } public void partBroughtToTop(IWorkbenchPart part) { if (part == VersionTreeView.this) { editorActivated(getViewSite().getPage().getActiveEditor()); } } public void partOpened(IWorkbenchPart part) { if (part == VersionTreeView.this) { editorActivated(getViewSite().getPage().getActiveEditor()); } } public void partClosed(IWorkbenchPart part) { } public void partDeactivated(IWorkbenchPart part) { } }; private IPartListener2 partListener2 = new IPartListener2() { public void partActivated(IWorkbenchPartReference ref) { } public void partBroughtToTop(IWorkbenchPartReference ref) { } public void partClosed(IWorkbenchPartReference ref) { } public void partDeactivated(IWorkbenchPartReference ref) { } public void partOpened(IWorkbenchPartReference ref) { } public void partHidden(IWorkbenchPartReference ref) { } public void partVisible(IWorkbenchPartReference ref) { if (ref.getPart(true) == VersionTreeView.this) { editorActivated(getViewSite().getPage().getActiveEditor()); } } public void partInputChanged(IWorkbenchPartReference ref) { } }; /** * Implementation is similar to: * org.eclipse.team.internal.ui.history.GenericHistoryView.selectionListener * * @see org.eclipse.team.internal.ui.history.GenericHistoryView */ private ISelectionListener selectionListener = new ISelectionListener() { public void selectionChanged(final IWorkbenchPart part, final ISelection selection) { if (!isLinkingEnabled() || !checkIfPageIsVisible()) { return; } if (selection instanceof IStructuredSelection == false) { return; } IStructuredSelection structSelection = (IStructuredSelection) selection; // always take the first element - this is not intended to work with multiple selection Object firstElement = structSelection.getFirstElement(); if (firstElement != null) { IResource resource; if (firstElement instanceof SyncInfoModelElement) { SyncInfoModelElement syncInfoModelElement = (SyncInfoModelElement) firstElement; resource = syncInfoModelElement.getSyncInfo().getLocal(); } else { resource = (IResource) Utils.getAdapter(firstElement, IResource.class); } if (firstElement instanceof ICVSRemoteFile) { ICVSRemoteFile remoteFile = (ICVSRemoteFile) firstElement; showVersionTree(remoteFile); } else { showVersionTree(resource); } } } }; /** * Job that fetches the CVS log entries. */ private class FetchLogEntriesJob extends Job { public ICVSFile cvsFile; public FetchLogEntriesJob() { super(VersionTreePlugin.getResourceString("VersionTreeView.fetchHistoryJob")); //$NON-NLS-1$ } public void setRemoteFile(ICVSFile file) { this.cvsFile = file; } @Override public IStatus run(IProgressMonitor monitor) { try { if (cvsFile != null && !shutdown) { IResource rc = cvsFile.getIResource(); entries = cvsFile.getLogEntries(monitor); if (entries.length == 0 && rc != null) { //Get the parent folder ICVSFolder folder = cvsFile.getParent(); if (folder.isManaged()) { String remoteFolderLocation = folder.getRemoteLocation(folder); if (remoteFolderLocation != null) { String remoteFileName = remoteFolderLocation .concat(Session.SERVER_SEPARATOR + cvsFile.getName()); //Create remote file CVSTeamProvider pro = (CVSTeamProvider) RepositoryProvider .getProvider(rc.getProject()); if (pro != null) { CVSWorkspaceRoot root = pro.getCVSWorkspaceRoot(); CVSRepositoryLocation location = CVSRepositoryLocation .fromString(root.getRemoteLocation().getLocation(false)); RemoteFile remFile = RemoteFile.create(remoteFileName, location); entries = remFile.getLogEntries(monitor); } } } } ILogEntry currentEntry = null; if (entries != null && entries.length > 0) { ICVSRemoteFile remoteFile = rc != null ? (ICVSRemoteFile) CVSWorkspaceRoot.getRemoteResourceFor(rc) : null; String revisionId = remoteFile != null ? remoteFile.getRevision() : null; // Create tree pulling entries from CVS repository branchTree = new BranchTree(entries, revisionId); // Find current revision if (revisionId != null) { for (ILogEntry entry : entries) { if (entry.getRevision().equals(revisionId)) { currentEntry = entry; break; } } } } else { branchTree = null; } final ILogEntry currentEntryFinal = currentEntry; getSite().getShell().getDisplay().asyncExec(new Runnable() { public void run() { if (treeView != null && !treeView.isDisposed()) { renderVersionTree(branchTree); setCurrentEntry(currentEntryFinal); } } }); } return Status.OK_STATUS; } catch (TeamException e) { return e.getStatus(); } } }; /** * The constructor. */ public VersionTreeView() { } /** * This is a callback that will allow us * to create the viewer and initialize it. */ @Override public void createPartControl(Composite parent) { prefs = VersionTreePlugin.getDefault().getPreferenceStore(); linkingEnabled = prefs.getBoolean(VersionTreePlugin.PREF_HISTORY_VIEW_EDITOR_LINKING); initializeImages(); sashForm = new SashForm(parent, prefs.getInt(VersionTreePlugin.PREF_DETAILS_POS)); sashForm.setLayoutData(new GridData(GridData.FILL_BOTH)); treeView = new TreeView(sashForm, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, this); innerSashForm = new SashForm(sashForm, SWT.VERTICAL); innerSashForm.setLayoutData(new GridData(GridData.FILL_BOTH)); tableViewer = createTableViewer(innerSashForm); tagViewer = createTagViewer(innerSashForm); commentViewer = createTextViewer(innerSashForm); searchField = new Text(innerSashForm, SWT.SEARCH); searchField .setMessage(VersionTreePlugin.getResourceString("VersionTreePreferencePage.Default_Branch_Filter")); searchField.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent e) { treeView.getTreeViewConfig().setBranchFilter(searchField.getText()); renderCurrentVersionTree(); tagViewer.refresh(); } }); sashForm.setWeights(new int[] { 65, 35 }); innerSashForm.setWeights(new int[] { 30, 30, 30, 10 }); makeActions(); hookContextMenu(); //hookDoubleClickAction(); contributeToActionBars(); // add listener for editor page activation - this is to support editor linking getSite().getPage().addPartListener(partListener); getSite().getPage().addPartListener(partListener2); // see GenericHistoryView behaviour getSite().getPage().addPostSelectionListener(selectionListener); } /** * Shows the version tree for the given IResource in the view. * * Only files are supported for now. */ public void showVersionTree(IResource resource) { if (resource != null && resource instanceof IFile) { IFile file = (IFile) resource; setFile(file); RepositoryProvider teamProvider = RepositoryProvider.getProvider(file.getProject(), CVSProviderPlugin.getTypeId()); if (teamProvider != null) { ICVSFile remoteFile = CVSWorkspaceRoot.getCVSFileFor(file); showVersionTree(remoteFile); } } else { setFile(null); this.setCurrentEntry(null); treeView.clear(); } } /** * Shows the version tree for the given ICVSRemoteFile in the view. */ public void showVersionTree(ICVSFile remoteFile) { if (remoteFile != null) { getLogEntries(remoteFile); } } /** * Relayouts and draws the current tree without connecting to the CVS * server. */ public void renderCurrentVersionTree() { if (branchTree != null) { renderVersionTree(branchTree); } } private void renderVersionTree(BranchTree bt) { treeView.clear(); if (bt == null) { return; } // Choose Drawers and dispatcher that will be supplied to walk algorithm IDrawMethod[] id = new IDrawMethod[1]; id[0] = treeView; // id[1] = new ConflictDrawer(); // for debugging alogrithms // id[2] = new SysOutDrawer(); // textual output //int direction = treeView.getTreeViewConfig().getDirection(); int direction = VersionTreePlugin.getDefault().getPreferenceStore() .getInt(VersionTreePlugin.PREF_DIRECTION); ILayout il = getLayoutAlgorithm(new DrawerDispatcher(id, direction)); il.walk(bt); treeView.show(); // draw connectors ITreeElement head = bt.getHeadBranch(); treeView.drawConnectors(head); } private ILayout getLayoutAlgorithm(DrawerDispatcher dp) { ILayout layout = treeView.getTreeViewConfig().getLayoutAlgorithm(); layout.configure(dp, treeView.getTreeViewConfig().drawEmptyBranches(), treeView.getTreeViewConfig().drawNABranches(), treeView.getTreeViewConfig().getBranchFilter()); return layout; } /** * @param theCurrentEntry */ private void updateTableData(ILogEntry theCurrentEntry) { DateFormat dateFormat = new SimpleDateFormat( VersionTreePlugin.getResourceString("VersionTreeView.DateFormat")); //$NON-NLS-1$ if (theCurrentEntry == null) { tableData[0][1] = ""; //$NON-NLS-1$ tableData[1][1] = ""; //$NON-NLS-1$ tableData[2][1] = ""; //$NON-NLS-1$ tableData[3][1] = ""; //$NON-NLS-1$ tableData[4][1] = ""; //$NON-NLS-1$ } else { tableData[0][1] = theCurrentEntry.getRemoteFile().getName(); tableData[1][1] = theCurrentEntry.getRevision(); tableData[2][1] = dateFormat.format(theCurrentEntry.getDate()); tableData[3][1] = theCurrentEntry.getAuthor(); tableData[4][1] = theCurrentEntry.getState(); } tableViewer.setInput(tableData); } private void getLogEntries(final ICVSFile remoteFile) { if (fetchLogEntriesJob == null) { fetchLogEntriesJob = new FetchLogEntriesJob(); } if (fetchLogEntriesJob.getState() != Job.NONE) { fetchLogEntriesJob.cancel(); try { fetchLogEntriesJob.join(); } catch (InterruptedException e) { CVSUIPlugin.log(CVSException.wrapException(e)); } } fetchLogEntriesJob.setRemoteFile(remoteFile); Utils.schedule(fetchLogEntriesJob, getViewSite()); } private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager manager) { VersionTreeView.this.fillContextMenu(manager); } }); Menu menu = menuMgr.createContextMenu(treeView); treeView.setMenu(menu); getSite().registerContextMenu(menuMgr, treeView.getSelectionProvider()); } private void contributeToActionBars() { IActionBars bars = getViewSite().getActionBars(); fillLocalPullDown(bars.getMenuManager()); fillLocalToolBar(bars.getToolBarManager()); } private void fillLocalToolBar(IToolBarManager manager) { manager.add(showNABranchesAction); manager.add(showEmptyBranchesAction); manager.add(refreshAction); manager.add(linkWithEditorAction); } private void fillLocalPullDown(IMenuManager manager) { manager.add(deepLayoutAction); manager.add(wideLayoutAction); manager.add(new Separator()); manager.add(showNABranchesAction); manager.add(showEmptyBranchesAction); manager.add(toggleHorVerDisplayAction); manager.add(refreshAction); } private void fillContextMenu(IMenuManager manager) { manager.add(getContentsAction); manager.add(getRevisionAction); manager.add(tagWithExistingAction); manager.add(new Separator()); // Other plug-ins can contribute there actions here manager.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); } private void makeActions() { CVSUIPlugin plugin = CVSUIPlugin.getPlugin(); // open action delegate openActionDelegate = new OpenLogEntryAction(); toggleHorVerDisplayAction = new Action( VersionTreePlugin.getResourceString("VersionTreeView.Toggle_Detail_View_Action")) { //$NON-NLS-1$ @Override public void run() { if (sashForm.getOrientation() == SWT.HORIZONTAL) { sashForm.setOrientation(SWT.VERTICAL); } else { sashForm.setOrientation(SWT.HORIZONTAL); } prefs.setValue(VersionTreePlugin.PREF_DETAILS_POS, sashForm.getOrientation()); } }; getContentsAction = getContextMenuAction( VersionTreePlugin.getResourceString("VersionTreeView.Get_Content_Action"), //$NON-NLS-1$ new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { ICVSRemoteFile remoteFile = currentSelection.getRemoteFile(); monitor.beginTask(null, 100); try { if (confirmOverwrite()) { InputStream in = remoteFile.getContents(new SubProgressMonitor(monitor, 50)); getFile().setContents(in, false, true, new SubProgressMonitor(monitor, 50)); } } catch (TeamException e) { throw new CoreException(e.getStatus()); } finally { monitor.done(); } } }); WorkbenchHelp.setHelp(getContentsAction, IHelpContextIds.GET_FILE_CONTENTS_ACTION); getRevisionAction = getContextMenuAction( VersionTreePlugin.getResourceString("VersionTreeView.Get_Sticky_Revision_Action"), //$NON-NLS-1$ new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { ICVSRemoteFile remoteFile = currentSelection.getRemoteFile(); try { if (confirmOverwrite()) { // CVSTeamProvider provider = (CVSTeamProvider) RepositoryProvider.getProvider(file.getProject()); CVSTag revisionTag = new CVSTag(remoteFile.getRevision(), CVSTag.VERSION); if (CVSAction.checkForMixingTags(getSite().getShell(), new IResource[] { getFile() }, revisionTag)) { //TODO update no longer available // provider.update(new IResource[] { file }, new Command.LocalOption[] { Update.IGNORE_LOCAL_CHANGES }, // revisionTag, true /*create backups*/, monitor); refresh(); } } } catch (TeamException e) { throw new CoreException(e.getStatus()); } } }); WorkbenchHelp.setHelp(getRevisionAction, IHelpContextIds.GET_FILE_REVISION_ACTION); // show/hide empty branches action showEmptyBranchesAction = new ShowEmptyBranchesAction(this, treeView); showEmptyBranchesAction .setImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_BRANCHES_CATEGORY)); showEmptyBranchesAction.setChecked(treeView.getTreeViewConfig().drawEmptyBranches()); // show/hide empty branches action showNABranchesAction = new ShowNABranchesAction(this, treeView); showNABranchesAction .setImageDescriptor(VersionTreeImages.getImageDescriptor(VersionTreeImages.IMG_NA_BRANCH)); showNABranchesAction.setChecked(treeView.getTreeViewConfig().drawNABranches()); // deep layout deepLayoutAction = new Action(VersionTreePlugin.getResourceString("VersionTreeView.Deep_Layout_Name"), //$NON-NLS-1$ IAction.AS_RADIO_BUTTON) { @Override public void run() { if (isChecked()) { treeView.getTreeViewConfig().setLayoutAlgorithm(TreeViewConfig.DEEP_LAYOUT); wideLayoutAction.setChecked(false); renderVersionTree(branchTree); } setChecked(true); } }; if (treeView.getTreeViewConfig().isLayoutSelected(TreeViewConfig.DEEP_LAYOUT)) { deepLayoutAction.setChecked(true); } // wide layout wideLayoutAction = new Action(VersionTreePlugin.getResourceString("VersionTreeView.Wide_Layout_Name"), //$NON-NLS-1$ IAction.AS_RADIO_BUTTON) { @Override public void run() { if (isChecked()) { treeView.getTreeViewConfig().setLayoutAlgorithm(TreeViewConfig.WIDE_LAYOUT); deepLayoutAction.setChecked(false); renderVersionTree(branchTree); } setChecked(true); } }; if (treeView.getTreeViewConfig().isLayoutSelected(TreeViewConfig.WIDE_LAYOUT)) { wideLayoutAction.setChecked(true); } // refresh action refreshAction = new Action(VersionTreePlugin.getResourceString("VersionTreeView.Refresh_View_Action")) {//$NON-NLS-1$ @Override public void run() { refresh(); } }; refreshAction.setToolTipText(VersionTreePlugin.getResourceString("VersionTreeView.Refresh_View_ToolTip")); //$NON-NLS-1$ refreshAction.setDisabledImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_REFRESH_DISABLED)); refreshAction.setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_REFRESH)); // Link with Editor (toolbar) linkWithEditorAction = new Action(VersionTreePlugin.getResourceString("VersionTreeView.linkWithLabel"), plugin.getImageDescriptor(ICVSUIConstants.IMG_LINK_WITH_EDITOR_ENABLED)) { @Override public void run() { setLinkingEnabled(isChecked()); } }; linkWithEditorAction.setToolTipText(VersionTreePlugin.getResourceString("VersionTreeView.linkWithLabel")); //$NON-NLS-1$ linkWithEditorAction .setHoverImageDescriptor(plugin.getImageDescriptor(ICVSUIConstants.IMG_LINK_WITH_EDITOR)); linkWithEditorAction.setChecked(isLinkingEnabled()); // Override MoveRemoteTagAction to work for log entries final IActionDelegate tagActionDelegate = new MoveRemoteTagAction() { @Override protected ICVSResource[] getSelectedCVSResources() { ICVSResource[] resources = super.getSelectedCVSResources(); if (resources == null || resources.length == 0) { ArrayList<ICVSRemoteFile> logEntrieFiles = null; if (!getSelection().isEmpty()) { logEntrieFiles = new ArrayList<ICVSRemoteFile>(); Iterator elements = getSelection().iterator(); while (elements.hasNext()) { Object next = elements.next(); if (next instanceof ILogEntry) { logEntrieFiles.add(((ILogEntry) next).getRemoteFile()); continue; } if (next instanceof IAdaptable) { IAdaptable a = (IAdaptable) next; Object adapter = a.getAdapter(ICVSResource.class); if (adapter instanceof ICVSResource) { logEntrieFiles.add(((ILogEntry) adapter).getRemoteFile()); continue; } } } } if (logEntrieFiles != null && !logEntrieFiles.isEmpty()) { return logEntrieFiles.toArray(new ICVSResource[logEntrieFiles.size()]); } } return resources; } }; tagWithExistingAction = new Action(VersionTreePlugin.getResourceString("VersionTreeView.TagWithExisting")) { //$NON-NLS-1$ @Override public void run() { if (getFile() == null) { return; } ISelection selection = treeView.getSelection(); if (!(selection instanceof IStructuredSelection)) { return; } IStructuredSelection ss = (IStructuredSelection) selection; Object o = ss.getFirstElement(); currentSelection = (ILogEntry) o; tagActionDelegate.selectionChanged(tagWithExistingAction, treeView.getSelection()); tagActionDelegate.run(tagWithExistingAction); Display.getDefault().asyncExec(new Runnable() { public void run() { if (!((TagAction) tagActionDelegate).wasCancelled()) { refresh(); } } }); } @Override public boolean isEnabled() { ISelection selection = treeView.getSelection(); if (!(selection instanceof IStructuredSelection)) { return false; } IStructuredSelection ss = (IStructuredSelection) selection; if (ss.size() != 1) { return false; } return true; } }; WorkbenchHelp.setHelp(tagWithExistingAction, IHelpContextIds.TAG_AS_VERSION_DIALOG); IActionBars actionBars = getViewSite().getActionBars(); // Create actions for the text editor copyCommentAction = new TextViewerAction(commentViewer, ITextOperationTarget.COPY); copyCommentAction.setText(VersionTreePlugin.getResourceString("VersionTreeView.Copy_Action")); //$NON-NLS-1$ actionBars.setGlobalActionHandler(ITextEditorActionConstants.COPY, copyCommentAction); selectAllAction = new TextViewerAction(commentViewer, ITextOperationTarget.SELECT_ALL); selectAllAction.setText(VersionTreePlugin.getResourceString("VersionTreeView.Select_All_Action")); //$NON-NLS-1$ actionBars.setGlobalActionHandler(ITextEditorActionConstants.SELECT_ALL, selectAllAction); actionBars.updateActionBars(); MenuManager menuMgr = new MenuManager(); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager theMenuMgr) { fillTextMenu(theMenuMgr); } }); StyledText text = commentViewer.getTextWidget(); Menu menu = menuMgr.createContextMenu(text); text.setMenu(menu); // Create actions for the tags copyTagAction = new CopyTagAction(tagViewer); copyTagAction.setText(VersionTreePlugin.getResourceString("VersionTreeView.Copy_Action")); copyTagAction.setEnabled(false); menuMgr = new MenuManager(); menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { public void menuAboutToShow(IMenuManager menuMgr) { menuMgr.add(copyTagAction); } }); menu = menuMgr.createContextMenu(tagViewer.getControl()); tagViewer.getControl().setMenu(menu); tagViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { copyTagAction.setEnabled(false); if (event.getSelection() instanceof StructuredSelection) { if (((StructuredSelection) event.getSelection()).getFirstElement() != null) { copyTagAction.setEnabled(true); } } } }); } private void fillTextMenu(IMenuManager manager) { manager.add(copyCommentAction); manager.add(selectAllAction); } /** * Passing the focus request to the viewer's control. */ @Override public void setFocus() { treeView.setFocus(); } private void initializeImages() { CVSUIPlugin plugin = CVSUIPlugin.getPlugin(); versionImage = plugin.getImageDescriptor(ICVSUIConstants.IMG_PROJECT_VERSION).createImage(); branchImage = plugin.getImageDescriptor(ICVSUIConstants.IMG_TAG).createImage(); lockedImage = VersionTreeImages.getImage(VersionTreeImages.IMG_LOCKED); requestImage = VersionTreeImages.getImage(VersionTreeImages.IMG_REQUEST); mergeToImage = VersionTreeImages.getImage(VersionTreeImages.IMG_MERGE_TO); mergeFromImage = VersionTreeImages.getImage(VersionTreeImages.IMG_MERGE_FROM); closedImage = VersionTreeImages.getImage(VersionTreeImages.IMG_CLOSED); } /** * @param sashForm * @return */ private TextViewer createTextViewer(SashForm parent) { TextViewer result = new TextViewer(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.BORDER | SWT.READ_ONLY); result.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { copyCommentAction.update(); } }); return result; } /** * @param sashForm * @return */ private TableViewer createTagViewer(SashForm parent) { Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION | SWT.BORDER); TableViewer result = new TableViewer(table); TableLayout layout = new TableLayout(); layout.addColumnData(new ColumnWeightData(100)); table.setLayout(layout); result.setContentProvider(new SimpleContentProvider() { @Override public Object[] getElements(Object inputElement) { if (inputElement == null) { return new Object[0]; } CVSTag[] tags = (CVSTag[]) inputElement; return tags; } }); result.setLabelProvider(new TagLabelProvider()); result.setSorter(new ViewerSorter() { @Override public int compare(Viewer viewer, Object e1, Object e2) { if (!(e1 instanceof CVSTag) || !(e2 instanceof CVSTag)) { return super.compare(viewer, e1, e2); } CVSTag tag1 = (CVSTag) e1; CVSTag tag2 = (CVSTag) e2; int type1 = tag1.getType(); int type2 = tag2.getType(); if (type1 != type2) { return type2 - type1; } return super.compare(viewer, tag1, tag2); } }); return result; } /** * @param sashForm * @return */ private TableViewer createTableViewer(SashForm parent) { detailProvider = new DetailTableProvider(); TableViewer viewer = detailProvider.createTable(parent); viewer.setContentProvider(new ViewContentProvider()); return viewer; } @Override public void dispose() { shutdown = true; if (branchImage != null) { branchImage.dispose(); branchImage = null; } if (versionImage != null) { versionImage.dispose(); versionImage = null; } getSite().getPage().removePartListener(partListener); getSite().getPage().removePartListener(partListener2); } /** * Enabled linking to the active editor * @since 3.0 */ public void setLinkingEnabled(boolean enabled) { linkingEnabled = enabled; // remember the last setting in the dialog settings prefs.setValue(VersionTreePlugin.PREF_HISTORY_VIEW_EDITOR_LINKING, enabled); // if turning linking on, update the selection to correspond to the active editor if (enabled) { editorActivated(getSite().getPage().getActiveEditor()); } } /** * Returns if linking to the ative editor is enabled or disabled. * @return boolean indicating state of editor linking. */ private boolean isLinkingEnabled() { return linkingEnabled; } /** * An editor has been activated. Fetch the history if it is shared with CVS and the history view * is visible in the current page. * * @param editor the active editor * @since 3.0 */ protected void editorActivated(IEditorPart editor) { // Only fetch contents if the view is shown in the current page. if (editor == null || !isLinkingEnabled() || !checkIfPageIsVisible()) { return; } IEditorInput input = editor.getEditorInput(); IFile file = ResourceUtil.getFile(input); showVersionTree(file); } private boolean checkIfPageIsVisible() { return getViewSite().getPage().isPartVisible(this); } /** * Refresh the view by refetching the log entries for the remote file */ private void refresh() { showVersionTree(getFile()); } /** * Display details of selected log * @see net.sf.versiontree.ui.LogEntrySelectionListener#logEntrySelected(org.eclipse.team.internal.ccvs.core.client.listeners.LogEntry) */ public void logEntrySelected(ILogEntry log) { // return if file is already selected ILogEntry oldCurrentEntry = getCurrentEntry(); if (oldCurrentEntry != null && oldCurrentEntry.getRevision().equals(log.getRevision())) { return; } // update display setCurrentEntry(log); } /** * Open selected revision * @see net.sf.versiontree.ui.LogEntrySelectionListener#logEntryDoubleClicked(IStructuredSelection) */ public void logEntryDoubleClicked(IStructuredSelection selection) { openActionDelegate.selectionChanged(null, selection); openActionDelegate.run(null); } private Action getContextMenuAction(String title, final IWorkspaceRunnable action) { return new Action(title) { @Override public void run() { try { if (getFile() == null) { return; } ISelection selection = treeView.getSelection(); if (!(selection instanceof IStructuredSelection)) { return; } IStructuredSelection ss = (IStructuredSelection) selection; Object o = ss.getFirstElement(); currentSelection = (ILogEntry) o; new ProgressMonitorDialog(getViewSite().getShell()).run(false, true, new WorkspaceModifyOperation() { @Override protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { action.run(monitor); } catch (CoreException e) { throw new InvocationTargetException(e); } } }); } catch (InvocationTargetException e) { CVSUIPlugin.openError(getViewSite().getShell(), null, null, e, CVSUIPlugin.LOG_NONTEAM_EXCEPTIONS); } catch (InterruptedException e) { // Do nothing } } @Override public boolean isEnabled() { ISelection selection = treeView.getSelection(); if (!(selection instanceof IStructuredSelection)) { return false; } IStructuredSelection ss = (IStructuredSelection) selection; if (ss.size() != 1) { return false; } return true; } }; } private boolean confirmOverwrite() { IFile file = getFile(); if (file != null && file.exists()) { ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file); try { if (cvsFile.isModified(null)) { String title = VersionTreePlugin.getResourceString("VersionTreeView.CVS_Version_Tree_Name"); //$NON-NLS-1$ String msg = VersionTreePlugin.getResourceString("VersionTreeView.Overwrite_Changes_Question"); //$NON-NLS-1$ final MessageDialog dialog = new MessageDialog(getViewSite().getShell(), title, null, msg, MessageDialog.QUESTION, new String[] { IDialogConstants.YES_LABEL, IDialogConstants.CANCEL_LABEL }, 0); final int[] result = new int[1]; getViewSite().getShell().getDisplay().syncExec(new Runnable() { public void run() { result[0] = dialog.open(); } }); if (result[0] != 0) { // cancel return false; } } } catch (CVSException e) { CVSUIPlugin.log(e.getStatus()); } } return true; } /** * @return currently selected entry or {@code null} */ protected ILogEntry getCurrentEntry() { return this.currentEntry; } protected void setCurrentEntry(ILogEntry currentEntry) { if (this.currentEntry != currentEntry) { this.currentEntry = currentEntry; updateTableData(currentEntry); // tableViewer.setInput(tableData); if (currentEntry != null) { tagViewer.setInput(currentEntry.getTags()); commentViewer.setDocument(new Document(currentEntry.getComment())); } else { tagViewer.setInput(null); commentViewer.setDocument(new Document("")); //$NON-NLS-1$ } } } protected IFile getFile() { return file; } protected void setFile(IFile file) { this.file = file; } }