/******************************************************************************* * 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.editors; import java.text.NumberFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.databinding.Binding; import org.eclipse.core.databinding.DataBindingContext; import org.eclipse.core.databinding.UpdateValueStrategy; import org.eclipse.core.databinding.beans.BeansObservables; import org.eclipse.core.databinding.beans.PojoObservables; import org.eclipse.core.databinding.conversion.Converter; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.databinding.swt.ISWTObservableValue; import org.eclipse.jface.databinding.swt.SWTObservables; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jubula.client.core.model.ClientProfileNames; import org.eclipse.jubula.client.core.model.IObjectMappingPO; import org.eclipse.jubula.client.core.model.IObjectMappingProfilePO; import org.eclipse.jubula.client.ui.constants.ContextHelpIds; import org.eclipse.jubula.client.ui.rcp.Plugin; import org.eclipse.jubula.client.ui.rcp.databinding.InverseBooleanConverter; import org.eclipse.jubula.client.ui.rcp.editors.JBEditorHelper.EditableState; import org.eclipse.jubula.client.ui.rcp.i18n.Messages; import org.eclipse.jubula.tools.internal.objects.StandardProfiles; import org.eclipse.jubula.tools.internal.xml.businessmodell.Profile; import org.eclipse.jubula.tools.internal.xml.businessprocess.ProfileBuilder; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.graphics.GC; 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.Label; import org.eclipse.swt.widgets.Scale; /** * Component for selecting/modifying object mapping profiles. * * @author BREDEX GmbH * @created Nov 5, 2008 */ public class ObjectMappingConfigComponent { /** * Takes care of IJBEditor-specific steps when changing a value via a * databinding. This includes requesting an editable state and marking the * editor as dirty, if necessary. * * @author BREDEX GmbH * @created Nov 24, 2008 */ private class JBEditorUpdateValueStrategy extends UpdateValueStrategy { /** * Constructor * * @param updatePolicy The updatePolicy to use. */ public JBEditorUpdateValueStrategy(int updatePolicy) { super(updatePolicy); } /** * {@inheritDoc} */ @SuppressWarnings("synthetic-access") protected IStatus doSet( IObservableValue observableValue, Object value) { if (m_editor.getEditorHelper().requestEditableState() == EditableState.OK) { IStatus status = super.doSet(observableValue, value); if (!m_editor.isDirty()) { m_editor.getEditorHelper().setDirty(true); } setComboValue(); return status; } return Status.CANCEL_STATUS; } } /** 1 column */ private static final int NUM_COLUMNS = 1; /** 10 horizontal spaces */ private static final int HORIZONTAL_SPACING_10 = 10; /** 10 vertical spaces */ private static final int VERTICAL_SPACING_10 = 10; /** * 100 % */ private static final int HUNDRED_PERCENT = 200; /** * step */ private static final int STEP = 1; /** * the maximum number of digits displayable in labels corresponding to * sliders */ private static final int MAX_NUM_DIGITS = 5; /** * Databinding converter: Model => Label text * * @author BREDEX GmbH * @created Nov 19, 2008 */ private static class ModelToLabelConverter extends Converter { /** the string to use for formatting percentage label text */ private static final String FORMAT_STRING = "%3.1f"; //$NON-NLS-1$ /** * the factor for converting from model percentage values to label * text values */ private static final int CONVERSION_FACTOR = 100; /** * Constructor */ public ModelToLabelConverter() { super(double.class, String.class); } /** * * {@inheritDoc} */ public Object convert(Object fromObject) { Double fromDouble = (Double)fromObject; return String.format(FORMAT_STRING, fromDouble * CONVERSION_FACTOR); } } /** * Databinding converter: Label => Model * * @author BREDEX GmbH * @created Nov 19, 2008 */ private static class LabelToModelConverter extends Converter { /** * Constructor */ public LabelToModelConverter() { super(String.class, double.class); } /** * * {@inheritDoc} */ public Object convert(Object fromObject) { String doubleString = (String)fromObject; try { return NumberFormat.getInstance(). parse(doubleString).doubleValue() / 100; } catch (ParseException e) { // in theory shouldn't happen because the received String is a converted double return 0; } } } /** * Databinding converter: IObjectMappingProfilePO => UI component enablement * * @author BREDEX GmbH * @created Nov 24, 2008 */ private static class ModelToEnablementConverter extends Converter { /** * Constructor */ public ModelToEnablementConverter() { super(IObjectMappingProfilePO.class, boolean.class); } /** * {@inheritDoc} */ public Object convert(Object fromObject) { if (fromObject instanceof IObjectMappingProfilePO) { return ((IObjectMappingProfilePO)fromObject).getName() == null; } return true; } } /** * reusable instance of converter, in order to avoid having to instantiate * multiple converters */ private ModelToEnablementConverter m_modelToEnablementConverter = new ModelToEnablementConverter(); /** * reusable instance of converter, in order to avoid having to instantiate * multiple converters */ private InverseBooleanConverter m_inverseBooleanConverter = new InverseBooleanConverter(); /** * Databinding converter: Slider value (int) => Model value (double) * * @author BREDEX GmbH * @created Nov 24, 2008 */ private static class SliderToModelConverter extends Converter { /** * Constructor */ public SliderToModelConverter() { super(0, 0.0); } /** * {@inheritDoc} */ public Object convert(Object fromObject) { Object retVal = fromObject; if (retVal instanceof Integer) { retVal = ((Integer)fromObject).doubleValue() / HUNDRED_PERCENT; } return retVal; } } /** * reusable instance of converter, in order to avoid having to instantiate * multiple converters */ private SliderToModelConverter m_sliderToModelConverter = new SliderToModelConverter(); /** * Databinding converter: Model value (double) => Slider value (int) * * @author BREDEX GmbH * @created Nov 24, 2008 */ private static class ModelToSliderConverter extends Converter { /** * @param fromType * @param toType */ public ModelToSliderConverter() { super(double.class, int.class); } /** * {@inheritDoc} */ public Object convert(Object fromObject) { Integer retVal = null; if (fromObject instanceof Double) { retVal = (int)(((Double)fromObject) * HUNDRED_PERCENT); } return retVal; } } /** * reusable instance of converter, in order to avoid having to instantiate * multiple converters */ private ModelToSliderConverter m_modelToSliderConverter = new ModelToSliderConverter(); /** * slider for recognitionParameter */ private Scale m_threshold = null; /** * Textfield for m_nameFactor */ private Label m_thresholdText = null; /** * combo for profiles */ private Combo m_profileCombo = null; /** * composite for slider */ private Composite m_sliderComposite; /** * reusable instance of converter, in order to avoid having to instantiate * multiple converters */ private ModelToLabelConverter m_modelToLabelConverter = new ModelToLabelConverter(); /** instance to convert the label Text to a value in the model **/ private LabelToModelConverter m_labelToModelConverter = new LabelToModelConverter(); /** Model */ private IObjectMappingPO m_input; /** editor reference */ private IJBEditor m_editor; /** used for triggered updates */ private DataBindingContext m_bindingContext; /** observable for the editor input */ private IObservableValue m_profileObservable; /** map for the sliders. this is necessary for the binding update **/ private Map<Scale, String> m_factorSliders; /** map for the value labels. this is necessary for the binding update **/ private Map<Scale, Label> m_factorLabels = new HashMap<Scale, Label>(); /** * Constructor * * @param parent The parent for the created controls. * @param input The initial value being edited by this component. * @param editor The editor supplying the data for this component. */ public ObjectMappingConfigComponent(Composite parent, IObjectMappingPO input, IJBEditor editor) { m_input = input; m_editor = editor; createAndInitControl(parent, input, editor); } /** * Creates all controls for this component and initializes data * binding. * * @param parent The parent for the created controls. * @param input The initial value being edited by this component. * @param editor The editor supplying the data for this component. */ private void createAndInitControl( Composite parent, IObjectMappingPO input, IJBEditor editor) { /** Add layer to parent widget */ final ScrolledComposite scrollComposite = new ScrolledComposite(parent, SWT.V_SCROLL | SWT.H_SCROLL); scrollComposite.setLayoutData(GridDataFactory.fillDefaults() .grab(true, true).create()); final Composite composite = new Composite(scrollComposite, SWT.NONE); m_bindingContext = new DataBindingContext(); /** Define layout rules for widget placement */ compositeGridData(composite); // add widgets to composite createProfileCombo(composite); m_sliderComposite = createSliderComposite(composite); m_factorSliders = new HashMap<Scale, String>(); m_profileObservable = PojoObservables.observeValue(input, IObjectMappingPO.PROP_PROFILE); m_factorSliders.put(createFactorSlider(m_sliderComposite, Messages.ObjectMappingPreferencePagePathFactor, IObjectMappingProfilePO.PROP_PATH_FACTOR, m_bindingContext, m_profileObservable, editor), IObjectMappingProfilePO.PROP_PATH_FACTOR); m_factorSliders.put(createFactorSlider(m_sliderComposite, Messages.ObjectMappingPreferencePageNameFactor, IObjectMappingProfilePO.PROP_NAME_FACTOR, m_bindingContext, m_profileObservable, editor), IObjectMappingProfilePO.PROP_NAME_FACTOR); m_factorSliders.put(createFactorSlider(m_sliderComposite, Messages.ObjectMappingPreferencePageContextFactor, IObjectMappingProfilePO.PROP_CONTEXT_FACTOR, m_bindingContext, m_profileObservable, editor), IObjectMappingProfilePO.PROP_CONTEXT_FACTOR); linkFactorSliders(m_bindingContext, m_factorSliders.keySet(), editor); createThresholdSlider(m_sliderComposite, m_bindingContext, m_profileObservable, editor); m_bindingContext.updateTargets(); // context sensitive help Plugin.getHelpSystem().setHelp(parent, ContextHelpIds.PREFPAGE_OBJECT_MAP); /** return the widget used as the base for the user interface */ m_profileCombo.setSize( m_factorSliders.keySet().iterator().next().getSize().x, m_profileCombo.getSize().y); scrollComposite.setContent(composite); scrollComposite.setExpandHorizontal(true); scrollComposite.setExpandVertical(true); scrollComposite.setMinSize(composite.computeSize( SWT.DEFAULT, SWT.DEFAULT)); scrollComposite.addControlListener(new ControlAdapter() { public void controlResized(ControlEvent e) { scrollComposite.setMinSize(composite.computeSize( SWT.DEFAULT, SWT.DEFAULT)); } }); } /** * @param composite The parent for the slider composite. * @return The slider composite. This contains the sliders and related * UI components for the editor. */ private Composite createSliderComposite(final Composite composite) { Composite sliderComposite = new Composite(composite, SWT.BORDER); GridLayout compositeLayout = new GridLayout(); compositeLayout.numColumns = 4; compositeLayout.horizontalSpacing = 5; compositeLayout.verticalSpacing = 5; sliderComposite.setLayout(compositeLayout); sliderComposite.setLayoutData(GridDataFactory.fillDefaults() .grab(true, true).create()); Label label = new Label(sliderComposite, SWT.CENTER); label = new Label(sliderComposite, SWT.CENTER); label = new Label(sliderComposite, SWT.CENTER); label.setText(" %"); //$NON-NLS-1$ label = new Label(sliderComposite, SWT.NONE); label.setText(Messages.ObjectMappingPreferencePageLock); return sliderComposite; } /** * * @param bindingContext The context to use for databinding for all factor * slider. * @param factorSliders All sliders in the UI that correspond to an object * mapping profile "factor". * @param editor The editor containing the sliders. */ private void linkFactorSliders(final DataBindingContext bindingContext, final Set<Scale> factorSliders, final IJBEditor editor) { for (final Scale slider : factorSliders) { slider.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) { // Do nothing } public void widgetSelected(SelectionEvent e) { if (editor.getEditorHelper().requestEditableState() == EditableState.OK) { checkSum(slider, factorSliders); bindingContext.updateModels(); if (!editor.isDirty()) { editor.getEditorHelper().setDirty(true); } } } }); } } /** * @param parent The parent for the created UI elements. * @param labelText Text to use for the label for the created slider. * @param boundProperty The model property to use for databinding for * the created UI elements. * @param bindingContext The context to use for databinding for the created * UI elements. * @param masterObservable Observable for the master element for which these * UI elements serve as detail. Essentially, the * created UI elements represent detailed * information about this element. * @param editor The editor containing the slider. * @return the created slider. */ private Scale createFactorSlider(Composite parent, String labelText, String boundProperty, final DataBindingContext bindingContext, IObservableValue masterObservable, IJBEditor editor) { // create Widget Label label = new Label(parent, SWT.NONE); label.setText(labelText); final Scale factorScale = new Scale(parent, SWT.NONE); factorScale.setMinimum(0); factorScale.setMaximum(HUNDRED_PERCENT); factorScale.setIncrement(STEP); factorScale.setPageIncrement(STEP); factorScale.setLayoutData(GridDataFactory.fillDefaults() .grab(true, false).create()); Label factorText = new Label(parent, SWT.NONE); setLabelWidth(factorText); Button lockCheckbox = new Button(parent, SWT.CHECK); bindFactor(boundProperty, bindingContext, factorScale, factorText, lockCheckbox, masterObservable, editor); new Label(parent, SWT.NONE); new Label(parent, SWT.NONE); new Label(parent, SWT.NONE); new Label(parent, SWT.NONE); m_factorLabels.put(factorScale, factorText); return factorScale; } /** * * @param boundProperty The model property to use for databinding for * the created UI elements. * @param bindingContext The context to use for databinding for the created * UI elements. * @param factorScale Slider to bind. * @param factorText Label to bind. * @param lockCheckbox Checkbox to bind. * @param masterObservable Observable for the master element for which these * UI elements serve as detail. Essentially, the * created UI elements represent detailed * information about this element. * @param editor The editor containing the factor UI elements. */ private void bindFactor(String boundProperty, final DataBindingContext bindingContext, final Scale factorScale, Label factorText, Button lockCheckbox, IObservableValue masterObservable, IJBEditor editor) { IObservableValue uiElement = SWTObservables.observeSelection(factorScale); IObservableValue modelElement = BeansObservables.observeDetailValue(masterObservable, boundProperty, double.class); bindingContext.bindValue(uiElement, modelElement, new JBEditorUpdateValueStrategy( UpdateValueStrategy.POLICY_ON_REQUEST) .setConverter(m_sliderToModelConverter), new UpdateValueStrategy() .setConverter(m_modelToSliderConverter)); uiElement = SWTObservables.observeText(factorText); bindingContext.bindValue(uiElement, modelElement, new UpdateValueStrategy() .setConverter(m_labelToModelConverter), new UpdateValueStrategy() .setConverter(m_modelToLabelConverter)); IObservableValue checkboxSelection = SWTObservables.observeSelection(lockCheckbox); uiElement = SWTObservables.observeEnabled(factorScale); bindingContext.bindValue(uiElement, masterObservable, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy().setConverter( m_modelToEnablementConverter)); bindingContext.bindValue(uiElement, checkboxSelection, new UpdateValueStrategy().setConverter( m_inverseBooleanConverter), new UpdateValueStrategy().setConverter( m_inverseBooleanConverter)); uiElement = SWTObservables.observeEnabled(factorText); bindingContext.bindValue(uiElement, masterObservable, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy().setConverter( m_modelToEnablementConverter)); bindingContext.bindValue(uiElement, checkboxSelection, new UpdateValueStrategy().setConverter( m_inverseBooleanConverter), new UpdateValueStrategy().setConverter( m_inverseBooleanConverter)); uiElement = SWTObservables.observeEnabled(lockCheckbox); bindingContext.bindValue(uiElement, masterObservable, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy().setConverter( m_modelToEnablementConverter)); } /** * Updates the binding between the given scale and its corresponding model * value. This is done by removing the old bindings and creating new ones. * * @param boundProperty the property for the binding * @param bindingContext the binding context * @param factorScale the scale * @param masterObservable the observable */ private void updateBindFactor(String boundProperty, final DataBindingContext bindingContext, final Scale factorScale, IObservableValue masterObservable) { IObservableValue uiElement = SWTObservables.observeSelection(factorScale); IObservableValue modelElement = BeansObservables.observeDetailValue( masterObservable, boundProperty, double.class); removeBinding(uiElement, modelElement); bindingContext.bindValue(uiElement, modelElement, new JBEditorUpdateValueStrategy( UpdateValueStrategy.POLICY_ON_REQUEST) .setConverter(m_sliderToModelConverter), new UpdateValueStrategy() .setConverter(m_modelToSliderConverter)); Label factorText = m_factorLabels.get(factorScale); uiElement = SWTObservables.observeText(factorText); removeBinding(uiElement, modelElement); bindingContext.bindValue(uiElement, modelElement, new UpdateValueStrategy().setConverter(m_labelToModelConverter), new UpdateValueStrategy() .setConverter(m_modelToLabelConverter)); uiElement = SWTObservables.observeEnabled(factorScale); removeBinding(uiElement, masterObservable); bindingContext.bindValue(uiElement, masterObservable, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy() .setConverter(m_modelToEnablementConverter)); } /** * Updates the binding for the threshold * @param bindingContext the binding context * @param masterObservable the model observable */ private void updateThresholdBind(final DataBindingContext bindingContext, IObservableValue masterObservable) { IObservableValue uiElement; IObservableValue modelElement; String boundProperty = IObjectMappingProfilePO.PROP_THRESHOLD; uiElement = SWTObservables.observeSelection(m_threshold); modelElement = BeansObservables.observeDetailValue(masterObservable, boundProperty, double.class); removeBinding(uiElement, masterObservable); bindingContext.bindValue(uiElement, modelElement, new UpdateValueStrategy() .setConverter(m_sliderToModelConverter), new UpdateValueStrategy() .setConverter(m_modelToSliderConverter)); uiElement = SWTObservables.observeText(m_thresholdText); removeBinding(uiElement, masterObservable); bindingContext.bindValue(uiElement, modelElement, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy() .setConverter(m_modelToLabelConverter)); } /** * Removes all bindings between the given UI-Element and the Model element * in the binding context * * @param uiElement the UI-Element * @param modelElement the model element */ private void removeBinding(IObservableValue uiElement, IObservableValue modelElement) { ArrayList<Binding> binds = new ArrayList<Binding>( m_bindingContext.getBindings()); for (Binding object : binds) { if (object.getTarget().equals(uiElement) || object.getModel().equals(modelElement)) { m_bindingContext.removeBinding(object); } } } /** * @param composite The composite. */ private void compositeGridData(Composite composite) { GridLayout compositeLayout = new GridLayout(); compositeLayout.numColumns = NUM_COLUMNS; compositeLayout.horizontalSpacing = HORIZONTAL_SPACING_10; compositeLayout.verticalSpacing = VERTICAL_SPACING_10; compositeLayout.marginHeight = 0; compositeLayout.marginWidth = 0; composite.setLayout(compositeLayout); composite.setLayoutData(GridDataFactory.fillDefaults() .grab(true, true).create()); } /** * @param parent Parent of this Combo. */ private void createProfileCombo(Composite parent) { // create Widget Composite composite = new Composite(parent, SWT.NONE); GridLayout compositeLayout = new GridLayout(); compositeLayout.numColumns = 2; composite.setLayout(compositeLayout); Label label = new Label(composite, SWT.NONE); label.setText(Messages.ObjectMappingPreferencePageProfile); m_profileCombo = new Combo(composite, SWT.CHECK | SWT.READ_ONLY); m_profileCombo.setTextLimit(20); List<String> names = StandardProfiles.getProfileNames(); m_profileCombo.setItems(names.toArray(new String[names.size()])); m_profileCombo.add(ClientProfileNames.CUSTOM); setComboValue(); m_profileCombo.addModifyListener(new ModifyListener() { @SuppressWarnings("synthetic-access") public void modifyText(ModifyEvent e) { if (m_editor.getEditorHelper().requestEditableState() == EditableState.OK) { if (!m_editor.isDirty()) { m_editor.getEditorHelper().setDirty(true); } String name = m_profileCombo.getText(); if (name != null) { Profile p = ProfileBuilder.getProfile(name); if (p != null) { m_input.getProfile().useTemplate(p); m_bindingContext.updateTargets(); m_bindingContext.updateModels(); setComboValue(); } } } } }); } /** * selects a combo entry depending on the profile values */ private void setComboValue() { List<Profile> profiles = ProfileBuilder.getProfiles(); for (Profile profile : profiles) { if (m_input.getProfile().matchesTemplate(profile)) { int index = m_profileCombo.indexOf(profile.getName()); if (index != -1) { if (index != m_profileCombo.getSelectionIndex()) { m_profileCombo.select(index); } return; } } } int index = m_profileCombo.indexOf(ClientProfileNames.CUSTOM); if (index != -1) { if (index != m_profileCombo.getSelectionIndex()) { m_profileCombo.select(index); } return; } } /** * Creates the labels and slider for the Threshold property as * well as the corresponding data bindings. * * @param parent Parent of the created components. * @param bindingContext The data binding context. * @param masterObservable Observable value used to determine * which model object is currently * being observed in detail. * @param editor the editor */ private void createThresholdSlider(Composite parent, DataBindingContext bindingContext, IObservableValue masterObservable, final IJBEditor editor) { String boundProperty = IObjectMappingProfilePO.PROP_THRESHOLD; // create Widget Label label = new Label(parent, SWT.NONE); label.setText(Messages.ObjectMappingPreferencePageThreshold); m_threshold = new Scale(parent, SWT.NONE); m_threshold.setMinimum(0); m_threshold.setMaximum(HUNDRED_PERCENT); m_threshold.setIncrement(STEP); m_threshold.setPageIncrement(STEP); m_threshold.setLayoutData(GridDataFactory.fillDefaults() .grab(true, false).create()); m_thresholdText = new Label(parent, SWT.NONE); setLabelWidth(m_thresholdText); new Label(parent, SWT.NONE); ISWTObservableValue uiElement = SWTObservables.observeSelection(m_threshold); IObservableValue modelElement = BeansObservables.observeDetailValue(masterObservable, boundProperty, double.class); bindingContext.bindValue(uiElement, modelElement, new UpdateValueStrategy() .setConverter(m_sliderToModelConverter), new UpdateValueStrategy() .setConverter(m_modelToSliderConverter)); uiElement = SWTObservables.observeText(m_thresholdText); bindingContext.bindValue(uiElement, modelElement, new UpdateValueStrategy( UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy().setConverter( m_modelToLabelConverter)); uiElement = SWTObservables.observeEnabled(m_threshold); bindingContext.bindValue(uiElement, masterObservable, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy().setConverter( m_modelToEnablementConverter)); uiElement = SWTObservables.observeEnabled(m_thresholdText); bindingContext.bindValue(uiElement, masterObservable, new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy().setConverter( m_modelToEnablementConverter)); m_threshold.addSelectionListener(new SelectionListener() { @Override public void widgetDefaultSelected(SelectionEvent e) { // Do nothing } @Override public void widgetSelected(SelectionEvent e) { if (editor.getEditorHelper().requestEditableState() == EditableState.OK && !editor.isDirty()) { editor.getEditorHelper().setDirty(true); } } }); } /** * Sets the correct width and layout data for the given label. Assumes that * the parent uses a grid layout. * * @param label The label for which to set the width and layout data. */ private void setLabelWidth(Label label) { GC gc = new GC(label); GridData gd = new GridData(SWT.FILL, SWT.CENTER, false, false); gd.minimumWidth = gc.getFontMetrics().getAverageCharWidth() * MAX_NUM_DIGITS; label.setLayoutData(gd); gc.dispose(); } /** * checks and corrects the scales to not get over 100% * @param s * Scale * @param factorSliders all sliders in the UI that correspond to an object * mapping profile "factor". */ void checkSum(Scale s, Set<Scale> factorSliders) { while (getSum(factorSliders) > HUNDRED_PERCENT) { boolean didDecrement = false; for (Scale toDecrement : factorSliders) { if (getSum(factorSliders) > HUNDRED_PERCENT && toDecrement.isEnabled() && !toDecrement.equals(s) && toDecrement.getSelection() > 0) { toDecrement.setSelection(toDecrement.getSelection() - STEP); didDecrement = true; } } if (!didDecrement) { s.setSelection(s.getSelection() - STEP); } } while (getSum(factorSliders) < HUNDRED_PERCENT) { boolean didIncrement = false; for (Scale toIncrement : factorSliders) { if (getSum(factorSliders) < HUNDRED_PERCENT && !s.equals(toIncrement) && toIncrement.isEnabled() && toIncrement.getSelection() < HUNDRED_PERCENT) { toIncrement.setSelection(toIncrement.getSelection() + STEP); didIncrement = true; } } if (!didIncrement) { s.setSelection(s.getSelection() + STEP); } } } /** * * @param factorSliders all sliders in the UI that correspond to an object * mapping profile "factor". * @return the sum of all factor scales */ public double getSum(Set<Scale> factorSliders) { double sum = 0; for (Scale slider : factorSliders) { if (slider != null && !slider.isDisposed()) { sum += slider.getSelection(); } } return sum; } /** * sets the correct value into a scale * @param s * Scale * @param d * double */ public void setValue(Scale s, double d) { s.setSelection((int)(HUNDRED_PERCENT * d)); } /** * Sets the input for this component, updating all data bindings * to reflect this change. * * @param input The new input to use for this component. */ public void setInput(IObjectMappingPO input) { m_input = input; m_profileObservable.setValue(input.getProfile()); for (Scale scale : m_factorSliders.keySet()) { updateBindFactor(m_factorSliders.get(scale), m_bindingContext, scale, m_profileObservable); } updateThresholdBind(m_bindingContext, m_profileObservable); m_bindingContext.updateTargets(); setComboValue(); } }