Java tutorial
/***************************************************************************** * 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); } }); } }