org.tigris.subversion.subclipse.ui.repository.RepositoriesView.java Source code

Java tutorial

Introduction

Here is the source code for org.tigris.subversion.subclipse.ui.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
 ******************************************************************************/
package org.tigris.subversion.subclipse.ui.repository;

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;

import org.eclipse.core.runtime.IProgressMonitor;
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.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProviderListener;
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.window.SameShellProvider;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Image;
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.dialogs.PropertyDialogAction;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.DrillDownAdapter;
import org.eclipse.ui.part.PluginTransfer;
import org.eclipse.ui.part.PluginTransferData;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.part.WorkbenchPart;
import org.tigris.subversion.subclipse.core.ISVNRemoteFile;
import org.tigris.subversion.subclipse.core.ISVNRemoteFolder;
import org.tigris.subversion.subclipse.core.ISVNRemoteResource;
import org.tigris.subversion.subclipse.core.ISVNRepositoryLocation;
import org.tigris.subversion.subclipse.core.ISVNResource;
import org.tigris.subversion.subclipse.core.SVNProviderPlugin;
import org.tigris.subversion.subclipse.core.resources.RemoteFile;
import org.tigris.subversion.subclipse.ui.IHelpContextIds;
import org.tigris.subversion.subclipse.ui.ISVNUIConstants;
import org.tigris.subversion.subclipse.ui.Policy;
import org.tigris.subversion.subclipse.ui.SVNUIPlugin;
import org.tigris.subversion.subclipse.ui.WorkspacePathValidator;
import org.tigris.subversion.subclipse.ui.actions.OpenRemoteFileAction;
import org.tigris.subversion.subclipse.ui.actions.RemoteResourceTransfer;
import org.tigris.subversion.subclipse.ui.actions.SVNAction;
import org.tigris.subversion.subclipse.ui.repository.model.AllRootsElement;
import org.tigris.subversion.subclipse.ui.repository.model.RemoteContentProvider;
import org.tigris.subversion.subclipse.ui.wizards.ClosableWizardDialog;
import org.tigris.subversion.subclipse.ui.wizards.NewLocationWizard;
import org.tigris.subversion.subclipse.ui.wizards.dialogs.SvnWizard;
import org.tigris.subversion.subclipse.ui.wizards.dialogs.SvnWizardDialog;
import org.tigris.subversion.subclipse.ui.wizards.dialogs.SvnWizardNewRepositoryPage;

/**
 * RepositoriesView is a view on a set of known SVN repositories
 * which allows navigation of the structure of the repository and
 * the performing of SVN-specific operations on the repository contents.
 */
public class RepositoriesView extends ViewPart implements ISelectionListener {
    public static final String VIEW_ID = "org.tigris.subversion.subclipse.ui.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 OpenRemoteFileAction openAction;
    private Action propertiesAction;

    private RemoteContentProvider contentProvider;
    // this listener is used when a repository is added, removed or changed
    private IRepositoryListener repositoryListener = new IRepositoryListener() {
        public void repositoryAdded(final ISVNRepositoryLocation root) {
            getViewer().getControl().getDisplay().syncExec(new Runnable() {
                public void run() {
                    refreshViewer(null, false);
                    getViewer().setSelection(new StructuredSelection(root));
                }
            });
        }

        public void repositoryRemoved(ISVNRepositoryLocation root) {
            refresh(null, false);
        }

        public void repositoriesChanged(ISVNRepositoryLocation[] roots) {
            refresh(null, false);
        }

        public void remoteResourceDeleted(ISVNRemoteResource resource) {
            refresh(resource.getParent(), false);
        }

        public void remoteResourceCreated(ISVNRemoteFolder parent, String resourceName) {
            refresh(parent, true);
        }

        public void remoteResourceCopied(ISVNRemoteResource source, ISVNRemoteFolder destination) {
            refresh(destination, false);
        }

        public void remoteResourceMoved(ISVNRemoteResource resource, ISVNRemoteFolder destinationFolder,
                String destinationResourceName) {
            refresh(resource.getParent(), false);
            refresh(destinationFolder, false);
        }

        private void refresh(Object object, boolean refreshRepositoriesFolders) {
            final Object finalObject = object;
            final boolean finalRefreshReposFolders = refreshRepositoriesFolders;
            Display display = getViewer().getControl().getDisplay();
            display.syncExec(new Runnable() {
                public void run() {
                    RepositoriesView.this.refreshViewer(finalObject, finalRefreshReposFolders);
                }
            });
        }

        public void repositoryModified(ISVNRepositoryLocation root) {
            refresh(null, false);
        }
    };

    private static final class RepositoryDragSourceListener implements DragSourceListener {
        private IStructuredSelection selection;

        public void dragStart(DragSourceEvent event) {
            if (selection != null) {
                final Object[] array = selection.toArray();
                // event.doit = Utils.getResources(array).length > 0;
                for (int i = 0; i < array.length; i++) {
                    if (array[i] instanceof ISVNRemoteResource) {
                        event.doit = true;
                        return;
                    }
                }
                event.doit = false;
            }
        }

        public void dragSetData(DragSourceEvent event) {
            if (selection != null && RemoteResourceTransfer.getInstance().isSupportedType(event.dataType)) {
                final Object[] array = selection.toArray();
                for (int i = 0; i < array.length; i++) {
                    if (array[i] instanceof ISVNRemoteResource) {
                        event.data = array[i];
                        return;
                    }
                }
            } else if (PluginTransfer.getInstance().isSupportedType(event.dataType)) {
                final Object[] array = selection.toArray();
                for (int i = 0; i < array.length; i++) {
                    if (array[i] instanceof ISVNRemoteResource) {
                        event.data = new PluginTransferData("org.tigris.subversion.subclipse.ui.svnRemoteDrop", //$NON-NLS-1$
                                RemoteResourceTransfer.getInstance().toByteArray((ISVNRemoteResource) array[i]));
                        return;
                    }
                }

            }
        }

        public void dragFinished(DragSourceEvent event) {
        }

        public void updateSelection(IStructuredSelection selection) {
            this.selection = selection;
        }
    }

    RepositoryDragSourceListener repositoryDragSourceListener;

    /**
     * Constructor for RepositoriesView.
     * @param partName
     */
    public RepositoriesView() {
        //   super(VIEW_ID);
    }

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

        final Shell shell = getShell();

        // Create actions

        // New Repository (popup)
        newAction = new Action(Policy.bind("RepositoriesView.new"), //$NON-NLS-1$
                SVNUIPlugin.getPlugin().getImageDescriptor(ISVNUIConstants.IMG_NEWLOCATION)) { //$NON-NLS-1$
            public void run() {
                if (!WorkspacePathValidator.validateWorkspacePath())
                    return;
                NewLocationWizard wizard = new NewLocationWizard();
                WizardDialog dialog = new ClosableWizardDialog(shell, wizard);
                dialog.open();
            }
        };
        PlatformUI.getWorkbench().getHelpSystem().setHelp(newAction,
                IHelpContextIds.NEW_REPOSITORY_LOCATION_ACTION);

        // Properties
        propertiesAction = new PropertyDialogAction(new SameShellProvider(shell), getViewer());
        getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), propertiesAction);
        IStructuredSelection selection = (IStructuredSelection) getViewer().getSelection();
        if (selection.size() == 1 && selection.getFirstElement() instanceof ISVNRepositoryLocation) {
            propertiesAction.setEnabled(true);
        } else {
            propertiesAction.setEnabled(false);
        }
        getViewer().addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection ss = (IStructuredSelection) event.getSelection();
                boolean enabled = ss.size() == 1 && ss.getFirstElement() instanceof ISVNRepositoryLocation;
                propertiesAction.setEnabled(enabled);
            }
        });

        // Remove Root
        removeRootAction = new RemoveRootAction(treeViewer.getControl().getShell());
        removeRootAction.selectionChanged((IStructuredSelection) null);
        PlatformUI.getWorkbench().getHelpSystem().setHelp(removeRootAction,
                IHelpContextIds.REMOVE_REPOSITORY_LOCATION_ACTION);

        IActionBars bars = getViewSite().getActionBars();
        bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), removeRootAction);

        // Refresh action (toolbar)
        SVNUIPlugin plugin = SVNUIPlugin.getPlugin();
        refreshAction = new Action(Policy.bind("RepositoriesView.refresh"), //$NON-NLS-1$
                SVNUIPlugin.getPlugin().getImageDescriptor(ISVNUIConstants.IMG_REFRESH_ENABLED)) {
            public void run() {
                refreshViewer(null, true);
            }
        };
        refreshAction.setToolTipText(Policy.bind("RepositoriesView.refreshTooltip")); //$NON-NLS-1$
        refreshAction.setDisabledImageDescriptor(plugin.getImageDescriptor(ISVNUIConstants.IMG_REFRESH_DISABLED));
        refreshAction.setHoverImageDescriptor(plugin.getImageDescriptor(ISVNUIConstants.IMG_REFRESH));
        getViewSite().getActionBars().setGlobalActionHandler(ActionFactory.REFRESH.getId(), refreshAction);

        refreshPopupAction = new Action(Policy.bind("RepositoriesView.refreshPopup"), //$NON-NLS-1$
                SVNUIPlugin.getPlugin().getImageDescriptor(ISVNUIConstants.IMG_REFRESH)) {
            public void run() {
                refreshViewerNode();
            }
        };

        // Collapse action
        collapseAllAction = new Action(Policy.bind("RepositoriesView.collapseAll"), //$NON-NLS-1$
                SVNUIPlugin.getPlugin().getImageDescriptor(ISVNUIConstants.IMG_COLLAPSE_ALL_ENABLED)) {
            public void run() {
                collapseAll();
            }
        };
        collapseAllAction.setToolTipText(Policy.bind("RepositoriesView.collapseAllTooltip")); //$NON-NLS-1$
        collapseAllAction.setHoverImageDescriptor(plugin.getImageDescriptor(ISVNUIConstants.IMG_COLLAPSE_ALL));

        // 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();
        drillPart.addNavigationActions(tbm);
        tbm.add(refreshAction);
        tbm.add(new Separator());
        tbm.add(collapseAllAction);
        tbm.update(false);

        // Create the open action for double clicks
        openAction = new OpenRemoteFileAction();
        bars.updateActionBars();

        IActionBars actionBars = getViewSite().getActionBars();
        IMenuManager actionBarsMenu = actionBars.getMenuManager();
        Action newRepositoryAction = new Action(Policy.bind("RepositoriesView.newRepository")) { //$NON-NLS-1$
            public void run() {
                SvnWizardNewRepositoryPage newRepositoryPage = new SvnWizardNewRepositoryPage();
                SvnWizard wizard = new SvnWizard(newRepositoryPage);
                SvnWizardDialog dialog = new SvnWizardDialog(getShell(), wizard);
                if (dialog.open() == SvnWizardDialog.OK)
                    refreshViewer(null, false);
            }
        };
        actionBarsMenu.add(newRepositoryAction);
    } // contributeActions

    /**
     * @see org.tigris.subversion.subclipse.ui.repo.RemoteViewPart#addWorkbenchActions(org.eclipse.jface.action.IMenuManager)
     */
    protected void addWorkbenchActions(IMenuManager manager) {
        // New actions go next

        MenuManager sub = new MenuManager(Policy.bind("RepositoriesView.newSubmenu"), //$NON-NLS-1$
                IWorkbenchActionConstants.GROUP_ADD);
        sub.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
        manager.add(sub);

        // 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$
        manager.add(new Separator("miscGroup")); //$NON-NLS-1$

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

        manager.add(refreshPopupAction);

        IStructuredSelection selection = (IStructuredSelection) getViewer().getSelection();
        removeRootAction.selectionChanged(selection);
        if (removeRootAction.isEnabled()) {
            manager.add(removeRootAction);
        }

        if (selection.size() == 1 && selection.getFirstElement() instanceof ISVNRepositoryLocation) {
            manager.add(new Separator());
            manager.add(propertiesAction);
        }
        sub.add(newAction);
    }

    /*
     * @see WorkbenchPart#createPartControl
     */
    public void createPartControl(Composite parent) {
        treeViewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
        contentProvider = new RemoteContentProvider();
        treeViewer.setContentProvider(contentProvider);
        final RepositoriesViewDecorator decorator = new RepositoriesViewDecorator();
        DecoratingLabelProvider labelProvider = new DecoratingLabelProvider(new WorkbenchLabelProvider(),
                new ILabelDecorator() {
                    public Image decorateImage(Image image, Object obj) {
                        if (obj instanceof RemoteFile) {
                            RemoteFile remoteFile = (RemoteFile) obj;
                            if (remoteFile.getLock() != null) {
                                return decorator.getImage(image);
                            }
                        }
                        return null;
                    }

                    public String decorateText(String text, Object obj) {
                        return null;
                    }

                    public void addListener(ILabelProviderListener listener) {
                    }

                    public void dispose() {
                    }

                    public boolean isLabelProperty(Object obj, String prop) {
                        return false;
                    }

                    public void removeListener(ILabelProviderListener listener) {
                    }
                });
        treeViewer.setLabelProvider(labelProvider);

        getSite().setSelectionProvider(treeViewer);
        root = new AllRootsElement();
        treeViewer.setInput(root);
        treeViewer.setSorter(new RepositorySorter());
        drillPart = new DrillDownAdapter(treeViewer);

        contributeActions();

        // F1 Help
        String helpID = getHelpContextId();
        if (helpID != null)
            PlatformUI.getWorkbench().getHelpSystem().setHelp(treeViewer.getControl(), helpID);
        initializeListeners();
        SVNUIPlugin.getPlugin().getRepositoryManager().addRepositoryListener(repositoryListener);
    }

    /**
     * initialize the listeners
     */
    protected void initializeListeners() {
        getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(this);
        treeViewer.addSelectionChangedListener(removeRootAction);

        // when F5 is pressed, refresh this view
        treeViewer.getControl().addKeyListener(new KeyAdapter() {
            public void keyPressed(KeyEvent event) {
                if (event.keyCode == SWT.F5) {
                    /*                    IStructuredSelection selection = (IStructuredSelection)getViewer().getSelection();
                                         if (selection.size() == 1)
                                         {
                     getViewer().refresh(selection.getFirstElement());     
                                         }      
                      */
                    refreshAction.run();
                }
            }
        });

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

        repositoryDragSourceListener = new RepositoryDragSourceListener();
        treeViewer.addDragSupport(DND.DROP_LINK | DND.DROP_DEFAULT,
                new Transfer[] { RemoteResourceTransfer.getInstance(), PluginTransfer.getInstance() },
                repositoryDragSourceListener);

        treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                repositoryDragSourceListener.updateSelection((IStructuredSelection) event.getSelection());
            }
        });
    }

    /**
     * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
     */
    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 String getStatusLineMessage(ISelection selection) {
        if (selection == null || selection.isEmpty())
            return ""; //$NON-NLS-1$
        if (!(selection instanceof IStructuredSelection))
            return ""; //$NON-NLS-1$
        IStructuredSelection s = (IStructuredSelection) selection;

        if (s.size() > 1)
            return Policy.bind("RepositoriesView.NItemsSelected", String.valueOf(s.size())); //$NON-NLS-1$
        Object element = SVNAction.getAdapter(s.getFirstElement(), ISVNResource.class);
        if (element instanceof ISVNRemoteResource) {
            ISVNRemoteResource res = (ISVNRemoteResource) element;
            String name;
            if (res.isContainer()) {
                name = res.getRepositoryRelativePath();
            } else {
                name = res.getRepositoryRelativePath() + " " + ((ISVNRemoteFile) res).getLastChangedRevision(); //$NON-NLS-1$
            }
            return Policy.bind("RepositoriesView.ResourceInRepository", name, res.getRepository().getLocation()); //$NON-NLS-1$

        }
        return Policy.bind("RepositoriesView.OneItemSelected"); //$NON-NLS-1$
    }

    /**
     * @see org.tigris.subversion.subclipse.ui.repo.RemoteViewPart#getHelpContextId()
     */
    protected String getHelpContextId() {
        return IHelpContextIds.REPOSITORIES_VIEW;
    }

    /**
     * @see WorkbenchPart#setFocus
     */
    public void setFocus() {
        treeViewer.getControl().setFocus();
    }

    /**
     * Method getShell.
     * @return Shell
     */
    protected Shell getShell() {
        return treeViewer.getTree().getShell();
    }

    /**
     * Returns the viewer.
     * @return TreeViewer
     */
    protected TreeViewer getViewer() {
        return treeViewer;
    }

    /**
     * this is called whenever a new repository location is added for example
     * or when user wants to refresh
     */
    protected void refreshViewer(Object object, boolean refreshRepositoriesFolders) {
        if (treeViewer == null)
            return;
        if (refreshRepositoriesFolders) {
            IRunnableWithProgress runnable = new IRunnableWithProgress() {
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    SVNProviderPlugin.getPlugin().getRepositories().refreshRepositoriesFolders(monitor);
                }
            };
            try {
                new ProgressMonitorDialog(getShell()).run(true, false, runnable);
            } catch (Exception e) {
                SVNUIPlugin.openError(getShell(), null, null, e, SVNUIPlugin.LOG_TEAM_EXCEPTIONS);
            }
        }
        if (object == null)
            treeViewer.refresh();
        else {
            if (object instanceof ISVNRemoteFolder) {
                ISVNRemoteFolder parent = ((ISVNRemoteFolder) object).getParent();
                if (parent == null) {
                    treeViewer.refresh();
                    return;
                }
            }
            treeViewer.refresh(object);
        }
    }

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

    public void collapseAll() {
        if (treeViewer == null)
            return;
        treeViewer.getControl().setRedraw(false);
        treeViewer.collapseToLevel(treeViewer.getInput(), TreeViewer.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) {
            IStructuredSelection structured = (IStructuredSelection) selection;
            if (structured.size() == 1) {
                Object first = structured.getFirstElement();
                if (first instanceof ISVNRemoteFile) {
                    // It's a file, open it.
                    openAction.selectionChanged(null, selection);
                    openAction.run(null);
                } else {
                    // Try to expand/contract
                    treeViewer.setExpandedState(first, !treeViewer.getExpandedState(first));
                }
            }
        }
    }

    /**
     * @see org.eclipse.ui.IWorkbenchPart#dispose()
     */
    public void dispose() {
        SVNUIPlugin.getPlugin().getRepositoryManager().removeRepositoryListener(repositoryListener);
        super.dispose();
        treeViewer = null;
    }

}