/******************************************************************************* * 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.search.internal.ui; import java.util.Arrays; import java.util.HashSet; import java.util.Set; 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.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.ui.IWorkbenchPage; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.IWorkingSetManager; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog; import org.eclipse.search.internal.ui.util.SWTUtil; import org.eclipse.search.ui.ISearchPageContainer; import org.eclipse.search.ui.NewSearchUI; 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$ 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(); } 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 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 IWorkingSet[] getStoredWorkingSets() { String[] lruWorkingSetNames= fSettingsStore.getArray(STORE_LRU_WORKING_SET_NAMES); IWorkingSetManager workingSetManager= PlatformUI.getWorkbench().getWorkingSetManager(); if (lruWorkingSetNames != null) { Set existingWorkingSets= new HashSet(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 (IWorkingSet[]) 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; } /** * Returns the scope selected in this part * * @return the selected scope */ public int getSelectedScope() { return 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(); } public void setActiveEditorCanProvideScopeSelection(boolean state) { fActiveEditorCanProvideScopeSelection= state; fUseSelection.setEnabled(canSearchInSelection()); // Reinitialize the controls fScope= getStoredScope(fSettingsStore, fCanSearchEnclosingProjects); setSelectedScope(fScope); } private void updateSearchPageContainerActionPerformedEnablement() { fSearchDialog.notifyScopeSelectionChanged(); } /** * 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; } /** * 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 existingWorkingSets= new HashSet(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= (IWorkingSet[]) existingWorkingSets.toArray(new IWorkingSet[existingWorkingSets.size()]); saveState(); if (fWorkingSetText != null) fWorkingSetText.setText(toString(fWorkingSets)); } /** * 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); } } /** * 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; } private boolean canSearchInSelection() { ISelection selection= fSearchDialog.getSelection(); return (selection instanceof IStructuredSelection) && !selection.isEmpty() || fActiveEditorCanProvideScopeSelection && fSearchDialog.getActiveEditorInput() != null; } 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()); } } 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; } void setVisible(boolean state) { if (state) fPart.layout(); fPart.setVisible(state); } 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; } }