/******************************************************************************* * Copyright (c) 2000, 2011 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 * * Contributors: * Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation * (report 36180: Callers/Callees view) * Michael Fraenkel (fraenkel@us.ibm.com) - patch * (report 60714: Call Hierarchy: display search scope in view title) *******************************************************************************/ package org.eclipse.jdt.internal.ui.callhierarchy; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IMemento; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.ActionGroup; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.ui.IContextMenuConstants; class SearchScopeActionGroup extends ActionGroup { private static final String TAG_SEARCH_SCOPE_TYPE= "search_scope_type"; //$NON-NLS-1$ private static final String TAG_SELECTED_WORKING_SET= "working_set"; //$NON-NLS-1$ private static final String TAG_WORKING_SET_COUNT = "working_set_count"; //$NON-NLS-1$ private static final String DIALOGSTORE_SCOPE_TYPE= "SearchScopeActionGroup.search_scope_type"; //$NON-NLS-1$ private static final String DIALOGSTORE_SELECTED_WORKING_SET= "SearchScopeActionGroup.working_set"; //$NON-NLS-1$ static final int SEARCH_SCOPE_TYPE_WORKSPACE= 1; static final int SEARCH_SCOPE_TYPE_PROJECT= 2; // static final int SEARCH_SCOPE_TYPE_HIERARCHY= 3; static final int SEARCH_SCOPE_TYPE_WORKING_SET= 4; private SearchScopeAction fSelectedAction = null; private String[] fSelectedWorkingSetNames = null; private CallHierarchyViewPart fView; private IDialogSettings fDialogSettings; private SearchScopeProjectAction fSearchScopeProjectAction; private SearchScopeWorkspaceAction fSearchScopeWorkspaceAction; private SelectWorkingSetAction fSelectWorkingSetAction; public SearchScopeActionGroup(CallHierarchyViewPart view, IDialogSettings dialogSettings) { this.fView= view; this.fDialogSettings= dialogSettings; createActions(); } /** * Returns the current search scope. * * @param includeMask the include mask * @return the current search scope * @since 3.7 */ public IJavaSearchScope getSearchScope(int includeMask) { if (fSelectedAction != null) { return fSelectedAction.getSearchScope(includeMask); } return null; } @Override public void fillActionBars(IActionBars actionBars) { super.fillActionBars(actionBars); fillContextMenu(actionBars.getMenuManager()); } protected void setActiveWorkingSets(IWorkingSet[] sets) { if (sets != null) { fSelectedWorkingSetNames = getWorkingSetNames(sets); fSelectedAction = new SearchScopeWorkingSetAction(this, sets, getScopeDescription(sets)); fSelectedAction.run(); } else { fSelectedWorkingSetNames = null; fSelectedAction = null; } } private String[] getWorkingSetNames(IWorkingSet[] sets) { String[] result= new String[sets.length]; for (int i = 0; i < sets.length; i++) { result[i]= sets[i].getName(); } return result; } protected IWorkingSet[] getActiveWorkingSets() { if (fSelectedWorkingSetNames != null) { return getWorkingSets(fSelectedWorkingSetNames); } return null; } private IWorkingSet[] getWorkingSets(String[] workingSetNames) { if (workingSetNames == null) { return null; } Set<IWorkingSet> workingSets= new HashSet<IWorkingSet>(2); for (int j= 0; j < workingSetNames.length; j++) { IWorkingSet workingSet= getWorkingSetManager().getWorkingSet(workingSetNames[j]); if (workingSet != null) { workingSets.add(workingSet); } } return workingSets.toArray(new IWorkingSet[workingSets.size()]); } /** * Sets the new search scope type. * * @param newSelection New action which should be the checked one (can be null iff <code>ignoreUnchecked == false</code>) * @param ignoreUnchecked Ignores actions which are unchecked (necessary since both the old and the new action fires). */ protected void setSelected(SearchScopeAction newSelection, boolean ignoreUnchecked) { if (!ignoreUnchecked || newSelection.isChecked()) { if (newSelection instanceof SearchScopeWorkingSetAction) { fSelectedWorkingSetNames = getWorkingSetNames(((SearchScopeWorkingSetAction) newSelection).getWorkingSets()); } else { fSelectedWorkingSetNames = null; } if (newSelection != null) { fSelectedAction= newSelection; } else { fSelectedAction= fSearchScopeWorkspaceAction; } fDialogSettings.put(DIALOGSTORE_SCOPE_TYPE, getSearchScopeType()); fDialogSettings.put(DIALOGSTORE_SELECTED_WORKING_SET, fSelectedWorkingSetNames); } } protected CallHierarchyViewPart getView() { return fView; } protected IWorkingSetManager getWorkingSetManager() { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench() .getWorkingSetManager(); return workingSetManager; } protected void fillSearchActions(IMenuManager javaSearchMM) { Action[] actions = getActions(); for (int i = 0; i < actions.length; i++) { Action action = actions[i]; if (action.isEnabled()) { javaSearchMM.add(action); } } javaSearchMM.setVisible(!javaSearchMM.isEmpty()); } @Override public void fillContextMenu(IMenuManager menu) { MenuManager javaSearchMM = new MenuManager(CallHierarchyMessages.SearchScopeActionGroup_searchScope, IContextMenuConstants.GROUP_SEARCH); javaSearchMM.setRemoveAllWhenShown(true); javaSearchMM.addMenuListener(new IMenuListener() { /* (non-Javadoc) * @see org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager) */ public void menuAboutToShow(IMenuManager manager) { fillSearchActions(manager); } }); fillSearchActions(javaSearchMM); menu.appendToGroup(IContextMenuConstants.GROUP_SEARCH, javaSearchMM); } private Action[] getActions() { List<Action> actions = new ArrayList<Action>(SearchUtil.LRU_WORKINGSET_LIST_SIZE + 4); addAction(actions, fSearchScopeWorkspaceAction); addAction(actions, fSearchScopeProjectAction); addAction(actions, fSelectWorkingSetAction); Iterator<IWorkingSet[]> iter= SearchUtil.getLRUWorkingSets().sortedIterator(); while (iter.hasNext()) { IWorkingSet[] workingSets= iter.next(); String description = SearchUtil.toString(workingSets); SearchScopeWorkingSetAction workingSetAction = new SearchScopeWorkingSetAction(this, workingSets, description); if (isSelectedWorkingSet(workingSets)) { workingSetAction.setChecked(true); } actions.add(workingSetAction); } Action[] result = actions.toArray(new Action[actions.size()]); ensureExactlyOneCheckedAction(result); return result; } private void ensureExactlyOneCheckedAction(Action[] result) { int checked = getCheckedActionCount(result); if (checked != 1) { if (checked > 1) { for (int i = 0; i < result.length; i++) { Action action = result[i]; action.setChecked(false); } } fSearchScopeWorkspaceAction.setChecked(true); } } private int getCheckedActionCount(Action[] result) { // Ensure that exactly one action is selected int checked= 0; for (int i = 0; i < result.length; i++) { Action action = result[i]; if (action.isChecked()) { checked++; } } return checked; } private void addAction(List<Action> actions, Action action) { if (action == fSelectedAction) { action.setChecked(true); } else { action.setChecked(false); } actions.add(action); } private void createActions() { fSearchScopeWorkspaceAction = new SearchScopeWorkspaceAction(this); fSelectWorkingSetAction = new SelectWorkingSetAction(this); fSearchScopeProjectAction = new SearchScopeProjectAction(this); int searchScopeType; try { searchScopeType= fDialogSettings.getInt(DIALOGSTORE_SCOPE_TYPE); } catch (NumberFormatException e) { searchScopeType= SEARCH_SCOPE_TYPE_WORKSPACE; } String[] workingSetNames= fDialogSettings.getArray(DIALOGSTORE_SELECTED_WORKING_SET); setSelected(getSearchScopeAction(searchScopeType, workingSetNames), false); } public void saveState(IMemento memento) { int type= getSearchScopeType(); memento.putInteger(TAG_SEARCH_SCOPE_TYPE, type); if (type == SEARCH_SCOPE_TYPE_WORKING_SET) { memento.putInteger(TAG_WORKING_SET_COUNT, fSelectedWorkingSetNames.length); for (int i = 0; i < fSelectedWorkingSetNames.length; i++) { String workingSetName = fSelectedWorkingSetNames[i]; memento.putString(TAG_SELECTED_WORKING_SET+i, workingSetName); } } } public void restoreState(IMemento memento) { String[] workingSetNames= null; Integer scopeType= memento.getInteger(TAG_SEARCH_SCOPE_TYPE); if (scopeType != null) { if (scopeType.intValue() == SEARCH_SCOPE_TYPE_WORKING_SET) { Integer workingSetCount= memento.getInteger(TAG_WORKING_SET_COUNT); if (workingSetCount != null) { workingSetNames = new String[workingSetCount.intValue()]; for (int i = 0; i < workingSetCount.intValue(); i++) { workingSetNames[i]= memento.getString(TAG_SELECTED_WORKING_SET+i); } } } setSelected(getSearchScopeAction(scopeType.intValue(), workingSetNames), false); } } private SearchScopeAction getSearchScopeAction(int searchScopeType, String[] workingSetNames) { switch (searchScopeType) { case SEARCH_SCOPE_TYPE_WORKSPACE: return fSearchScopeWorkspaceAction; case SEARCH_SCOPE_TYPE_PROJECT: return fSearchScopeProjectAction; case SEARCH_SCOPE_TYPE_WORKING_SET: IWorkingSet[] workingSets= getWorkingSets(workingSetNames); if (workingSets != null && workingSets.length > 0) { return new SearchScopeWorkingSetAction(this, workingSets, getScopeDescription(workingSets)); } return null; } return null; } private int getSearchScopeType() { if (fSelectedAction != null) { return fSelectedAction.getSearchScopeType(); } return 0; } private String getScopeDescription(IWorkingSet[] workingSets) { return Messages.format(CallHierarchyMessages.WorkingSetScope, new String[] {SearchUtil.toString(workingSets)}); } /** * Determines whether the specified working sets correspond to the currently selected working * sets. * * @param workingSets the array of working sets * @return <code>true</code> if the specified working sets correspond to the currently selected * working sets */ private boolean isSelectedWorkingSet(IWorkingSet[] workingSets) { if (fSelectedWorkingSetNames != null && fSelectedWorkingSetNames.length == workingSets.length) { Set<String> workingSetNames= new HashSet<String>(workingSets.length); for (int i = 0; i < workingSets.length; i++) { workingSetNames.add(workingSets[i].getName()); } for (int i = 0; i < fSelectedWorkingSetNames.length; i++) { if (!workingSetNames.contains(fSelectedWorkingSetNames[i])) { return false; } } return true; } return false; } /** * Fetches the full description of the scope with the appropriate include mask. * * @param includeMask the include mask * @return the description of the scope with the appropriate include mask * @since 3.7 */ public String getFullDescription(int includeMask) { if (fSelectedAction != null) return fSelectedAction.getFullDescription(includeMask); return null; } }