org.eclipse.team.internal.ccvs.ui.HistoryTableProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.team.internal.ccvs.ui.HistoryTableProvider.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2011 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Olexiy Buyanskyy <olexiyb@gmail.com> - Bug 76386 - [History View] CVS Resource History shows revisions from all branches
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui;

import com.ibm.icu.text.DateFormat;
import java.util.Date;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;

/**
 * This class provides the table and it's required components for a file's revision
 * history
 */
public class HistoryTableProvider {

    private ICVSFile currentFile;
    private String currentRevision;
    private TableViewer viewer;
    private Font currentRevisionFont;

    /**
     * Constructor for HistoryTableProvider.
     */
    public HistoryTableProvider() {
        super();
    }

    //column constants
    private static final int COL_REVISION = 0;
    private static final int COL_BRANCHES = 1;
    private static final int COL_TAGS = 2;
    private static final int COL_DATE = 3;
    private static final int COL_AUTHOR = 4;
    private static final int COL_COMMENT = 5;

    /**
     * The history label provider.
     */
    class HistoryLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider, IFontProvider {
        private DateFormat dateFormat;

        public Image getColumnImage(Object element, int columnIndex) {
            return null;
        }

        public String getColumnText(Object element, int columnIndex) {
            ILogEntry entry = adaptToLogEntry(element);
            if (entry == null)
                return ""; //$NON-NLS-1$
            switch (columnIndex) {
            case COL_REVISION:
                String revision = entry.getRevision();
                String currentRevision = getCurrentRevision();
                if (currentRevision != null && currentRevision.equals(revision)) {
                    revision = NLS.bind(CVSUIMessages.currentRevision, new String[] { revision });
                }
                return revision;
            case COL_BRANCHES:
                CVSTag[] branches = entry.getBranches();
                StringBuffer result = new StringBuffer();
                for (int i = 0; i < branches.length; i++) {
                    result.append(branches[i].getName());
                    if (i < branches.length - 1) {
                        result.append(", "); //$NON-NLS-1$
                    }
                }
                return result.toString();
            case COL_TAGS:
                CVSTag[] tags = entry.getTags();
                result = new StringBuffer();
                for (int i = 0; i < tags.length; i++) {
                    result.append(tags[i].getName());
                    if (i < tags.length - 1) {
                        result.append(", "); //$NON-NLS-1$
                    }
                }
                return result.toString();
            case COL_DATE:
                Date date = entry.getDate();
                if (date == null)
                    return CVSUIMessages.notAvailable;
                return getDateFormat().format(date);
            case COL_AUTHOR:
                return entry.getAuthor();
            case COL_COMMENT:
                String comment = entry.getComment();
                int index = comment.indexOf("\n"); //$NON-NLS-1$
                switch (index) {
                case -1:
                    return comment;
                case 0:
                    return CVSUIMessages.HistoryView_______4;
                default:
                    return NLS.bind(CVSUIMessages.CVSCompareRevisionsInput_truncate,
                            new String[] { comment.substring(0, index) });
                }
            }
            return ""; //$NON-NLS-1$
        }

        private synchronized DateFormat getDateFormat() {
            if (dateFormat == null)
                dateFormat = DateFormat.getInstance();
            return dateFormat;
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.IColorProvider#getForeground(java.lang.Object)
         */
        public Color getForeground(Object element) {
            ILogEntry entry = adaptToLogEntry(element);
            if (entry.isDeletion()) {
                return Display.getCurrent().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
            } else {
                return null;
            }
        }

        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.IColorProvider#getBackground(java.lang.Object)
         */
        public Color getBackground(Object element) {
            return null;
        }

        /*
         * (non-Javadoc)
         * @see org.eclipse.jface.viewers.IFontProvider#getFont(java.lang.Object)
         */
        public Font getFont(Object element) {
            ILogEntry entry = adaptToLogEntry(element);
            if (entry == null)
                return null;
            String revision = entry.getRevision();
            String currentRevision = getCurrentRevision();
            if (currentRevision != null && currentRevision.equals(revision)) {
                if (currentRevisionFont == null) {
                    Font defaultFont = JFaceResources.getDefaultFont();
                    FontData[] data = defaultFont.getFontData();
                    for (int i = 0; i < data.length; i++) {
                        data[i].setStyle(SWT.BOLD);
                    }
                    currentRevisionFont = new Font(viewer.getTable().getDisplay(), data);
                }
                return currentRevisionFont;
            }
            return null;
        }
    }

    /**
     * The history sorter
     */
    class HistoryComparator extends ViewerComparator {
        private boolean reversed = false;
        private int columnNumber;

        private VersionCollator versionCollator = new VersionCollator();

        // column headings:   "Revision" "Branches" "Tags" "Date" "Author" "Comment"
        private int[][] SORT_ORDERS_BY_COLUMN = {
                { COL_REVISION, COL_DATE, COL_AUTHOR, COL_COMMENT, COL_TAGS, COL_BRANCHES }, /* revision */
                { COL_BRANCHES, COL_REVISION, COL_DATE, COL_AUTHOR, COL_COMMENT, COL_TAGS }, /* tags */
                { COL_TAGS, COL_REVISION, COL_DATE, COL_AUTHOR, COL_COMMENT, COL_BRANCHES }, /* tags */
                { COL_DATE, COL_REVISION, COL_AUTHOR, COL_COMMENT, COL_TAGS, COL_BRANCHES }, /* date */
                { COL_AUTHOR, COL_REVISION, COL_DATE, COL_COMMENT, COL_TAGS, COL_BRANCHES }, /* author */
                { COL_COMMENT, COL_REVISION, COL_DATE, COL_AUTHOR, COL_TAGS, COL_BRANCHES } /* comment */
        };

        /**
         * The constructor.
         */
        public HistoryComparator(int columnNumber) {
            this.columnNumber = columnNumber;
        }

        /**
         * Compares two log entries, 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) {
            ILogEntry e1 = adaptToLogEntry(o1);
            ILogEntry e2 = adaptToLogEntry(o2);
            int result = 0;
            if (e1 == null || e2 == 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], e1, e2);
                    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, ILogEntry e1, ILogEntry e2) {
            switch (columnNumber) {
            case COL_REVISION: /* revision */
                return versionCollator.compare(e1.getRevision(), e2.getRevision());
            case COL_BRANCHES: /* branches */
                CVSTag[] branches1 = e1.getBranches();
                CVSTag[] branches2 = e2.getBranches();
                if (branches2.length == 0) {
                    return -1;
                }
                if (branches1.length == 0) {
                    return 1;
                }
                return getComparator().compare(branches1[0].getName(), branches2[0].getName());
            case COL_TAGS: /* tags */
                CVSTag[] tags1 = e1.getTags();
                CVSTag[] tags2 = e2.getTags();
                if (tags2.length == 0) {
                    return -1;
                }
                if (tags1.length == 0) {
                    return 1;
                }
                return getComparator().compare(tags1[0].getName(), tags2[0].getName());
            case COL_DATE: /* date */
                Date date1 = e1.getDate();
                Date date2 = e2.getDate();
                return date1.compareTo(date2);
            case COL_AUTHOR: /* author */
                return getComparator().compare(e1.getAuthor(), e2.getAuthor());
            case COL_COMMENT: /* comment */
                return getComparator().compare(e1.getComment(), e2.getComment());
            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;
        }
    }

    protected ILogEntry adaptToLogEntry(Object element) {
        // Get the log entry for the provided object
        ILogEntry entry = null;
        if (element instanceof ILogEntry) {
            entry = (ILogEntry) element;
        } else if (element instanceof IAdaptable) {
            entry = (ILogEntry) ((IAdaptable) element).getAdapter(ILogEntry.class);
        }
        return entry;
    }

    /**
     * Create a TableViewer that can be used to display a list of ILogEntry instances.
     * Ths method provides the labels and sorter but does not provide a content provider
     * 
     * @param parent
     * @return TableViewer
     */
    public TableViewer createTable(Composite parent) {
        Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        GridData data = new GridData(GridData.FILL_BOTH);
        table.setLayoutData(data);

        TableLayout layout = new TableLayout();
        table.setLayout(layout);

        TableViewer viewer = new TableViewer(table);

        createColumns(table, layout, viewer);

        viewer.setLabelProvider(new HistoryLabelProvider());

        // By default, reverse sort by revision.
        HistoryComparator sorter = new HistoryComparator(COL_REVISION);
        sorter.setReversed(true);
        viewer.setComparator(sorter);

        table.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                if (currentRevisionFont != null) {
                    currentRevisionFont.dispose();
                }
            }
        });

        this.viewer = viewer;
        return viewer;
    }

    /**
     * Create a CheckBoxTableViewer that can be used to display a list of ILogEntry instances.
     * Ths method provides the labels and sorter but does not provide a content provider
     * 
     * @param parent
     * @return TableViewer
     */
    public CheckboxTableViewer createCheckBoxTable(Composite parent) {
        Table table = new Table(parent, SWT.CHECK | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);
        GridData data = new GridData(GridData.FILL_BOTH);
        table.setLayoutData(data);

        TableLayout layout = new TableLayout();
        table.setLayout(layout);

        CheckboxTableViewer viewer = new CheckboxTableViewer(table);

        createColumns(table, layout, viewer);

        viewer.setLabelProvider(new HistoryLabelProvider());

        // By default, reverse sort by revision.
        HistoryComparator sorter = new HistoryComparator(COL_REVISION);
        sorter.setReversed(true);
        viewer.setComparator(sorter);

        table.addDisposeListener(new DisposeListener() {
            public void widgetDisposed(DisposeEvent e) {
                if (currentRevisionFont != null) {
                    currentRevisionFont.dispose();
                }
            }
        });

        this.viewer = viewer;
        return viewer;
    }

    /**
     * Creates the columns for the history table.
     */
    private void createColumns(Table table, TableLayout layout, TableViewer viewer) {
        SelectionListener headerListener = getColumnListener(viewer);
        // revision
        TableColumn col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(CVSUIMessages.HistoryView_revision);
        col.addSelectionListener(headerListener);
        layout.addColumnData(new ColumnWeightData(20, true));

        // branches
        col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(CVSUIMessages.HistoryView_branches);
        col.addSelectionListener(headerListener);
        layout.addColumnData(new ColumnWeightData(20, true));

        // tags
        col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(CVSUIMessages.HistoryView_tags);
        col.addSelectionListener(headerListener);
        layout.addColumnData(new ColumnWeightData(20, true));

        // creation date
        col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(CVSUIMessages.HistoryView_date);
        col.addSelectionListener(headerListener);
        layout.addColumnData(new ColumnWeightData(20, true));

        // author
        col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(CVSUIMessages.HistoryView_author);
        col.addSelectionListener(headerListener);
        layout.addColumnData(new ColumnWeightData(20, true));

        //comment
        col = new TableColumn(table, SWT.NONE);
        col.setResizable(true);
        col.setText(CVSUIMessages.HistoryView_comment);
        col.addSelectionListener(headerListener);
        layout.addColumnData(new ColumnWeightData(50, true));
    }

    /**
     * Adds the listener that sets the sorter.
     */
    private SelectionListener getColumnListener(final TableViewer tableViewer) {
        /**
          * This class handles selections of the column headers.
         * Selection of the column header will cause resorting
         * of the shown tasks 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 tasklist 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 = tableViewer.getTable().indexOf((TableColumn) e.widget);
                HistoryComparator oldSorter = (HistoryComparator) tableViewer.getComparator();
                if (oldSorter != null && column == oldSorter.getColumnNumber()) {
                    oldSorter.setReversed(!oldSorter.isReversed());
                    tableViewer.refresh();
                } else {
                    tableViewer.setComparator(new HistoryComparator(column));
                }
            }
        };
    }

    public String getCurrentRevision() {
        return currentRevision;
    }

    /**
     * Method getRevision.
     * @param currentEdition
     */
    private String getRevision(ICVSFile currentEdition) throws CVSException {
        if (currentEdition == null)
            return ""; //$NON-NLS-1$
        ResourceSyncInfo info = currentEdition.getSyncInfo();
        if (info == null)
            return ""; //$NON-NLS-1$
        return info.getRevision();
    }

    public void setFile(ICVSFile file) throws CVSException {
        this.currentFile = file;
        this.currentRevision = getRevision(this.currentFile);
    }

    public ICVSFile getICVSFile() {
        return this.currentFile;
    }
}