/******************************************************************************* * Copyright (c) 2000, 2017 IBM Corporation 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 * *******************************************************************************/ package org.eclipse.dltk.internal.ui.wizards.buildpath.newsourcepage; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.dltk.core.DLTKCore; import org.eclipse.dltk.core.IModelElement; import org.eclipse.dltk.core.IProjectFragment; import org.eclipse.dltk.core.IScriptFolder; import org.eclipse.dltk.core.IScriptProject; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.ModelException; import org.eclipse.dltk.internal.corext.buildpath.AddSelectedSourceFolderOperation; import org.eclipse.dltk.internal.corext.buildpath.BuildpathModifier; import org.eclipse.dltk.internal.corext.buildpath.BuildpathModifier.IBuildpathModifierListener; import org.eclipse.dltk.internal.corext.buildpath.BuildpathModifierOperation; import org.eclipse.dltk.internal.corext.buildpath.CreateFolderOperation; import org.eclipse.dltk.internal.corext.buildpath.EditFiltersOperation; import org.eclipse.dltk.internal.corext.buildpath.ExcludeOperation; import org.eclipse.dltk.internal.corext.buildpath.IBuildpathInformationProvider; import org.eclipse.dltk.internal.corext.buildpath.IPackageExplorerActionListener; import org.eclipse.dltk.internal.corext.buildpath.LinkedSourceFolderOperation; import org.eclipse.dltk.internal.corext.buildpath.PackageExplorerActionEvent; import org.eclipse.dltk.internal.corext.buildpath.RemoveFromBuildpathOperation; import org.eclipse.dltk.internal.corext.buildpath.ResetAllOperation; import org.eclipse.dltk.internal.corext.buildpath.UnexcludeOperation; import org.eclipse.dltk.internal.ui.actions.CompositeActionGroup; import org.eclipse.dltk.internal.ui.scriptview.BuildPathContainer; import org.eclipse.dltk.internal.ui.util.ViewerPane; import org.eclipse.dltk.internal.ui.wizards.NewWizardMessages; import org.eclipse.dltk.ui.DLTKPluginImages; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.ui.actions.ActionContext; /** * Action group for the package explorer. Creates and manages a set of * <code>BuildpathModifierOperation</code>s and creates a * <code>ToolBarManager</code> on request. Based on this operations, * <code>BuildpathModifierAction</code>s are generated. The available operations * are: * * @see org.eclipse.dltk.internal.corext.buildpath.AddSelectedSourceFolderOperation * @see org.eclipse.dltk.internal.corext.buildpath.RemoveFromBuildpathOperation * @see org.eclipse.dltk.internal.corext.buildpath.IncludeOperation * @see org.eclipse.dltk.internal.corext.buildpath.UnincludeOperation * @see org.eclipse.dltk.internal.corext.buildpath.ExcludeOperation * @see org.eclipse.dltk.internal.corext.buildpath.UnexcludeOperation * @see org.eclipse.dltk.internal.corext.buildpath.EditFiltersOperation * @see org.eclipse.dltk.internal.corext.buildpath.ResetOperation */ public class DialogPackageExplorerActionGroup extends CompositeActionGroup { public static class DialogExplorerActionContext extends ActionContext { private IScriptProject fScriptProject; private List fSelectedElements; /** * Constructor to create an action context for the dialog package * explorer. * * For reasons of completeness, the selection of the super class * <code>ActionContext</code> is also set, but is not intendet to be * used. * * @param selection * the current selection * @param jProject * the element's script project */ public DialogExplorerActionContext(ISelection selection, IScriptProject jProject) { super(null); fScriptProject = jProject; fSelectedElements = ((IStructuredSelection) selection).toList(); IStructuredSelection structuredSelection = new StructuredSelection( new Object[] { fSelectedElements, jProject }); super.setSelection(structuredSelection); } /** * Constructor to create an action context for the dialog package * explorer. * * For reasons of completeness, the selection of the super class * <code>ActionContext</code> is also set, but is not intendet to be * used. * * @param selectedElements * a list of currently selected elements * @param jProject * the element's script project */ public DialogExplorerActionContext(List selectedElements, IScriptProject jProject) { super(null); fScriptProject = jProject; fSelectedElements = selectedElements; IStructuredSelection structuredSelection = new StructuredSelection( new Object[] { fSelectedElements, jProject }); super.setSelection(structuredSelection); } public IScriptProject getScriptProject() { return fScriptProject; } public List getSelectedElements() { return fSelectedElements; } } /** script project */ public static final int SCRIPT_PROJECT = 0x01; /** Package fragment root */ public static final int PACKAGE_FRAGMENT_ROOT = 0x02; /** Package fragment */ public static final int PACKAGE_FRAGMENT = 0x03; /** Compilation unit */ public static final int SOURCE_MODULE = 0x04; /** File */ public static final int FILE = 0x05; /** Normal folder */ public static final int FOLDER = 0x06; /** Excluded folder */ public static final int EXCLUDED_FOLDER = 0x07; /** Excluded file */ public static final int EXCLUDED_FILE = 0x08; /** Included file */ public static final int INCLUDED_FILE = 0xA; /** Included folder */ public static final int INCLUDED_FOLDER = 0xB; /** An archive element */ public static final int ARCHIVE = 0xD; /** A IProjectFragment with include/exclude filters set */ public static final int MODIFIED_FRAGMENT_ROOT = 0xE; /** Default package fragment */ public static final int DEFAULT_FRAGMENT = 0xF; /** Undefined type */ public static final int UNDEFINED = 0x10; /** Multi selection */ public static final int MULTI = 0x11; /** No elements selected */ public static final int NULL_SELECTION = 0x12; /** Elements that are contained in an archive */ public static final int ARCHIVE_RESOURCE = 0x13; public static final int EXTERNAL_RESOURCE = 0x15; /** Elements that represent Buildpath container (= libraries) */ public static final int CONTAINER = 0x14; private BuildpathModifierAction[] fActions; private int fLastType; private List fListeners; private static final int fContextSensitiveActions = 5; /** * Constructor which creates the operations and based on this operations the * actions. * * @param provider * a information provider to pass necessary information to the * operations * @param listener * a listener for the changes on Buildpath entries, that is the * listener will be notified whenever a Buildpath entry changed. * @see IBuildpathModifierListener */ public DialogPackageExplorerActionGroup( IBuildpathInformationProvider provider, IBuildpathModifierListener listener) { super(); fLastType = UNDEFINED; fListeners = new ArrayList(); fActions = new BuildpathModifierAction[8]; BuildpathModifierOperation op; op = new AddSelectedSourceFolderOperation(listener, provider); // TODO User disabled image when available addAction(new BuildpathModifierAction(op, DLTKPluginImages.DESC_ELCL_ADD_AS_SOURCE_FOLDER, null, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_AddSelSFToCP_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_AddSelSFToCP_tooltip, IAction.AS_PUSH_BUTTON), 0); op = new RemoveFromBuildpathOperation(listener, provider); addAction(new BuildpathModifierAction(op, DLTKPluginImages.DESC_ELCL_REMOVE_AS_SOURCE_FOLDER, DLTKPluginImages.DESC_DLCL_REMOVE_AS_SOURCE_FOLDER, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_RemoveFromCP_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_RemoveFromCP_tooltip, IAction.AS_PUSH_BUTTON), 1); op = new ExcludeOperation(listener, provider); addAction(new BuildpathModifierAction(op, DLTKPluginImages.DESC_ELCL_EXCLUDE_FROM_BUILDPATH, DLTKPluginImages.DESC_DLCL_EXCLUDE_FROM_BUILDPATH, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Exclude_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Exclude_tooltip, IAction.AS_PUSH_BUTTON), 2); op = new UnexcludeOperation(listener, provider); addAction(new BuildpathModifierAction(op, DLTKPluginImages.DESC_ELCL_INCLUDE_ON_BUILDPATH, DLTKPluginImages.DESC_DLCL_INCLUDE_ON_BUILDPATH, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Unexclude_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Unexclude_tooltip, IAction.AS_PUSH_BUTTON), 3); op = new EditFiltersOperation(listener, provider); BuildpathModifierAction action = new BuildpathModifierAction(op, DLTKPluginImages.DESC_ELCL_CONFIGURE_BUILDPATH_FILTERS, DLTKPluginImages.DESC_DLCL_CONFIGURE_BUILDPATH_FILTERS, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Edit_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Edit_tooltip, IAction.AS_PUSH_BUTTON); BuildpathModifierDropDownAction dropDown = new BuildpathModifierDropDownAction( action, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Configure_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Configure_tooltip); addAction(dropDown, 4); /* * addAction(new BuildpathModifierAction(op, * DLTKPluginImages.DESC_OBJS_TEXT_EDIT, * DLTKPluginImages.DESC_DLCL_TEXT_EDIT, NewWizardMessages.getString( * "NewSourceContainerWorkbookPage.ToolBar.Edit.label"), //$NON-NLS-1$ * NewWizardMessages.getString( * "NewSourceContainerWorkbookPage.ToolBar.Edit.tooltip"), * IAction.AS_PUSH_BUTTON), //$NON-NLS-1$ * IBuildpathInformationProvider.EDIT); */ op = new LinkedSourceFolderOperation(listener, provider); addAction(new BuildpathModifierAction(op, DLTKPluginImages.DESC_ELCL_ADD_LINKED_SOURCE_TO_BUILDPATH, DLTKPluginImages.DESC_DLCL_ADD_LINKED_SOURCE_TO_BUILDPATH, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Link_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_Link_tooltip, IAction.AS_PUSH_BUTTON), 5); op = new CreateFolderOperation(listener, provider); addAction(new BuildpathModifierAction(op, DLTKPluginImages.DESC_OBJS_PACKFRAG_ROOT, null, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_CreateSrcFolder_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_CreateSrcFolder_tooltip, IAction.AS_PUSH_BUTTON), 6); op = new ResetAllOperation(listener, provider); addAction(new BuildpathModifierAction(op, DLTKPluginImages.DESC_ELCL_CLEAR, DLTKPluginImages.DESC_DLCL_CLEAR, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_ClearAll_label, NewWizardMessages.NewSourceContainerWorkbookPage_ToolBar_ClearAll_tooltip, IAction.AS_PUSH_BUTTON), 7); } private void addAction(BuildpathModifierAction action, int index) { fActions[index] = action; } /** * Get an action of the specified type * * @param type * the type of the desired action, must be a constante of * <code>IBuildpathInformationProvider</code> * @return the requested action * * @see IBuildpathInformationProvider */ public BuildpathModifierAction getAction(int type) { for (int i = 0; i < fActions.length; i++) { if (fActions[i].getOperation().getTypeId() == type) return fActions[i]; } throw new ArrayIndexOutOfBoundsException(); } public BuildpathModifierAction[] getActions() { List<BuildpathModifierAction> result = new ArrayList<>(); for (int i = 0; i < fActions.length; i++) { BuildpathModifierAction action = fActions[i]; if (action instanceof BuildpathModifierDropDownAction) { BuildpathModifierDropDownAction dropDownAction = (BuildpathModifierDropDownAction) action; BuildpathModifierAction[] actions = dropDownAction.getActions(); for (int j = 0; j < actions.length; j++) { result.add(actions[j]); } } else { result.add(action); } } return result.toArray(new BuildpathModifierAction[result.size()]); } /** * Create a toolbar manager for a given <code>ViewerPane</code> * * @param pane * the pane to create the <code> * ToolBarManager</code> for. * @return the created <code>ToolBarManager</code> */ public ToolBarManager createLeftToolBarManager(ViewerPane pane) { ToolBarManager tbm = pane.getToolBarManager(); for (int i = 0; i < fContextSensitiveActions; i++) { tbm.add(fActions[i]); if (i == 1 || i == 3) tbm.add(new Separator()); } tbm.update(true); return tbm; } /** * Create a toolbar manager for a given <code>ViewerPane</code> * * @param pane * the pane to create the help toolbar for * @return the created <code>ToolBarManager</code> */ public ToolBarManager createLeftToolBar(ViewerPane pane) { ToolBar tb = new ToolBar(pane, SWT.FLAT); pane.setTopRight(tb); ToolBarManager tbm = new ToolBarManager(tb); for (int i = fContextSensitiveActions; i < fActions.length; i++) { tbm.add(fActions[i]); } if (DLTKCore.DEBUG) { System.err.println("Add help support here..."); //$NON-NLS-1$ } // tbm.add(new HelpAction()); tbm.update(true); return tbm; } /** * Forces the action group to recompute the available actions and fire an * event to all listeners * * @throws ModelException * * @see #setContext(DialogExplorerActionContext) * @see #informListeners(String[], BuildpathModifierAction[]) */ public void refresh(DialogExplorerActionContext context) throws ModelException { super.setContext(context); if (context == null) // can happen when disposing return; List selectedElements = context.getSelectedElements(); IScriptProject project = context.getScriptProject(); int type = MULTI; if (selectedElements.size() == 0) { type = NULL_SELECTION; if (type == fLastType) return; } else if (selectedElements.size() == 1 || identicalTypes(selectedElements, project)) { type = getType(selectedElements.get(0), project); } internalSetContext(selectedElements, project, type); } /** * Set the context for the action group. This also includes updating the * actions (that is, enable or disable them). The decision which actions * should be enabled or disabled is based on the content of the * <code>DialogExplorerActionContext</code> * * If the type of the selection changes, then listeners will be notified * about the new set of available actions. * * Note: notification is only done if the TYPE changes (not the selected * object as such). This means that if elements of the same type are * selected (for example two times a folder), NO notification will take * place. There might be situations where the type of two objects is the * same but the set of available actions is not. However, if clients decide * that upon some action a recomputation of the available actions has to be * forced, then * <code>PackageExplorerActionGroup.refresh(DialogExplorerActionContext)</code> * can be called. * * @param context * the action context * * @see IPackageExplorerActionListener * @see PackageExplorerActionEvent * @see DialogExplorerActionContext * @see #addListener(IPackageExplorerActionListener) * @see #refresh(DialogExplorerActionContext) * * @throws ModelException * if there is a failure while computing the available actions. */ public void setContext(DialogExplorerActionContext context) throws ModelException { super.setContext(context); if (context == null) // can happen when disposing return; List selectedElements = context.getSelectedElements(); IScriptProject project = context.getScriptProject(); int type = MULTI; if (selectedElements.size() == 0) { type = NULL_SELECTION; if (type == fLastType) return; } else if (selectedElements.size() == 1 || identicalTypes(selectedElements, project)) { type = getType(selectedElements.get(0), project); if (selectedElements.size() > 1) type = type | MULTI; if (type == fLastType) return; } internalSetContext(selectedElements, project, type); } /** * Get a description for the last selection explaining why no operation is * possible. * <p> * This can be usefull if a context sensitive widget does not want to * display all operations although some of them are valid. * * @return a description for the last selection that explains why no * operation is available. */ public String getNoActionDescription() { String[] description = noAction(fLastType); return description[0]; } /** * Internal method to set the context of the action group. * * @param selectedElements * a list of selected elements, can be empty * @param project * the script project * @param type * the type of the selected element(s) * @throws ModelException */ private void internalSetContext(List selectedElements, IScriptProject project, int type) throws ModelException { fLastType = type; List availableActions = getAvailableActions(selectedElements, project); BuildpathModifierAction[] actions = new BuildpathModifierAction[availableActions .size()]; String[] descriptions = new String[availableActions.size()]; if (availableActions.size() > 0) { for (int i = 0; i < availableActions.size(); i++) { BuildpathModifierAction action = (BuildpathModifierAction) availableActions .get(i); actions[i] = action; descriptions[i] = action.getDescription(type); } } else descriptions = noAction(type); informListeners(descriptions, actions); } /** * Finds out wheter the list of elements consists only of elements having * the same type (for example all are of type * DialogPackageExplorerActionGroup.COMPILATION_UNIT). This allows to use a * description for the available actions which is more specific and * therefore provides more information. * * @param elements * a list of elements to be compared to each other * @param project * the script project * @return <code>true</code> if all elements are of the same type, * <code>false</code> otherwise. * @throws ModelException */ private boolean identicalTypes(List elements, IScriptProject project) throws ModelException { if (elements.size() == 0) { return false; } Object firstElement = elements.get(0); int firstType = getType(firstElement, project); for (int i = 1; i < elements.size(); i++) { if (firstType != getType(elements.get(i), project)) return false; } return true; } /** * Inform all listeners about new actions. * * @param descriptions * an array of descriptions for each actions, where the * description at position 'i' belongs to the action at position * 'i' * @param actions * an array of available actions */ private void informListeners(String[] descriptions, BuildpathModifierAction[] actions) { Iterator iterator = fListeners.iterator(); PackageExplorerActionEvent event = new PackageExplorerActionEvent( descriptions, actions); while (iterator.hasNext()) { IPackageExplorerActionListener listener = (IPackageExplorerActionListener) iterator .next(); listener.handlePackageExplorerActionEvent(event); } } /** * Returns string array with only one element which contains a short reason * to indicate why there are no actions available. * * @return a description to explain why there are no actions available */ private String[] noAction(int type) { String reason; switch (type) { case FILE: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_File; break; case FILE | MULTI: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_File; break; case DEFAULT_FRAGMENT: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_DefaultPackage; break; case DEFAULT_FRAGMENT | MULTI: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_DefaultPackage; break; case NULL_SELECTION: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_NullSelection; break; case MULTI: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_MultiSelection; break; case ARCHIVE_RESOURCE: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_ArchiveResource; break; default: reason = NewWizardMessages.PackageExplorerActionGroup_NoAction_NoReason; } return new String[] { reason }; } /** * Computes the type based on the current selection. The type can be usefull * to set the content of the hint text group properly. * * @param obj * the object to get the type from * @return the type of the current selection or UNDEFINED if no appropriate * type could be found. Possible types are:<br> * PackageExplorerActionGroup.FOLDER<br> * PackageExplorerActionGroup.EXCLUDED_FOLDER;<br> * PackageExplorerActionGroup.EXCLUDED_FILE<br> * PackageExplorerActionGroup.DEFAULT_OUTPUT<br> * PackageExplorerActionGroup.INCLUDED_FILE<br> * PackageExplorerActionGroup.INCLUDED_FOLDER<br> * PackageExplorerActionGroup.OUTPUT<br> * PackageExplorerActionGroup.MODIFIED_FRAGMENT_ROOT<br> * PackageExplorerActionGroup.DEFAULT_FRAGMENT<br> * PackageExplorerActionGroup.JAVA_PROJECT<br> * PackageExplorerActionGroup.PACKAGE_FRAGMENT_ROOT<br> * PackageExplorerActionGroup.PACKAGE_FRAGMENT<br> * PackageExplorerActionGroup.COMPILATION_UNIT<br> * PackageExplorerActionGroup.FILE<br> * @throws ModelException */ public static int getType(Object obj, IScriptProject project) throws ModelException { if (obj instanceof IScriptProject) return SCRIPT_PROJECT; if (obj instanceof BuildPathContainer) return CONTAINER; if (obj instanceof IProjectFragment) return BuildpathModifier.filtersSet((IProjectFragment) obj) ? MODIFIED_FRAGMENT_ROOT : PACKAGE_FRAGMENT_ROOT; if (obj instanceof IScriptFolder) { if (BuildpathModifier.isDefaultFragment((IScriptFolder) obj)) { if (((IProjectFragment) ((IModelElement) obj) .getAncestor(IModelElement.PROJECT_FRAGMENT)) .isArchive()) return ARCHIVE_RESOURCE; return DEFAULT_FRAGMENT; } if (BuildpathModifier.isIncluded((IModelElement) obj, project, null)) return INCLUDED_FOLDER; if (((IProjectFragment) ((IModelElement) obj) .getAncestor(IModelElement.PROJECT_FRAGMENT)).isArchive()) return ARCHIVE_RESOURCE; if (((IProjectFragment) ((IModelElement) obj) .getAncestor(IModelElement.PROJECT_FRAGMENT)).isExternal()) return EXTERNAL_RESOURCE; return PACKAGE_FRAGMENT; } if (obj instanceof ISourceModule) { if (((IProjectFragment) ((IModelElement) obj) .getAncestor(IModelElement.PROJECT_FRAGMENT)).isArchive()) { return ARCHIVE_RESOURCE; } if (((IProjectFragment) ((IModelElement) obj) .getAncestor(IModelElement.PROJECT_FRAGMENT)) .isExternal()) { return EXTERNAL_RESOURCE; } return BuildpathModifier.isIncluded((IModelElement) obj, project, null) ? INCLUDED_FILE : SOURCE_MODULE; } if (obj instanceof IFolder) { return getFolderType((IFolder) obj, project); } if (obj instanceof IFile) return getFileType((IFile) obj, project); return UNDEFINED; } /** * Get the type of the folder * * @param folder * folder to get the type from * @return the type code for the folder. Possible types are:<br> * PackageExplorerActionGroup.FOLDER<br> * PackageExplorerActionGroup.EXCLUDED_FOLDER;<br> * @throws ModelException */ private static int getFolderType(IFolder folder, IScriptProject project) throws ModelException { IContainer folderParent = folder.getParent(); if (folderParent.getFullPath().equals(project.getPath())) return FOLDER; if (BuildpathModifier.getFragment(folderParent) != null) return EXCLUDED_FOLDER; IProjectFragment fragmentRoot = BuildpathModifier .getFragmentRoot(folder, project, null); if (fragmentRoot == null) return FOLDER; if (fragmentRoot.equals(DLTKCore.create(folderParent))) return EXCLUDED_FOLDER; return FOLDER; } /** * Get the type of the file * * @param file * file to get the type from * @return the type code for the file. Possible types are:<br> * PackageExplorerActionGroup.EXCLUDED_FILE<br> * PackageExplorerActionGroup.FILE * @throws ModelException */ private static int getFileType(IFile file, IScriptProject project) throws ModelException { if (BuildpathModifier.isArchive(file, project)) return ARCHIVE; if (DLTKCore.DEBUG) { System.err.println( "DialogPackageExplorerActionGroup:: Add some filters here"); //$NON-NLS-1$ } // if (!DLTKCore.isScriptLikeFileName(file.getName())) // return FILE; IContainer fileParent = file.getParent(); if (fileParent.getFullPath().equals(project.getPath())) { if (project.isOnBuildpath(project)) return EXCLUDED_FILE; return FILE; } IProjectFragment fragmentRoot = BuildpathModifier.getFragmentRoot(file, project, null); if (fragmentRoot == null) return FILE; if (fragmentRoot.isArchive()) return ARCHIVE_RESOURCE; if (fragmentRoot.equals(DLTKCore.create(fileParent))) return EXCLUDED_FILE; if (BuildpathModifier.getFragment(fileParent) == null) { if (BuildpathModifier.parentExcluded(fileParent, project)) return FILE; return EXCLUDED_FILE; } return EXCLUDED_FILE; } /** * Based on the given list of elements, get the list of available actions * that can be applied on this elements * * @param selectedElements * the list of elements to get the actions for * @param project * the script project * @return a list of <code>BuildpathModifierAction</code>s * @throws ModelException */ private List getAvailableActions(List selectedElements, IScriptProject project) throws ModelException { if (project == null || !project.exists()) { return new ArrayList(); } List actions = new ArrayList(); int[] types = new int[selectedElements.size()]; for (int i = 0; i < types.length; i++) { types[i] = getType(selectedElements.get(i), project); } for (int i = 0; i < fActions.length; i++) { if (fActions[i] instanceof BuildpathModifierDropDownAction) { if (changeEnableState(fActions[i], selectedElements, types)) { BuildpathModifierAction[] dropDownActions = ((BuildpathModifierDropDownAction) fActions[i]) .getActions(); for (int j = 0; j < dropDownActions.length; j++) { if (changeEnableState(dropDownActions[j], selectedElements, types)) actions.add(dropDownActions[j]); } } } else if (changeEnableState(fActions[i], selectedElements, types)) { actions.add(fActions[i]); } } return actions; } /** * Changes the enabled state of an action if necessary. * * @param action * the action to change it's state for * @param selectedElements * a list of selected elements * @param types * an array of types corresponding to the types of the selected * elements * @return <code>true</code> if the action is valid (= enabled), * <code>false</code> otherwise * @throws ModelException */ private boolean changeEnableState(BuildpathModifierAction action, List selectedElements, int[] types) throws ModelException { if (action.isValid(selectedElements, types)) { if (!action.isEnabled()) action.setEnabled(true); return true; } else { if (action.isEnabled()) action.setEnabled(false); return false; } } /** * Fill the context menu with the available actions * * @param menu * the menu to be filled up with actions */ @Override public void fillContextMenu(IMenuManager menu) { for (int i = 0; i < fContextSensitiveActions; i++) { IAction action = getAction(i); if (action instanceof BuildpathModifierDropDownAction) { if (action.isEnabled()) { IAction[] actions = ((BuildpathModifierDropDownAction) action) .getActions(); for (int j = 0; j < actions.length; j++) { if (actions[j].isEnabled()) menu.add(actions[j]); } } } else if (action.isEnabled()) menu.add(action); } super.fillContextMenu(menu); } /** * Add listeners for the <code>PackageExplorerActionEvent</code>. * * @param listener * the listener to be added * * @see PackageExplorerActionEvent * @see IPackageExplorerActionListener */ public void addListener(IPackageExplorerActionListener listener) { fListeners.add(listener); } /** * Remove the listener from the list of registered listeners. * * @param listener * the listener to be removed */ public void removeListener(IPackageExplorerActionListener listener) { fListeners.remove(listener); } @Override public void dispose() { fListeners.clear(); super.dispose(); } }