/*
* Carrot2 project.
*
* Copyright (C) 2002-2016, Dawid Weiss, Stanisław Osiński.
* All rights reserved.
*
* Refer to the full license file "carrot2.LICENSE"
* in the root folder of the repository checkout or at:
* http://www.carrot2.org/carrot2.LICENSE
*/
package org.carrot2.workbench.core.ui;
import java.io.IOException;
import java.util.*;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.carrot2.core.*;
import org.carrot2.core.attribute.Processing;
import org.carrot2.util.attribute.*;
import org.carrot2.util.attribute.BindableDescriptor.GroupingMethod;
import org.carrot2.workbench.core.WorkbenchCorePlugin;
import org.carrot2.workbench.core.helpers.*;
import org.carrot2.workbench.core.preferences.PreferenceConstants;
import org.carrot2.workbench.core.ui.actions.ActiveSearchEditorActionDelegate;
import org.carrot2.workbench.core.ui.actions.GroupingMethodAction;
import org.carrot2.workbench.core.ui.widgets.CScrolledComposite;
import org.carrot2.workbench.editors.AttributeEvent;
import org.carrot2.workbench.editors.AttributeListenerAdapter;
import org.eclipse.core.commands.operations.OperationStatus;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.action.*;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.*;
import org.eclipse.ui.part.ViewPart;
import org.carrot2.shaded.guava.common.base.Predicate;
import org.carrot2.shaded.guava.common.base.Predicates;
import org.carrot2.shaded.guava.common.collect.Lists;
import org.carrot2.shaded.guava.common.collect.Maps;
/**
* The search view defines a combination of source, algorithm and required input
* parameters required to open a new editor.
*/
public class SearchInputView extends ViewPart
{
/**
* Public identifier of this view.
*/
public static final String ID = "org.carrot2.workbench.core.views.search";
/**
* Filter showing only required attributes.
*/
private final static Predicate<AttributeDescriptor> SHOW_REQUIRED = new AnnotationsPredicate(
false, Required.class);
/**
* Filter showing all attributes.
*/
private final static Predicate<AttributeDescriptor> SHOW_ALL = Predicates
.alwaysTrue();
/**
* State persistence.
*/
private SearchInputViewMemento state;
private ComboViewer sourceViewer;
private ComboViewer algorithmViewer;
private Button processButton;
/**
* Scroller composite container.
*/
private CScrolledComposite scroller;
/**
* A composite holding holding an {@link AttributeGroups} (editors for the current
* combination of input/ source).
*/
private Composite editorCompositeContainer;
/**
* The current editor composite.
*/
private AttributeGroups attributeGroups;
/**
* A joint set of attributes for all sources from and default attribute values for
* algorithms.
*/
private final AttributeValueSet attributes = new AttributeValueSet("global");
/**
* A map of {@link BindableDescriptor} for each document source ID and
* algorithm ID from {@link WorkbenchCorePlugin#getComponentSuite()}.
*/
private Map<String, BindableDescriptor> descriptors = Maps.newHashMap();
/**
* All {@link DocumentSourceDescriptor}s related to {@link IDocumentSource}s in
* {@link #sourceViewer}.
*/
private HashMap<String, DocumentSourceDescriptor> sources;
/**
* All {@link ProcessingComponentDescriptor}s related to {@link IClusteringAlgorithm}s
* in {@link #algorithmViewer}.
*/
private HashMap<String, ProcessingComponentDescriptor> algorithms;
/**
* Link the GUI with currently selected editor.
*/
private boolean linkWithEditor = false;
/**
* Selection listener on {@link #sourceViewer}.
*/
private ISelectionChangedListener sourceSelectionListener = new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
final DocumentSourceDescriptor impl = (DocumentSourceDescriptor) ((IStructuredSelection) event
.getSelection()).getFirstElement();
setSourceId(impl.getId());
}
};
/*
*
*/
private IAction linkWithEditorAction;
/**
* Validation validationStatus.
*/
private CLabel validationStatus;
/**
* If <code>true</code>, validation validationStatus is immediately propagated to
* the user interface (this happens after the first click on {@link #processButton}.
*/
private boolean showValidationStatus;
/*
*
*/
private Image errorStatusImage = WorkbenchCorePlugin.getImageDescriptor(
"icons/error.png").createImage();
/**
* Link the GUI of {@link SearchInputView} with the currently active
* {@link SearchEditor}.
*/
private class LinkWithEditorActionDelegate extends ActiveSearchEditorActionDelegate
{
/* */
@Override
protected void run(SearchEditor editor)
{
linkWithEditor = !linkWithEditor;
super.getAction().setChecked(linkWithEditor);
if (linkWithEditor)
{
if (isEnabled(getEditor()))
{
linkWith((SearchEditor) getEditor());
}
}
}
/**
* Is this action enabled for the given editor?
*/
protected boolean isEnabled(IEditorPart activeEditor)
{
return activeEditor != null && activeEditor instanceof SearchEditor;
}
/**
* Detect editor switch.
*/
@Override
protected void switchingEditors(IEditorPart previous, IEditorPart activeEditor)
{
super.switchingEditors(previous, activeEditor);
if (activeEditor != null && linkWithEditor)
{
final SearchEditor editor = (SearchEditor) activeEditor;
linkWith(editor);
}
}
/**
* Synchronize the view with the given editor.
*/
private void linkWith(SearchEditor editor)
{
final SearchInput input = editor.getSearchResult().getInput();
setAlgorithmId(input.getAlgorithmId());
attributes.setAttributeValues(input.getAttributeValueSet()
.getAttributeValues());
setSourceId(input.getSourceId());
}
}
/**
* Toggles between {@link SearchInputView#SHOW_REQUIRED} and
* {@link SearchInputView#SHOW_ALL}.
*/
private static class ShowOptionalAction extends Action
{
public ShowOptionalAction()
{
super("Show optional attributes", SWT.TOGGLE);
setImageDescriptor(WorkbenchCorePlugin.getImageDescriptor("icons/optional.png"));
/*
* Subscribe to change events on the global preference property and update
* initial state.
*/
final IPreferenceStore preferenceStore = WorkbenchCorePlugin.getDefault()
.getPreferenceStore();
preferenceStore.addPropertyChangeListener(new IPropertyChangeListener()
{
public void propertyChange(PropertyChangeEvent event)
{
if (PreferenceConstants.SHOW_OPTIONAL.equals(event.getProperty()))
{
updateState();
}
}
});
updateState();
}
/*
* Update selection state.
*/
private void updateState()
{
final boolean state = WorkbenchCorePlugin.getDefault().getPreferenceStore()
.getBoolean(PreferenceConstants.SHOW_OPTIONAL);
setChecked(state);
}
@Override
public void run()
{
final IPreferenceStore preferenceStore = WorkbenchCorePlugin.getDefault()
.getPreferenceStore();
final boolean state = preferenceStore
.getBoolean(PreferenceConstants.SHOW_OPTIONAL);
preferenceStore.setValue(PreferenceConstants.SHOW_OPTIONAL, !state);
}
}
/*
*
*/
@Override
public void init(IViewSite site) throws PartInitException
{
super.init(site);
/*
* Create toolbar and menu contributions.
*/
final IActionBars bars = getViewSite().getActionBars();
createToolbar(bars.getToolBarManager());
bars.updateActionBars();
}
/*
*
*/
@Override
public void init(IViewSite site, IMemento memento) throws PartInitException
{
super.init(site, memento);
this.state = null;
try
{
if (memento != null)
{
this.state = SimpleXmlMemento.getChild(SearchInputViewMemento.class, memento);
}
}
catch (IOException e)
{
Utils.logError(e, false);
this.state = null;
}
}
/*
*
*/
private void createToolbar(IToolBarManager toolBarManager)
{
// Link with editor action.
final IAction linkWithEditor = new ActionDelegateProxy(
new LinkWithEditorActionDelegate(), IAction.AS_CHECK_BOX);
linkWithEditor.setImageDescriptor(WorkbenchCorePlugin
.getImageDescriptor("icons/link_e.png"));
linkWithEditor.setToolTipText("Link the interface with current editor");
toolBarManager.add(linkWithEditor);
this.linkWithEditorAction = linkWithEditor;
// Optional attributes action toggle.
final IAction showRequiredOnly = new ShowOptionalAction();
toolBarManager.add(showRequiredOnly);
// Grouping method action.
toolBarManager.add(new GroupingMethodAction(
PreferenceConstants.GROUPING_INPUT_VIEW));
// Add save attributes action.
toolBarManager.add(new SaveDocumentSourceAttributesAction(this));
}
/**
* Create user interface for the view.
*/
@Override
public void createPartControl(Composite parent)
{
/*
* Create GUI components.
*/
createComponents(parent);
/*
* Hook processing event to the processing button and on traversal (when all
* attributes are given).
*/
processButton.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
final String source = getSourceId();
if (hasAllRequiredAttributes(source))
{
fireProcessing();
}
else
{
showValidationStatus = true;
checkAllRequiredAttributes();
}
}
});
parent.addTraverseListener(new TraverseListener()
{
public void keyTraversed(TraverseEvent e)
{
if (e.detail == SWT.TRAVERSE_RETURN)
{
/*
* Consume the traversal event, spawn a new editor.
*/
e.doit = false;
e.detail = SWT.TRAVERSE_NONE;
fireProcessing();
}
}
});
/*
* Hook global preference updates.
*/
final IPreferenceStore preferenceStore = WorkbenchCorePlugin.getDefault()
.getPreferenceStore();
preferenceStore.addPropertyChangeListener(new PropertyChangeListenerAdapter(
PreferenceConstants.SHOW_OPTIONAL)
{
public void propertyChangeFiltered(PropertyChangeEvent event)
{
displayEditorSet();
}
});
preferenceStore.addPropertyChangeListener(new PropertyChangeListenerAdapter(
PreferenceConstants.GROUPING_INPUT_VIEW)
{
public void propertyChangeFiltered(PropertyChangeEvent event)
{
displayEditorSet();
}
});
}
/**
* Display a new composite with editors for the current combination of the source,
* algorithm and grouping/ filtering flags.
*/
private void displayEditorSet()
{
final IPreferenceStore preferenceStore = WorkbenchCorePlugin.getDefault()
.getPreferenceStore();
final Predicate<AttributeDescriptor> filter;
if (preferenceStore.getBoolean(PreferenceConstants.SHOW_OPTIONAL))
{
filter = SHOW_ALL;
}
else
{
filter = SHOW_REQUIRED;
}
this.editorCompositeContainer.setRedraw(false);
/*
* Dispose of last editor.
*/
Map<String, Boolean> expansionState = Collections.emptyMap();
if (this.attributeGroups != null)
{
expansionState = this.attributeGroups.getExpansionStates();
this.attributeGroups.dispose();
this.attributeGroups = null;
}
/*
* Create a new editor set.
*/
final IPreferenceStore prefStore = WorkbenchCorePlugin.getDefault()
.getPreferenceStore();
final String sourceID = getSourceId();
final GroupingMethod groupingMethod = GroupingMethod.valueOf(prefStore
.getString(PreferenceConstants.GROUPING_INPUT_VIEW));
final BindableDescriptor sourceDescriptor = this.descriptors.get(sourceID);
if (StringUtils.isEmpty(getSourceId()))
{
final Label label = new Label(editorCompositeContainer, SWT.CENTER);
label.setText("No active sources");
final GridData gd = new GridData();
gd.horizontalAlignment = org.eclipse.swt.layout.GridData.FILL;
gd.grabExcessHorizontalSpace = true;
label.setLayoutData(gd);
}
else
{
this.attributeGroups = new AttributeGroups(editorCompositeContainer,
sourceDescriptor, groupingMethod, filter, attributes.getAttributeValues());
final GridData gd = new GridData();
gd.horizontalAlignment = org.eclipse.swt.layout.GridData.FILL;
gd.grabExcessHorizontalSpace = true;
attributeGroups.setLayoutData(gd);
attributeGroups.setExpanded(expansionState);
/*
* Set default values for those attributes that do not have any assigned.
*/
Map<String,Object> defaultValues = sourceDescriptor.getDefaultValues();
for (Map.Entry<String, Object> e : defaultValues.entrySet())
{
if (attributes.getAttributeValue(e.getKey()) == null)
{
attributes.setAttributeValue(e.getKey(), e.getValue());
}
}
/*
* Set initial values of editors.
*/
attributeGroups.setAttributes(filterAttributesOf(sourceID));
/*
* Hook up listeners updating attributes on changes in editors.
*/
attributeGroups.addAttributeListener(new AttributeListenerAdapter()
{
public void valueChanged(AttributeEvent event)
{
if (event.key.equals(AttributeList.ENABLE_VALIDATION_OVERLAYS))
{
return;
}
attributes.setAttributeValue(event.key, event.value);
checkAllRequiredAttributes();
}
public void valueChanging(AttributeEvent event)
{
/*
* On content changing, eagerly substitute the value of the given
* attribute with the new value. In the input view, early commit of
* attribute values should not trigger any additional consequences, so
* we can do it.
*/
valueChanged(event);
}
});
}
/*
* Redraw GUI.
*/
this.editorCompositeContainer.setRedraw(true);
this.editorCompositeContainer.layout(true);
checkAllRequiredAttributes();
scroller.reflow(true);
}
/**
* Creates permanent GUI elements (source, algorithm combos, placeholder for the
* editors).
*/
private void createComponents(Composite parent)
{
final WorkbenchCorePlugin core = WorkbenchCorePlugin.getDefault();
parent.setLayout(new FillLayout());
this.scroller = new CScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL);
scroller.setExpandHorizontal(true);
scroller.setExpandVertical(false);
final Composite innerComposite = GUIFactory.createSpacer(scroller);
final GridLayout gridLayout = (GridLayout) innerComposite.getLayout();
gridLayout.numColumns = 2;
gridLayout.makeColumnsEqualWidth = false;
scroller.setContent(innerComposite);
// Initialize sources, descriptors and source combo.
final ProcessingComponentSuite suite = core.getComponentSuite();
sourceViewer = createComboViewer(innerComposite, "Source", suite.getSources());
sourceViewer.addSelectionChangedListener(sourceSelectionListener);
sources = Maps.newHashMap();
for (DocumentSourceDescriptor e : suite.getSources())
{
try
{
sources.put(e.getId(), e);
addFilteredDescriptor(e);
}
catch (Exception x)
{
Utils.logError("Could not initialize source: " + e.getId(), false);
}
}
// Initialize algorithms and algorithm combo.
algorithmViewer = createComboViewer(innerComposite, "Algorithm", suite
.getAlgorithms());
algorithms = Maps.newHashMap();
for (ProcessingComponentDescriptor e : suite.getAlgorithms())
{
algorithms.put(e.getId(), e);
addFilteredDescriptor(e);
}
final Label l = new Label(innerComposite, SWT.SEPARATOR | SWT.HORIZONTAL);
l.setLayoutData(GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(
2, 1).minSize(SWT.DEFAULT, 10).create());
// Initialize a place holder for the editors.
this.editorCompositeContainer = new Composite(innerComposite, SWT.NONE);
this.editorCompositeContainer.setLayoutData(GridDataFactory.fillDefaults().span(
2, 1).create());
this.editorCompositeContainer
.setLayout(GridLayoutFactory.fillDefaults().create());
final Composite processStatus = new Composite(innerComposite, SWT.NONE);
processStatus.setLayoutData(GridDataFactory.fillDefaults().span(2, 1).grab(true,
false).create());
processStatus.setLayout(GridLayoutFactory.fillDefaults().numColumns(2).spacing(3,
0).create());
this.validationStatus = new CLabel(processStatus, SWT.LEFT);
validationStatus.setLayoutData(GridDataFactory.fillDefaults().hint(250,
SWT.DEFAULT).grab(true, false).create());
// Initialize process button.
processButton = new Button(processStatus, SWT.PUSH);
processButton.setText("Process");
final GridData processButtonGridData = new GridData();
processButtonGridData.horizontalAlignment = GridData.END;
processButtonGridData.verticalAlignment = GridData.END;
processButtonGridData.horizontalSpan = 1;
processButton.setLayoutData(processButtonGridData);
// Restore view state.
restoreState();
// Initial editor display for the current input.
displayEditorSet();
// Restore initial expansion state for groups.
if (attributeGroups != null)
{
if (state != null)
{
if (state.sectionsExpansionState != null)
{
this.attributeGroups.setExpanded(state.sectionsExpansionState);
}
}
else
{
// Set the default expansion state.
this.attributeGroups.setExpanded(false);
this.attributeGroups.setExpanded(AttributeLevel.BASIC.toString(), true);
}
}
}
/**
* Adds a {@link BindableDescriptor} to {@link #descriptors}, filtering
* to only {@link Input} and {@link Processing} attributes.
*/
private void addFilteredDescriptor(ProcessingComponentDescriptor e)
{
final WorkbenchCorePlugin core = WorkbenchCorePlugin.getDefault();
descriptors.put(e.getId(),
core.getComponentDescriptor(e.getId()).only(
Input.class, Processing.class));
}
/**
* Creates a JFace ComboViewer around a collection of extension point implementations.
*/
private ComboViewer createComboViewer(Composite parent, String comboLabel,
List<? extends ProcessingComponentDescriptor> components)
{
final Label label = new Label(parent, SWT.CENTER);
label.setLayoutData(new GridData());
label.setText(comboLabel);
final GridData gridData = new GridData();
gridData.horizontalAlignment = GridData.FILL;
gridData.grabExcessHorizontalSpace = true;
final Combo combo = new Combo(parent, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.BORDER);
combo.setLayoutData(gridData);
combo.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
final ComboViewer viewer = new ComboViewer(combo);
viewer.setLabelProvider(new LabelProvider()
{
public String getText(Object element)
{
return ((ProcessingComponentDescriptor) element).getLabel();
}
});
viewer.setComparator(new ViewerComparator(new Comparator<String>()
{
public int compare(String s1, String s2)
{
return s1.toLowerCase().compareTo(s2.toLowerCase());
}
}));
viewer.setContentProvider(new ArrayContentProvider());
viewer.setInput(components);
return viewer;
}
/**
* Initiate query processing. Open an editor with the current parameter values.
*/
private void fireProcessing()
{
if (!hasAllRequiredAttributes(getSourceId()))
{
return;
}
final IWorkbenchPage page = getViewSite().getWorkbenchWindow().getActivePage();
/*
* Clone current attribute values so that they can be freely modified in the
* editor and in the input view.
*/
final AttributeValueSet requestAttrs = new AttributeValueSet("request");
requestAttrs.setAttributeValues(filterAttributesOf(getSourceId()));
requestAttrs.setAttributeValues(filterAttributesOf(getAlgorithmId()));
final SearchInput input = new SearchInput(
getSourceId(), getAlgorithmId(), requestAttrs);
try
{
page.openEditor(input, SearchEditor.ID);
}
catch (Exception x)
{
final IStatus status = new OperationStatus(IStatus.ERROR,
WorkbenchCorePlugin.PLUGIN_ID, -2, "Editor could not be opened.", x);
Utils.showError(status);
}
}
/**
* Check if all required {@link Input} attributes of a given source are properly
* initialized.
*/
private boolean hasAllRequiredAttributes(String sourceId)
{
if (StringUtils.isEmpty(sourceId))
{
return false;
}
return getEmptyRequiredAttributes(sourceId).isEmpty();
}
/**
* Returns descriptors of all required attributes that still have no values or have
* invalid values.
*/
private Collection<AttributeDescriptor> getEmptyRequiredAttributes(String sourceId)
{
final Collection<AttributeDescriptor> desc = descriptors.get(sourceId).flatten().attributeDescriptors
.values();
final ArrayList<AttributeDescriptor> remaining = Lists.newArrayList();
for (AttributeDescriptor d : desc)
{
final Object value = attributes.getAttributeValue(d.key);
if (!d.isValid(value))
{
remaining.add(d);
}
}
return remaining;
}
/**
* Check if all required attributes for the current configuration are available and
* update the {@link #processButton}.
*/
private void checkAllRequiredAttributes()
{
if (!showValidationStatus)
{
this.validationStatus.setText("");
this.validationStatus.setImage(null);
}
else
{
attributeGroups.setAttribute(
AttributeList.ENABLE_VALIDATION_OVERLAYS, true);
final String source = getSourceId();
if (!StringUtils.isEmpty(source))
{
final Collection<AttributeDescriptor> remaining = getEmptyRequiredAttributes(source);
if (remaining.size() > 0)
{
final String firstBad = remaining.iterator().next().metadata.getLabelOrTitle();
validationStatus.setText("Invalid attribute value: " + firstBad);
validationStatus.setImage(errorStatusImage);
}
else
{
this.validationStatus.setText("");
this.validationStatus.setImage(null);
}
}
}
}
/**
* Restore state of UI components from saved state.
*/
private void restoreState()
{
if (state != null)
{
this.attributes.setAttributeValues(state.attributes.getAttributeValues());
this.linkWithEditor = state.linkWithEditor;
}
this.linkWithEditorAction.setChecked(linkWithEditor);
ProcessingComponentDescriptor source = null;
ProcessingComponentDescriptor algorithm = null;
if (state != null)
{
source = sources.get(state.sourceId);
algorithm = algorithms.get(state.algorithmId);
}
if (source == null)
{
// Try to select the default set in preferences.
String id = WorkbenchCorePlugin.getDefault().getPreferenceStore().getString(
PreferenceConstants.DEFAULT_SOURCE_ID);
source = sources.get(id);
}
if (algorithm == null)
{
// Try to select the default set in preferences.
String id = WorkbenchCorePlugin.getDefault().getPreferenceStore().getString(
PreferenceConstants.DEFAULT_ALGORITHM_ID);
algorithm = algorithms.get(id);
}
restoreState(sourceViewer, source);
restoreState(algorithmViewer, algorithm);
/*
* Disable GUI if no inputs or algorithms.
*/
if (sources.isEmpty())
{
disableComboWithMessage(sourceViewer.getCombo(), "No document sources.");
processButton.setEnabled(false);
}
if (algorithms.isEmpty())
{
disableComboWithMessage(algorithmViewer.getCombo(), "No clustering algorithms.");
processButton.setEnabled(false);
}
}
/**
* Attempt to set selection to the given descriptor, if failed, select the first
* available element.
*/
@SuppressWarnings("unchecked")
private void restoreState(ComboViewer combo, ProcessingComponentDescriptor descriptor)
{
if (descriptor == null)
{
Collection<ProcessingComponentDescriptor> options =
(Collection<ProcessingComponentDescriptor>) combo.getInput();
if (options.size() > 0)
{
descriptor = options.iterator().next();
}
}
if (descriptor != null)
{
combo.setSelection(new StructuredSelection(descriptor), true);
}
}
/*
*
*/
private void disableComboWithMessage(Combo toDisable, String message)
{
toDisable.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
toDisable.setToolTipText(message);
toDisable.setEnabled(false);
}
/**
* Return the current source component identifier.
*/
String getSourceId()
{
return getSelectedId(sourceViewer);
}
/**
* Switch to user interface to the given source.
*/
private void setSourceId(String sourceID)
{
sourceViewer.removeSelectionChangedListener(sourceSelectionListener);
sourceViewer.setSelection(new StructuredSelection(sources.get(sourceID)));
sourceViewer.addSelectionChangedListener(sourceSelectionListener);
showValidationStatus = false;
displayEditorSet();
}
/*
*
*/
private String getAlgorithmId()
{
return getSelectedId(algorithmViewer);
}
/*
*
*/
private void setAlgorithmId(String algorithmID)
{
algorithmViewer
.setSelection(new StructuredSelection(algorithms.get(algorithmID)));
}
/**
*
*/
private String getSelectedId(ComboViewer combo)
{
if (combo.getSelection().isEmpty())
{
return null;
}
final IStructuredSelection selection = ((IStructuredSelection) combo
.getSelection());
return ((ProcessingComponentDescriptor) selection.getFirstElement()).getId();
}
/**
* Filter only those keys from {@link #attributes} that belong to source
* <code>sourceID</code>.
*/
Map<String, Object> filterAttributesOf(String componentId)
{
final Map<String, Object> filtered = Maps.newLinkedHashMap(
attributes.getAttributeValues());
filtered.keySet().retainAll(
descriptors.get(componentId).attributeDescriptors.keySet());
return filtered;
}
/**
* Update an attribute stored in the input view.
*/
void setAttribute(String key, Object value)
{
/*
* Force update of attributes map directly because this method
* updates algorithm attributes that are not covered by editorComposite.
*/
this.attributes.setAttributeValue(key, value);
this.attributeGroups.setAttribute(key, value);
}
/*
*
*/
@Override
public void saveState(IMemento memento)
{
final SearchInputViewMemento state = new SearchInputViewMemento();
state.sourceId = getSourceId();
state.algorithmId = getAlgorithmId();
state.linkWithEditor = linkWithEditor;
state.attributes = attributes;
if (attributeGroups != null) {
state.sectionsExpansionState = attributeGroups.getExpansionStates();
}
try
{
SimpleXmlMemento.addChild(memento, state);
}
catch (IOException e)
{
Utils.logError(e, false);
}
}
/**
* We set the focus to the current {@link #attributeGroups}'s default element if
* possible. Otherwise, set the focus to the input source combo.
*/
@Override
public void setFocus()
{
if (attributeGroups != null)
{
attributeGroups.setFocus();
}
else
{
this.sourceViewer.getCombo().setFocus();
}
}
/*
*
*/
@Override
public void dispose()
{
if (this.attributeGroups != null) attributeGroups.dispose();
if (this.errorStatusImage != null) this.errorStatusImage.dispose();
super.dispose();
}
/**
* Returns the active page's view instance.
*/
public static SearchInputView getView()
{
final IWorkbenchPage page = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
return (SearchInputView) page.findView(SearchInputView.ID);
}
}