com.vectrace.MercurialEclipse.repository.RepositoriesView.java Source code

Java tutorial

Introduction

Here is the source code for com.vectrace.MercurialEclipse.repository.RepositoriesView.java

Source

/*******************************************************************************
 * Copyright (c) 2003, 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
 *     Bastian Doetsch              - adaptation
 *     Andrei Loskutov              - bug fixes
 ******************************************************************************/
package com.vectrace.MercurialEclipse.repository;

import java.util.Iterator;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.SelectionProviderAction;
import org.eclipse.ui.internal.dialogs.PropertyDialog;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;

import com.vectrace.MercurialEclipse.MercurialEclipsePlugin;
import com.vectrace.MercurialEclipse.commands.HgInitClient;
import com.vectrace.MercurialEclipse.exception.HgException;
import com.vectrace.MercurialEclipse.model.HgPath;
import com.vectrace.MercurialEclipse.model.IHgRepositoryLocation;
import com.vectrace.MercurialEclipse.repository.actions.RemoveRootAction;
import com.vectrace.MercurialEclipse.repository.model.AllRootsElement;
import com.vectrace.MercurialEclipse.repository.model.RemoteContentProvider;
import com.vectrace.MercurialEclipse.ui.HgProjectPropertyPage;
import com.vectrace.MercurialEclipse.utils.ResourceUtils;
import com.vectrace.MercurialEclipse.wizards.CloneRepoWizard;
import com.vectrace.MercurialEclipse.wizards.ImportProjectsFromRepoWizard;
import com.vectrace.MercurialEclipse.wizards.NewLocationWizard;

/**
 * RepositoriesView is a view on a set of known Hg repositories
 */
public class RepositoriesView extends ViewPart implements ISelectionListener {

    private final class InitAction extends Action {

        private final Shell shell;

        private InitAction(String text, ImageDescriptor image, Shell shell) {
            super(text, image);
            this.shell = shell;
        }

        @Override
        public void run() {
            IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
            if (selection.size() != 1 || !(selection.getFirstElement() instanceof IHgRepositoryLocation)) {
                return;
            }
            final IHgRepositoryLocation repo = (IHgRepositoryLocation) selection.getFirstElement();
            final String[] initResult = new String[] { "" };
            Job job = new Job("Init for " + repo.toString()) {

                @Override
                protected IStatus run(IProgressMonitor monitor) {
                    try {
                        initResult[0] = HgInitClient.init(repo);
                    } catch (HgException e) {
                        initResult[0] = e.getMessage();
                        MercurialEclipsePlugin.logError(e);
                        return e.getStatus();
                    }
                    return Status.OK_STATUS;
                }
            };
            job.addJobChangeListener(new JobChangeAdapter() {
                @Override
                public void done(final IJobChangeEvent event) {
                    Display.getDefault().asyncExec(new Runnable() {
                        public void run() {
                            String message;
                            if (event.getResult().isOK()) {
                                message = "Hg init for repository '" + repo.toString() + "' was successful!";
                            } else {
                                message = "Hg init for repository '" + repo.toString() + "' failed!";
                            }
                            if (initResult[0] != null && initResult[0].length() > 0) {
                                message += "\nHg said: " + initResult[0];
                            }
                            MessageDialog.openInformation(shell, "Hg init result", message);
                        }
                    });
                }
            });
            IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) getSite()
                    .getService(IWorkbenchSiteProgressService.class);
            service.schedule(job);
        }
    }

    public static final String VIEW_ID = "com.vectrace.MercurialEclipse.repository.RepositoriesView"; //$NON-NLS-1$

    // The root
    private AllRootsElement root;

    // Actions
    private Action newAction;
    private RemoveRootAction removeRootAction;

    // The tree viewer
    protected TreeViewer treeViewer;

    // Drill down adapter
    private DrillDownAdapter drillPart; // Home, back, and "drill into"

    private Action refreshAction;
    private Action refreshPopupAction;
    private Action collapseAllAction;
    private Action propertiesAction;
    private Action cloneAction;

    private RemoteContentProvider contentProvider;

    /** this listener is used when a repository is added, removed or changed */
    private final IRepositoryListener repositoryListener = new IRepositoryListener() {
        public void repositoryAdded(final IHgRepositoryLocation loc) {
            refresh(loc);
        }

        public void repositoryRemoved(IHgRepositoryLocation loc) {
            refresh(null);
        }

        public void repositoriesChanged(IHgRepositoryLocation[] roots) {
            refresh(null);
        }

        private void refresh(final Object object) {
            Display display = getViewer().getControl().getDisplay();
            display.asyncExec(new Runnable() {
                public void run() {
                    refreshViewer(object, false);
                }
            });
        }

        public void repositoryModified(IHgRepositoryLocation loc) {
            refresh(null);
        }
    };

    private Action importAction;

    private Action initAction;

    public RepositoriesView() {
        super();
    }

    /**
     * Contribute actions to the view
     */
    protected void contributeActions() {

        final Shell shell = getShell();

        // Create actions

        // New Repository (popup)
        newAction = new Action(Messages.getString("RepositoriesView.createRepo"), MercurialEclipsePlugin //$NON-NLS-1$
                .getImageDescriptor("wizards/newlocation_wiz.gif")) { //$NON-NLS-1$
            @Override
            public void run() {
                NewLocationWizard wizard = new NewLocationWizard();
                WizardDialog dialog = new WizardDialog(shell, wizard);
                dialog.open();
            }
        };

        // Clone Repository (popup)
        cloneAction = new Action(Messages.getString("RepositoriesView.cloneRepo"), MercurialEclipsePlugin //$NON-NLS-1$
                .getImageDescriptor("clone_repo.gif")) { //$NON-NLS-1$
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
                CloneRepoWizard wizard = new CloneRepoWizard();
                wizard.init(PlatformUI.getWorkbench(), selection);
                WizardDialog dialog = new WizardDialog(shell, wizard);
                dialog.open();
            }
        };

        // Init Repository (popup)
        initAction = new InitAction(Messages.getString("RepositoriesView.initRepo"), MercurialEclipsePlugin //$NON-NLS-1$
                .getImageDescriptor("release_rls.gif"), shell);

        // Import project (popup)
        importAction = new Action(Messages.getString("RepositoriesView.importProject"),
                MercurialEclipsePlugin.getImageDescriptor("import_project.gif")) { //$NON-NLS-1$
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();

                ImportProjectsFromRepoWizard wizard = new ImportProjectsFromRepoWizard();
                wizard.init(PlatformUI.getWorkbench(), selection);
                WizardDialog dialog = new WizardDialog(shell, wizard);
                dialog.open();
            }
        };

        // Properties
        propertiesAction = new SelectionProviderAction(treeViewer, "Properties") {
            @Override
            public void run() {
                IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
                if (selection.isEmpty()) {
                    return;
                }
                Object firstElement = selection.getFirstElement();
                PreferenceDialog dialog = createDialog(firstElement);
                if (dialog != null) {
                    dialog.open();
                }
                if (!selection.isEmpty()) {
                    treeViewer.refresh(firstElement);
                }
            }

            public PreferenceDialog createDialog(Object element) {
                String initialPageId = null;
                if (element instanceof IProject) {
                    initialPageId = HgProjectPropertyPage.ID;
                }
                return PropertyDialog.createDialogOn(shell, initialPageId, element);
            }
        };

        IActionBars bars = getViewSite().getActionBars();
        bars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), propertiesAction);
        IStructuredSelection selection = (IStructuredSelection) getViewer().getSelection();
        if (selection.size() == 1) {
            propertiesAction.setEnabled(true);
        } else {
            propertiesAction.setEnabled(false);
        }

        getViewer().addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection ss = (IStructuredSelection) event.getSelection();
                propertiesAction.setEnabled(ss.size() == 1);
            }
        });

        // Remove Root
        removeRootAction = new RemoveRootAction(treeViewer.getControl().getShell());
        removeRootAction.selectionChanged((IStructuredSelection) null);

        bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), removeRootAction);

        // Refresh action (toolbar)
        refreshAction = new Action(Messages.getString("RepositoriesView.refreshRepos"), //$NON-NLS-1$
                MercurialEclipsePlugin.getImageDescriptor("elcl16/refresh.gif")) { //$NON-NLS-1$
            @Override
            public void run() {
                refreshViewer(null, true);
            }
        };
        refreshAction.setToolTipText(Messages.getString("RepositoriesView.refresh")); //$NON-NLS-1$
        refreshAction.setDisabledImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("dlcl16/refresh.gif")); //$NON-NLS-1$
        refreshAction.setHoverImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("clcl16/refresh.gif")); //$NON-NLS-1$
        getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction);

        refreshPopupAction = new Action(Messages.getString("RepositoriesView.refresh"), MercurialEclipsePlugin //$NON-NLS-1$
                .getImageDescriptor("clcl16/refresh.gif")) { //$NON-NLS-1$
            @Override
            public void run() {
                refreshViewerNode();
            }
        };

        // Collapse action
        collapseAllAction = new Action(Messages.getString("RepositoriesView.collapseAll"), //$NON-NLS-1$
                MercurialEclipsePlugin.getImageDescriptor("elcl16/collapseall.gif")) { //$NON-NLS-1$
            @Override
            public void run() {
                collapseAll();
            }
        };
        collapseAllAction.setToolTipText(Messages.getString("RepositoriesView.collapseAll")); //$NON-NLS-1$
        collapseAllAction
                .setHoverImageDescriptor(MercurialEclipsePlugin.getImageDescriptor("clcl16/collapseall.gif")); //$NON-NLS-1$

        // Create the popup menu
        MenuManager menuMgr = new MenuManager();
        Tree tree = treeViewer.getTree();
        Menu menu = menuMgr.createContextMenu(tree);
        menuMgr.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                addWorkbenchActions(manager);
            }

        });
        menuMgr.setRemoveAllWhenShown(true);
        tree.setMenu(menu);
        getSite().registerContextMenu(menuMgr, treeViewer);

        // Create the local tool bar
        IToolBarManager tbm = bars.getToolBarManager();
        IMenuManager mm = bars.getMenuManager();
        drillPart.addNavigationActions(tbm);
        drillPart.addNavigationActions(mm);
        tbm.add(new Separator());
        mm.add(new Separator());
        tbm.add(newAction);
        mm.add(newAction);
        tbm.add(refreshAction);
        mm.add(refreshAction);
        tbm.add(new Separator());
        mm.add(new Separator());
        tbm.add(collapseAllAction);
        mm.add(collapseAllAction);
        tbm.update(false);
        mm.update(false);

        bars.updateActionBars();
    }

    protected void addWorkbenchActions(IMenuManager manager) {
        IStructuredSelection selection = (IStructuredSelection) getViewer().getSelection();

        // File actions go first (view file)
        manager.add(new Separator(IWorkbenchActionConstants.GROUP_FILE));
        // Misc additions
        manager.add(new Separator("historyGroup")); //$NON-NLS-1$
        manager.add(new Separator("checkoutGroup")); //$NON-NLS-1$
        manager.add(new Separator("exportImportGroup")); //$NON-NLS-1$

        boolean singleFile = selection.size() == 1 && selection.getFirstElement() instanceof HgPath;

        if (singleFile) {
            HgPath path = (HgPath) selection.getFirstElement();
            if (path.isDirectory()) {
                manager.add(importAction);
            }
        }

        manager.add(new Separator("miscGroup")); //$NON-NLS-1$

        boolean singleRepoSelected = selection.size() == 1
                && selection.getFirstElement() instanceof IHgRepositoryLocation;

        if (singleRepoSelected) {
            manager.add(cloneAction);
            IHgRepositoryLocation repo = (IHgRepositoryLocation) selection.getFirstElement();
            if (!repo.isLocal() && repo.getLocation().startsWith("ssh:")) {
                manager.add(initAction);
            }
            manager.add(refreshPopupAction);
        }

        removeRootAction.selectionChanged(selection);
        if (removeRootAction.isEnabled()) {
            manager.add(removeRootAction);
        }

        manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));

        if (selection.size() == 1) {
            manager.add(propertiesAction);
        }
    }

    @Override
    public void createPartControl(Composite parent) {
        treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
        contentProvider = new RemoteContentProvider();
        treeViewer.setContentProvider(contentProvider);
        treeViewer.setLabelProvider(WorkbenchLabelProvider.getDecoratingWorkbenchLabelProvider());
        root = new AllRootsElement();
        treeViewer.setInput(root);
        treeViewer.setSorter(new RepositorySorter());
        drillPart = new DrillDownAdapter(treeViewer);

        contributeActions();

        initializeListeners();
        MercurialEclipsePlugin.getRepoManager().addRepositoryListener(repositoryListener);
        getSite().setSelectionProvider(treeViewer);
    }

    protected void initializeListeners() {
        getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(this);
        treeViewer.addSelectionChangedListener(removeRootAction);

        // FIXME This will fail if the user has assigned a key other than F5
        // when F5 is pressed, refresh this view
        treeViewer.getControl().addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent event) {
                if (event.keyCode == SWT.F5) {
                    refreshAction.run();
                }
            }
        });

        treeViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent e) {
                handleDoubleClick(e);
            }
        });
    }

    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        String msg = getStatusLineMessage(selection);
        getViewSite().getActionBars().getStatusLineManager().setMessage(msg);
    }

    /**
     * When selection is changed we update the status line
     */
    private static String getStatusLineMessage(ISelection selection) {
        if (!(selection instanceof IStructuredSelection) || selection.isEmpty()) {
            return ""; //$NON-NLS-1$
        }
        IStructuredSelection s = (IStructuredSelection) selection;

        if (s.size() > 1) {
            return String.valueOf(s.size()) + Messages.getString("RepositoriesView.multiSelected"); //$NON-NLS-1$
        }
        return Messages.getString("RepositoriesView.oneSelected"); //$NON-NLS-1$
    }

    @Override
    public void setFocus() {
        treeViewer.getControl().setFocus();
    }

    protected Shell getShell() {
        return treeViewer.getTree().getShell();
    }

    public TreeViewer getViewer() {
        return treeViewer;
    }

    /**
     * this is called whenever a new repository location is added for example or
     * when user wants to refresh
     */
    public void refreshViewer(Object object, boolean refreshRepositoriesFolders) {
        if (treeViewer == null || treeViewer.getControl() == null || treeViewer.getControl().isDisposed()) {
            return;
        }
        if (refreshRepositoriesFolders) {
            try {
                MercurialEclipsePlugin.getRepoManager().refreshRepositories(null);
            } catch (HgException e) {
                MercurialEclipsePlugin.logError(e);
            }
        }
        treeViewer.refresh();
        if (object != null) {
            treeViewer.setSelection(new StructuredSelection(object), true);
        }
    }

    @SuppressWarnings("rawtypes")
    protected void refreshViewerNode() {
        IStructuredSelection selection = (IStructuredSelection) treeViewer.getSelection();
        Iterator iter = selection.iterator();
        while (iter.hasNext()) {
            Object object = iter.next();
            if (object instanceof IHgRepositoryLocation) {
                refreshAction.run();
                break;
            }
            treeViewer.refresh(object);
        }
    }

    public void collapseAll() {
        if (treeViewer == null) {
            return;
        }
        treeViewer.getControl().setRedraw(false);
        treeViewer.collapseToLevel(treeViewer.getInput(), AbstractTreeViewer.ALL_LEVELS);
        treeViewer.getControl().setRedraw(true);
    }

    /**
     * The mouse has been double-clicked in the tree, perform appropriate
     * behaviour.
     */
    private void handleDoubleClick(DoubleClickEvent e) {
        // Only act on single selection
        ISelection selection = e.getSelection();
        if (!(selection instanceof IStructuredSelection)) {
            return;
        }
        IStructuredSelection structured = (IStructuredSelection) selection;
        if (structured.size() != 1) {
            return;
        }
        Object firstElement = structured.getFirstElement();
        IResource resource = ResourceUtils.getResource(firstElement);
        if (resource != null && resource.exists() && resource.getType() == IResource.FILE) {
            ResourceUtils.openEditor(null, (IFile) resource);
            return;
        }
        propertiesAction.run();
    }

    @Override
    public void dispose() {
        MercurialEclipsePlugin.getRepoManager().removeRepositoryListener(repositoryListener);
        super.dispose();
        treeViewer = null;
    }

}