Java tutorial
/******************************************************************************* * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> * * 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 *******************************************************************************/ package org.eclipse.egit.ui.internal.history; import java.io.IOException; import java.util.Iterator; import org.eclipse.compare.ITypedElement; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.UIUtils; import org.eclipse.egit.ui.internal.CompareUtils; import org.eclipse.egit.ui.internal.EgitUiEditorUtils; import org.eclipse.egit.ui.internal.GitCompareFileRevisionEditorInput; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IOpenListener; 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.OpenEvent; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jgit.diff.DiffEntry.ChangeType; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.FocusListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Table; import org.eclipse.team.core.history.IFileRevision; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.part.IPageSite; class CommitFileDiffViewer extends TableViewer { private static final String LINESEP = System.getProperty("line.separator"); //$NON-NLS-1$ private Repository db; private TreeWalk walker; private Clipboard clipboard; private StyledText noInputText; private final StackLayout stackLayout; private IAction selectAll; private IAction copy; private IAction open; private IAction compare; private final IPageSite site; /** * Shows a list of file changed by a commit. * * If no input is available, an error message is shown instead. * * @param parent * @param site */ CommitFileDiffViewer(final Composite parent, final IPageSite site) { // since out parent is a SashForm, we can't add the alternate // text to be displayed in case of no input directly to that // parent; we create our own parent instead and set the // StackLayout on it instead super(new Composite(parent, SWT.NONE), SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION); this.site = site; final Table rawTable = getTable(); Composite main = rawTable.getParent(); stackLayout = new StackLayout(); main.setLayout(stackLayout); // this is the text to be displayed if there is no input noInputText = new StyledText(main, SWT.NONE); // use the same font as in message viewer noInputText.setFont(UIUtils.getFont(UIPreferences.THEME_CommitMessageFont)); noInputText.setText(UIText.CommitFileDiffViewer_SelectOneCommitMessage); rawTable.setLinesVisible(true); setLabelProvider(new FileDiffLabelProvider()); setContentProvider(new FileDiffContentProvider()); addOpenListener(new IOpenListener() { public void open(final OpenEvent event) { final ISelection s = event.getSelection(); if (s.isEmpty() || !(s instanceof IStructuredSelection)) return; final IStructuredSelection iss = (IStructuredSelection) s; final FileDiff d = (FileDiff) iss.getFirstElement(); if (Activator.getDefault().getPreferenceStore() .getBoolean(UIPreferences.RESOURCEHISTORY_COMPARE_MODE)) { if (d.getBlobs().length <= 2) showTwoWayFileDiff(d); else MessageDialog.openInformation( PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), UIText.CommitFileDiffViewer_CanNotOpenCompareEditorTitle, UIText.CommitFileDiffViewer_MergeCommitMultiAncestorMessage); } else openFileInEditor(d); } }); addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { updateActionEnablement(event.getSelection()); } }); clipboard = new Clipboard(rawTable.getDisplay()); rawTable.addDisposeListener(new DisposeListener() { public void widgetDisposed(final DisposeEvent e) { clipboard.dispose(); } }); final MenuManager mgr = new MenuManager(); Control c = getControl(); c.setMenu(mgr.createContextMenu(c)); open = new Action(UIText.CommitFileDiffViewer_OpenInEditorMenuLabel) { @SuppressWarnings("unchecked") @Override public void run() { final ISelection s = getSelection(); if (s.isEmpty() || !(s instanceof IStructuredSelection)) return; final IStructuredSelection iss = (IStructuredSelection) s; for (Iterator<FileDiff> it = iss.iterator();; it.hasNext()) { openFileInEditor(it.next()); } } }; compare = new Action(UIText.CommitFileDiffViewer_CompareMenuLabel) { @Override public void run() { final ISelection s = getSelection(); if (s.isEmpty() || !(s instanceof IStructuredSelection)) return; final IStructuredSelection iss = (IStructuredSelection) s; final FileDiff d = (FileDiff) iss.getFirstElement(); if (d.getBlobs().length <= 2) showTwoWayFileDiff(d); else MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), UIText.CommitFileDiffViewer_CanNotOpenCompareEditorTitle, UIText.CommitFileDiffViewer_MergeCommitMultiAncestorMessage); } }; mgr.add(open); mgr.add(compare); mgr.add(new Separator()); mgr.add(selectAll = createStandardAction(ActionFactory.SELECT_ALL)); mgr.add(copy = createStandardAction(ActionFactory.COPY)); getControl().addFocusListener(new FocusListener() { public void focusLost(FocusEvent e) { site.getActionBars().setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), null); site.getActionBars().setGlobalActionHandler(ActionFactory.COPY.getId(), null); site.getActionBars().updateActionBars(); } public void focusGained(FocusEvent e) { updateActionEnablement(getSelection()); site.getActionBars().setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAll); site.getActionBars().setGlobalActionHandler(ActionFactory.COPY.getId(), copy); site.getActionBars().updateActionBars(); } }); } private void updateActionEnablement(ISelection selection) { if (!(selection instanceof IStructuredSelection)) return; IStructuredSelection sel = (IStructuredSelection) selection; boolean allSelected = !sel.isEmpty() && sel.size() == getTable().getItemCount(); selectAll.setEnabled(!allSelected); copy.setEnabled(!sel.isEmpty()); open.setEnabled(!sel.isEmpty()); compare.setEnabled(sel.size() == 1); } private IAction createStandardAction(final ActionFactory af) { final String text = af.create(PlatformUI.getWorkbench().getActiveWorkbenchWindow()).getText(); IAction action = new Action() { @Override public String getActionDefinitionId() { return af.getCommandId(); } @Override public String getId() { return af.getId(); } @Override public String getText() { return text; } @Override public void run() { if (af == ActionFactory.SELECT_ALL) { doSelectAll(); } if (af == ActionFactory.COPY) { doCopy(); } } }; action.setEnabled(true); return action; } @Override protected void inputChanged(final Object input, final Object oldInput) { boolean inputChanged; if (oldInput == null && input == null) { inputChanged = false; } else if (oldInput == null || input == null) { inputChanged = true; } else { inputChanged = !input.equals(oldInput); } if (inputChanged) { if (input == null && stackLayout.topControl != noInputText) { stackLayout.topControl = noInputText; getTable().getParent().layout(false); } else if (input != null && stackLayout.topControl != getTable()) { stackLayout.topControl = getTable(); getTable().getParent().layout(false); } super.inputChanged(input, oldInput); } } private void openFileInEditor(FileDiff d) { try { IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); IWorkbenchPage page = window.getActivePage(); IFileRevision rev = CompareUtils.getFileRevision(d.getPath(), d.getChange().equals(ChangeType.DELETE) ? d.getCommit().getParent(0) : d.getCommit(), db, d.getChange().equals(ChangeType.DELETE) ? d.getBlobs()[0] : d.getBlobs()[d.getBlobs().length - 1]); if (rev != null) EgitUiEditorUtils.openEditor(page, rev, new NullProgressMonitor()); else { String message = NLS.bind(UIText.CommitFileDiffViewer_notContainedInCommit, d.getPath(), d.getCommit().getId().getName()); Activator.showError(message, null); } } catch (IOException e) { Activator.logError(UIText.GitHistoryPage_openFailed, e); Activator.showError(UIText.GitHistoryPage_openFailed, null); } catch (CoreException e) { Activator.logError(UIText.GitHistoryPage_openFailed, e); Activator.showError(UIText.GitHistoryPage_openFailed, null); } } void showTwoWayFileDiff(final FileDiff d) { final GitCompareFileRevisionEditorInput in; final String p = d.getPath(); final RevCommit c = d.getCommit(); final ITypedElement base; final ITypedElement next; if (d.getBlobs().length == 2 && !d.getChange().equals(ChangeType.ADD)) base = CompareUtils.getFileRevisionTypedElement(p, c.getParent(0), db, d.getBlobs()[0]); else // Initial import base = new GitCompareFileRevisionEditorInput.EmptyTypedElement(""); //$NON-NLS-1$ if (d.getChange().equals(ChangeType.DELETE)) next = new GitCompareFileRevisionEditorInput.EmptyTypedElement(""); //$NON-NLS-1$ else next = CompareUtils.getFileRevisionTypedElement(p, c, db, d.getBlobs()[1]); in = new GitCompareFileRevisionEditorInput(next, base, null); CompareUtils.openInCompare(site.getWorkbenchWindow().getActivePage(), in); } TreeWalk getTreeWalk() { return walker; } void setTreeWalk(Repository repository, TreeWalk walk) { db = repository; walker = walk; } private void doSelectAll() { final IStructuredContentProvider cp; final Object in = getInput(); if (in == null) return; cp = ((IStructuredContentProvider) getContentProvider()); final Object[] el = cp.getElements(in); if (el == null || el.length == 0) return; setSelection(new StructuredSelection(el)); } @SuppressWarnings("unchecked") private void doCopy() { final ISelection s = getSelection(); if (s.isEmpty() || !(s instanceof IStructuredSelection)) return; final IStructuredSelection iss = (IStructuredSelection) s; final Iterator<FileDiff> itr = iss.iterator(); final StringBuilder r = new StringBuilder(); while (itr.hasNext()) { final FileDiff d = itr.next(); if (r.length() > 0) r.append(LINESEP); r.append(d.getPath()); } clipboard.setContents(new Object[] { r.toString() }, new Transfer[] { TextTransfer.getInstance() }, DND.CLIPBOARD); } }