Java tutorial
/******************************************************************************* * Copyright (c) 2004, 2006 Subclipse project and others. * 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: * Subclipse project committers - initial API and implementation ******************************************************************************/ package org.tigris.subversion.subclipse.ui.history; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.IFontProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; 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.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; 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.Table; import org.eclipse.swt.widgets.TableColumn; import org.tigris.subversion.subclipse.core.ISVNRemoteResource; import org.tigris.subversion.subclipse.core.ISVNResource; import org.tigris.subversion.subclipse.core.SVNProviderPlugin; import org.tigris.subversion.subclipse.core.history.ILogEntry; import org.tigris.subversion.subclipse.core.history.LogEntryChangePath; import org.tigris.subversion.subclipse.ui.Policy; import org.tigris.subversion.svnclientadapter.SVNUrl; /** * This class provides the table and it's required components for a change path * This is used from HistoryView */ public class ChangePathsTableProvider extends TableViewer { ILogEntry currentLogEntry; Font currentPathFont; public ChangePathsTableProvider(Composite parent, IContentProvider contentProvider) { super(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION); TableLayout layout = new TableLayout(); GridData data = new GridData(GridData.FILL_BOTH); Table table = (Table) getControl(); table.setHeaderVisible(true); table.setLinesVisible(true); table.setLayoutData(data); table.setLayout(layout); table.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (currentPathFont != null) { currentPathFont.dispose(); } } }); createColumns(table, layout); setLabelProvider(new ChangePathLabelProvider()); setContentProvider(contentProvider); ChangePathsSorter sorter = new ChangePathsSorter(COL_PATH); setSorter(sorter); table.setSortDirection(SWT.UP); } /** * Constructor for HistoryTableProvider. */ public ChangePathsTableProvider(Composite parent, SVNHistoryPage page) { this(parent, new ChangePathsTableContentProvider(page)); } protected void inputChanged(Object input, Object oldInput) { super.inputChanged(input, oldInput); this.currentLogEntry = (ILogEntry) input; } /** * Creates the columns for the history table. */ private void createColumns(Table table, TableLayout layout) { SelectionListener headerListener = getColumnListener(); // action TableColumn col = new TableColumn(table, SWT.NONE); col.setResizable(true); col.setText(Policy.bind("ChangePathsTableProvider.action")); //$NON-NLS-1$ col.addSelectionListener(headerListener); layout.addColumnData(new ColumnWeightData(10, true)); // path col = new TableColumn(table, SWT.NONE); col.setResizable(true); col.setText(Policy.bind("ChangePathsTableProvider.path")); //$NON-NLS-1$ col.addSelectionListener(headerListener); layout.addColumnData(new ColumnWeightData(45, true)); table.setSortColumn(col); // description col = new TableColumn(table, SWT.NONE); col.setResizable(true); col.setText(Policy.bind("ChangePathsTableProvider.description")); //$NON-NLS-1$ col.addSelectionListener(headerListener); layout.addColumnData(new ColumnWeightData(50, true)); } /** * Adds the listener that sets the sorter. */ private SelectionListener getColumnListener() { /** * This class handles selections of the column headers. * Selection of the column header will cause resorting * of the shown paths using that column's sorter. * Repeated selection of the header will toggle * sorting order (ascending versus descending). */ return new SelectionAdapter() { /** * Handles the case of user selecting the * header area. * <p>If the column has not been selected previously, * it will set the sorter of that column to be * the current sorter. Repeated * presses on the same column header will * toggle sorting order (ascending/descending). */ public void widgetSelected(SelectionEvent e) { // column selected - need to sort int column = getTable().indexOf((TableColumn) e.widget); ChangePathsSorter oldSorter = (ChangePathsSorter) getSorter(); if (oldSorter != null && column == oldSorter.getColumnNumber()) { oldSorter.setReversed(!oldSorter.isReversed()); refresh(); } else { setSorter(new ChangePathsSorter(column)); } getTable().setSortColumn((TableColumn) e.widget); if (getTable().getSortDirection() == SWT.UP) getTable().setSortDirection(SWT.DOWN); else getTable().setSortDirection(SWT.UP); } }; } //column constants private static final int COL_ACTION = 0; private static final int COL_PATH = 1; private static final int COL_DESCRIPTION = 2; /** * The label provider. */ class ChangePathLabelProvider extends LabelProvider implements ITableLabelProvider, IFontProvider, IColorProvider { public Image getColumnImage(Object element, int columnIndex) { return null; } public String getColumnText(Object element, int columnIndex) { LogEntryChangePath changePath = (LogEntryChangePath) element; if (changePath == null) return ""; //$NON-NLS-1$ switch (columnIndex) { case COL_ACTION: return "" + changePath.getAction(); //$NON-NLS-1$ case COL_PATH: return changePath.getPath(); case COL_DESCRIPTION: if (changePath.getCopySrcPath() != null) { return Policy.bind("ChangePathsTableProvider.copiedfrom", //$NON-NLS-1$ changePath.getCopySrcPath(), changePath.getCopySrcRevision().toString()); } return ""; //$NON-NLS-1$ } return ""; //$NON-NLS-1$ } /* * (non-Javadoc) * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object) */ public Font getFont(Object element) { if (currentLogEntry == null || element == null) { return null; } SVNUrl url = ((LogEntryChangePath) element).getUrl(); ISVNRemoteResource remoteResource = currentLogEntry.getRemoteResource(); if (remoteResource == null) { return null; } SVNUrl currentUrl = remoteResource.getUrl(); if (currentUrl == null || !currentUrl.equals(url)) { return null; } if (currentPathFont == null) { Font defaultFont = JFaceResources.getDefaultFont(); FontData[] data = defaultFont.getFontData(); for (int i = 0; i < data.length; i++) { data[i].setStyle(SWT.BOLD); } currentPathFont = new Font(getControl().getDisplay(), data); } return currentPathFont; } public Color getBackground(Object element) { return null; } public Color getForeground(Object element) { if (currentLogEntry == null) { return null; } ISVNResource resource = currentLogEntry.getResource(); if (resource == null) return null; boolean isPartOfSelection = false; if (element instanceof HistoryFolder) { HistoryFolder historyFolder = (HistoryFolder) element; isPartOfSelection = (resource.getRepository().getUrl().toString() + historyFolder.getPath()) .startsWith(currentLogEntry.getResource().getUrl().toString()); } if (element instanceof LogEntryChangePath) { LogEntryChangePath logEntryChangePath = (LogEntryChangePath) element; isPartOfSelection = (resource.getRepository().getUrl().toString() + logEntryChangePath.getPath()) .startsWith(currentLogEntry.getResource().getUrl().toString()); } if (!isPartOfSelection) return Display.getDefault().getSystemColor(SWT.COLOR_GRAY); return null; } } static final LogEntryChangePath[] EMPTY_CHANGE_PATHS = new LogEntryChangePath[0]; static class ChangePathsTableContentProvider implements IStructuredContentProvider { private final SVNHistoryPage page; ChangePathsTableContentProvider(SVNHistoryPage page) { this.page = page; } public Object[] getElements(Object inputElement) { if (!this.page.isShowChangePaths() || !(inputElement instanceof ILogEntry)) { return EMPTY_CHANGE_PATHS; } ILogEntry logEntry = (ILogEntry) inputElement; if (SVNProviderPlugin.getPlugin().getSVNClientManager().isFetchChangePathOnDemand()) { if (this.page.currentLogEntryChangePath != null) { return this.page.currentLogEntryChangePath; } this.page.scheduleFetchChangePathJob(logEntry); return EMPTY_CHANGE_PATHS; } return logEntry.getLogEntryChangePaths(); } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { this.page.currentLogEntryChangePath = null; } } /** * The change paths sorter */ class ChangePathsSorter extends ViewerSorter { private boolean reversed = false; private int columnNumber; // column headings: "Revision" "Tags" "Date" "Author" "Comment" private int[][] SORT_ORDERS_BY_COLUMN = { { COL_ACTION, COL_PATH, COL_DESCRIPTION }, /* action */ { COL_PATH, COL_ACTION, COL_DESCRIPTION }, /* path */ { COL_DESCRIPTION, COL_ACTION, COL_PATH } /* description */ }; /** * The constructor. */ public ChangePathsSorter(int columnNumber) { this.columnNumber = columnNumber; } /** * Compares two changed paths, sorting first by the main column of this sorter, * then by subsequent columns, depending on the column sort order. */ public int compare(Viewer viewer, Object o1, Object o2) { LogEntryChangePath p1 = (LogEntryChangePath) o1; LogEntryChangePath p2 = (LogEntryChangePath) o2; int result = 0; if (p1 == null || p2 == null) { result = super.compare(viewer, o1, o2); } else { int[] columnSortOrder = SORT_ORDERS_BY_COLUMN[columnNumber]; for (int i = 0; i < columnSortOrder.length; ++i) { result = compareColumnValue(columnSortOrder[i], p1, p2); if (result != 0) break; } } if (reversed) result = -result; return result; } /** * Compares two markers, based only on the value of the specified column. */ int compareColumnValue(int columnNumber, LogEntryChangePath p1, LogEntryChangePath p2) { switch (columnNumber) { case COL_ACTION: /* action */ return getCollator().compare("" + p1.getAction(), "" + p2.getAction()); case COL_PATH: /* path */ return getCollator().compare(p1.getPath(), p2.getPath()); case COL_DESCRIPTION: /* description */ String d1; String d2; if (p1.getCopySrcPath() != null) { d1 = Policy.bind("ChangePathsTableProvider.copiedfrom", //$NON-NLS-1$ p1.getCopySrcPath(), p1.getCopySrcRevision().toString()); } else { d1 = ""; //$NON-NLS-1$ } if (p2.getCopySrcPath() != null) { d2 = Policy.bind("ChangePathsTableProvider.copiedfrom", //$NON-NLS-1$ p2.getCopySrcPath(), p2.getCopySrcRevision().toString()); } else { d2 = ""; //$NON-NLS-1$ } return getCollator().compare(d1, d2); default: return 0; } } /** * Returns the number of the column by which this is sorting. */ public int getColumnNumber() { return columnNumber; } /** * Returns true for descending, or false * for ascending sorting order. */ public boolean isReversed() { return reversed; } /** * Sets the sorting order. */ public void setReversed(boolean newReversed) { reversed = newReversed; } } public void setCurrentLogEntry(ILogEntry currentLogEntry) { this.currentLogEntry = currentLogEntry; } }