/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.tools.search.internal.ui; import com.google.dart.tools.search.internal.ui.util.SWTUtil; import com.google.dart.tools.search.ui.ISearchPageContainer; import com.google.dart.tools.search.ui.NewSearchUI; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.layout.PixelConverter; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.accessibility.AccessibleAdapter; import org.eclipse.swt.accessibility.AccessibleEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class ScopePart { // Settings store private static final String DIALOG_SETTINGS_KEY = "SearchDialog.ScopePart"; //$NON-NLS-1$ private static final String STORE_SCOPE = "scope"; //$NON-NLS-1$ private static final String STORE_LRU_WORKING_SET_NAME = "lastUsedWorkingSetName"; //$NON-NLS-1$ private static final String STORE_LRU_WORKING_SET_NAMES = "lastUsedWorkingSetNames"; //$NON-NLS-1$ @SuppressWarnings("unchecked") public static String toString(IWorkingSet[] workingSets) { String result = ""; //$NON-NLS-1$ if (workingSets != null && workingSets.length > 0) { Arrays.sort(workingSets, new WorkingSetComparator()); boolean firstFound = false; for (int i = 0; i < workingSets.length; i++) { String workingSetName = workingSets[i].getLabel(); if (firstFound) { result = Messages.format(SearchMessages.ScopePart_workingSetConcatenation, new String[] { result, workingSetName}); } else { result = workingSetName; firstFound = true; } } } return result; } private static int getStoredScope(IDialogSettings settingsStore, boolean canSearchEnclosingProjects) { int scope; try { scope = settingsStore.getInt(STORE_SCOPE); } catch (NumberFormatException ex) { scope = ISearchPageContainer.WORKSPACE_SCOPE; } if (scope != ISearchPageContainer.WORKING_SET_SCOPE && scope != ISearchPageContainer.SELECTION_SCOPE && scope != ISearchPageContainer.SELECTED_PROJECTS_SCOPE && scope != ISearchPageContainer.WORKSPACE_SCOPE) { scope = ISearchPageContainer.WORKSPACE_SCOPE; } if (!canSearchEnclosingProjects && scope == ISearchPageContainer.SELECTED_PROJECTS_SCOPE) { scope = ISearchPageContainer.WORKSPACE_SCOPE; } return scope; } private IDialogSettings fSettingsStore; private Group fPart; // Scope radio buttons private Button fUseWorkspace; private Button fUseSelection; private Button fUseProject; private Button fUseWorkingSet; private int fScope; private boolean fCanSearchEnclosingProjects; private Text fWorkingSetText; private IWorkingSet[] fWorkingSets; // Reference to its search page container (can be null) private SearchDialog fSearchDialog; private boolean fActiveEditorCanProvideScopeSelection; /** * Returns a new scope part with workspace as initial scope. The part is not yet created. * * @param searchDialog The parent container * @param searchEnclosingProjects If true, add the 'search enclosing project' radio button */ public ScopePart(SearchDialog searchDialog, boolean searchEnclosingProjects) { fSearchDialog = searchDialog; fCanSearchEnclosingProjects = searchEnclosingProjects; fSettingsStore = SearchPlugin.getDefault().getDialogSettingsSection(DIALOG_SETTINGS_KEY); fScope = getStoredScope(fSettingsStore, searchEnclosingProjects); fWorkingSets = getStoredWorkingSets(); } /** * Creates this scope part. * * @param parent a widget which will be the parent of the new instance (cannot be null) * @return Returns the created part control */ public Composite createPart(Composite parent) { fPart = new Group(parent, SWT.NONE); fPart.setText(SearchMessages.ScopePart_group_text); GridLayout layout = new GridLayout(); layout.numColumns = 4; fPart.setLayout(layout); fPart.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fUseWorkspace = new Button(fPart, SWT.RADIO); fUseWorkspace.setData(new Integer(ISearchPageContainer.WORKSPACE_SCOPE)); fUseWorkspace.setText(SearchMessages.ScopePart_workspaceScope_text); fUseSelection = new Button(fPart, SWT.RADIO); fUseSelection.setData(new Integer(ISearchPageContainer.SELECTION_SCOPE)); fUseSelection.setText(SearchMessages.ScopePart_selectedResourcesScope_text); boolean canSearchInSelection = canSearchInSelection(); fUseSelection.setEnabled(canSearchInSelection); GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalIndent = 8; fUseSelection.setLayoutData(gd); fUseProject = new Button(fPart, SWT.RADIO); fUseProject.setData(new Integer(ISearchPageContainer.SELECTED_PROJECTS_SCOPE)); fUseProject.setText(SearchMessages.ScopePart_enclosingProjectsScope_text); fUseProject.setEnabled(fSearchDialog.getEnclosingProjectNames().length > 0); gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING); gd.horizontalSpan = 2; gd.horizontalIndent = 8; fUseProject.setLayoutData(gd); if (!fCanSearchEnclosingProjects) { fUseProject.setVisible(false); } fUseWorkingSet = new Button(fPart, SWT.RADIO); fUseWorkingSet.setData(new Integer(ISearchPageContainer.WORKING_SET_SCOPE)); fUseWorkingSet.setText(SearchMessages.ScopePart_workingSetScope_text); fWorkingSetText = new Text(fPart, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY); fWorkingSetText.getAccessible().addAccessibleListener(new AccessibleAdapter() { @Override public void getName(AccessibleEvent e) { e.result = SearchMessages.ScopePart_workingSetText_accessible_label; } }); Button chooseWorkingSet = new Button(fPart, SWT.PUSH); chooseWorkingSet.setLayoutData(new GridData()); chooseWorkingSet.setText(SearchMessages.ScopePart_workingSetChooseButton_text); SWTUtil.setButtonDimensionHint(chooseWorkingSet); chooseWorkingSet.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (handleChooseWorkingSet()) { setSelectedScope(ISearchPageContainer.WORKING_SET_SCOPE); } } }); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalIndent = 8; gd.horizontalSpan = 2; gd.widthHint = new PixelConverter(fWorkingSetText).convertWidthInCharsToPixels(30); fWorkingSetText.setLayoutData(gd); // Add scope change listeners SelectionAdapter scopeChangedLister = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleScopeChanged(e); } }; fUseWorkspace.addSelectionListener(scopeChangedLister); fUseSelection.addSelectionListener(scopeChangedLister); fUseProject.addSelectionListener(scopeChangedLister); fUseWorkingSet.addSelectionListener(scopeChangedLister); // Set initial scope setSelectedScope(fScope); // Set initial working set if (fWorkingSets != null) { fWorkingSetText.setText(toString(fWorkingSets)); } return fPart; } /** * Returns the scope selected in this part * * @return the selected scope */ public int getSelectedScope() { return fScope; } /** * Returns the selected working set of this part. * * @return the selected working set or null - if the scope is not WORKING_SET_SCOPE - if there is * no working set selected */ public IWorkingSet[] getSelectedWorkingSets() { if (getSelectedScope() == ISearchPageContainer.WORKING_SET_SCOPE) { return fWorkingSets; } return null; } public void setActiveEditorCanProvideScopeSelection(boolean state) { fActiveEditorCanProvideScopeSelection = state; fUseSelection.setEnabled(canSearchInSelection()); // Reinitialize the controls fScope = getStoredScope(fSettingsStore, fCanSearchEnclosingProjects); setSelectedScope(fScope); } /** * Sets the selected scope. This method must only be called on a created part. * * @param scope the scope to be selected in this part */ public void setSelectedScope(int scope) { Assert.isLegal(scope >= 0 && scope <= 3); Assert.isNotNull(fUseWorkspace); Assert.isNotNull(fUseSelection); Assert.isNotNull(fUseWorkingSet); Assert.isNotNull(fUseProject); fSettingsStore.put(STORE_SCOPE, scope); if (scope == ISearchPageContainer.SELECTED_PROJECTS_SCOPE) { if (!fCanSearchEnclosingProjects) { SearchPlugin.log(new Status( IStatus.WARNING, NewSearchUI.PLUGIN_ID, IStatus.WARNING, "Enclosing projects scope set on search page that does not support it", null)); //$NON-NLS-1$ scope = ISearchPageContainer.WORKSPACE_SCOPE; } else if (!fUseProject.isEnabled()) { scope = ISearchPageContainer.WORKSPACE_SCOPE; } } else if (scope == ISearchPageContainer.SELECTION_SCOPE && !fUseSelection.isEnabled()) { scope = fUseProject.isEnabled() ? ISearchPageContainer.SELECTED_PROJECTS_SCOPE : ISearchPageContainer.WORKSPACE_SCOPE; } fScope = scope; fUseWorkspace.setSelection(scope == ISearchPageContainer.WORKSPACE_SCOPE); fUseSelection.setSelection(scope == ISearchPageContainer.SELECTION_SCOPE); fUseProject.setSelection(scope == ISearchPageContainer.SELECTED_PROJECTS_SCOPE); fUseWorkingSet.setSelection(scope == ISearchPageContainer.WORKING_SET_SCOPE); updateSearchPageContainerActionPerformedEnablement(); } /** * Sets the selected working set for this part. This method must only be called on a created part. * * @param workingSets the working set to be selected */ public void setSelectedWorkingSets(IWorkingSet[] workingSets) { Assert.isNotNull(workingSets); setSelectedScope(ISearchPageContainer.WORKING_SET_SCOPE); fWorkingSets = null; Set<IWorkingSet> existingWorkingSets = new HashSet<IWorkingSet>(workingSets.length); for (int i = 0; i < workingSets.length; i++) { String name = workingSets[i].getName(); IWorkingSet workingSet = PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSet(name); if (workingSet != null) { existingWorkingSets.add(workingSet); } } if (!existingWorkingSets.isEmpty()) { fWorkingSets = existingWorkingSets.toArray(new IWorkingSet[existingWorkingSets.size()]); } saveState(); if (fWorkingSetText != null) { fWorkingSetText.setText(toString(fWorkingSets)); } } void setVisible(boolean state) { if (state) { fPart.layout(); } fPart.setVisible(state); } private boolean canSearchInSelection() { ISelection selection = fSearchDialog.getSelection(); return (selection instanceof IStructuredSelection) && !selection.isEmpty() || fActiveEditorCanProvideScopeSelection && fSearchDialog.getActiveEditorInput() != null; } private IWorkingSet[] getStoredWorkingSets() { String[] lruWorkingSetNames = fSettingsStore.getArray(STORE_LRU_WORKING_SET_NAMES); IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); if (lruWorkingSetNames != null) { Set<IWorkingSet> existingWorkingSets = new HashSet<IWorkingSet>(lruWorkingSetNames.length); for (int i = 0; i < lruWorkingSetNames.length; i++) { IWorkingSet workingSet = getWorkingSet(workingSetManager, lruWorkingSetNames[i]); if (workingSet != null) { existingWorkingSets.add(workingSet); } } if (!existingWorkingSets.isEmpty()) { return existingWorkingSets.toArray(new IWorkingSet[existingWorkingSets.size()]); } } else { // Backward compatibility String workingSetName = fSettingsStore.get(STORE_LRU_WORKING_SET_NAME); if (workingSetName != null) { IWorkingSet workingSet = getWorkingSet(workingSetManager, workingSetName); if (workingSet != null) { return new IWorkingSet[] {workingSet}; } } } return null; } private IWorkingSet getWorkingSet(IWorkingSetManager workingSetManager, String storedName) { if (storedName.length() == 0) { IWorkbenchPage page = fSearchDialog.getWorkbenchWindow().getActivePage(); if (page != null) { return page.getAggregateWorkingSet(); } return null; } return workingSetManager.getWorkingSet(storedName); } private boolean handleChooseWorkingSet() { IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); IWorkingSetSelectionDialog dialog = workingSetManager.createWorkingSetSelectionDialog( fUseSelection.getShell(), true); if (fWorkingSets != null) { dialog.setSelection(fWorkingSets); } if (dialog.open() == Window.OK) { Object[] result = dialog.getSelection(); if (result.length > 0) { setSelectedWorkingSets((IWorkingSet[]) result); return true; } fWorkingSetText.setText(""); //$NON-NLS-1$ fWorkingSets = null; if (fScope == ISearchPageContainer.WORKING_SET_SCOPE) { setSelectedScope(ISearchPageContainer.WORKSPACE_SCOPE); } return false; } if (fWorkingSets != null) { // test if selected working set has been removed int i = 0; while (i < fWorkingSets.length) { IWorkingSet workingSet = fWorkingSets[i]; if (!workingSet.isAggregateWorkingSet() && workingSetManager.getWorkingSet(workingSet.getName()) == null) { break; } i++; } if (i < fWorkingSets.length) { fWorkingSetText.setText(""); //$NON-NLS-1$ fWorkingSets = null; updateSearchPageContainerActionPerformedEnablement(); } } return false; } private void handleScopeChanged(SelectionEvent e) { Object source = e.getSource(); if (source instanceof Button) { Button button = (Button) source; if (button.getSelection()) { setSelectedScope(((Integer) button.getData()).intValue()); } } } /** * Saves the last recently used working sets, if any. */ private void saveState() { if (fWorkingSets != null && fWorkingSets.length > 0) { String[] existingWorkingSetNames = new String[fWorkingSets.length]; for (int i = 0; i < fWorkingSets.length; i++) { IWorkingSet curr = fWorkingSets[i]; // use empty name for aggregateWS existingWorkingSetNames[i] = curr.isAggregateWorkingSet() ? "" : curr.getName(); //$NON-NLS-1$ } fSettingsStore.put(STORE_LRU_WORKING_SET_NAMES, existingWorkingSetNames); } } private void updateSearchPageContainerActionPerformedEnablement() { fSearchDialog.notifyScopeSelectionChanged(); } }