/******************************************************************************* * 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.callhierarchy; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.eclipse.dltk.core.IDLTKLanguageToolkit; import org.eclipse.dltk.core.search.IDLTKSearchScope; import org.eclipse.dltk.internal.corext.util.Messages; import org.eclipse.dltk.ui.IContextMenuConstants; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; 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; public abstract 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 SearchScopeHierarchyAction fSearchScopeHierarchyAction; private SearchScopeProjectAction fSearchScopeProjectAction; private SearchScopeWorkspaceAction fSearchScopeWorkspaceAction; private SelectWorkingSetAction fSelectWorkingSetAction; public SearchScopeActionGroup(CallHierarchyViewPart view, IDialogSettings dialogSettings) { this.fView = view; this.fDialogSettings = dialogSettings; createActions(); } /** * @return IJavaSearchScope */ public IDLTKSearchScope getSearchScope() { if (fSelectedAction != null) { return fSelectedAction.getSearchScope(); } return null; } @Override public void fillActionBars(IActionBars actionBars) { super.fillActionBars(actionBars); fillContextMenu(actionBars.getMenuManager()); } protected abstract IDLTKLanguageToolkit getLangaugeToolkit(); protected void setActiveWorkingSets(IWorkingSet[] sets) { if (sets != null) { fSelectedWorkingSetNames = getWorkingSetNames(sets); fSelectedAction = new SearchScopeWorkingSetAction(this, sets, getScopeDescription(sets)); } 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<>(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 * @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) { menu.add(new Separator(IContextMenuConstants.GROUP_SEARCH)); MenuManager javaSearchMM = new MenuManager( CallHierarchyMessages.SearchScopeActionGroup_searchScope, IContextMenuConstants.GROUP_SEARCH); javaSearchMM.setRemoveAllWhenShown(true); javaSearchMM.addMenuListener(manager -> fillSearchActions(manager)); fillSearchActions(javaSearchMM); menu.appendToGroup(IContextMenuConstants.GROUP_SEARCH, javaSearchMM); } private Action[] getActions() { List<Action> actions = new ArrayList<>( SearchUtil.LRU_WORKINGSET_LIST_SIZE + 4); addAction(actions, fSearchScopeWorkspaceAction); addAction(actions, fSearchScopeProjectAction); addAction(actions, fSearchScopeHierarchyAction); addAction(actions, fSelectWorkingSetAction); Iterator iter = SearchUtil.getLRUWorkingSets().sortedIterator(); while (iter.hasNext()) { IWorkingSet[] workingSets = (IWorkingSet[]) 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 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); fSearchScopeHierarchyAction = new SearchScopeHierarchyAction(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_HIERARCHY: return fSearchScopeHierarchyAction; 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 * @return Returns true 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<>(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; } public String getFullDescription() { if (fSelectedAction != null) return fSelectedAction.getFullDescription(); return null; } }