/*
* 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.navigator.model;
import static org.teiid.designer.ui.PluginConstants.Prefs.General.SHOW_IMPORTS_IN_MODEL_EXPLORER;
import static org.teiid.designer.ui.PluginConstants.Prefs.General.SHOW_NON_MODELS_IN_MODEL_EXPLORER;
import static org.teiid.designer.ui.PluginConstants.Prefs.General.SORT_MODEL_CONTENTS;
import static org.teiid.designer.ui.UiConstants.Util;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.createRenameActionErrorMessage;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.defaultCopyActionNotFoundMessage;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.refreshActionText;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.refreshActionToolTip;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.showImportsActionText;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.showNonModelsActionText;
import static org.teiid.designer.ui.navigator.model.ModelNavigatorMessages.sortModelContentsActionText;
import java.util.EventObject;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.edit.provider.INotifyChangedListener;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
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.preference.IPreferenceStore;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IActionDelegate;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.actions.OpenFileAction;
import org.eclipse.ui.actions.RefreshAction;
import org.eclipse.ui.navigator.CommonActionProvider;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.ICommonActionExtensionSite;
import org.eclipse.ui.navigator.ICommonViewerSite;
import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite;
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.workspace.DotProjectUtils;
import org.teiid.designer.ui.PluginConstants;
import org.teiid.designer.ui.UiConstants.Extensions;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.actions.CloneProjectAction2;
import org.teiid.designer.ui.actions.DelegatableAction;
import org.teiid.designer.ui.actions.DeleteResourceAction;
import org.teiid.designer.ui.actions.IModelerActionConstants;
import org.teiid.designer.ui.actions.IModelerActionConstants.ContextMenu;
import org.teiid.designer.ui.actions.ModelResourceActionManager;
import org.teiid.designer.ui.actions.ModelerActionBarIdManager;
import org.teiid.designer.ui.actions.ModelerActionService;
import org.teiid.designer.ui.actions.ModelerGlobalActionsMap;
import org.teiid.designer.ui.actions.ModelerSpecialActionManager;
import org.teiid.designer.ui.actions.PasteInResourceAction;
import org.teiid.designer.ui.actions.PasteSpecialAction;
import org.teiid.designer.ui.actions.PropertyDialogAction;
import org.teiid.designer.ui.actions.RemoveProjectAction;
import org.teiid.designer.ui.common.actions.ActionService;
import org.teiid.designer.ui.common.actions.GlobalActionsMap;
import org.teiid.designer.ui.common.actions.IActionConstants.EclipseGlobalActions;
import org.teiid.designer.ui.common.eventsupport.SelectionUtilities;
import org.teiid.designer.ui.common.util.WidgetUtil;
import org.teiid.designer.ui.editors.ModelEditor;
import org.teiid.designer.ui.event.ModelResourceEvent;
import org.teiid.designer.ui.refactor.actions.RenameRefactorAction;
import org.teiid.designer.ui.viewsupport.IExtendedModelObject;
import org.teiid.designer.ui.viewsupport.ModelUtilities;
import org.teiid.designer.ui.viewsupport.NonModelViewerFilter;
/**
*
*/
public class ModelActionProvider extends CommonActionProvider {
private static final String ECLIPSE_DELETE_ID = "org.eclipse.ui.DeleteResourceAction"; //$NON-NLS-1$
private static final String ECLIPSE_MOVE_ID = "org.eclipse.ui.MoveResourceAction"; //$NON-NLS-1$
private static final String ECLIPSE_PASTE_ID = "org.eclipse.ui.PasteAction"; //$NON-NLS-1$
private static final String ECLIPSE_RENAME_ID = "org.eclipse.ui.RenameResourceAction"; //$NON-NLS-1$
private static final String MENU_GROUP = "modelExplorerMenuGroup"; //$NON-NLS-1$
private static final String MODELING_LABEL = Util.getString("ModelerSpecialActionManager.specialLabel"); //$NON-NLS-1$
private static final String TOOLBAR_GROUP = "modelExplorerToolBarGroup"; //$NON-NLS-1$
private ModelerGlobalActionsMap actionsMap;
private CloneProjectAction2 cloneProjectAction;
private ModelExplorerCopyAction copyAction;
private IResourceChangeListener markerListener;
private EventObjectListener modelResourceListener;
private ModelNavigatorMoveAction moveAction;
private INotifyChangedListener notificationHandler;
private IPartListener partListener;
private PropertyDialogAction propertyAction;
private RemoveProjectAction removeProjectAction;
private ModelNavigatorRenameAction renameAction;
private ISelectionListener selectionListener;
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.actions.ActionGroup#dispose()
*/
@Override
public void dispose() {
if (this.selectionListener != null) {
getWorkbenchSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this.selectionListener);
}
if (this.copyAction != null) {
getWorkbenchSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this.copyAction);
}
if (this.notificationHandler != null) {
ModelUtilities.removeNotifyChangedListener(this.notificationHandler);
}
if (this.markerListener != null) {
ModelerCore.getWorkspace().removeResourceChangeListener(this.markerListener);
}
if (this.modelResourceListener != null) {
try {
UiPlugin.getDefault().getEventBroker().removeListener(this.modelResourceListener);
} catch (EventSourceException e) {
Util.log(IStatus.ERROR, e, e.getMessage());
}
}
if (this.partListener != null) {
getWorkbenchSite().getPage().removePartListener(this.partListener);
}
if (getViewer().getContentProvider() != null) {
getViewer().getContentProvider().dispose();
}
if (getViewer().getLabelProvider() != null) {
getViewer().getLabelProvider().dispose();
}
super.dispose();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.actions.ActionGroup#fillActionBars(org.eclipse.ui.IActionBars)
*/
@Override
public void fillActionBars( IActionBars actionBars ) {
super.fillActionBars(actionBars);
// Note: this method gets call when view is constructed and each time selection changes
//
// customize view menu (add show imports action)
//
IMenuManager menuMgr = actionBars.getMenuManager();
if (menuMgr.find(MENU_GROUP) == null) {
menuMgr.add(new GroupMarker(MENU_GROUP));
menuMgr.add(new ShowImportsAction());
menuMgr.add(new ShowNonModelsAction());
}
//
// customize view toolbar (add preview data, sort model contents, and refresh actions)
//
IToolBarManager toolBarMgr = actionBars.getToolBarManager();
if (toolBarMgr.find(TOOLBAR_GROUP) == null) {
toolBarMgr.add(new Separator(TOOLBAR_GROUP));
// preview data action
IAction previewAction = ModelerSpecialActionManager.getAction(Extensions.PREVIEW_DATA_ACTION_ID);
if (previewAction != null) {
toolBarMgr.add(previewAction);
toolBarMgr.add(new Separator());
}
// selection of the sort button sets the preference, which will trigger a refresh
toolBarMgr.add(new SortModelContentsAction());
// add refresh tree action
IAction refreshAction = new RefreshAction(getWorkbenchSite().getSite());
refreshAction.setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.REFRESH_ICON));
refreshAction.setToolTipText(refreshActionToolTip);
refreshAction.setText(refreshActionText);
refreshAction.setId("modelExplorerResourceNavigator.refreshAction"); //$NON-NLS-1$
toolBarMgr.add(refreshAction);
}
if (this.renameAction != null) {
this.renameAction.selectionChanged(getSelection());
}
if (this.moveAction != null) {
this.moveAction.selectionChanged(getSelection());
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.actions.ActionGroup#fillContextMenu(org.eclipse.jface.action.IMenuManager)
*/
@Override
public void fillContextMenu( IMenuManager menu ) {
super.fillContextMenu(menu);
IStructuredSelection selection = getSelection();
if (isAllExtendedModelObjects(selection)) {
// Get the context menu from the extended model Objects
boolean didOverride = false;
for (Object obj : SelectionUtilities.getSelectedObjects(selection)) {
IExtendedModelObject extendedModelObject = (IExtendedModelObject)obj;
if (extendedModelObject.overrideContextMenu()) {
didOverride = true;
extendedModelObject.fillContextMenu(menu);
}
}
if (didOverride) {
if (menu.find(IModelerActionConstants.ContextMenu.ADDITIONS) == null) {
menu.add(new Separator(IModelerActionConstants.ContextMenu.ADDITIONS));
}
return;
}
}
// if single or multi selection has only EObjects show our action service context menu
// else show the ResourceNavigators
if (SelectionUtilities.isAllEObjects(selection)) {
getActionService().contributeToContextMenu(menu, actionsMap, selection);
} else {
super.fillContextMenu(menu);
try {
// need to override the delete in the context menu. the only way i could figure out was by
// removing and adding. our action makes sure to close the model and close it's editor
// (if necessary) prior to deleting.
if (menu.find(ECLIPSE_DELETE_ID) != null) {
IAction deleteAction = getActionService().getAction(DeleteResourceAction.class);
menu.insertAfter(ECLIPSE_DELETE_ID, deleteAction);
menu.remove(ECLIPSE_DELETE_ID);
}
// Add PasteSpecialAction after PasteAction
// (if single selection and model resource)
if (SelectionUtilities.isSingleSelection(selection)) {
Object obj = SelectionUtilities.getSelectedObject(selection);
if ((obj instanceof IResource) && ModelUtilities.isModelFile((IResource)obj)) {
// Add PasteSpecial Action after Paste
if (menu.find(ECLIPSE_PASTE_ID) != null) {
IAction pasteSpecialAction = getActionService().getAction(PasteSpecialAction.class);
menu.insertAfter(ECLIPSE_PASTE_ID, pasteSpecialAction);
}
}
}
// need to override the paste in the context menu. the only way i could figure out was by
// removing and adding. our action makes sure to close the model and close it's editor
// (if necessary) prior to pasting.
if (menu.find(ECLIPSE_PASTE_ID) != null) {
IAction pasteAction = getActionService().getAction(PasteInResourceAction.class);
menu.insertAfter(ECLIPSE_PASTE_ID, pasteAction);
menu.remove(ECLIPSE_PASTE_ID);
}
// override the rename in the context menu same as delete.
if (menu.find(ECLIPSE_RENAME_ID) != null) {
menu.insertAfter(ECLIPSE_RENAME_ID, this.renameAction);
menu.remove(ECLIPSE_RENAME_ID);
this.renameAction.selectionChanged(getSelection());
}
// override the move in the context menu same as delete.
if (menu.find(ECLIPSE_MOVE_ID) != null) {
menu.insertAfter(ECLIPSE_MOVE_ID, this.moveAction);
menu.remove(ECLIPSE_MOVE_ID);
this.moveAction.selectionChanged(selection);
}
// override the properties dialog action in the context menu.
// unfortunately the default action does not use the ID setup in IWorkbenchConstants:-(
// so can't use the menu.find(id) method
// so first time the action is found set it's ID
if (menu.find(ActionFactory.PROPERTIES.getId()) == null) {
IContributionItem[] items = menu.getItems();
IContributionItem oldItem = null;
// loop backwards since the item we're looking for is always at/near the bottom of the menu
for (int i = (items.length - 1); i >= 0; i--) {
if (items[i] instanceof ActionContributionItem) {
IAction action = ((ActionContributionItem)items[i]).getAction();
if (action instanceof org.eclipse.ui.dialogs.PropertyDialogAction) {
action.setId(ActionFactory.PROPERTIES.getId());
oldItem = items[i];
break;
}
}
}
// since the contribution id is set the action's id at construction, setting the
// action id above does not affect the contribution id. so the find done below will
// not work. so have to do a remove and add here.
if (oldItem != null) {
menu.remove(oldItem);
menu.add(this.propertyAction);
}
}
if (menu.find(ActionFactory.PROPERTIES.getId()) != null) {
menu.insertAfter(ActionFactory.PROPERTIES.getId(), this.propertyAction);
menu.remove(ActionFactory.PROPERTIES.getId());
this.propertyAction.selectionChanged(selection);
}
} catch (CoreException theException) {
Util.log(theException);
}
// Let's set up/insert our Insert markers
if (menu.find(OpenFileAction.ID) != null) {
menu.insertBefore(OpenFileAction.ID, new GroupMarker(ContextMenu.INSERT_START));
menu.insertAfter(ContextMenu.INSERT_START, new Separator(ContextMenu.INSERT_END));
}
// if single selection and model resource add new child menu
if (SelectionUtilities.isSingleSelection(selection)) {
Object obj = SelectionUtilities.getSelectedObject(selection);
if ((obj instanceof IResource) && ModelUtilities.isModelFile((IResource)obj)) {
MenuManager newChildMenu = getActionService().getInsertChildMenu(selection);
getActionService().contributePermanentActionsToContextMenu(newChildMenu, selection);
// insert menu after New submenu.
// the new submenu doesn't have an ID so put it before the open action
//
// Menu item group for insert child and sibling
//
menu.insertAfter(ContextMenu.INSERT_START, newChildMenu);
}
}
// add group for model related actions. this group is added to by actions in the manifest
// Example actions are close model and rebuild imports.
menu.insertBefore(ActionFactory.IMPORT.getId(), new GroupMarker(ContextMenu.MODEL_START));
menu.insertBefore(ActionFactory.IMPORT.getId(), new Separator(ContextMenu.MODEL_START));
menu.insertAfter(ContextMenu.MODEL_START, new GroupMarker(ContextMenu.MODEL_END));
// Combine ModelResourceActions & Special ModelObject actions into a Modeling Menu
MenuManager modelingActionMenu = getModelingActionMenu(selection);
if (modelingActionMenu != null && modelingActionMenu.getItems().length > 0) {
menu.insertBefore(ContextMenu.INSERT_END, modelingActionMenu);
}
}
// if single selection and ANY resource add refactor menu
if (SelectionUtilities.isSingleSelection(selection)) {
Object obj = SelectionUtilities.getSelectedObject(selection);
if (obj instanceof IResource) {
MenuManager refactorMenu = getActionService().getRefactorMenu(selection);
// insert menu at end of the cut/copy/paste group
if (refactorMenu != null) {
// find the location. Default to the end of the whole
// context menu.
if (menu.find(ECLIPSE_RENAME_ID) != null) {
menu.insertAfter(ECLIPSE_RENAME_ID, refactorMenu);
} else {
menu.insertBefore(ContextMenu.ADDITIONS, refactorMenu);
}
}
// remove the 'other' rename and move
if (menu.find(ECLIPSE_RENAME_ID) != null) {
menu.remove(ECLIPSE_RENAME_ID);
}
// override the move in the context menu same as delete.
if (menu.find(ECLIPSE_MOVE_ID) != null) {
menu.remove(ECLIPSE_MOVE_ID);
}
}
// Add Remove project action if selection is IProject and it is closed
if (obj instanceof IProject) {
if (!((IProject)obj).isOpen()) {
menu.insertBefore(ContextMenu.ADDITIONS, removeProjectAction);
} else {
if (DotProjectUtils.isModelerProject((IProject)obj)) {
menu.insertBefore(ContextMenu.ADDITIONS, cloneProjectAction);
}
}
}
}
}
/**
* @return the modeler action service (never <code>null</code>)
*/
private ModelerActionService getActionService() {
return (ModelerActionService)UiPlugin.getDefault().getActionService(getWorkbenchSite().getPage());
}
/**
* @param selection the Model Explorer's current selection
* @return the modeling action sub-menu for a given selection
*/
private MenuManager getModelingActionMenu( ISelection selection ) {
MenuManager menu = new MenuManager(MODELING_LABEL, ModelerActionBarIdManager.getModelingMenuId());
// add special model object actions
MenuManager actionMenu = ModelerSpecialActionManager.getModeObjectSpecialActionMenu(selection);
if ((actionMenu != null) && (actionMenu.getItems().length > 0)) {
for (IContributionItem item : actionMenu.getItems()) {
menu.add(item);
}
menu.add(new Separator());
}
// add special model resource actions
actionMenu = ModelResourceActionManager.getModelResourceActionMenu(selection);
if ((actionMenu != null) && (actionMenu.getItems().length > 0)) {
for (IContributionItem item : actionMenu.getItems()) {
menu.add(item);
}
menu.add(new Separator());
}
return menu;
}
CommonNavigator getNavigator() {
return (CommonNavigator)getWorkbenchSite().getPart();
}
/**
* @return the preference store
*/
IPreferenceStore getPreferenceStore() {
return UiPlugin.getDefault().getPreferenceStore();
}
/**
* @return the current selection in the Model Explorer's viewer
*/
private IStructuredSelection getSelection() {
return (IStructuredSelection)getViewer().getSelection();
}
TreeViewer getViewer() {
assert (getActionSite().getStructuredViewer() instanceof TreeViewer) : "This class should only be used in the ModelExplorer"; //$NON-NLS-1$
return (TreeViewer)getActionSite().getStructuredViewer();
}
ICommonViewerWorkbenchSite getWorkbenchSite() {
ICommonViewerSite site = getActionSite().getViewSite();
assert (site instanceof ICommonViewerWorkbenchSite) : "This class should only be used in the ModelExplorer"; //$NON-NLS-1$
return (ICommonViewerWorkbenchSite)site;
}
protected void handleKeyPressed( KeyEvent event ) {
if (event.stateMask != 0) {
return;
}
if (event.keyCode == SWT.F2) {
// rename action
/*
* ModelerActionService fix for defect 12372: if selection is a single IResource, use the refactor rename instead
*/
ISelection selection = getViewer().getSelection();
// if single selection see if it is an IResource
if (SelectionUtilities.isSingleSelection(selection)) {
Object obj = SelectionUtilities.getSelectedObject(selection);
// if single selection and ANY resource use refactor rename
if (obj instanceof IResource) {
// rename
IWorkbenchWindow window = UiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
IActionDelegate delRefactorRename = new RenameRefactorAction();
IAction refactorRenameAction = new DelegatableAction(delRefactorRename, window);
refactorRenameAction.setText(""); //$NON-NLS-1$
refactorRenameAction.setToolTipText(""); //$NON-NLS-1$
delRefactorRename.selectionChanged(refactorRenameAction, selection);
if (refactorRenameAction.isEnabled()) {
refactorRenameAction.run();
}
} else if ((this.renameAction != null) && this.renameAction.isEnabled()) {
// if single, but not an IResource, use the normal Rename
this.renameAction.run();
}
} else if ((this.renameAction != null) && this.renameAction.isEnabled()) {
// if not single, use the normal Rename
this.renameAction.run();
}
} else if (event.character == SWT.DEL) {
// delete action
try {
IAction deleteAction = null;
ISelection selection = getSelection();
if (SelectionUtilities.isAllEObjects(selection)) {
deleteAction = getActionService().getAction(ActionFactory.DELETE.getId());
} else {
deleteAction = getWorkbenchSite().getActionBars().getGlobalActionHandler(ActionFactory.DELETE.getId());
}
if ((deleteAction != null) && deleteAction.isEnabled()) {
deleteAction.run();
event.doit = false;
}
} catch (CoreException e) {
Util.log(e);
}
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.navigator.CommonActionProvider#init(org.eclipse.ui.navigator.ICommonActionExtensionSite)
*/
@Override
public void init( ICommonActionExtensionSite actionSite ) {
super.init(actionSite);
// register global actions
final IWorkbenchWindow wdw = UiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
final ModelerActionService svc = getActionService();
final IActionBars bars = getWorkbenchSite().getActionBars();
// MUST construct this action before registering default actions in order to cache the default eclipse copy action. if
// this is done after the registering default actions then there is no way to get the ResourceNavigators default copy
// action.
this.copyAction = new ModelExplorerCopyAction(bars, svc);
// register to receive workspace selection events in order to swap out copy actions
wdw.getSelectionService().addSelectionListener(this.copyAction);
this.removeProjectAction = new RemoveProjectAction();
// register to receive workspace selection events in order to swap out copy actions
wdw.getSelectionService().addSelectionListener(this.removeProjectAction);
this.cloneProjectAction = new CloneProjectAction2();
// register to receive workspace selection events in order to swap out copy actions
wdw.getSelectionService().addSelectionListener(this.cloneProjectAction);
svc.registerDefaultGlobalActions(bars);
this.actionsMap = new ModelerGlobalActionsMap();
try {
bars.setGlobalActionHandler(EclipseGlobalActions.COPY, this.copyAction);
// rename action
this.renameAction = new ModelNavigatorRenameAction(wdw, getViewer());
this.renameAction.selectionChanged((IStructuredSelection)getViewer().getSelection()); // initial tree selection
this.actionsMap.put(EclipseGlobalActions.RENAME, this.renameAction);
bars.setGlobalActionHandler(EclipseGlobalActions.RENAME, this.renameAction);
final IAction deleteAction = svc.getAction(DeleteResourceAction.class);
bars.setGlobalActionHandler(ActionFactory.DELETE.getId(), deleteAction);
final IAction pasteAction = svc.getAction(PasteInResourceAction.class);
bars.setGlobalActionHandler(ActionFactory.PASTE.getId(), pasteAction);
// move action
this.moveAction = new ModelNavigatorMoveAction(wdw, getViewer());
bars.setGlobalActionHandler(ActionFactory.MOVE.getId(), this.moveAction);
bars.updateActionBars();
} catch (final CoreException e) {
Util.log(e);
WidgetUtil.showError(createRenameActionErrorMessage);
}
// used in context menu to replace default action
this.propertyAction = new PropertyDialogAction(getViewer().getControl(), getViewer());
bars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(), this.propertyAction);
registerListeners();
}
/**
* @param selection the selection being checked
* @return <code>true</code> if all selected objects are {@link IExtendedModelObject}s
*/
private boolean isAllExtendedModelObjects( ISelection selection ) {
if (SelectionUtilities.isEmptySelection(selection)) {
return false;
}
for (Object obj : SelectionUtilities.getSelectedObjects(selection)) {
if (!(obj instanceof IExtendedModelObject)) {
return false;
}
}
return true;
}
private void registerListeners() {
final TreeViewer viewer = getViewer();
KeyListener keyListener = new KeyListener() {
/**
* {@inheritDoc}
*
* @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent)
*/
@Override
public void keyPressed( KeyEvent event ) {
handleKeyPressed(event);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent)
*/
@Override
public void keyReleased( KeyEvent event ) {
// nothing to do
}
};
viewer.getControl().addKeyListener(keyListener);
// register to listen for Change Notifications
this.notificationHandler = new ModelNavigatorNotificationHandler(viewer, getNavigator());
ModelUtilities.addNotifyChangedListener(this.notificationHandler);
this.selectionListener = new ISelectionListener() {
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
@Override
public void selectionChanged( IWorkbenchPart part,
final ISelection selection ) {
if ((part != getNavigator()) && getNavigator().isLinkingEnabled()) {
if ((selection instanceof IStructuredSelection) && !selection.isEmpty()) {
int nObj = ((IStructuredSelection)selection).size();
int nEObj = SelectionUtilities.getSelectedEObjects(selection).size();
if (nObj == nEObj) {
viewer.setSelection(selection, true);
} else {
// Defect 23541: Newly created models were not getting selected in the tree
if ((nObj == 1) && (((IStructuredSelection)selection).getFirstElement() instanceof IResource)) {
Runnable runnable = new Runnable() {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (!viewer.getControl().isDisposed()) {
viewer.setSelection(selection, true);
// do a refresh if the viewer selection is
// empty in order to force
// the treeitems to be created.
if (viewer.getSelection().isEmpty()) {
ITreeContentProvider cp = (ITreeContentProvider)viewer.getContentProvider();
Object parent = cp.getParent(((IStructuredSelection)selection).getFirstElement());
if (parent == null) {
viewer.refresh(true);
} else {
viewer.refresh(parent, true);
}
// set selection one more time
viewer.setSelection(selection, true);
}
}
}
};
// do an async here to ensure the resource treeitem has been created first
viewer.getControl().getDisplay().asyncExec(runnable);
}
}
}
}
}
};
// register a part listener to refresh resource icons when ModelEditors open/close
// use my page, not the active page:
this.partListener = new IPartListener() {
private void checkResource( final IWorkbenchPart part ) {
if (part instanceof ModelEditor) {
Runnable runnable = new Runnable() {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (!viewer.getTree().isDisposed()) {
viewer.refresh(((ModelEditor)part).getModelFile());
}
}
};
Display.getCurrent().asyncExec(runnable);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
*/
@Override
public void partActivated( IWorkbenchPart part ) {
// nothing to do
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
*/
@Override
public void partBroughtToTop( IWorkbenchPart part ) {
// nothing to do
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
*/
@Override
public void partClosed( IWorkbenchPart part ) {
// nothing to do
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
*/
@Override
public void partDeactivated( IWorkbenchPart part ) {
// nothing to do
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
*/
@Override
public void partOpened( IWorkbenchPart part ) {
checkResource(part);
}
};
getWorkbenchSite().getPage().addPartListener(this.partListener);
this.markerListener = new IResourceChangeListener() {
/**
* {@inheritDoc}
*
* @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
*/
@Override
public void resourceChanged( IResourceChangeEvent event ) {
final IMarkerDelta[] deltas = event.findMarkerDeltas(null, true);
if ((deltas != null) && (deltas.length > 0)) {
final Set<IProject> projects = new HashSet<IProject>(deltas.length);
for (IMarkerDelta delta : deltas) {
projects.add(delta.getResource().getProject());
}
Runnable runnable = new Runnable() {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (!viewer.getTree().isDisposed()) {
for (IProject project : projects) {
viewer.refresh(project, true);
}
}
}
};
Display.getDefault().asyncExec(runnable);
}
}
};
ModelerCore.getWorkspace().addResourceChangeListener(this.markerListener);
this.modelResourceListener = new EventObjectListener() {
/**
* {@inheritDoc}
*
* @see org.teiid.core.designer.event.EventObjectListener#processEvent(java.util.EventObject)
*/
@Override
public void processEvent( EventObject obj ) {
ModelResourceEvent event = (ModelResourceEvent)obj;
final IResource file = event.getResource();
if (event.getType() == ModelResourceEvent.CLOSING) {
Runnable runnable = new Runnable() {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (!viewer.getTree().isDisposed()) {
viewer.collapseToLevel(file, AbstractTreeViewer.ALL_LEVELS);
}
}
};
Display.getDefault().asyncExec(runnable);
} else if (event.getType() == ModelResourceEvent.CLOSED) {
Runnable runnable = new Runnable() {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (!viewer.getTree().isDisposed()) {
viewer.remove(file);
viewer.refresh(file.getParent(), false);
}
}
};
Display.getDefault().asyncExec(runnable);
} else if (event.getType() == ModelResourceEvent.RELOADED) {
Runnable runnable = new Runnable() {
/**
* {@inheritDoc}
*
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
if (!viewer.getTree().isDisposed()) {
viewer.refresh(file.getParent(), false);
}
}
};
Display.getDefault().asyncExec(runnable);
}
}
};
try {
UiPlugin.getDefault().getEventBroker().addListener(ModelResourceEvent.class, modelResourceListener);
} catch (EventSourceException e) {
Util.log(IStatus.ERROR, e, e.getMessage());
}
}
/**
* The <code>ModelExplorerCopyAction</code> delegates the copying to either the default Eclipse ResourceNavigator copy action or
* to the EObject copy action based on workspace selection. Must be constructed before global actions are overwritten.
*/
class ModelExplorerCopyAction extends Action implements ISelectionListener {
private IAction currentAction = null; // current action based on selection
private IAction defaultAction = null; // default eclipse copy action
private IAction modelerAction = null; // eobject copy action
public ModelExplorerCopyAction( IActionBars theActionBars,
ActionService theService ) {
// cache the eclipse resource copy action
this.defaultAction = theActionBars.getGlobalActionHandler(EclipseGlobalActions.COPY);
if (this.defaultAction == null) {
this.defaultAction = GlobalActionsMap.UNSUPPORTED_ACTION;
Util.log(IStatus.ERROR, defaultCopyActionNotFoundMessage);
}
// cache the EObject copy action
try {
this.modelerAction = theService.getAction(EclipseGlobalActions.COPY);
} catch (CoreException theException) {
Util.log(theException);
}
if (this.modelerAction == null) {
this.modelerAction = GlobalActionsMap.UNSUPPORTED_ACTION;
}
// initialize state
this.currentAction = defaultAction;
setEnabled(this.currentAction.isEnabled());
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
this.currentAction.runWithEvent(new Event());
}
/**
* {@inheritDoc}
*
* @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
* org.eclipse.jface.viewers.ISelection)
*/
@Override
public void selectionChanged( IWorkbenchPart thePart,
ISelection theSelection ) {
IAction handler = (SelectionUtilities.isAllEObjects(theSelection)) ? this.modelerAction : this.defaultAction;
// switch handlers if necessary
if (this.currentAction != handler) {
this.currentAction = handler;
}
setEnabled(this.currentAction.isEnabled());
}
}
class ShowImportsAction extends Action {
public ShowImportsAction() {
super(showImportsActionText, IAction.AS_CHECK_BOX);
this.setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.IMPORT_CONTAINER));
// set initial state based on preference
IPreferenceStore store = getPreferenceStore();
boolean prefValue = true;
if (store.contains(SHOW_IMPORTS_IN_MODEL_EXPLORER)) {
prefValue = store.getBoolean(SHOW_IMPORTS_IN_MODEL_EXPLORER);
} else {
prefValue = store.getDefaultBoolean(SHOW_IMPORTS_IN_MODEL_EXPLORER);
}
setChecked(prefValue);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
// update preference value
IPreferenceStore store = getPreferenceStore();
store.setValue(SHOW_IMPORTS_IN_MODEL_EXPLORER, isChecked());
// refresh viewer
getViewer().refresh();
}
}
class ShowNonModelsAction extends Action {
private final ViewerFilter filter = new NonModelViewerFilter();
public ShowNonModelsAction() {
super(showNonModelsActionText, IAction.AS_CHECK_BOX);
// set initial state based on preference
IPreferenceStore store = getPreferenceStore();
boolean prefValue = true;
if (store.contains(SHOW_NON_MODELS_IN_MODEL_EXPLORER)) {
prefValue = store.getBoolean(SHOW_NON_MODELS_IN_MODEL_EXPLORER);
} else {
prefValue = store.getDefaultBoolean(SHOW_NON_MODELS_IN_MODEL_EXPLORER);
}
setChecked(prefValue);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
// update preference value
IPreferenceStore store = getPreferenceStore();
store.setValue(SHOW_NON_MODELS_IN_MODEL_EXPLORER, isChecked());
// refresh viewer
if (isChecked()) {
getViewer().removeFilter(this.filter);
} else {
getViewer().addFilter(this.filter);
}
}
}
class SortModelContentsAction extends Action {
public SortModelContentsAction() {
super(sortModelContentsActionText, IAction.AS_CHECK_BOX);
this.setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.ALPHA_SORT_ICON));
// set initial state based on preference
IPreferenceStore store = getPreferenceStore();
boolean prefValue = true;
if (store.contains(SORT_MODEL_CONTENTS)) {
prefValue = store.getBoolean(SORT_MODEL_CONTENTS);
} else {
prefValue = store.getDefaultBoolean(SORT_MODEL_CONTENTS);
}
setChecked(prefValue);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jface.action.Action#run()
*/
@Override
public void run() {
// update preference value
IPreferenceStore store = getPreferenceStore();
store.setValue(SORT_MODEL_CONTENTS, isChecked());
// refresh viewer
getViewer().refresh();
}
}
}