eu.geclipse.ui.views.GridModelViewPart.java Source code

Java tutorial

Introduction

Here is the source code for eu.geclipse.ui.views.GridModelViewPart.java

Source

/*****************************************************************************
 * Copyright (c) 2006-2008 g-Eclipse Consortium 
 * 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
 *
 * Initial development of the original code was made for the
 * g-Eclipse project founded by European Union
 * project number: FP6-IST-034327  http://www.geclipse.eu/
 *
 * Contributors:
 *    Mathias Stuempert - initial API and implementation
 *****************************************************************************/

package eu.geclipse.ui.views;

import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.util.DelegatingDragAdapter;
import org.eclipse.jface.util.DelegatingDropAdapter;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.actions.ActionGroup;
import org.eclipse.ui.navigator.ICommonMenuConstants;
import org.eclipse.ui.part.ViewPart;

import eu.geclipse.core.model.GridModel;
import eu.geclipse.core.model.IGridElement;
import eu.geclipse.core.model.IGridModelEvent;
import eu.geclipse.core.model.IGridModelListener;
import eu.geclipse.ui.decorators.GridProjectFolderDecorator;
import eu.geclipse.ui.internal.actions.AccessControlActions;
import eu.geclipse.ui.internal.actions.ActionGroupManager;
import eu.geclipse.ui.internal.actions.CommonActions;
import eu.geclipse.ui.internal.actions.FileActions;
import eu.geclipse.ui.internal.actions.MountActions;
import eu.geclipse.ui.internal.actions.OpenActions;
import eu.geclipse.ui.internal.actions.TreeViewerActions;
import eu.geclipse.ui.internal.transfer.SelectionTransferDragAdapter;
import eu.geclipse.ui.internal.transfer.SelectionTransferDropAdapter;

/**
 * Abstract superclass of all views that show
 * {@link eu.geclipse.core.model.GridModel} related data. Views that
 * extend this class mainly consist of a {@link StructuredViewer} and
 * may contribute actions to context menus for instance. The root
 * element of the viewer has to be an {@link IGridElement} that is returned
 * by the {@link #getRootElement()} method. Subclasses also have to
 * specified the content and label providers that are used to render
 * the data. These providers are specified by the
 * {@link #createContentProvider()} and {@link #createLabelProvider()}
 * methods.
 */
public abstract class GridModelViewPart extends ViewPart implements IGridModelListener {

    /**
     * The viewer that is used to render the data.
     */
    StructuredViewer viewer;

    private ActionGroup actions;

    private OpenActions openActions;

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    public void createPartControl(final Composite parent) {

        // Initialize the viewer
        this.viewer = createViewer(parent);
        initViewer(this.viewer);

        this.getSite().setSelectionProvider(this.viewer);

        this.actions = createActions();
        fillActionBars(this.actions);
        createContextMenu(this.viewer);

        GridModel.getRoot().addGridModelListener(this);

        updateActionBars();
    }

    private void updateActionBars() {
        if (this.actions != null) {
            ISelection selection = this.viewer.getSelection();
            this.actions.setContext(new ActionContext(selection));
            this.actions.updateActionBars();
        }
    }

    @Override
    public void dispose() {

        if (this.actions != null) {
            this.actions.dispose();
        }

        GridModel.getRoot().removeGridModelListener(this);

        super.dispose();

    }

    /**
     * Get the {@link StructuredViewer} that is associated with this
     * view.
     * 
     * @return The viewer that is responsible to show the content of this
     * view.
     */
    public StructuredViewer getViewer() {
        return this.viewer;
    }

    /* (non-Javadoc)
     * @see eu.geclipse.core.model.IGridModelListener#gridModelChanged(eu.geclipse.core.model.IGridModelEvent)
     */
    public void gridModelChanged(final IGridModelEvent event) {
        if ((event.getType() == IGridModelEvent.ELEMENTS_ADDED)
                || (event.getType() == IGridModelEvent.ELEMENTS_REMOVED)) {
            refreshViewer(event.getSource());
        } else if (event.getType() == IGridModelEvent.PROJECT_FOLDER_CHANGED) {
            GridProjectFolderDecorator decorator = GridProjectFolderDecorator.getDecorator();
            if (decorator != null) {
                decorator.refresh(event.getElements());
            }
        }
    }

    /**
     * Determines if drag'n'drop should be made available for the specified
     * element.
     * 
     * @param element The element for which drag'n'drop operations should
     * be either allowed or forbidden.
     * @return True if drag'n'drop should be enabled for the specified
     * element, false otherwise.
     */
    public boolean isDragSource(final IGridElement element) {
        return !element.isVirtual();
    }

    /**
     * Refresh the associated {@link StructuredViewer}. Calls the
     * {@link StructuredViewer#refresh()} method and ensures that
     * this method is called in an UI thread.
     * 
     * @see StructuredViewer#refresh()
     */
    public void refreshViewer() {
        refreshViewer(null);
    }

    /**
     * Refresh the associated {@link StructuredViewer}. Calls the
     * {@link StructuredViewer#refresh(Object)} method and ensures that
     * this method is called in an UI thread.
     * 
     * @param element The element that should be refreshed recursively.
     * @see StructuredViewer#refresh(Object)
     */
    public void refreshViewer(final IGridElement element) {
        if (this.viewer != null) {
            Control control = this.viewer.getControl();
            if (!control.isDisposed()) {
                Display display = control.getDisplay();
                display.asyncExec(new Runnable() {
                    public void run() {
                        if (!GridModelViewPart.this.viewer.getControl().isDisposed()) {
                            if (element == null) {
                                GridModelViewPart.this.viewer.refresh(false);
                            } else {
                                GridModelViewPart.this.viewer.refresh(element, false);
                            }
                        }
                    }
                });
            }
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
     */
    @Override
    public void setFocus() {
        this.viewer.getControl().setFocus();
    }

    protected void addDragSourceListeners(final DelegatingDragAdapter adapter) {
        adapter.addDragSourceListener(new SelectionTransferDragAdapter(this));
    }

    protected void addDropTargetListeners(final DelegatingDropAdapter adapter) {
        adapter.addDropTargetListener(new SelectionTransferDropAdapter());
    }

    protected ActionGroup createActions() {
        ActionGroupManager manager = new ActionGroupManager();
        contributeAdditionalActions(manager);
        contributeStandardActions(manager);
        return manager;
    }

    protected void contributeStandardActions(final ActionGroupManager groups) {

        this.openActions = new OpenActions(this);
        groups.addGroup(this.openActions);

        FileActions fileActions = new FileActions(this);
        groups.addGroup(fileActions);

        MountActions mountActions = new MountActions(getSite());
        groups.addGroup(mountActions);

        AccessControlActions aclActions = new AccessControlActions(getSite());
        groups.addGroup(aclActions);

        CommonActions commonActions = new CommonActions(this);
        groups.addGroup(commonActions);

        StructuredViewer sViewer = getViewer();
        if (sViewer instanceof TreeViewer) {
            TreeViewer tViewer = (TreeViewer) sViewer;
            TreeViewerActions treeViewerActions = new TreeViewerActions(tViewer);
            groups.addGroup(treeViewerActions);
        }
    }

    protected void contributeAdditionalActions(@SuppressWarnings("unused") final ActionGroupManager groups) {
        // empty implementation
    }

    /**
     * Create and return an instance of an {@link IContentProvider} that is
     * used to provide the content to be rendered in the viewer. This method
     * is called once on initialization and may not be called subsequently.
     * 
     * @return The newly created {@link IContentProvider} that is responsible
     * for providing the data rendered in the associated {@link StructuredViewer}.
     * @see #createViewer(Composite)
     * @see #createLabelProvider()
     */
    protected abstract IContentProvider createContentProvider();

    /**
     * Create the context menu for the specified viewer. This is the viewer obtained
     * by {@link #createContentProvider()}. This method is called
     * automatically by {@link #createPartControl(Composite)}.
     * @param sViewer The {@link StructuredViewer} to be initialised.
     * @see #createViewer(Composite)
     * @see #createPartControl(Composite)
     */
    protected void createContextMenu(final StructuredViewer sViewer) {
        MenuManager manager = new MenuManager();
        manager.setRemoveAllWhenShown(true);
        manager.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(final IMenuManager mgr) {
                fillContextMenu(mgr);
            }
        });
        Menu menu = manager.createContextMenu(sViewer.getControl());
        sViewer.getControl().setMenu(menu);
        getSite().registerContextMenu(manager, sViewer);
    }

    /**
     * Create the standard menu groups in the specified context
     * menu. Subclasses may overwrite this method in order to add
     * new groups or to completely change the groups.
     *  
     * @param menu The menu manager in which to create the groups.
     */
    protected void createContextMenuGroups(final IMenuManager menu) {
        menu.add(new Separator(ICommonMenuConstants.GROUP_NEW));
        menu.add(new GroupMarker(ICommonMenuConstants.GROUP_GOTO));
        menu.add(new GroupMarker(ICommonMenuConstants.GROUP_OPEN));
        menu.add(new GroupMarker(ICommonMenuConstants.GROUP_OPEN_WITH));
        menu.add(new Separator(ICommonMenuConstants.GROUP_EDIT));
        menu.add(new GroupMarker(ICommonMenuConstants.GROUP_SHOW));
        menu.add(new GroupMarker(ICommonMenuConstants.GROUP_REORGANIZE));
        menu.add(new GroupMarker(ICommonMenuConstants.GROUP_PORT));
        menu.add(new Separator(ICommonMenuConstants.GROUP_GENERATE));
        menu.add(new Separator(ICommonMenuConstants.GROUP_SEARCH));
        menu.add(new Separator(ICommonMenuConstants.GROUP_BUILD));
        menu.add(new Separator(ICommonMenuConstants.GROUP_ADDITIONS));
        menu.add(new Separator(ICommonMenuConstants.GROUP_PROPERTIES));
    }

    /**
     * Create and return an instance of an {@link IBaseLabelProvider} that is
     * used to render the content in the viewer. This method
     * is called once on initialization and may not be called subsequently.
     * 
     * @return The newly created {@link IBaseLabelProvider} that is responsible
     * for rendering the data in the associated {@link StructuredViewer}.
     * @see #createViewer(Composite)
     * @see #createContentProvider()
     */
    protected abstract IBaseLabelProvider createLabelProvider();

    /**
     * Create and return an instance of a {@link StructuredViewer} that is
     * used to render the data. This method
     * is called once on initialization and may not be called subsequently.
     * 
     * @param parent The parent composite.
     * @return The newly created {@link StructuredViewer}.
     * @see #createContentProvider()
     * @see #createLabelProvider()
     */
    protected abstract StructuredViewer createViewer(final Composite parent);

    /**
     * Fill the action bars of this view with the specified action group.
     * The group itself holds the functionality to fill the actions bars.
     * 
     * @param group The {@link ActionGroup} that is used to fill the
     * action bars.
     */
    protected void fillActionBars(final ActionGroup group) {
        IActionBars actionBars = getViewSite().getActionBars();
        group.fillActionBars(actionBars);
    }

    /**
     * Fill the context menu from the actions of this view. This is
     * called interactively when the menu is about to be shown.
     * 
     * @param menu The menu to be filled.
     */
    protected void fillContextMenu(final IMenuManager menu) {
        ISelection selection = this.viewer.getSelection();
        ActionContext context = new ActionContext(selection);
        createContextMenuGroups(menu);
        this.actions.setContext(context);
        this.actions.fillContextMenu(menu);
        this.actions.setContext(null);
    }

    /**
     * Get the root element that is used as the data for the structured
     * viewer.
     * 
     * @return The root data for the {@link StructuredViewer} of this
     * view.
     */
    protected abstract IGridElement getRootElement();

    /**
     * Handle a double click event that occurred in the viewer of this
     * view.
     * 
     * @param event The associated {@link DoubleClickEvent}.
     */
    protected void handleDoubleClick(final DoubleClickEvent event) {
        if (this.viewer instanceof TreeViewer) {
            TreeViewer treeViewer = (TreeViewer) this.viewer;
            ISelection selection = event.getSelection();
            if (selection instanceof IStructuredSelection) {
                Object element = ((IStructuredSelection) selection).getFirstElement();
                if (treeViewer.isExpandable(element)) {
                    boolean state = treeViewer.getExpandedState(element);
                    treeViewer.setExpandedState(element, !state);
                }
            }
        }
    }

    /**
     * Handle an open event that occurred in the associated viewer.
     * 
     * @param event The associated {@link OpenEvent}.
     */
    protected void handleOpen(final OpenEvent event) {
        this.openActions.delegateOpenEvent(event);
    }

    protected void initDragAndDrop(final StructuredViewer sViewer) {
        initDrag(sViewer);
        initDrop(sViewer);
    }

    protected void initDrag(final StructuredViewer sViewer) {
        int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
        DelegatingDragAdapter adapter = new DelegatingDragAdapter();
        addDragSourceListeners(adapter);
        sViewer.addDragSupport(operations, adapter.getTransfers(), adapter);
    }

    protected void initDrop(final StructuredViewer sViewer) {
        int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
        DelegatingDropAdapter adapter = new DelegatingDropAdapter();
        addDropTargetListeners(adapter);
        sViewer.addDropSupport(operations, adapter.getTransfers(), adapter);
    }

    /**
     * Initialize the specified viewer. This is the viewer obtained
     * by {@link #createContentProvider()}. This method is called
     * automatically by {@link #createPartControl(Composite)}.
     * 
     * @param sViewer The {@link StructuredViewer} to be initialised.
     * @see #createViewer(Composite)
     * @see #createPartControl(Composite)
     */
    protected void initViewer(final StructuredViewer sViewer) {
        sViewer.setLabelProvider(createLabelProvider());
        sViewer.setContentProvider(createContentProvider());
        sViewer.setInput(getRootElement());
        registerViewerListeners(sViewer);
        initDragAndDrop(sViewer);
    }

    /**
     * Register the listeners for the specified viewer. This is the viewer obtained
     * by {@link #createContentProvider()}. This method is called
     * automatically by {@link #createPartControl(Composite)}.
     * 
     * @param sViewer The {@link StructuredViewer} to be initialised.
     * @see #createViewer(Composite)
     * @see #createPartControl(Composite)
     */
    protected void registerViewerListeners(final StructuredViewer sViewer) {
        sViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(final DoubleClickEvent event) {
                handleDoubleClick(event);
            }
        });
        sViewer.addOpenListener(new IOpenListener() {
            public void open(final OpenEvent event) {
                handleOpen(event);
            }
        });
    }

}