blob: f09c1593185b8f564c98ed0dfa1f0f863afc73f8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2007 Boeing.
* 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:
* Boeing - initial API and implementation
*******************************************************************************/
package org.eclipse.osee.framework.ui.skynet.search;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import org.eclipse.jface.window.Window;
import org.eclipse.osee.framework.db.connection.exception.OseeCoreException;
import org.eclipse.osee.framework.jdk.core.util.StringFormat;
import org.eclipse.osee.framework.jdk.core.util.Strings;
import org.eclipse.osee.framework.logging.OseeLog;
import org.eclipse.osee.framework.skynet.core.attribute.AttributeType;
import org.eclipse.osee.framework.skynet.core.attribute.AttributeTypeManager;
import org.eclipse.osee.framework.ui.skynet.FrameworkImage;
import org.eclipse.osee.framework.ui.skynet.ImageManager;
import org.eclipse.osee.framework.ui.skynet.SkynetGuiPlugin;
import org.eclipse.osee.framework.ui.skynet.widgets.dialog.AttributeTypeCheckTreeDialog;
import org.eclipse.osee.framework.ui.swt.ALayout;
import org.eclipse.osee.framework.ui.swt.Widgets;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IMemento;
/**
* @author Roberto E. Escobar
*/
public class QuickSearchOptionComposite extends Composite {
private static final String CONFIG_BUTTON_TOOLTIP = "Select to configure option.";
private static final String OPTIONS_KEY_ID = "searchOption";
private static final String OPTION_CONFIGS_KEY_ID = "optionConfigs";
private static final String ENTRY_SEPARATOR = "##";
private Group optionGroup;
private final Map<String, Button> optionsButtons;
private final Map<String, Text> textAreas;
private final Map<String, Boolean> optionsMap;
private final Set<String> mutuallyExclusiveOptionSet;
private final Map<String, IOptionConfigurationHandler> configurableOptionSet;
private Composite wordOrderComposite;
public QuickSearchOptionComposite(Composite parent, int style) {
super(parent, style);
this.optionsButtons = new LinkedHashMap<String, Button>();
this.textAreas = new HashMap<String, Text>();
this.optionsMap = new LinkedHashMap<String, Boolean>();
this.mutuallyExclusiveOptionSet = new HashSet<String>();
this.configurableOptionSet = new HashMap<String, IOptionConfigurationHandler>();
for (String option : SearchOption.asLabels()) {
this.optionsMap.put(option, false);
}
for (String option : SearchOption.getMutuallyExclusiveOptions()) {
this.optionsMap.put(option, false);
this.mutuallyExclusiveOptionSet.add(option);
}
for (String option : SearchOption.getConfigurableOptions().keySet()) {
this.optionsMap.put(option, false);
this.configurableOptionSet.put(option, SearchOption.getConfigurableOptions().get(option));
}
createControl(this);
}
private void createControl(Composite parent) {
this.optionGroup = new Group(parent, SWT.NONE);
this.optionGroup.setLayout(new GridLayout());
this.optionGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
this.optionGroup.setText("Options");
initializeOptions(optionsMap);
for (SearchOption option : SearchOption.values()) {
setHelpContextForOption(option.asLabel(), option.getHelpContext());
setToolTipForOption(option.asLabel(), option.getToolTip());
}
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayout(ALayout.getZeroMarginLayout());
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}
private void updateTextArea(Text text, String[] data) {
text.setText(StringFormat.separateWith(data, ", "));
}
public Map<String, Boolean> getOptions() {
return optionsMap;
}
public Map<String, String[]> getConfigurations() {
Map<String, String[]> toReturn = new HashMap<String, String[]>();
for (String key : configurableOptionSet.keySet()) {
toReturn.put(key, configurableOptionSet.get(key).getConfiguration());
}
return toReturn;
}
public boolean isOptionSelected(String key) {
Boolean value = optionsMap.get(key);
return value != null ? value.booleanValue() : false;
}
public String[] getConfiguration(String key) {
IOptionConfigurationHandler handler = this.configurableOptionSet.get(key);
if (handler != null) {
return handler.getConfiguration();
} else {
return new String[0];
}
}
private void initializeOptions(Map<String, Boolean> options) {
for (String option : options.keySet()) {
Boolean isSelected = options.get(option);
Button button = getOrCreateOptionsButton(option);
button.setSelection(isSelected);
this.optionsMap.put(option, isSelected);
}
updateMatchWordOrderOptions();
}
private void updateMatchWordOrderOptions() {
boolean setEnabled = isMatchWordOrderEnabled();
if (Widgets.isAccessible(wordOrderComposite)) {
wordOrderComposite.setVisible(setEnabled);
wordOrderComposite.setEnabled(setEnabled);
if (!setEnabled) {
optionsMap.put(SearchOption.Case_Sensitive.asLabel(), setEnabled);
optionsMap.put(SearchOption.All_Match_Locations.asLabel(), setEnabled);
} else {
optionsMap.put(SearchOption.Case_Sensitive.asLabel(), optionsButtons.get(
SearchOption.Case_Sensitive.asLabel()).getSelection());
optionsMap.put(SearchOption.All_Match_Locations.asLabel(), optionsButtons.get(
SearchOption.All_Match_Locations.asLabel()).getSelection());
}
optionGroup.getParent().layout();
}
}
private Button getOrCreateOptionsButton(String option) {
Button toReturn = this.optionsButtons.get(option);
if (toReturn == null) {
toReturn = createButton(this.optionGroup, option);
this.optionsButtons.put(option, toReturn);
}
return toReturn;
}
private Button createButton(Composite parent, String option) {
final IOptionConfigurationHandler configHandler = configurableOptionSet.get(option);
Composite mainComposite = parent;
if (configHandler != null) {
mainComposite = new Composite(parent, SWT.NONE);
mainComposite.setLayout(ALayout.getZeroMarginLayout(4, false));
mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
} else if (option.equals(SearchOption.All_Match_Locations.asLabel()) || option.equals(SearchOption.Case_Sensitive.asLabel())) {
if (wordOrderComposite == null) {
wordOrderComposite = new InvisibleComposite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginLeft = 15;
wordOrderComposite.setLayout(layout);
wordOrderComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}
mainComposite = wordOrderComposite;
}
Button toReturn = new Button(mainComposite, SWT.CHECK);
toReturn.setData(option);
toReturn.setFont(getFont());
toReturn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Object object = e.getSource();
if (object instanceof Button) {
Button button = (Button) object;
if (mutuallyExclusiveOptionSet.contains(button.getData())) {
if (button.getSelection()) {
for (String entry : mutuallyExclusiveOptionSet) {
Button other = optionsButtons.get(entry);
if (!other.equals(button)) {
other.setSelection(false);
}
optionsMap.put((String) other.getData(), other.getSelection());
}
}
}
optionsMap.put((String) button.getData(), button.getSelection());
Object data = button.getData();
boolean selection = optionsMap.get(SearchOption.By_Id.asLabel()).booleanValue();
if (data.equals(SearchOption.By_Id.asLabel()) && selection) {
optionsMap.put(SearchOption.Match_Word_Order.asLabel(), false);
optionsButtons.get(SearchOption.Match_Word_Order.asLabel()).setSelection(false);
} else if (data.equals(SearchOption.Match_Word_Order.asLabel()) && selection) {
optionsMap.put(SearchOption.By_Id.asLabel(), false);
optionsButtons.get(SearchOption.By_Id.asLabel()).setSelection(false);
}
updateMatchWordOrderOptions();
}
}
});
if (configHandler != null) {
Label label = new Label(mainComposite, SWT.NONE);
label.setText(option + ":");
final Text text = new Text(mainComposite, SWT.READ_ONLY | SWT.BORDER);
text.setText(StringFormat.separateWith(configHandler.getConfiguration(), ", "));
GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
data.minimumWidth = 100;
text.setLayoutData(data);
textAreas.put(option, text);
Button filterConfig = new Button(mainComposite, SWT.PUSH);
String configToolTip = configHandler.getConfigToolTip();
filterConfig.setToolTipText(Strings.isValid(configToolTip) ? configToolTip : CONFIG_BUTTON_TOOLTIP);
filterConfig.setImage(ImageManager.getImage(FrameworkImage.GEAR));
filterConfig.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (configHandler != null) {
configHandler.configure();
updateTextArea(text, configHandler.getConfiguration());
}
}
});
} else {
toReturn.setText(option);
}
return toReturn;
}
public boolean isSearchByIdEnabled() {
return isOptionSelected(SearchOption.By_Id.asLabel());
}
public boolean isIncludeDeletedEnabled() {
return isOptionSelected(SearchOption.Include_Deleted.asLabel());
}
public boolean isMatchWordOrderEnabled() {
return isOptionSelected(SearchOption.Match_Word_Order.asLabel());
}
public boolean isMatchAllLocationsEnabled() {
return isOptionSelected(SearchOption.All_Match_Locations.asLabel());
}
public boolean isCaseSensitiveEnabled() {
return isOptionSelected(SearchOption.Case_Sensitive.asLabel());
}
public boolean isAttributeTypeFilterEnabled() {
return isOptionSelected(SearchOption.Attribute_Type_Filter.asLabel());
}
public String[] getAttributeTypeFilter() {
return isAttributeTypeFilterEnabled() ? getConfiguration(SearchOption.Attribute_Type_Filter.asLabel()) : null;
}
public void saveState(IMemento memento) {
for (String option : optionsMap.keySet()) {
memento.putString(OPTIONS_KEY_ID + option.replaceAll(" ", "_"), optionsMap.get(option).toString());
}
Map<String, String[]> data = getConfigurations();
for (String key : data.keySet()) {
String[] config = data.get(key);
if (config != null && config.length > 0) {
memento.putString(OPTION_CONFIGS_KEY_ID + key.replaceAll(" ", "_"), StringFormat.separateWith(config,
ENTRY_SEPARATOR));
}
}
}
public void loadState(IMemento memento) {
Map<String, String[]> configs = new HashMap<String, String[]>();
Map<String, Boolean> options = new HashMap<String, Boolean>();
for (SearchOption option : SearchOption.values()) {
options.put(option.asLabel(), new Boolean(memento.getString(OPTIONS_KEY_ID + option.name())));
if (option.isConfigurable()) {
String configuration = memento.getString(OPTION_CONFIGS_KEY_ID + option.name());
if (Strings.isValid(configuration)) {
String[] values = configuration.split(ENTRY_SEPARATOR);
configs.put(option.asLabel(), values);
}
}
}
initializeOptions(options);
initializeConfigurations(configs);
}
private void initializeConfigurations(Map<String, String[]> items) {
for (String key : items.keySet()) {
IOptionConfigurationHandler handler = configurableOptionSet.get(key);
if (handler != null) {
handler.setConfiguration(items.get(key));
Text text = textAreas.get(key);
if (text != null) {
updateTextArea(text, handler.getConfiguration());
}
}
}
}
private void setHelpContextForOption(String optionId, String helpContext) {
Control control = getOrCreateOptionsButton(optionId);
if (Widgets.isAccessible(control)) {
SkynetGuiPlugin.getInstance().setHelp(control, helpContext);
}
}
private void setToolTipForOption(String optionId, String toolTip) {
Control control = getOrCreateOptionsButton(optionId);
if (Widgets.isAccessible(control)) {
control.setToolTipText(toolTip);
}
}
private interface IOptionConfigurationHandler {
public void setConfiguration(String[] strings);
public void configure();
public String[] getConfiguration();
public String getConfigToolTip();
}
private enum SearchOption {
Attribute_Type_Filter("quick_search_attribute_type_filter", "When selected, searches only through the artifact's containing the selected attribute types.", true, new AttributeTypeFilterConfigHandler()),
By_Id("quick_search_by_id_option", "When selected, searches by GUID(s) or HRID(s). Accepts comma or space separated ids.", true),
Include_Deleted("quick_search_deleted_option", "When selected, does not filter out deleted artifacts from search results.", false),
Match_Word_Order("quick_search_word_order_option", "When selected, search will match query word order.", false),
All_Match_Locations("quick_search_all_match_locations_option", "When selected, returns all match locations. NOTE: If the search matches many artifacts, performance may be slow.", false),
Case_Sensitive("quick_search_case_sensitive_option", "When selected, performs a case sensitive search. NOTE: This is only applicable if match word order is also selected.", false);
private static String[] labels = null;
private static String[] mutuallyExclusive = null;
private static Map<String, IOptionConfigurationHandler> configurable = null;
private final String helpContext;
private final String toolTip;
private final boolean isRadio;
private final IOptionConfigurationHandler configHandler;
SearchOption(String helpContext, String toolTip, boolean isRadio) {
this(helpContext, toolTip, isRadio, null);
}
SearchOption(String helpContext, String toolTip, boolean isRadio, IOptionConfigurationHandler configHandler) {
this.helpContext = "";
this.toolTip = toolTip;
this.isRadio = isRadio;
this.configHandler = configHandler;
}
public String asLabel() {
return name().replaceAll("_", " ");
}
public String getHelpContext() {
return helpContext;
}
public String getToolTip() {
return toolTip;
}
public boolean isConfigurable() {
return configHandler != null;
}
public IOptionConfigurationHandler getConfigHandler() {
return configHandler;
}
public static String[] getMutuallyExclusiveOptions() {
if (mutuallyExclusive == null) {
List<String> exclusiveOptions = new ArrayList<String>();
for (SearchOption option : SearchOption.values()) {
if (option.isRadio) {
exclusiveOptions.add(option.asLabel());
}
}
mutuallyExclusive = exclusiveOptions.toArray(new String[exclusiveOptions.size()]);
}
return mutuallyExclusive;
}
public static Map<String, IOptionConfigurationHandler> getConfigurableOptions() {
if (configurable == null) {
configurable = new HashMap<String, IOptionConfigurationHandler>();
for (SearchOption option : SearchOption.values()) {
if (option.isConfigurable()) {
configurable.put(option.asLabel(), option.getConfigHandler());
}
}
}
return configurable;
}
public static String[] asLabels() {
if (labels == null) {
SearchOption[] options = SearchOption.values();
labels = new String[options.length];
for (int index = 0; index < options.length; index++) {
labels[index] = options[index].asLabel();
}
}
return labels;
}
}
private final static class AttributeTypeFilterConfigHandler implements IOptionConfigurationHandler {
private final List<String> configuration;
public AttributeTypeFilterConfigHandler() {
this.configuration = new ArrayList<String>();
this.configuration.add(getDefault());
}
/* (non-Javadoc)
* @see org.eclipse.osee.framework.ui.skynet.panels.SearchComposite.IOptionConfigurationHandler#configure()
*/
@Override
public void configure() {
try {
Collection<AttributeType> taggableItems = AttributeTypeManager.getTaggableTypes();
AttributeTypeCheckTreeDialog dialog = new AttributeTypeCheckTreeDialog(taggableItems);
dialog.setTitle("Attribute Type Filter Selection");
dialog.setMessage("Select attribute types to search in.");
List<AttributeType> selectedElements = new ArrayList<AttributeType>();
if (configuration.contains("All")) {
selectedElements.addAll(taggableItems);
} else {
for (AttributeType type : taggableItems) {
if (configuration.contains(type.getName())) {
selectedElements.add(type);
}
}
}
dialog.setInitialElementSelections(selectedElements);
int result = dialog.open();
if (result == Window.OK) {
configuration.clear();
Collection<AttributeType> results = dialog.getSelection();
if (org.eclipse.osee.framework.jdk.core.util.Collections.setComplement(taggableItems, results).isEmpty()) {
// All were selected
configuration.add("All");
} else {
for (AttributeType selected : results) {
configuration.add(selected.getName());
}
if (configuration.isEmpty()) {
configuration.add(getDefault());
}
}
}
Collections.sort(configuration);
} catch (OseeCoreException ex) {
OseeLog.log(SkynetGuiPlugin.class, Level.SEVERE, ex);
}
}
/* (non-Javadoc)
* @see org.eclipse.osee.framework.ui.skynet.panels.SearchComposite.IOptionConfigurationHandler#getConfigToolTip()
*/
@Override
public String getConfigToolTip() {
return "Select to configure attribute type filter.";
}
/* (non-Javadoc)
* @see org.eclipse.osee.framework.ui.skynet.panels.SearchComposite.IOptionConfigurationHandler#getConfiguration()
*/
@Override
public String[] getConfiguration() {
if (configuration.isEmpty()) {
configuration.add(getDefault());
}
return configuration.toArray(new String[configuration.size()]);
}
public String getDefault() {
return "Name";
}
/* (non-Javadoc)
* @see org.eclipse.osee.framework.ui.skynet.panels.SearchComposite.IOptionConfigurationHandler#setConfiguration(java.lang.String[])
*/
@Override
public void setConfiguration(String[] items) {
if (items != null) {
configuration.clear();
for (String entry : items) {
configuration.add(entry);
}
}
if (configuration.isEmpty()) {
configuration.add(getDefault());
}
}
}
private final class InvisibleComposite extends Composite {
public InvisibleComposite(Composite parent, int style) {
super(parent, style);
}
@Override
public Point computeSize(int wHint, int hHint, boolean changed) {
if (!isVisible()) {
return new Point(0, 0);
} else {
return super.computeSize(wHint, hHint, changed);
}
}
}
}