/******************************************************************************* * Copyright (c) 2004, 2010 BREDEX GmbH. * 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: * BREDEX GmbH - initial API and implementation and/or initial documentation *******************************************************************************/ package org.eclipse.jubula.client.ui.rcp.search.page; import java.util.List; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.beans.PojoObservables; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.jface.databinding.swt.WidgetProperties; import org.eclipse.jface.dialogs.DialogPage; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jubula.client.core.persistence.GeneralStorage; import org.eclipse.jubula.client.ui.constants.ContextHelpIds; import org.eclipse.jubula.client.ui.rcp.Plugin; import org.eclipse.jubula.client.ui.rcp.i18n.Messages; import org.eclipse.jubula.client.ui.rcp.search.data.FieldName; import org.eclipse.jubula.client.ui.rcp.search.data.SearchOptions; import org.eclipse.jubula.client.ui.rcp.search.data.TypeName; import org.eclipse.jubula.client.ui.utils.LayoutUtil; import org.eclipse.search.ui.ISearchPage; import org.eclipse.search.ui.ISearchPageContainer; import org.eclipse.search.ui.ISearchQuery; import org.eclipse.search.ui.NewSearchUI; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; /** * @author BREDEX GmbH * @created Jul 26, 2010 */ public abstract class AbstractSearchPage extends DialogPage implements ISearchPage, SelectionListener { /** number of columns = 4 */ private static final int NUM_COLUMNS = 4; /** vertical spacing */ private static final int VERTICAL_SPACING = 10; /** search Text Field */ private Combo m_searchStringCombo; /** CheckbBox to select use regular expression */ private Button m_useRegExCheck; /** CheckbBox to select use search case sensitive */ private Button m_caseSensitivCheck; /** group named "Use Selection In" */ private Group m_groupUseSelection; /** CheckbBox to select use search in test suit browser */ private Button m_scopeTestSuitBrowserCheck; /** CheckbBox to select use search in test case browser */ private Button m_scopeTestCaseBrowserCheck; /** radio button to select use search in selected nodes */ private Button m_scopeWholeProjectRadio; /** radio button to select use search in selected nodes */ private Button m_scopeSelectedNodesRadio; /** radio button to select use search in master test case browser */ private Button m_scopeTestCaseBrowserMasterRadio; /** radio button to select use search in all test case browser */ private Button m_scopeTestCaseBrowserAllRadio; /** Check box to select searching in reused Projects. */ private Button m_scopeSearchInReusedProjects; /** {@inheritDoc} */ public void createControl(Composite parent) { getButtonSelections().reset(); Composite pageContent = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = NUM_COLUMNS; layout.verticalSpacing = VERTICAL_SPACING; layout.marginWidth = LayoutUtil.MARGIN_WIDTH; layout.marginHeight = LayoutUtil.MARGIN_HEIGHT; pageContent.setLayout(layout); Label findLabel = new Label(pageContent, SWT.NONE); findLabel.setText(Messages.SimpleSearchPageSearch); m_searchStringCombo = new Combo(pageContent, SWT.BORDER); m_searchStringCombo.setLayoutData( createGridData(NUM_COLUMNS - 1, true)); m_searchStringCombo.setItems( getSearchData().getRecent().toArray( new String[getSearchData().getRecent().size()])); if (m_searchStringCombo.getItemCount() == 0) { m_searchStringCombo.setText(Messages.SimpleSearchPagePhrase); } else { m_searchStringCombo.select(0); } // select the hole search text m_searchStringCombo.setSelection( new Point(0, m_searchStringCombo.getTextLimit())); m_searchStringCombo.forceFocus(); // create the group boxes for search DataBindingContext dbc = new DataBindingContext(); createSearchOptionsGroup(pageContent); createSearchInGroup(dbc, pageContent); createSearchForGroup(dbc, pageContent); createScopeGroup(dbc, pageContent); dbc.updateTargets(); setControl(pageContent); setEnabledButtons(); Plugin.getHelpSystem().setHelp(parent, ContextHelpIds.FIND_DIALOG); } /** * creates the Direction Group * @param parent the parent to use */ private void createSearchOptionsGroup(Composite parent) { Group group = createGroup( parent, Messages.SimpleSearchPageOptionGroupHeader, 2); group.setLayoutData(createGridData(NUM_COLUMNS, true)); m_caseSensitivCheck = createCheck( group, Messages.SimpleSearchPageCaseSen, false); m_useRegExCheck = createCheck( group, Messages.SimpleSearchPageRegEx, false); } /** * Create search for group. Subclasses may override. * * @param dbc * The data binding context. * @param parent * the parent */ private void createSearchForGroup(DataBindingContext dbc, Composite parent) { Group group = createGroup(parent, Messages.SimpleSearchPageSearchForGroupHeader, 3); group.setLayoutData(createGridData(NUM_COLUMNS, true)); for (TypeName searchableType : getSearchData().getSearchableTypes()) { createTypeCheck(dbc, group, searchableType); } } /** * Create search in group. Subclasses may override. * * @param dbc * The data binding context. * @param parent * the parent */ private void createSearchInGroup(DataBindingContext dbc, Composite parent) { final FieldName[] searchableFieldNames = getSearchData().getSearchableFieldNames(); if (searchableFieldNames != null) { Group group = createGroup(parent, Messages.SimpleSearchPageSearchInGroupHeader, 3); group.setLayoutData(createGridData(NUM_COLUMNS, true)); for (FieldName searchableField : searchableFieldNames) { createFieldCheck(dbc, group, searchableField); } } } /** * subclasses may override * @param dbc The data binding context. * @param parent the parent */ private void createScopeGroup(DataBindingContext dbc, Composite parent) { Group group = createGroup( parent, Messages.SimpleSearchPageScope, 3); group.setLayoutData(createGridData(4, true)); m_scopeWholeProjectRadio = createRadio( group, Messages.SimpleSearchPageScopeWholeProject, true); m_scopeWholeProjectRadio.addSelectionListener(this); m_scopeSelectedNodesRadio = createRadio( group, Messages.SimpleSearchPageScopeSelectedNodes, false); m_scopeSelectedNodesRadio.addSelectionListener(this); m_scopeSearchInReusedProjects = createCheck( group, Messages.SimpleSearchPageScopeSearchInReusedProjects, false); m_groupUseSelection = createGroup( group, Messages.SimpleSearchPageScopeUseSelectionIn, 3); m_scopeTestSuitBrowserCheck = createCheck( m_groupUseSelection, Messages.SimpleSearchPageScopeTestSuiteBrowserCheck, true); m_scopeTestSuitBrowserCheck.setLayoutData(createGridData(2, true)); m_scopeTestCaseBrowserCheck = createCheck( m_groupUseSelection, Messages.SimpleSearchPageScopeTestCaseBrowserCheck, true); m_scopeTestCaseBrowserCheck.setLayoutData(createGridData(3, true)); m_scopeTestCaseBrowserCheck.addSelectionListener(this); m_scopeTestSuitBrowserCheck.addSelectionListener(this); m_scopeTestCaseBrowserMasterRadio = createRadio( m_groupUseSelection, Messages.SimpleSearchPageScopeTestCaseBrowserMainRadio, true); GridData gridData = createGridData(1, false); gridData.horizontalIndent = 20; m_scopeTestCaseBrowserMasterRadio.setLayoutData(gridData); m_scopeTestCaseBrowserAllRadio = createRadio( m_groupUseSelection, Messages.SimpleSearchPageScopeTestCaseBrowserAllRadio, false); } /** * @param dbc * the data binding context * @param parent * the parent * @param searchableType * the type to search for */ private void createTypeCheck(DataBindingContext dbc, Composite parent, TypeName searchableType) { Button check = new Button(parent, SWT.CHECK); GridData gd = new GridData(GridData.FILL_HORIZONTAL); check.setLayoutData(gd); check.setText(searchableType.getName()); IObservableValue guiElement = WidgetProperties.selection() .observe(check); IObservableValue modelElement = PojoObservables.observeValue( searchableType, "selected"); //$NON-NLS-1$ dbc.bindValue(guiElement, modelElement); } /** * @param dbc * the data binding context * @param parent * the parent * @param searchableField * the type to search for */ private void createFieldCheck(DataBindingContext dbc, Composite parent, FieldName searchableField) { Button check = new Button(parent, SWT.CHECK); GridData gd = new GridData(GridData.FILL_HORIZONTAL); check.setLayoutData(gd); check.setText(searchableField.getDescName()); IObservableValue guiElement = WidgetProperties.selection() .observe(check); IObservableValue modelElement = PojoObservables.observeValue( searchableField, "selected"); //$NON-NLS-1$ dbc.bindValue(guiElement, modelElement); } /** * @param horizontalSpan * the horizontal column span * @param grabHorizontal * set to true to grabExcessHorizontalSpace * @return a valid grid data */ private GridData createGridData( int horizontalSpan, boolean grabHorizontal) { GridData gd = GridDataFactory.fillDefaults().create(); gd.horizontalSpan = horizontalSpan; gd.grabExcessHorizontalSpace = grabHorizontal; return gd; } /** * Create a group box used for options with three columns. * @param parent The parent. * @param header The header text. * @param columns The number of columns. * @return The created group option box with the given parent, header text, * and number of columns. */ private Group createGroup(Composite parent, String header, int columns) { Group group = new Group(parent, SWT.NONE); group.setText(header); GridLayout layout = new GridLayout(); layout.numColumns = columns; layout.verticalSpacing = VERTICAL_SPACING; layout.marginWidth = LayoutUtil.MARGIN_WIDTH; layout.marginHeight = LayoutUtil.MARGIN_HEIGHT; group.setLayout(layout); group.setLayoutData(createGridData(columns, true)); return group; } /** * @param parent The parent. * @param text The text. * @param isSelected True, if the radio button is selected, otherwise False. * @return A radio button with the given parent, text and selected state. */ private Button createRadio( Composite parent, String text, boolean isSelected) { return createButton(parent, SWT.RADIO, text, isSelected); } /** * @param parent The parent. * @param text The text. * @param isSelected True, if the check box is selected, otherwise False. * @return A check box with the given parent, text, and selected state. */ private Button createCheck( Composite parent, String text, boolean isSelected) { return createButton(parent, SWT.CHECK, text, isSelected); } /** * @param parent The parent. * @param style The style of the button, e.g. * {@link SWT#CHECK} or {@link SWT#RADIO} * @param text The text. * @param isSelected True, if the radio button is selected, otherwise False. * @return A radio button with the given parent, text and selected state. */ private Button createButton( Composite parent, int style, String text, boolean isSelected) { Button button = new Button(parent, style); button.setText(text); getButtonSelections().next(button, isSelected); return button; } /** * @param e The event. */ public void widgetSelected(SelectionEvent e) { // ensure that Test Suite Browser or Test Case Browser is selected if (!m_scopeTestSuitBrowserCheck.getSelection() && !m_scopeTestCaseBrowserCheck.getSelection()) { if (e.getSource() == m_scopeTestCaseBrowserCheck) { m_scopeTestSuitBrowserCheck.setSelection(true); notifySelectionListener(m_scopeTestSuitBrowserCheck); } else if (e.getSource() == m_scopeTestSuitBrowserCheck) { m_scopeTestCaseBrowserCheck.setSelection(true); notifySelectionListener(m_scopeTestCaseBrowserCheck); } } setEnabledButtons(); } /** * @param button The button to notify listeners on. */ private static void notifySelectionListener(Button button) { Event event = new Event(); event.type = SWT.Selection; event.widget = button; button.notifyListeners(SWT.Selection, event); } /** * Validate the selection to enable and disable options. */ private void setEnabledButtons() { // enable "Use selection" group only, if selected nodes is checked setChildrenEnabled( m_groupUseSelection, m_scopeSelectedNodesRadio.getSelection()); if (!m_scopeTestCaseBrowserCheck.getSelection()) { // master is activated, if TCB is checked m_scopeTestCaseBrowserMasterRadio.setEnabled(false); // all only activated, if both TCB and selected nodes are checked m_scopeTestCaseBrowserAllRadio.setEnabled(false); } } /** * Set all children of a composite enabled or disabled. * @param composite The composite, e.g. a group. * @param isEnabled True, if content will be enabled, otherwise false. */ private void setChildrenEnabled(Composite composite, boolean isEnabled) { for (Control child : composite.getChildren()) { child.setEnabled(isEnabled); } } /** * @param e The event. */ public void widgetDefaultSelected(SelectionEvent e) { // do nothing } /** {@inheritDoc} */ public boolean performAction() { getButtonSelections().store(); if (GeneralStorage.getInstance().getProject() != null) { // fill search data from search dialog SearchOptions searchData = getSearchData(); searchData.setData( m_searchStringCombo.getText(), m_caseSensitivCheck.getSelection(), m_useRegExCheck.getSelection(), m_scopeSelectedNodesRadio.getSelection(), m_scopeTestSuitBrowserCheck.getSelection(), m_scopeTestCaseBrowserCheck.getSelection(), m_scopeTestCaseBrowserAllRadio.getSelection(), m_scopeSearchInReusedProjects.getSelection()); List<String> recent = searchData.getRecent(); m_searchStringCombo.setItems( recent.toArray(new String[recent.size()])); m_searchStringCombo.select(0); m_searchStringCombo.setFocus(); // do search NewSearchUI.runQueryInBackground(getNewQuery()); } return true; } /** {@inheritDoc} */ public void setContainer(ISearchPageContainer container) { // no container support yet } /** * @return The class storing the checked state of components. */ protected abstract ButtonSelections getButtonSelections(); /** * @return The search data for the search page. */ protected abstract SearchOptions getSearchData(); /** * @return A new search query for the search page. */ protected abstract ISearchQuery getNewQuery(); }