com.vectrace.MercurialEclipse.history.ChangePathsTableProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.vectrace.MercurialEclipse.history.ChangePathsTableProvider.java

Source

/*******************************************************************************
 * 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
 *     Andrei Loskutov        - bug fixes
 ******************************************************************************/
package com.vectrace.MercurialEclipse.history;

import java.util.List;
import java.util.WeakHashMap;

import org.eclipse.core.runtime.IPath;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
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.ui.PlatformUI;

import com.vectrace.MercurialEclipse.model.FileStatus;

public class ChangePathsTableProvider extends TableViewer {

    private static final FileStatus[] EMPTY_CHANGE_PATHS = new FileStatus[0];
    private final ChangedPathsPage page;
    private final ChangePathsTableContentProvider contentProvider;

    public ChangePathsTableProvider(Composite parent, ChangedPathsPage page) {
        super(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.MULTI | SWT.FULL_SELECTION);
        this.page = page;
        contentProvider = new ChangePathsTableContentProvider(page);
        setContentProvider(contentProvider);

        setLabelProvider(new ChangePathLabelProvider(page, this));

        GridData data = new GridData(GridData.FILL_BOTH);

        final Table table = (Table) getControl();
        table.setHeaderVisible(false);
        table.setLinesVisible(true);
        table.setLayoutData(data);
    }

    public int getElementsCount() {
        MercurialRevision revision = page.getCurrentRevision();
        if (revision == null || !revision.isFile()) {
            return 0;
        }
        return contentProvider.getElements(revision).length;
    }

    private static class ChangePathLabelProvider extends DecoratingLabelProvider implements ITableLabelProvider {

        private final ChangedPathsPage page;
        private final ChangePathsTableProvider tableProvider;

        public ChangePathLabelProvider(ChangedPathsPage page, ChangePathsTableProvider tableProvider) {
            super(new SimpleLabelImageProvider(),
                    PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator());
            this.page = page;
            this.tableProvider = tableProvider;
        }

        public Image getColumnImage(Object element, int columnIndex) {
            if (!(element instanceof FileStatus)) {
                return null;
            }
            return getImage(element);
        }

        public String getColumnText(Object element, int columnIndex) {
            if (!(element instanceof FileStatus)) {
                return null;
            }
            return getText(element);
        }

        @Override
        public Font getFont(Object element) {
            if (!(element instanceof FileStatus)) {
                return null;
            }
            MercurialRevision revision = page.getCurrentRevision();
            if (revision == null || !revision.isFile()) {
                return null;
            }
            IPath basePath = revision.getIPath();
            IPath currentPath = ((FileStatus) element).getRootRelativePath();
            if (basePath.equals(currentPath) && tableProvider.getElementsCount() > 1) {
                // highlight current file in the changeset, if there are more files
                return JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT);
            }
            return JFaceResources.getFontRegistry().get(JFaceResources.DEFAULT_FONT);
        }

    }

    private static class ChangePathsTableContentProvider implements IStructuredContentProvider {

        private final WeakHashMap<MercurialRevision, FileStatus[]> revToFiles;
        private final ChangedPathsPage page;
        private Viewer viewer;
        private boolean disposed;

        public ChangePathsTableContentProvider(ChangedPathsPage page) {
            this.page = page;
            revToFiles = new WeakHashMap<MercurialRevision, FileStatus[]>();
        }

        public Object[] getElements(Object inputElement) {
            if (!this.page.isShowChangePaths()) {
                return EMPTY_CHANGE_PATHS;
            }

            MercurialRevision rev = (MercurialRevision) inputElement;
            FileStatus[] fileStatus;
            synchronized (revToFiles) {
                fileStatus = revToFiles.get(rev);
            }
            if (fileStatus != null) {
                return fileStatus;
            }
            fetchPaths(rev);
            // but sometimes hg returns a null version map...
            return EMPTY_CHANGE_PATHS;
        }

        private void fetchPaths(final MercurialRevision rev) {
            synchronized (revToFiles) {
                if (revToFiles.containsKey(rev)) {
                    return;
                }
            }

            List<FileStatus> status = rev.getChangeSet().getChangedFiles();

            synchronized (revToFiles) {
                if (!revToFiles.containsKey(rev)) {
                    revToFiles.put(rev, status.toArray(new FileStatus[status.size()]));
                }
            }

            if (disposed) {
                return;
            }

            Runnable refresh = new Runnable() {
                public void run() {
                    if (!disposed && viewer != null) {
                        viewer.refresh();
                    }
                }
            };
            Display.getDefault().asyncExec(refresh);
        }

        public void dispose() {
            disposed = true;
            synchronized (revToFiles) {
                revToFiles.clear();
            }
        }

        public void inputChanged(Viewer viewer1, Object oldInput, Object newInput) {
            this.viewer = viewer1;
        }
    }
}