/** * This file is protected by Copyright. * Please refer to the COPYRIGHT file distributed with this source distribution. * * This file is part of REDHAWK IDE. * * 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. * */ package gov.redhawk.prf.internal.ui.editor.detailspart; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; 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.conversion.Converter; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.emf.common.command.Command; import org.eclipse.emf.databinding.EMFUpdateValueStrategy; import org.eclipse.emf.databinding.FeaturePath; import org.eclipse.emf.databinding.edit.EMFEditObservables; import org.eclipse.emf.databinding.edit.EMFEditProperties; import org.eclipse.emf.databinding.edit.IEMFEditValueProperty; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.command.AddCommand; import org.eclipse.emf.edit.command.RemoveCommand; import org.eclipse.emf.edit.command.ReplaceCommand; import org.eclipse.emf.edit.command.SetCommand; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.jface.databinding.swt.WidgetProperties; import org.eclipse.jface.databinding.viewers.ViewersObservables; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Text; import gov.redhawk.prf.internal.ui.editor.PropertiesSection; import gov.redhawk.prf.internal.ui.editor.composite.BasicSimplePropertyComposite; import gov.redhawk.prf.ui.wizard.EnumerationWizard; import gov.redhawk.ui.editor.SCAFormEditor; import gov.redhawk.ui.util.EMFEmptyStringToNullUpdateValueStrategy; import mil.jpeojtrs.sca.prf.Action; import mil.jpeojtrs.sca.prf.ActionType; import mil.jpeojtrs.sca.prf.Enumeration; import mil.jpeojtrs.sca.prf.Enumerations; import mil.jpeojtrs.sca.prf.Kind; import mil.jpeojtrs.sca.prf.PrfFactory; import mil.jpeojtrs.sca.prf.PrfPackage; import mil.jpeojtrs.sca.prf.PropertyConfigurationType; import mil.jpeojtrs.sca.prf.Range; import mil.jpeojtrs.sca.prf.Simple; import mil.jpeojtrs.sca.prf.SimpleSequence; //SUPPRESS CHECKSTYLE INLINE - Used in a Javadoc /** * Provides functionality common to {@link Simple} and {@link SimpleSequence} types, including data binding of all * common widgets. */ public abstract class BasicSimplePropertyDetailsPage extends AbstractPropertyDetailsPage { private EObject input; private Property property; private Binding minBinding; private Binding maxBinding; private final SelectionListener rangeListener = new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { if (BasicSimplePropertyDetailsPage.this.minBinding != null && !BasicSimplePropertyDetailsPage.this.minBinding.isDisposed()) { BasicSimplePropertyDetailsPage.this.minBinding.updateModelToTarget(); BasicSimplePropertyDetailsPage.this.minBinding.updateTargetToModel(); BasicSimplePropertyDetailsPage.this.minBinding.validateModelToTarget(); BasicSimplePropertyDetailsPage.this.minBinding.validateTargetToModel(); } if (BasicSimplePropertyDetailsPage.this.maxBinding != null && !BasicSimplePropertyDetailsPage.this.maxBinding.isDisposed()) { BasicSimplePropertyDetailsPage.this.maxBinding.updateModelToTarget(); BasicSimplePropertyDetailsPage.this.maxBinding.updateTargetToModel(); BasicSimplePropertyDetailsPage.this.maxBinding.validateModelToTarget(); BasicSimplePropertyDetailsPage.this.maxBinding.validateTargetToModel(); } } }; public BasicSimplePropertyDetailsPage(final PropertiesSection section) { super(section); } private void addRangeListener() { // NOTE: MUST remove listener prior to adding since // 1.) We don't want multiple listeners // 2.) This listener MUST be triggered AFTER the binding listener, therefore, it is adding every time in the // bind method ((BasicSimplePropertyComposite) getComposite()).getRangeButton().removeSelectionListener(this.rangeListener); ((BasicSimplePropertyComposite) getComposite()).getRangeButton().addSelectionListener(this.rangeListener); } @Override protected List<Binding> bind(final DataBindingContext dataBindingContext, final EObject input) { final BasicSimplePropertyComposite composite = getComposite(); final EditingDomain domain = getEditingDomain(); this.input = input; this.property = getProperty(this.input); final List<Binding> retVal = super.bind(dataBindingContext, input); // Type if (composite.getTypeViewer() != null) { retVal.add(dataBindingContext.bindValue(ViewersObservables.observeSingleSelection(composite.getTypeViewer()), EMFEditObservables.observeValue(domain, input, this.property.getType()), null, null)); } if (composite.getTypeModifier() != null) { retVal.add(dataBindingContext.bindValue(WidgetProperties.selection().observe(composite.getTypeModifier()), EMFEditObservables.observeValue(domain, input, this.property.getTypeModifier()), createTypeModifierTargetToModel(), createTypeModifierModelTarget())); } // Units if (composite.getUnitsEntry() != null) { retVal.add(dataBindingContext.bindValue( WidgetProperties.text(SWT.Modify).observeDelayed(SCAFormEditor.getFieldBindingDelay(), composite.getUnitsEntry().getText()), EMFEditObservables.observeValue(domain, input, this.property.getUnits()), new EMFEmptyStringToNullUpdateValueStrategy(), null)); } // Kind if (composite.getKindViewer() != null) { // Search for configure/execparam properties if they are being used for backwards compatibility boolean oldStyle = hasConfigureOrExecParamProperties(this.input); composite.showConfigureAndExecParam(oldStyle); retVal.add(dataBindingContext.bindValue(ViewersObservables.observeSingleSelection(composite.getKindViewer()), EMFEditObservables.observeValue(domain, input, this.property.getKind()), createKindTargetToModel(), createKindModelToTarget())); } // Action if (composite.getActionViewer() != null) { retVal.add(dataBindingContext.bindValue(ViewersObservables.observeSingleSelection(composite.getActionViewer()), EMFEditObservables.observeValue(domain, input, this.property.getAction()), createActionTargetToModel(), createActionModelToTarget())); } // Range if (composite.getRangeButton() != null) { retVal.addAll(bindRanges(input, dataBindingContext, domain)); addRangeListener(); } return retVal; } private UpdateValueStrategy createTypeModifierModelTarget() { EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(Boolean.class, String.class) { @Override public Object convert(Object fromObject) { if (fromObject == null) { return ""; } boolean state = false; if (fromObject instanceof Boolean) { state = (Boolean) fromObject; } if (state) { return "complex"; } else { return "real"; } } }); return strategy; } private UpdateValueStrategy createTypeModifierTargetToModel() { EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(String.class, Boolean.class) { @Override public Object convert(Object fromObject) { if (fromObject instanceof String) { String fromObjectStr = (String) fromObject; if (fromObjectStr.isEmpty()) { return null; } if ("real".equalsIgnoreCase(fromObjectStr)) { return false; } else if ("complex".equalsIgnoreCase(fromObjectStr)) { return true; } } return null; } }); return strategy; } /** * Creates a {@link UpdateValueStrategy} that converts the {@link List} < {@link Kind} > from the EMF model object * to a single {@link PropertyConfigurationType} for the drop-down combo box. * @return */ private UpdateValueStrategy createKindModelToTarget() { final EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(List.class, PropertyConfigurationType.class) { @Override public Object convert(final Object fromObject) { if (fromObject instanceof List) { final List< ? > kindList = (List< ? >) fromObject; // Normally, we expect exactly one kind type in the list if (kindList.size() == 1) { Kind kind = (Kind) kindList.get(0); if (kind.isSetType()) { // Message should only be shown as an option if the user explicitly enters it if (kind.getType().equals(PropertyConfigurationType.MESSAGE)) { BasicSimplePropertyDetailsPage.this.getComposite().showMessage(true); } else { BasicSimplePropertyDetailsPage.this.getComposite().showMessage(false); } return kind.getType(); } else { return PropertyConfigurationType.PROPERTY; } } // If empty, default to CONFIGURE if (kindList.size() == 0) { return PropertyConfigurationType.CONFIGURE; } // We can only display one kind type, even though the XML allows multiple. As of Redhawk 2.0, we // only expect one type to be used. Since we have multiple, we'll select the "most important" one to // show. Set<PropertyConfigurationType> kindTypeSet = new HashSet<PropertyConfigurationType>(); for (Object obj : kindList) { Kind kind = (Kind) obj; if (kind.isSetType()) { kindTypeSet.add(kind.getType()); } } if (kindTypeSet.contains(PropertyConfigurationType.PROPERTY)) { return PropertyConfigurationType.PROPERTY; } if (kindTypeSet.contains(PropertyConfigurationType.ALLOCATION)) { return PropertyConfigurationType.ALLOCATION; } if (kindTypeSet.contains(PropertyConfigurationType.CONFIGURE)) { return PropertyConfigurationType.CONFIGURE; } if (kindTypeSet.contains(PropertyConfigurationType.EXECPARAM)) { return PropertyConfigurationType.EXECPARAM; } if (kindTypeSet.contains(PropertyConfigurationType.MESSAGE)) { return PropertyConfigurationType.MESSAGE; } PropertyConfigurationType displayKindType = ((Kind) kindList.get(0)).getType(); return displayKindType; } throw new IllegalArgumentException(); } }); return strategy; } /** * Creates a {@link UpdateValueStrategy} that converts a {@link PropertyConfigurationType} from the drop-down combo * box to a {@link List} < {@link Kind} > for the EMF model object. * @return */ private UpdateValueStrategy createKindTargetToModel() { final EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(PropertyConfigurationType.class, List.class) { @Override public Object convert(final Object fromObject) { if (fromObject instanceof PropertyConfigurationType) { final PropertyConfigurationType kindType = (PropertyConfigurationType) fromObject; // Message should only be shown as an option if is already exists in the prf.xml boolean isMessageShown = BasicSimplePropertyDetailsPage.this.getComposite().isShowMessage(); if (!kindType.equals(PropertyConfigurationType.MESSAGE) && isMessageShown) { BasicSimplePropertyDetailsPage.this.getComposite().showMessage(false); } final Kind kind = PrfFactory.eINSTANCE.createKind(); kind.setType(kindType); List<Kind> kindList = new ArrayList<Kind>(); kindList.add(kind); return kindList; } throw new IllegalArgumentException(); } }); return strategy; } private UpdateValueStrategy createActionModelToTarget() { final EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(Action.class, Object.class) { @Override public Object convert(final Object fromObject) { if (fromObject instanceof Action) { final Action a = (Action) fromObject; return a.getType(); } else if (fromObject == null) { return ""; } throw new IllegalArgumentException(); } }); return strategy; } private UpdateValueStrategy createActionTargetToModel() { final EMFUpdateValueStrategy strategy = new EMFUpdateValueStrategy(); strategy.setConverter(new Converter(Object.class, ActionType.class) { @Override public Object convert(final Object fromObject) { if (fromObject instanceof ActionType) { final ActionType a = (ActionType) fromObject; final Action action = PrfFactory.eINSTANCE.createAction(); action.setType(a); return action; } else if (fromObject instanceof String) { return null; } throw new IllegalArgumentException(); } }); return strategy; } private List<Binding> bindRanges(final EObject input, final DataBindingContext context, final EditingDomain domain) { final BasicSimplePropertyComposite composite = (BasicSimplePropertyComposite) getComposite(); final List<Binding> retVal = new ArrayList<Binding>(); final Text minText = composite.getMinText().getText(); final Text maxText = composite.getMaxText().getText(); retVal.add(this.bindMin(context, minText)); retVal.add(this.bindMax(context, maxText)); retVal.addAll(this.bindButton(context, composite.getRangeButton(), minText, maxText)); // addRangeListener(); return retVal; } public List<Binding> bindButton(final DataBindingContext context, final Button rangeButton, final Text minText, final Text maxText) { final EMFUpdateValueStrategy targetToModel = new EMFUpdateValueStrategy(); targetToModel.setConverter(new Converter(Boolean.class, Range.class) { @Override public Object convert(final Object fromObject) { if ((Boolean) fromObject) { return PrfFactory.eINSTANCE.createRange(); } else { return null; } } }); final EMFUpdateValueStrategy modelToTarget = new EMFUpdateValueStrategy(); modelToTarget.setConverter(new Converter(Range.class, Boolean.class) { @Override public Object convert(final Object fromObject) { return fromObject != null; } }); final List<Binding> buttonBindings = new ArrayList<Binding>(); buttonBindings.add(context.bindValue(WidgetProperties.selection().observe(rangeButton), EMFEditObservables.observeValue(getEditingDomain(), this.input, this.property.getRange()), targetToModel, modelToTarget)); buttonBindings.add(context.bindValue(WidgetProperties.enabled().observe(minText), WidgetProperties.selection().observe(rangeButton))); buttonBindings.add(context.bindValue(WidgetProperties.enabled().observe(maxText), WidgetProperties.selection().observe(rangeButton))); return buttonBindings; } public Binding bindMin(final DataBindingContext context, final Text minText) { final IEMFEditValueProperty minProperty = EMFEditProperties.value(getEditingDomain(), FeaturePath.fromList(this.property.getRange(), PrfPackage.Literals.RANGE__MIN)); @SuppressWarnings({ "rawtypes", "unchecked" }) final IObservableValue minObserver = minProperty.observe(this.input); this.minBinding = context.bindValue(WidgetProperties.text(SWT.Modify).observeDelayed(SCAFormEditor.getFieldBindingDelay(), ((BasicSimplePropertyComposite) getComposite()).getMinText().getText()), minObserver, EMFEmptyStringToNullUpdateValueStrategy.INSTANCE, null); return this.minBinding; } public Binding bindMax(final DataBindingContext context, final Text maxText) { final IEMFEditValueProperty maxProperty = EMFEditProperties.value(getEditingDomain(), FeaturePath.fromList(this.property.getRange(), PrfPackage.Literals.RANGE__MAX)); @SuppressWarnings({ "rawtypes", "unchecked" }) final IObservableValue maxObserver = maxProperty.observe(this.input); this.maxBinding = context.bindValue(WidgetProperties.text(SWT.Modify).observeDelayed(SCAFormEditor.getFieldBindingDelay(), ((BasicSimplePropertyComposite) getComposite()).getMaxText().getText()), maxObserver, EMFEmptyStringToNullUpdateValueStrategy.INSTANCE, null); return this.maxBinding; } @Override protected void addListeners() { super.addListeners(); if (getComposite().getAddEnumButton() != null) { getComposite().getAddEnumButton().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleAddEnum(); } }); } if (getComposite().getEditEnumButton() != null) { getComposite().getEditEnumButton().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleEditEnumeration(); } }); } if (getComposite().getRemoveEnumButton() != null) { getComposite().getRemoveEnumButton().addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { handleRemoveEnumeration(); } }); } } @Override protected BasicSimplePropertyComposite getComposite() { return (BasicSimplePropertyComposite) super.getComposite(); } private Enumeration getEnumerationViewerSelection() { return (Enumeration) ((IStructuredSelection) getComposite().getEnumerationViewer().getSelection()).getFirstElement(); } public void handleAddEnum() { final EnumerationWizard wizard = new EnumerationWizard(); final WizardDialog dialog = new WizardDialog(getPage().getSite().getShell(), wizard); if (dialog.open() == Window.OK) { final Enumeration enumeration = wizard.getEnumeration(); if (enumeration != null) { Command command = null; if (input instanceof Simple) { Enumerations enums = ((Simple) this.input).getEnumerations(); if (enums == null) { enums = PrfFactory.eINSTANCE.createEnumerations(); enums.getEnumeration().add(enumeration); command = SetCommand.create(getEditingDomain(), this.input, PrfPackage.Literals.SIMPLE__ENUMERATIONS, enums); } else { command = AddCommand.create(getEditingDomain(), enums, PrfPackage.Literals.ENUMERATIONS__ENUMERATION, enumeration); } } execute(command); } } } protected void handleEditEnumeration() { final EnumerationWizard wizard = new EnumerationWizard(); final Enumeration enumeration = getEnumerationViewerSelection(); wizard.setEnumeration(enumeration); final WizardDialog dialog = new WizardDialog(getPage().getSite().getShell(), wizard); if (dialog.open() == Window.OK && input instanceof Simple) { Simple simple = (Simple) input; final Command command = ReplaceCommand.create(getEditingDomain(), simple.getEnumerations(), PrfPackage.Literals.ENUMERATIONS__ENUMERATION, enumeration, Collections.singleton(wizard.getEnumeration())); execute(command); } } protected void handleRemoveEnumeration() { Command command = null; if (input instanceof Simple) { Simple simple = (Simple) this.input; if (simple.getEnumerations() != null) { command = RemoveCommand.create(getEditingDomain(), simple.getEnumerations(), PrfPackage.Literals.ENUMERATIONS__ENUMERATION, getEnumerationViewerSelection()); if (simple.getEnumerations().getEnumeration().size() - 1 == 0) { command = SetCommand.create(getEditingDomain(), this.input, PrfPackage.Literals.SIMPLE__ENUMERATIONS, null); } } } if (command != null && command.canExecute()) { execute(command); } } }