| /******************************************************************************* |
| * Copyright (c) 2000, 2003 IBM Corporation and others. |
| * 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: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.team.internal.ccvs.ui; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.Collection; |
| import java.util.Iterator; |
| |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.jface.text.ITextSelection; |
| import org.eclipse.jface.viewers.ArrayContentProvider; |
| import org.eclipse.jface.viewers.IPostSelectionProvider; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.ISelectionProvider; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.viewers.ListViewer; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.team.internal.ccvs.core.CVSAnnotateBlock; |
| import org.eclipse.team.internal.ccvs.core.CVSException; |
| import org.eclipse.team.internal.ccvs.core.ICVSRemoteFile; |
| import org.eclipse.team.internal.ccvs.core.ICVSResource; |
| import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; |
| import org.eclipse.ui.IEditorDescriptor; |
| import org.eclipse.ui.IEditorPart; |
| import org.eclipse.ui.IEditorRegistry; |
| import org.eclipse.ui.IReusableEditor; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.help.WorkbenchHelp; |
| import org.eclipse.ui.internal.IWorkbenchConstants; |
| import org.eclipse.ui.internal.WorkbenchPlugin; |
| import org.eclipse.ui.internal.registry.EditorDescriptor; |
| import org.eclipse.ui.part.ViewPart; |
| import org.eclipse.ui.texteditor.IDocumentProvider; |
| import org.eclipse.ui.texteditor.ITextEditor; |
| |
| /** |
| * A view showing the results of the CVS Annotate Command. A linked |
| * combination of a View of annotations, a source editor and the |
| * Resource History View |
| */ |
| public class AnnotateView extends ViewPart implements ISelectionChangedListener { |
| |
| ITextEditor editor; |
| HistoryView historyView; |
| IWorkbenchPage page; |
| |
| ListViewer viewer; |
| IDocument document; |
| Collection cvsAnnotateBlocks; |
| ICVSResource cvsResource; |
| InputStream contents; |
| |
| IStructuredSelection previousListSelection; |
| ITextSelection previousTextSelection; |
| boolean lastSelectionWasText = false; |
| |
| |
| public static final String VIEW_ID = "org.eclipse.team.ccvs.ui.AnnotateView"; //$NON-NLS-1$ |
| private Composite top; |
| |
| public AnnotateView() { |
| super(); |
| } |
| |
| public void createPartControl(Composite parent) { |
| |
| this.top = parent; |
| |
| // Create default contents |
| Label label = new Label(top, SWT.WRAP); |
| label.setText(Policy.bind("CVSAnnotateView.viewInstructions")); //$NON-NLS-1$ |
| label.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| top.layout(); |
| } |
| |
| /** |
| * Show the annotation view. |
| * @param cvsResource |
| * @param cvsAnnotateBlocks |
| * @param contents |
| * @throws InvocationTargetException |
| */ |
| public void showAnnotations(ICVSResource cvsResource, Collection cvsAnnotateBlocks, InputStream contents) throws InvocationTargetException { |
| showAnnotations(cvsResource, cvsAnnotateBlocks, contents, true); |
| } |
| |
| /** |
| * Show the annotation view. |
| * @param cvsResource |
| * @param cvsAnnotateBlocks |
| * @param contents |
| * @param useHistoryView |
| * @throws InvocationTargetException |
| */ |
| public void showAnnotations(ICVSResource cvsResource, Collection cvsAnnotateBlocks, InputStream contents, boolean useHistoryView) throws InvocationTargetException { |
| |
| // Remove old viewer |
| Control[] oldChildren = top.getChildren(); |
| if (oldChildren != null) { |
| for (int i = 0; i < oldChildren.length; i++) { |
| oldChildren[i].dispose(); |
| } |
| } |
| |
| viewer = new ListViewer(top, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL); |
| viewer.setContentProvider(new ArrayContentProvider()); |
| viewer.setLabelProvider(new LabelProvider()); |
| viewer.addSelectionChangedListener(this); |
| viewer.getControl().setLayoutData(new GridData(GridData.FILL_BOTH)); |
| |
| WorkbenchHelp.setHelp(viewer.getControl(), IHelpContextIds.ANNOTATE_VIEW); |
| |
| top.layout(); |
| |
| this.cvsResource = cvsResource; |
| this.contents = contents; |
| this.cvsAnnotateBlocks = cvsAnnotateBlocks; |
| page = CVSUIPlugin.getActivePage(); |
| viewer.setInput(cvsAnnotateBlocks); |
| editor = (ITextEditor) openEditor(); |
| IDocumentProvider provider = editor.getDocumentProvider(); |
| document = provider.getDocument(editor.getEditorInput()); |
| |
| setTitle(Policy.bind("CVSAnnotateView.showFileAnnotation", new Object[] {cvsResource.getName()})); //$NON-NLS-1$ |
| try { |
| IResource localResource = cvsResource.getIResource(); |
| if (localResource != null) { |
| setTitleToolTip(localResource.getFullPath().toString()); |
| } else { |
| setTitleToolTip(cvsResource.getName()); |
| } |
| } catch (CVSException e) { |
| setTitleToolTip(cvsResource.getName()); |
| } |
| |
| if (!useHistoryView) { |
| return; |
| } |
| |
| // Get hook to the HistoryView |
| |
| try { |
| historyView = (HistoryView) page.showView(HistoryView.VIEW_ID); |
| historyView.showHistory((ICVSRemoteFile) CVSWorkspaceRoot.getRemoteResourceFor(cvsResource)); |
| } catch (PartInitException e) { |
| throw new InvocationTargetException(e); |
| } catch (CVSException e) { |
| throw new InvocationTargetException(e); |
| } |
| } |
| |
| /** |
| * Makes the view visible in the active perspective. If there |
| * isn't a view registered <code>null</code> is returned. |
| * Otherwise the opened view part is returned. |
| */ |
| public static AnnotateView openInActivePerspective() throws PartInitException { |
| return (AnnotateView) CVSUIPlugin.getActivePage().showView(VIEW_ID); |
| } |
| |
| /** |
| * Selection changed in either the Annotate List View or the |
| * Source editor. |
| */ |
| public void selectionChanged(SelectionChangedEvent event) { |
| |
| if (event.getSelection() instanceof IStructuredSelection) { |
| listSelectionChanged((IStructuredSelection) event.getSelection()); |
| } else if (event.getSelection() instanceof ITextSelection) { |
| textSelectionChanged((ITextSelection) event.getSelection()); |
| } |
| |
| |
| } |
| |
| /** |
| * A selection event in the Annotate Source Editor |
| * @param event |
| */ |
| private void textSelectionChanged(ITextSelection selection) { |
| |
| // Track where the last selection event came from to avoid |
| // a selection event loop. |
| lastSelectionWasText = true; |
| |
| // Locate the annotate block containing the selected line number. |
| CVSAnnotateBlock match = null; |
| for (Iterator iterator = cvsAnnotateBlocks.iterator(); iterator.hasNext();) { |
| CVSAnnotateBlock block = (CVSAnnotateBlock) iterator.next(); |
| if (block.contains(selection.getStartLine())) { |
| match = block; |
| break; |
| } |
| } |
| |
| // Select the annotate block in the List View. |
| if (match == null) { |
| return; |
| } |
| |
| StructuredSelection listSelection = new StructuredSelection(match); |
| viewer.setSelection(listSelection, true); |
| } |
| |
| /** |
| * A selection event in the Annotate List View |
| * @param selection |
| */ |
| private void listSelectionChanged(IStructuredSelection selection) { |
| |
| // If the editor was closed, reopen it. |
| if (editor == null || editor.getSelectionProvider() == null) { |
| try { |
| contents.reset(); |
| showAnnotations(cvsResource, cvsAnnotateBlocks, contents, false); |
| } catch (InvocationTargetException e) { |
| return; |
| } catch (IOException e) { |
| return; |
| } |
| } |
| |
| ISelectionProvider selectionProvider = editor.getSelectionProvider(); |
| if (selectionProvider == null) { |
| // Failed to open the editor but what else can we do. |
| return; |
| } |
| |
| ITextSelection textSelection = (ITextSelection) selectionProvider.getSelection(); |
| CVSAnnotateBlock listSelection = (CVSAnnotateBlock) selection.getFirstElement(); |
| |
| /** |
| * Ignore event if the current text selection is already equal to the corresponding |
| * list selection. Nothing to do. This prevents infinite event looping. |
| * |
| * Extra check to handle single line deltas |
| */ |
| |
| if (textSelection.getStartLine() == listSelection.getStartLine() && textSelection.getEndLine() == listSelection.getEndLine() && selection.equals(previousListSelection)) { |
| return; |
| } |
| |
| // If the last selection was a text selection then bale to prevent a selection loop. |
| if (!lastSelectionWasText) { |
| try { |
| int start = document.getLineOffset(listSelection.getStartLine()); |
| int end = document.getLineOffset(listSelection.getEndLine() + 1); |
| editor.selectAndReveal(start, end - start); |
| if (editor != null && !page.isPartVisible(editor)) { |
| page.activate(editor); |
| } |
| |
| } catch (BadLocationException e) { |
| // Ignore - nothing we can do. |
| } |
| } |
| |
| |
| // Select the revision in the history view. |
| if(historyView != null) { |
| historyView.selectRevision(listSelection.getRevision()); |
| } |
| lastSelectionWasText = false; |
| } |
| |
| /** |
| * Try and open the correct registered editor type for the file. If the registered |
| * editor is *not* an ITextEditor then open the source in a default text editor. |
| * @return |
| * @throws InvocationTargetException |
| */ |
| private IEditorPart openEditor() throws InvocationTargetException { |
| // Open the editor |
| IEditorPart part; |
| |
| IEditorRegistry registry = CVSUIPlugin.getPlugin().getWorkbench().getEditorRegistry(); |
| ICVSRemoteFile file; |
| |
| try { |
| file = (ICVSRemoteFile) CVSWorkspaceRoot.getRemoteResourceFor(cvsResource); |
| } catch (CVSException e1) { |
| throw new InvocationTargetException(e1); |
| } |
| |
| IEditorDescriptor descriptor = registry.getDefaultEditor(file.getName()); |
| |
| // Determine if the registered editor is an ITextEditor. |
| |
| String id; |
| |
| if (descriptor == null || !(descriptor instanceof EditorDescriptor) || !(((EditorDescriptor)descriptor).isInternal())) { |
| id = IWorkbenchConstants.DEFAULT_EDITOR_ID; //$NON-NLS-1$ |
| } else { |
| try { |
| Object obj = WorkbenchPlugin.createExtension(((EditorDescriptor) descriptor).getConfigurationElement(), "class"); //$NON-NLS-1$ |
| if (obj instanceof ITextEditor) { |
| id = descriptor.getId(); |
| } else { |
| id = IWorkbenchConstants.DEFAULT_EDITOR_ID; |
| } |
| } catch (CoreException e) { |
| id = IWorkbenchConstants.DEFAULT_EDITOR_ID; |
| } |
| } |
| |
| // Either reuse an existing editor or open a new editor of the correct type. |
| try { |
| try { |
| if (editor != null && editor instanceof IReusableEditor && page.isPartVisible(editor) && editor.getSite().getId().equals(id)) { |
| // We can reuse the editor |
| ((IReusableEditor) editor).setInput(new RemoteAnnotationEditorInput(file, contents)); |
| part = editor; |
| } else { |
| // We can not reuse the editor so close the existing one and open a new one. |
| if (editor != null) { |
| page.closeEditor(editor, false); |
| editor = null; |
| } |
| part = page.openEditor(new RemoteAnnotationEditorInput(file, contents), id); |
| } |
| } catch (PartInitException e) { |
| if (id.equals(IWorkbenchConstants.DEFAULT_EDITOR_ID)) { |
| throw e; |
| } else { |
| // Could not open desired editor, try a default text editor. |
| part = page.openEditor(new RemoteAnnotationEditorInput(file, contents), IWorkbenchConstants.DEFAULT_EDITOR_ID); //$NON-NLS-1$ |
| } |
| } |
| } catch (PartInitException e) { |
| // Total failure. |
| throw new InvocationTargetException(e); |
| } |
| |
| // Hook Editor post selection listener. |
| ITextEditor editor = (ITextEditor) part; |
| if (editor.getSelectionProvider() instanceof IPostSelectionProvider) { |
| ((IPostSelectionProvider) editor.getSelectionProvider()).addPostSelectionChangedListener(this); |
| } |
| |
| return part; |
| } |
| |
| // This method implemented to be an ISelectionChangeListener but we |
| // don't really care when the List or Editor get focus. |
| public void setFocus() { |
| return; |
| } |
| } |