Commit 4d1debad authored by fortissBot's avatar fortissBot
Browse files

cleanup of port property section. Pulled out initial value into its own Property section.

refs 3020
parent 75668aa4
......@@ -161,6 +161,16 @@
type="org.fortiss.af3.component.model.Port">
</input>
</propertySection>
<propertySection
afterSection="org.fortiss.af3.component.ui.properties.PortSpecificationPropertySection"
class="org.fortiss.af3.component.ui.properties.PortInitValueSection"
enablesFor="1"
id="org.fortiss.af3.component.ui.properties.PortInitValueSection"
tab="org.fortiss.tooling.kernel.ui.property.tab.general">
<input
type="org.fortiss.af3.component.model.Port">
</input>
</propertySection>
<propertySection
afterSection="org.fortiss.tooling.kernel.ui.internal.properties.NamedCommentedPropertySection"
class="org.fortiss.af3.component.ui.properties.ComponentSpecificationPropertySection"
......
/*--------------------------------------------------------------------------+
$Id: codetemplates.xml 1 2011-01-01 00:00:01Z hoelzl $
| |
| Copyright 2017 fortiss GmbH |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
+--------------------------------------------------------------------------*/
package org.fortiss.af3.component.ui.properties;
import static org.fortiss.af3.component.ui.utils.ComponentCompletionProposalUtils.createInitialValueProposals;
import java.util.function.Function;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.fortiss.af3.component.model.Component;
import org.fortiss.af3.component.model.OutputPort;
import org.fortiss.af3.component.model.Port;
import org.fortiss.af3.component.model.PortSpecification;
import org.fortiss.af3.component.model.impl.AF3ComponentPackageImpl;
import org.fortiss.af3.expression.model.terms.IExpressionTerm;
import org.fortiss.af3.expression.ui.complexdata.ComplexDataDialog;
import org.fortiss.af3.expression.ui.complexdata.ComplexDataDialogButtonEnableListener;
import org.fortiss.af3.expression.ui.databinding.convert.ITermToStringConverter;
import org.fortiss.af3.expression.ui.databinding.convert.StringToIExpressionTermConverter;
import org.fortiss.af3.expression.ui.databinding.validate.StringToIExpressionTermValidator;
import org.fortiss.tooling.base.ui.fieldassist.FieldAssist;
import org.fortiss.tooling.base.ui.fieldassist.ProposalProviderBase;
import org.fortiss.tooling.kernel.service.ICommandStackService;
import org.fortiss.tooling.kernel.ui.extension.base.PropertySectionBase;
import org.fortiss.tooling.kernel.ui.util.DataBindingUtils;
import org.fortiss.tooling.kernel.ui.util.ObservableUtils;
/**
* @author lazyBisa
* @author $Author: hoelzl $
* @version $Rev: 18709 $
* @ConQAT.Rating YELLOW Hash: A89899BB1B061BDA6B2C7E585A55CF29
*/
@SuppressWarnings("javadoc")
public class PortInitValueSection extends PropertySectionBase {
// MODEL ELEMENTS
private Port port;
private PortSpecification spec;
// WIDGETS
private Text initialValueText;
/** helper dialog to initialise structure members */
private Button structInitHelperButton;
/** listener to enable or disable the struct InitHelper button */
private ComplexDataDialogButtonEnableListener buttonEnabler;
public PortInitValueSection() {
}
/** {@inheritDoc} */
@Override
public void createControls(Composite parent, TabbedPropertySheetPage tabbedPropertySheetPage) {
super.createControls(parent, tabbedPropertySheetPage);
initialValueText =
createDecoratedText("Initial value", SWT.MULTI | SWT.BORDER | SWT.WRAP |
SWT.V_SCROLL);
structInitHelperButton = createDecoratedButton("...", initialValueText);
structInitHelperButton.addSelectionListener((SSL)e -> openComplexDataDialog());
buttonEnabler = new ComplexDataDialogButtonEnableListener(null, structInitHelperButton);
new FieldAssist(initialValueText, mkPP(word -> createInitialValueProposals(spec)));
composite.pack();
}
/** {@inheritDoc} */
@Override
protected void setSectionInput(Object input) {
if(input instanceof Port) {
this.port = (Port)input;
this.spec = port.getPortSpecification();
this.buttonEnabler.listenTo(this.spec,
AF3ComponentPackageImpl.Literals.PORT_SPECIFICATION__TYPE);
} else {
this.buttonEnabler.unlisten();
this.port = null;
this.spec = null;
}
}
@Override
public void refresh() {
super.refresh();
/**
* These controls depends on the port parent component: if the parent component
* is strong causal, the input value can be specified; if the parent component
* is not strong causal, the input value should be disabled.
*/
IObservableValue initValue =
ObservableUtils.observeValue(this.spec,
AF3ComponentPackageImpl.Literals.PORT_SPECIFICATION__INITIAL_VALUE);
DataBindingUtils.performComplexTextBinding(super.dbc, this.initialValueText, initValue,
new ITermToStringConverter(), new StringToIExpressionTermConverter(this.spec),
new StringToIExpressionTermValidator(this.spec), null);
boolean isEnabled =
((Component)port.getOwner()).isStronglyCausal() && port instanceof OutputPort;
initialValueText.setEnabled(isEnabled);
}
/** {@inheritDoc} */
@Override
public void dispose() {
super.dispose();
if(buttonEnabler != null)
buttonEnabler.dispose();
}
/** Open complex data dialog to display complex data. */
private void openComplexDataDialog() {
final IExpressionTerm initialValue =
ComplexDataDialog.openCDD(composite.getShell(), dbc, "Initial Value", spec
.getType().toString(), spec, spec.getType(), spec.getInitialValue(), true);
if(initialValue != null) {
ICommandStackService.getInstance().runAsCommand(spec, new Runnable() {
@Override
public void run() {
spec.setInitialValue(initialValue);
}
});
}
refresh();
}
/**
* Simple Selection Listener interface which provides a default (empty) implementation of
* widgedDefaultSelected. This way you can provide lambdas and method references as selection
* listeners by writing (SSL) e -> foo().
*
* @author lazyBisa
* @author $Author: hoelzl $
* @version $Rev: 18709 $
* @ConQAT.Rating RED Hash:
*/
@FunctionalInterface
private interface SSL extends SelectionListener {
/** {@inheritDoc} */
@Override
default public void widgetDefaultSelected(SelectionEvent e) {
// default is to do nothing. Documentation even states that this method might never be
// called.
}
}
/**
* Constructs a proposal provider with the supplied provider function. Uses whitespace policies
* from ProposalProviderBase.
*/
private static ProposalProviderBase mkPP(Function<String, String[]> provider) {
return new ProposalProviderBase() {
@Override
public String[] getProposals(String currentWord) {
return provider.apply(currentWord);
}
};
}
}
......@@ -17,14 +17,9 @@ $Id$
+--------------------------------------------------------------------------*/
package org.fortiss.af3.component.ui.properties;
import static org.conqat.ide.commons.ui.databinding.JFaceObservables.observeControlDecoration;
import static org.fortiss.af3.component.AF3ComponentActivator.getDefault;
import static org.fortiss.af3.component.ui.AF3ComponentUIActivator.PLUGIN_ID;
import static org.fortiss.af3.component.ui.properties.PortDataPropagation.getPortsToPropagate;
import static org.fortiss.af3.component.ui.utils.ComponentCompletionProposalUtils.createInitialValueProposals;
import static org.fortiss.af3.expression.utils.ExpressionUtils.getAllVisibleTypes;
import static org.fortiss.tooling.kernel.ui.util.DataBindingUtils.DECORATION_KEY;
import static org.fortiss.tooling.kernel.ui.util.WidgetsFactory.createTextWithUndo;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.copy;
import static org.fortiss.tooling.kernel.utils.LoggingUtils.error;
......@@ -32,11 +27,8 @@ import java.util.List;
import java.util.stream.Collectors;
import org.conqat.lib.commons.collections.Pair;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
......@@ -49,38 +41,25 @@ import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Text;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.fortiss.af3.component.model.Channel;
import org.fortiss.af3.component.model.Component;
import org.fortiss.af3.component.model.OutputPort;
import org.fortiss.af3.component.model.Port;
import org.fortiss.af3.component.model.PortSpecification;
import org.fortiss.af3.component.ui.AF3ComponentUIActivator;
import org.fortiss.af3.expression.language.ParseException;
import org.fortiss.af3.expression.model.DataDictionary;
import org.fortiss.af3.expression.model.terms.IExpressionTerm;
import org.fortiss.af3.expression.model.types.TInt;
import org.fortiss.af3.expression.ui.complexdata.ComplexDataDialog;
import org.fortiss.af3.expression.ui.complexdata.ComplexDataDialogButtonEnableListener;
import org.fortiss.af3.expression.ui.databinding.convert.StringToIExpressionTermConverter;
import org.fortiss.af3.expression.ui.databinding.validate.StringToIExpressionTermWithTypeCheckValidatorBase;
import org.fortiss.af3.expression.ui.editor.DataDictionaryEditorGUI;
import org.fortiss.af3.expression.utils.DataDictionaryUtils;
import org.fortiss.af3.expression.utils.ExpressionUtils;
import org.fortiss.af3.project.model.typesystem.IType;
import org.fortiss.tooling.base.model.element.IModelElementSpecification;
import org.fortiss.tooling.base.ui.fieldassist.FieldAssist;
import org.fortiss.tooling.base.ui.fieldassist.ProposalProviderBase;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.ICommandStackService;
import org.fortiss.tooling.kernel.service.IPersistencyService;
import org.fortiss.tooling.kernel.ui.extension.base.PropertySectionBase;
import org.fortiss.tooling.kernel.ui.service.IModelEditorBindingService;
......@@ -89,41 +68,17 @@ import org.fortiss.tooling.kernel.ui.util.WidgetsFactory;
/**
* Property section for {@link PortSpecification}s.
*
* TODO: USE DATABINDINGS, OMG
*
* @author eder
* @author $Author$
* @version $Rev$
* @ConQAT.Rating YELLOW Hash: 0B79C0E6BCB1590B5946B58653C132DC
* @ConQAT.Rating YELLOW Hash: AD268AFF9EF744E9FF9FFB751C9092DF
*/
@SuppressWarnings("javadoc")
public final class PortSpecificationPropertySection extends PropertySectionBase implements
PortDataPropagation.PortDataAccess {
/** Top level element for all transactions. */
private ITopLevelElement topLevel;
/** The selected {@link PortSpecification}. */
protected PortSpecification spec;
/** All the specifications of the port. Useful for propagation. */
private EList<IModelElementSpecification> allSpecs;
/** Port type combo widget. */
private ComboViewer typeComboViewer;
/** Button of Structure */
private Button structButton;
/** Port initial value widget. */
private Text initialValueText;
/** listener to enable or disable struct button */
private ComplexDataDialogButtonEnableListener buttonEnabler;
/** data propagation buttons */
private PortDataPropagation propagate;
/** The port. */
private Port port;
/**
* <p>
* Flag to know whether the input is made programmatically in this class or by the user.
......@@ -132,53 +87,34 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
* Needed because a "selected" event / text changed event is triggered in all cases and we do
* not want to register any transaction if the change does not come from the user. Not so nice
* but the interface of the {@link ComboViewer} / {@link Text} does not provide any tool
* allowing to do better.
* allowing to do better. TODO: WTF, DATABINDINGS?
* </p>
*/
private boolean userInput;
/**
* Boolean flag determining if the initial value controls (comboviewer and text)
* should be enabled or disabled.
* These controls depends on the port parent component: if the parent component
* is strong causal, the input value can be specified; if the parent component
* is not strong causal, the input value should be disabled.
*/
private boolean initialValueEnabled = false;
// MODEL ELEMENTS
private Port port;
private PortSpecification spec;
/** Control for the label of the initial value. */
private Control initialValueLabel;
/** Top level element, needed for transactions. */
private ITopLevelElement topLevel;
/** Button to go to the type. */
private Button typeButton;
// WIDGETS
/** Type Selection */
private ComboViewer typeComboViewer;
/** data propagation buttons */
private PortDataPropagation propagate;
/** Button to go to the type. */
private Button goToTypeButton;
/** Composite for variable bounds specification */
private Composite variableBounds;
/** Text field for upper bound value. */
private Text upperBound;
/** Text field for lower bound value. */
private Text lowerBound;
/** Composite for variable bounds specification */
private Composite variableBounds;
/** {@inheritDoc} */
@Override
public PortSpecification getPortSpecification() {
return spec;
}
/** {@inheritDoc} */
@Override
public EList<IModelElementSpecification> getSpecifications() {
return allSpecs;
}
/** {@inheritDoc} */
@Override
public Port getPort() {
return (Port)spec.eContainer();
}
/** {@inheritDoc} */
@Override
public void createControls(Composite parent, TabbedPropertySheetPage aTabbedPropertySheetPage) {
......@@ -190,15 +126,15 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
typeComboViewer.setComparator(new ViewerComparator() {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
return selectedTypeIsEqual(e1, e2);
return compareTypes(e1, e2);
}
});
typeButton = getWidgetFactory().createButton(composite, "Go to type", SWT.NONE);
createFormEntry(typeButton, "");
GridDataFactory.defaultsFor(typeButton).hint("Go to type".length() * 10, SWT.DEFAULT)
.align(SWT.BEGINNING, SWT.BEGINNING).applyTo(typeButton);
typeButton.addSelectionListener(new SelectionListener() {
goToTypeButton = getWidgetFactory().createButton(composite, "Go to type", SWT.NONE);
createFormEntry(goToTypeButton, "");
GridDataFactory.defaultsFor(goToTypeButton).hint("Go to type".length() * 10, SWT.DEFAULT)
.align(SWT.BEGINNING, SWT.BEGINNING).applyTo(goToTypeButton);
goToTypeButton.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
......@@ -211,34 +147,6 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
}
});
initialValueText = createTextWithUndo(getWidgetFactory(), composite, "");
initialValueText.setData(DECORATION_KEY, new ControlDecoration(initialValueText, SWT.LEFT |
SWT.TOP));
initialValueLabel = createFormEntryAndReturnLabel(initialValueText, "Initial value");
initialValueText.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if(userInput) {
topLevel.runAsCommand(new Runnable() {
@Override
public void run() {
initialValueSelectionChangeHandler();
}
});
}
}
});
structButton = createDecoratedButton("...", initialValueText);
structButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
openComplexDataDialog();
}
});
buttonEnabler = new ComplexDataDialogButtonEnableListener(spec, structButton);
typeComboViewer.addSelectionChangedListener(buttonEnabler);
typeComboViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
......@@ -255,7 +163,6 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
propagate = new PortDataPropagation(getWidgetFactory(), composite, this);
createFormEntry(propagate.createPropagationControls(), "Propagate data");
setupFieldAssist();
variableBounds = getWidgetFactory().createComposite(composite);
variableBounds.setLayout(new GridLayout(3, false));
......@@ -298,7 +205,7 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
IType selectedType = (IType)selection.getFirstElement();
if(!isBuiltInType(selectedType)) {
DataDictionary dd = DataDictionaryUtils.findDataDictionary(port);
typeButton.setEnabled(true);
goToTypeButton.setEnabled(true);
IModelEditorBindingService.getInstance().openInEditor(dd);
DataDictionaryEditorGUI.setFilteredTree(selectedType.toString());
}
......@@ -330,7 +237,7 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
private void typeSelectionChangeHandler() {
IStructuredSelection selection = (IStructuredSelection)typeComboViewer.getSelection();
IType selectedType = (IType)selection.getFirstElement();
if(selectedTypeIsEqual(selectedType, spec.getType()) != 0) {
if(!typesAreEqual(selectedType, spec.getType())) {
spec.setType(copy(selectedType));
for(Pair<Channel, Port> c : getPortsToPropagate(port, getPart())) {
c.getSecond().getPortSpecification().setType(copy(selectedType));
......@@ -351,9 +258,6 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
return;
}
buttonEnabler.setContext(spec);
buttonEnabler.selectionChanged(new SelectionChangedEvent(typeComboViewer, typeComboViewer
.getSelection()));
refreshGotoTypeButton();
refreshBoundsControls();
......@@ -362,12 +266,8 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
typeComboViewer.setInput(types);
typeComboViewer.setSelection(new StructuredSelection(types.stream()
.filter(t -> this.selectedTypeIsEqual(t, spec.getType()) == 0)
.collect(Collectors.toList())));
initialValueText.setText(initialValueEnabled ? spec.getInitialValue().toString() : "");
.filter(t -> typesAreEqual(t, spec.getType())).collect(Collectors.toList())));
userInput = true;
initialValueText.setEnabled(initialValueEnabled);
initialValueLabel.setEnabled(initialValueEnabled);
propagate.refresh(port);
}
......@@ -381,7 +281,6 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
if(input instanceof Port) {
port = (Port)input;
spec = ((Port)input).getPortSpecification();
allSpecs = ((Port)input).getSpecifications();
}
if(spec == null) {
......@@ -390,8 +289,6 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
} else {
// Check if the parent component of the port is strong causal or not.
try {
Component component = (Component)port.getOwner();
initialValueEnabled = component.isStronglyCausal() && port instanceof OutputPort;
refreshBoundsControls();
} catch(ClassCastException ex) {
error(getDefault(), "The port parent component was not found.", ex);
......@@ -415,7 +312,7 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
/** need to disable for non-dictionary types */
private void refreshGotoTypeButton() {
typeButton.setEnabled(!isBuiltInType(spec.getType()));
goToTypeButton.setEnabled(!isBuiltInType(spec.getType()));
}
/** enables the Bound controls */
......@@ -430,40 +327,6 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
upperBound.setEnabled(false);
}
/** Handles changes in the initial value selection. */
private void initialValueSelectionChangeHandler() {
String text = initialValueText.getText();
IExpressionTerm initialValue = null;
IStatus status = null;
try {
initialValue = new StringToIExpressionTermConverter(spec).convertBase(text);
status = new InitialValueValidator().validate(text);
} catch(ParseException e) {
status = new Status(IStatus.ERROR, PLUGIN_ID, "Parse error");
}
ControlDecoration controlData = (ControlDecoration)initialValueText.getData(DECORATION_KEY);
observeControlDecoration(controlData).setValue(status);
if(status.isOK()) {
if(initialValue != null && !(initialValue.equals(spec.getInitialValue()))) {
spec.setInitialValue(copy(initialValue));
for(Pair<Channel, Port> c : getPortsToPropagate(port, getPart())) {
c.getSecond().getPortSpecification().setInitialValue(copy(initialValue));
}
}
}
}
/** Creates {@link FieldAssist} for text fields. */
private void setupFieldAssist() {
new FieldAssist(initialValueText, new ProposalProviderBase() {
@Override
/** {@inheritDoc} */
public String[] getProposals(String currentWord) {
return createInitialValueProposals(spec);
}
});
}
/** {@inheritDoc} */
@Override
protected void disableControls() {
......@@ -492,54 +355,37 @@ public final class PortSpecificationPropertySection extends PropertySectionBase
channel.setName(port.getName());
}
/** Validator for initial port value. */
private class InitialValueValidator extends StringToIExpressionTermWithTypeCheckValidatorBase {
/** Constructor. */
public InitialValueValidator() {
super(spec);
}