/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.ui.outline; import java.util.EventObject; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.provider.INotifyChangedListener; import org.eclipse.emf.edit.ui.dnd.LocalTransfer; import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IStatusLineManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.Transfer; 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.IEditorInput; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.part.IPageSite; import org.eclipse.ui.views.contentoutline.ContentOutline; import org.eclipse.ui.views.contentoutline.ContentOutlinePage; import org.teiid.core.designer.event.EventObjectListener; import org.teiid.core.designer.event.EventSourceException; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.container.ContainerImpl; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.ui.PluginConstants; import org.teiid.designer.ui.UiConstants; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.actions.IModelerActionConstants; import org.teiid.designer.ui.actions.ModelerActionService; import org.teiid.designer.ui.actions.ModelerGlobalActionsMap; import org.teiid.designer.ui.actions.TreeViewerRenameAction; import org.teiid.designer.ui.common.actions.ExtendedMenuManager; import org.teiid.designer.ui.common.util.UiUtil; import org.teiid.designer.ui.editors.ModelEditor; import org.teiid.designer.ui.editors.ModelEditorPageOutline; import org.teiid.designer.ui.event.ModelResourceEvent; import org.teiid.designer.ui.explorer.ModelExplorerLabelProvider; import org.teiid.designer.ui.views.ModelViewer; import org.teiid.designer.ui.viewsupport.ModelUtilities; import org.teiid.designer.ui.viewsupport.StatusBarUpdater; /** * ModelOutlineTreeViewer * * @since 8.0 */ public class ModelOutlineTreeViewer extends ContentOutlinePage implements ModelEditorPageOutline, IMenuListener, IModelerActionConstants, ModelViewer { ModelEditor modelEditor; private ISelectionListener selectionListener; private ModelerGlobalActionsMap actionsMap; private INotifyChangedListener notificationHandler; private ImageDescriptor icon = UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.OUTLINE_ICON); private String toolTipText = "ModelOutlineTreeViewer.tooltip"; //$NON-NLS-1$ private IWorkbenchPart workbenchPart; private ILabelProvider labelProvider; private TreeViewerRenameAction renameAction; private EventObjectListener modelResourceListener; public ModelOutlineTreeViewer( ModelEditor editor ) { this.modelEditor = editor; } @Override public void init( IPageSite thePageSite ) { super.init(thePageSite); } /* Overridden based on JavaDoc comments in the superclass. * @see org.eclipse.ui.views.contentoutline.ContentOutlinePage#createControl(org.eclipse.swt.widgets.Composite) */ @Override public void createControl( Composite parent ) { super.createControl(parent); IEditorInput input = modelEditor.getEditorInput(); ITreeContentProvider contentProvider = new ModelOutlineContentProvider(input); getTreeViewer().setContentProvider(contentProvider); ILabelDecorator decorator = UiUtil.getWorkbench().getDecoratorManager().getLabelDecorator(); labelProvider = new DecoratingLabelProvider(new ModelExplorerLabelProvider(), decorator); getTreeViewer().setLabelProvider(labelProvider); getTreeViewer().setInput(input); getTreeViewer().expandToLevel(2); getTreeViewer().reveal(contentProvider.getElements(input)[0]); // hook up our status bar manager for EObjects IStatusLineManager slManager = getSite().getActionBars().getStatusLineManager(); addSelectionChangedListener(new StatusBarUpdater(slManager)); // hook up a selection listener to the seleciton service getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(getModelObjectSelectionListener()); // hook up this view's selection provider to this site getSite().setSelectionProvider(getModelObjectSelectionProvider()); // Register to listen for Change Notifications notificationHandler = new ModelOutlineNotificationHandler(this); ModelUtilities.addNotifyChangedListener(notificationHandler); // create up the inline tree rename action renameAction = new TreeViewerRenameAction(); renameAction.setTreeViewer(getTreeViewer(), labelProvider); final ModelerActionService svc = (ModelerActionService)UiPlugin.getDefault().getActionService(getSite().getPage()); svc.addWorkbenchSelectionListener(renameAction); // add the rename action to the Global Action Map actionsMap = new ModelerGlobalActionsMap(); actionsMap.put(EclipseGlobalActions.RENAME, this.renameAction); // register rename with global actions final IActionBars bars = getSite().getActionBars(); svc.registerDefaultGlobalActions(bars); bars.setGlobalActionHandler(EclipseGlobalActions.RENAME, renameAction); bars.updateActionBars(); // construct context menu - this is populated in the menuAboutToShow(IMenuManager) method String contextMenuId = ModelOutlinePage.class.getName() + ContextMenu.MENU_ID_SUFFIX; MenuManager mgr = new ExtendedMenuManager(null, contextMenuId); mgr.setRemoveAllWhenShown(true); mgr.addMenuListener(this); Control control = getControl(); Menu contextMenu = mgr.createContextMenu(control); control.setMenu(contextMenu); getSite().registerContextMenu(contextMenuId, mgr, getModelObjectSelectionProvider()); initDragAndDrop(); modelResourceListener = new EventObjectListener() { @Override public void processEvent( EventObject obj ) { ModelResource modelResource = ((ModelResourceEvent)obj).getModelResource(); if (modelEditor.getModelResource().equals(modelResource)) { refresh(); } } }; try { UiPlugin.getDefault().getEventBroker().addListener(ModelResourceEvent.class, modelResourceListener); } catch (EventSourceException e) { UiConstants.Util.log(IStatus.ERROR, e, e.getMessage()); } } void refresh() { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { handleRefresh(); } }); } void handleRefresh() { if (getTreeViewer() != null && !getTreeViewer().getTree().isDisposed()) { getTreeViewer().refresh(); } } /** * @see org.eclipse.ui.views.navigator.ResourceNavigator#initDragAndDrop() */ protected void initDragAndDrop() { try { EditingDomain domain = ((ContainerImpl)ModelerCore.getModelContainer()).getEditingDomain(); int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; Transfer[] transfers = new Transfer[] {LocalTransfer.getInstance()}; getTreeViewer().addDragSupport(dndOperations, transfers, new OutlineDragAdapter(getTreeViewer())); getTreeViewer().addDropSupport(dndOperations, transfers, new ModelOutlineTreeViewerDropAdapter(domain, getTreeViewer())); } catch (Exception e) { e.printStackTrace(); } } /** * Accessor for the ModelOutlineNotificationHandler to operate on the TreeViewer. * * @return */ TreeViewer getTree() { return getTreeViewer(); } /** * Accessor for the ModelOutlineNotificationHandler to run the TreeViewerRenameAction when a new object is created in this * viewer. * * @return */ IWorkbenchPart getWorkbenchPart() { return workbenchPart; } /** * @See org.teiid.designer.ui.views.ModelViewer#addModelObjectDoubleClickListener(org.eclipse.jface.viewers.IDoubleClickListener) */ @Override public void addModelObjectDoubleClickListener( IDoubleClickListener listener ) { getTreeViewer().addDoubleClickListener(listener); } /** * Obtain the selection listener that will be used to synchronize this model object viewer * * @return */ public ISelectionListener getModelObjectSelectionListener() { if (selectionListener == null) { selectionListener = new ISelectionListener() { @Override public void selectionChanged( IWorkbenchPart part, ISelection selection ) { if (!(part instanceof ContentOutline) && isSynchronized()) { if ((selection instanceof IStructuredSelection) && !selection.isEmpty() && !ModelOutlineTreeViewer.this.getSelection().equals(selection)) { ModelOutlineTreeViewer.this.setSelection(selection); } } } }; } return selectionListener; } /** * Gets the <code>ModelResource</code> for the editor whose being shown in this outline. * * @return the model resource */ ModelResource getModelResource() { return this.modelEditor.getModelResource(); } /** * @See org.teiid.designer.ui.views.ModelViewer#getModelObjectSelectionProvider() */ public ISelectionProvider getModelObjectSelectionProvider() { return getTreeViewer(); } /** * @See org.teiid.designer.ui.views.ModelViewer#isSynchronized() */ public boolean isSynchronized() { // the outline view is always synchronized return true; } /** * @see org.eclipse.jface.action.IMenuListener#init(org.eclipse.jface.action..IMenuManager) */ @Override public void menuAboutToShow( IMenuManager theMenuMgr ) { IWorkbenchWindow window = modelEditor.getSite().getWorkbenchWindow(); ModelerActionService actionService = (ModelerActionService)UiPlugin.getDefault().getActionService(getSite().getPage()); ISelection selection = getTreeViewer().getSelection(); actionService.contributeToContextMenu(theMenuMgr, actionsMap, selection); if (workbenchPart == null) { workbenchPart = window.getActivePage().getActivePart(); } } @Override public void removeModelObjectDoubleClickListener( IDoubleClickListener listener ) { getTreeViewer().removeDoubleClickListener(listener); } /** * @see org.eclipse.ui.part.IPage#dispose() */ @Override public void dispose() { // unhook the selection listener from the seleciton service getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(getModelObjectSelectionListener()); // unhook the notification handler ModelUtilities.removeNotifyChangedListener(notificationHandler); // unregister from the plugin's EventBroker if (this.modelResourceListener != null) { try { UiPlugin.getDefault().getEventBroker().removeListener(this.modelResourceListener); } catch (EventSourceException e) { // no need to do anything } } super.dispose(); } /** * @see org.teiid.designer.ui.editors.ModelEditorPageOutline#getIcon() */ @Override public ImageDescriptor getIcon() { return icon; } /** * @see org.teiid.designer.ui.editors.ModelEditorPageOutline#getToolTipText() */ @Override public String getToolTipText() { return UiPlugin.getDefault().getPluginUtil().getString(toolTipText); } /** * @see org.teiid.designer.ui.editors.ModelEditorPageOutline#isEnabled() */ @Override public boolean isEnabled() { return true; } /** * @see org.teiid.designer.ui.editors.ModelEditorPageOutline#setVisible(boolean) */ @Override public void setVisible( boolean isVisible ) { } private class OutlineDragAdapter extends ViewerDragAdapter { public OutlineDragAdapter( Viewer theViewer ) { super(theViewer); } /** * @see org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter#dragStart(org.eclipse.swt.dnd.DragSourceEvent) */ @Override public void dragStart( DragSourceEvent theEvent ) { // if model is read-only stop the drag if (ModelUtilities.isReadOnly(getModelResource())) { theEvent.doit = false; } super.dragStart(theEvent); } } }