Java tutorial
/******************************************************************************* * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br> * 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.util.HashMap; import java.util.Iterator; import java.util.Map; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.IParameter; import org.eclipse.core.commands.Parameterization; import org.eclipse.core.commands.ParameterizedCommand; import org.eclipse.core.commands.common.NotDefinedException; import org.eclipse.core.resources.IResource; import org.eclipse.egit.ui.Activator; import org.eclipse.egit.ui.UIIcons; import org.eclipse.egit.ui.UIPreferences; import org.eclipse.egit.ui.UIText; import org.eclipse.egit.ui.UIUtils; import org.eclipse.egit.ui.internal.history.command.HistoryViewCommands; 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.viewers.ColumnWeightData; import org.eclipse.jface.viewers.IOpenListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.OpenEvent; 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.jgit.revplot.PlotCommit; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevFlag; import org.eclipse.swt.SWT; 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.events.MenuDetectEvent; import org.eclipse.swt.events.MenuDetectListener; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionFactory; import org.eclipse.ui.commands.ICommandService; import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.menus.CommandContributionItem; import org.eclipse.ui.menus.CommandContributionItemParameter; import org.eclipse.ui.part.IPageSite; class CommitGraphTable { private static Font highlightFont() { final Font n, h; n = UIUtils.getFont(UIPreferences.THEME_CommitGraphNormalFont); h = UIUtils.getFont(UIPreferences.THEME_CommitGraphHighlightFont); final FontData[] nData = n.getFontData(); final FontData[] hData = h.getFontData(); if (nData.length != hData.length) return h; for (int i = 0; i < nData.length; i++) if (!nData[i].equals(hData[i])) return h; return UIUtils.getBoldFont(UIPreferences.THEME_CommitGraphNormalFont); } private static final String LINESEP = System.getProperty("line.separator"); //$NON-NLS-1$ private final TableViewer table; private Clipboard clipboard; private final SWTPlotRenderer renderer; private final Font nFont; private final Font hFont; private SWTCommitList allCommits; private RevFlag highlight; private HistoryPageInput input; IAction copy; MenuListener menuListener; CommitGraphTable(final Composite parent, final IPageSite site, final MenuManager menuMgr) { nFont = UIUtils.getFont(UIPreferences.THEME_CommitGraphNormalFont); hFont = highlightFont(); Table rawTable = new Table(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL); rawTable.setHeaderVisible(true); rawTable.setLinesVisible(false); rawTable.setFont(nFont); final TableLayout layout = new TableLayout(); rawTable.setLayout(layout); createColumns(rawTable, layout); createPaintListener(rawTable); table = new TableViewer(rawTable) { protected Widget doFindItem(final Object element) { return element != null ? ((SWTCommit) element).widget : null; } protected void mapElement(final Object element, final Widget item) { ((SWTCommit) element).widget = item; } }; table.setLabelProvider(new GraphLabelProvider()); table.setContentProvider(new GraphContentProvider()); renderer = new SWTPlotRenderer(rawTable.getDisplay()); clipboard = new Clipboard(rawTable.getDisplay()); rawTable.addDisposeListener(new DisposeListener() { public void widgetDisposed(final DisposeEvent e) { clipboard.dispose(); } }); final IAction selectAll = createStandardAction(ActionFactory.SELECT_ALL); copy = createStandardAction(ActionFactory.COPY); table.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { copy.setEnabled(canDoCopy()); } }); 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) { site.getActionBars().setGlobalActionHandler(ActionFactory.SELECT_ALL.getId(), selectAll); site.getActionBars().setGlobalActionHandler(ActionFactory.COPY.getId(), copy); site.getActionBars().updateActionBars(); } }); getTableView().addOpenListener(new IOpenListener() { public void open(OpenEvent event) { if (input == null || !input.isSingleFile()) { return; } ICommandService srv = (ICommandService) site.getService(ICommandService.class); IHandlerService hsrv = (IHandlerService) site.getService(IHandlerService.class); Command cmd = srv.getCommand(HistoryViewCommands.SHOWVERSIONS); Parameterization[] parms; if (Activator.getDefault().getPreferenceStore() .getBoolean(UIPreferences.RESOURCEHISTORY_COMPARE_MODE)) { try { IParameter parm = cmd.getParameter(HistoryViewCommands.COMPARE_MODE_PARAM); parms = new Parameterization[] { new Parameterization(parm, Boolean.TRUE.toString()) }; } catch (NotDefinedException e) { Activator.handleError(e.getMessage(), e, true); parms = null; } } else parms = null; ParameterizedCommand pcmd = new ParameterizedCommand(cmd, parms); try { hsrv.executeCommandInContext(pcmd, null, hsrv.getCurrentState()); } catch (Exception e) { Activator.handleError(e.getMessage(), e, true); } } }); Control c = getControl(); c.setMenu(menuMgr.createContextMenu(c)); c.addMenuDetectListener(menuListener = new MenuListener(menuMgr, getTableView(), site, copy)); } Control getControl() { return table.getControl(); } void selectCommit(final RevCommit c) { table.setSelection(new StructuredSelection(c)); table.reveal(c); } void addSelectionChangedListener(final ISelectionChangedListener l) { table.addPostSelectionChangedListener(l); } void removeSelectionChangedListener(final ISelectionChangedListener l) { table.removePostSelectionChangedListener(l); } private boolean canDoCopy() { return !table.getSelection().isEmpty(); } @SuppressWarnings("unchecked") private void doCopy() { final ISelection s = table.getSelection(); if (s.isEmpty() || !(s instanceof IStructuredSelection)) return; final IStructuredSelection iss = (IStructuredSelection) s; final Iterator<PlotCommit> itr = iss.iterator(); final StringBuilder r = new StringBuilder(); while (itr.hasNext()) { final PlotCommit d = itr.next(); if (r.length() > 0) r.append(LINESEP); r.append(d.getId().name()); } clipboard.setContents(new Object[] { r.toString() }, new Transfer[] { TextTransfer.getInstance() }, DND.CLIPBOARD); } void setInput(final RevFlag hFlag, final SWTCommitList list, final SWTCommit[] asArray, HistoryPageInput input) { this.input = input; menuListener.setInput(input); final SWTCommitList oldList = allCommits; highlight = hFlag; allCommits = list; table.setInput(asArray); if (asArray != null && asArray.length > 0) { if (oldList != list) selectCommit(asArray[0]); } else { table.getTable().deselectAll(); } } private void createColumns(final Table rawTable, final TableLayout layout) { final TableColumn graph = new TableColumn(rawTable, SWT.NONE); graph.setResizable(true); graph.setText(""); //$NON-NLS-1$ graph.setWidth(250); layout.addColumnData(new ColumnWeightData(20, true)); final TableColumn author = new TableColumn(rawTable, SWT.NONE); author.setResizable(true); author.setText(UIText.HistoryPage_authorColumn); author.setWidth(250); layout.addColumnData(new ColumnWeightData(10, true)); final TableColumn date = new TableColumn(rawTable, SWT.NONE); date.setResizable(true); date.setText(UIText.HistoryPage_dateColumn); date.setWidth(250); layout.addColumnData(new ColumnWeightData(5, true)); final TableColumn commitId = new TableColumn(rawTable, SWT.NONE); commitId.setResizable(true); commitId.setText(UIText.CommitGraphTable_CommitId); commitId.setWidth(100); layout.addColumnData(new ColumnWeightData(5, true)); final TableColumn committer = new TableColumn(rawTable, SWT.NONE); committer.setResizable(true); committer.setText(UIText.CommitGraphTable_Committer); committer.setWidth(100); layout.addColumnData(new ColumnWeightData(5, true)); } private void createPaintListener(final Table rawTable) { // Tell SWT we will completely handle painting for some columns. // rawTable.addListener(SWT.EraseItem, new Listener() { public void handleEvent(final Event event) { if (0 <= event.index && event.index <= 4) event.detail &= ~SWT.FOREGROUND; } }); rawTable.addListener(SWT.PaintItem, new Listener() { public void handleEvent(final Event event) { doPaint(event); } }); } void doPaint(final Event event) { final RevCommit c = (RevCommit) ((TableItem) event.item).getData(); if (highlight != null && c.has(highlight)) event.gc.setFont(hFont); else event.gc.setFont(nFont); if (event.index == 0) { renderer.paint(event); return; } final ITableLabelProvider lbl; final String txt; lbl = (ITableLabelProvider) table.getLabelProvider(); txt = lbl.getColumnText(c, event.index); final Point textsz = event.gc.textExtent(txt); final int texty = (event.height - textsz.y) / 2; event.gc.drawString(txt, event.x, event.y + texty, true); } /** * Returns the SWT TableView of this CommitGraphTable. * * @return Table the SWT Table */ public TableViewer getTableView() { return table; } 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) { table.getTable().selectAll(); } if (af == ActionFactory.COPY) { doCopy(); } } }; return action; } private final static class MenuListener implements MenuDetectListener { private final MenuManager popupMgr; private final ISelectionProvider selectionProvider; private final IPageSite site; private final IAction copyAction; private HistoryPageInput input; MenuListener(MenuManager menuManager, ISelectionProvider selectionProvider, IPageSite site, IAction copyAction) { this.popupMgr = menuManager; this.selectionProvider = selectionProvider; this.site = site; this.copyAction = copyAction; } public void setInput(HistoryPageInput input) { this.input = input; } public void menuDetected(MenuDetectEvent e) { popupMgr.removeAll(); int selectionSize = ((IStructuredSelection) selectionProvider.getSelection()).size(); if (input.isSingleFile()) { if (selectionSize == 1) if (input.getSingleFile() instanceof IResource) popupMgr.add(getCommandContributionItem(HistoryViewCommands.COMPARE_WITH_TREE, UIText.GitHistoryPage_CompareWithWorkingTreeMenuMenuLabel)); else popupMgr.add(getCommandContributionItem(HistoryViewCommands.COMPARE_WITH_TREE, UIText.GitHistoryPage_CompareWithCurrentHeadMenu)); else if (selectionSize == 2) popupMgr.add(getCommandContributionItem(HistoryViewCommands.COMPARE_VERSIONS, UIText.GitHistoryPage_CompareWithEachOtherMenuLabel)); if (selectionSize > 0) { popupMgr.add(getCommandContributionItem(HistoryViewCommands.OPEN, UIText.GitHistoryPage_OpenMenuLabel)); popupMgr.add(getCommandContributionItem(HistoryViewCommands.OPEN_IN_TEXT_EDITOR, UIText.GitHistoryPage_OpenInTextEditorLabel)); } } if (selectionSize == 1) { popupMgr.add(new Separator()); popupMgr.add(getCommandContributionItem(HistoryViewCommands.CHECKOUT, UIText.GitHistoryPage_CheckoutMenuLabel)); popupMgr.add(getCommandContributionItem(HistoryViewCommands.CREATE_BRANCH, UIText.GitHistoryPage_CreateBranchMenuLabel)); popupMgr.add(getCommandContributionItem(HistoryViewCommands.CREATE_TAG, UIText.GitHistoryPage_CreateTagMenuLabel)); popupMgr.add(getCommandContributionItem(HistoryViewCommands.CREATE_PATCH, UIText.GitHistoryPage_CreatePatchMenuLabel)); popupMgr.add(getCommandContributionItem(HistoryViewCommands.CHERRYPICK, UIText.GitHistoryPage_cherryPickMenuItem)); popupMgr.add(new Separator()); MenuManager resetManager = new MenuManager(UIText.GitHistoryPage_ResetMenuLabel, UIIcons.RESET, "Reset"); //$NON-NLS-1$ popupMgr.add(resetManager); Map<String, String> parameters = new HashMap<String, String>(); parameters.put(HistoryViewCommands.RESET_MODE, "Soft"); //$NON-NLS-1$ resetManager.add(getCommandContributionItem(HistoryViewCommands.RESET, UIText.GitHistoryPage_ResetSoftMenuLabel, parameters)); parameters = new HashMap<String, String>(); parameters.put(HistoryViewCommands.RESET_MODE, "Mixed"); //$NON-NLS-1$ resetManager.add(getCommandContributionItem(HistoryViewCommands.RESET, UIText.GitHistoryPage_ResetMixedMenuLabel, parameters)); parameters = new HashMap<String, String>(); parameters.put(HistoryViewCommands.RESET_MODE, "Hard"); //$NON-NLS-1$ resetManager.add(getCommandContributionItem(HistoryViewCommands.RESET, UIText.GitHistoryPage_ResetHardMenuLabel, parameters)); } popupMgr.add(new Separator()); MenuManager quickDiffManager = new MenuManager(UIText.GitHistoryPage_QuickdiffMenuLabel, null, "Quickdiff"); //$NON-NLS-1$ popupMgr.add(quickDiffManager); quickDiffManager.add(getCommandContributionItem(HistoryViewCommands.SET_QUICKDIFF_BASELINE, UIText.GitHistoryPage_SetAsBaselineMenuLabel)); Map<String, String> parameters = new HashMap<String, String>(); parameters.put(HistoryViewCommands.BASELINE_TARGET, "HEAD"); //$NON-NLS-1$ quickDiffManager.add(getCommandContributionItem(HistoryViewCommands.RESET_QUICKDIFF_BASELINE, UIText.GitHistoryPage_ResetBaselineToHeadMenuLabel, parameters)); parameters = new HashMap<String, String>(); parameters.put(HistoryViewCommands.BASELINE_TARGET, "HEAD^1"); //$NON-NLS-1$ quickDiffManager.add(getCommandContributionItem(HistoryViewCommands.RESET_QUICKDIFF_BASELINE, UIText.GitHistoryPage_ResetBaselineToParentOfHeadMenuLabel, parameters)); // copy and such after additions popupMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); popupMgr.add(copyAction); popupMgr.add(new Separator()); } private CommandContributionItem getCommandContributionItem(String commandId, String menuLabel) { CommandContributionItemParameter parameter = new CommandContributionItemParameter(site, commandId, commandId, CommandContributionItem.STYLE_PUSH); parameter.label = menuLabel; return new CommandContributionItem(parameter); } private CommandContributionItem getCommandContributionItem(String commandId, String menuLabel, Map<String, String> parameters) { CommandContributionItemParameter parameter = new CommandContributionItemParameter(site, commandId, commandId, CommandContributionItem.STYLE_PUSH); parameter.label = menuLabel; parameter.parameters = parameters; return new CommandContributionItem(parameter); } } }