Commit a0a29f85 authored by Saad bin Abid's avatar Saad bin Abid
Browse files

Extended the Signal aspect with new attributes. In Mira.ecore new attributes,...

Extended the Signal aspect with new attributes. In Mira.ecore new attributes, 1) initalValue, 2) rangeTo and 3) rangeFrom. Also extended the UI of Signal aspect. Initial attempt also made to put a new editor for functional aspect that will replace the existing graphical one.
parent 0d82f2aa
......@@ -2,7 +2,7 @@
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry excluding="org/fortiss/af3/mira/ui/constraints/RequirementBasicConstraintsUI.java" kind="src" path="src"/>
<classpathentry excluding="org/fortiss/af3/mira/ui/constraints/RequirementBasicConstraintsUI.java|org/fortiss/af3/mira/ui/constraints/SignalInitialValueConstraintUI.java" kind="src" path="src"/>
<classpathentry kind="src" path="test-src"/>
<classpathentry kind="output" path="build"/>
</classpath>
......@@ -127,6 +127,12 @@
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.DerivedRequirementSpecification">
</modelElementClass>
</modelElementHandler>
<modelElementHandler
handler="org.fortiss.af3.mira.ui.handler.AspectHandlers$FunctionalRequirementHandler">
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.FunctionalSpecification">
</modelElementClass>
</modelElementHandler>
<modelElementHandler
handler="org.fortiss.af3.mira.ui.handler.AspectHandlers$TimingRequirementHandler">
......@@ -406,6 +412,12 @@
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.Requirement">
</modelElementClass>
</modelEditorBinding>
<modelEditorBinding
binding="org.fortiss.af3.mira.ui.editorbinding.AspectBindings$FunctionalRequirementBinding">
<modelElementClass
modelElementClass="org.fortiss.af3.mira.model.Requirement">
</modelElementClass>
</modelEditorBinding>
<modelEditorBinding
binding="org.fortiss.af3.mira.ui.editorbinding.AspectBindings$TimingRequirementBinding">
......
......@@ -30,6 +30,7 @@ import org.fortiss.af3.mira.constraints.OnlyOneSILConstraint;
import org.fortiss.af3.mira.constraints.ParameterTypeConstraint;
import org.fortiss.af3.mira.constraints.RationaleConstraint;
import org.fortiss.af3.mira.constraints.RequirementContainsTestSuiteConstraint;
import org.fortiss.af3.mira.constraints.SignalConstraints.SignalInitialValueConstraint;
import org.fortiss.af3.mira.constraints.SignalConstraints.SignalTypeConstraint;
import org.fortiss.af3.mira.constraints.SignalConstraints.UniqueSignalNameConstraint;
import org.fortiss.af3.mira.constraints.SourceConstraint;
......@@ -45,6 +46,7 @@ import org.fortiss.af3.mira.ui.constraints.OnlyOneSILConstraintUI;
import org.fortiss.af3.mira.ui.constraints.ParameterTypeConstraintUI;
import org.fortiss.af3.mira.ui.constraints.RationaleConstraintUI;
import org.fortiss.af3.mira.ui.constraints.RequirementContainsTestSuiteConstraintUI;
import org.fortiss.af3.mira.ui.constraints.SignalConstraintsUI.SignalInitialValueConstraintUI;
import org.fortiss.af3.mira.ui.constraints.SignalConstraintsUI.SignalTypeConstraintUI;
import org.fortiss.af3.mira.ui.constraints.SignalConstraintsUI.UniqueSignalNameConstraintUI;
import org.fortiss.af3.mira.ui.constraints.SourceConstraintUI;
......@@ -118,6 +120,8 @@ public class AF3MiraUIActivator extends AbstractUIPlugin {
IConstraintUIService.getInstance().registerConstraintUI(
IdentifiedInputOutputDefinedConstraintUI.class,
IdentifiedInputOutputDefinedConstraint.class);
IConstraintUIService.getInstance().registerConstraintUI(
SignalInitialValueConstraintUI.class, SignalInitialValueConstraint.class);
}
/** {@inheritDoc} */
......
......@@ -154,4 +154,27 @@ public class SignalConstraintsUI {
return super.fixes(ci, status);
}
}
/**
*
* @author abid
* @author $Author$
* @version $Rev$
* @ConQAT.Rating RED Hash:
*/
public static class SignalInitialValueConstraintUI extends ConstraintUIBaseAutocheck {
/** {@inheritDoc} */
@Override
public String getDescription() {
return "All signals should have initial value same as data type, the initial value should be between ranges (i.e., from-to) and for boolean data type initial value should be true/false";
}
/** {@inheritDoc} */
@Override
public boolean shouldBeManuallyActivated() {
return true;
}
}
}
/*--------------------------------------------------------------------------+
$Id$
| |
| Copyright 2011 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.mira.ui.editor;
import static org.eclipse.core.runtime.IStatus.ERROR;
import static org.eclipse.jface.dialogs.ErrorDialog.openError;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickFirstInstanceOf;
import static org.fortiss.tooling.kernel.utils.EcoreUtils.pickInstanceOf;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.conqat.ide.commons.ui.jface.TreeContentProviderBase;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.EditingSupport;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.actions.TextStyledTextActionHandler;
import org.fortiss.af3.expression.language.ParseException;
import org.fortiss.af3.expression.ui.databinding.convert.StringToTypeConverter;
import org.fortiss.af3.expression.ui.databinding.convert.TypeToStringConverter;
import org.fortiss.af3.mira.model.FunctionalComponent;
import org.fortiss.af3.mira.model.FunctionalSpecification;
import org.fortiss.af3.mira.model.MiraFactory;
import org.fortiss.af3.mira.model.Requirement;
import org.fortiss.af3.project.model.typesystem.IType;
import org.fortiss.tooling.base.model.element.IModelElementSpecification;
import org.fortiss.tooling.base.ui.ToolingBaseUIActivator;
import org.fortiss.tooling.base.ui.editor.TextCellEditorWithTextStyledTextActionHandler;
import org.fortiss.tooling.kernel.extension.data.ITopLevelElement;
import org.fortiss.tooling.kernel.service.IPersistencyService;
import org.fortiss.tooling.kernel.ui.service.IActionService;
import org.fortiss.tooling.kernel.ui.util.SelectionUtils;
/**
* Editor for the functional specification aspect of a {@link Requirement}.
*
* @author mou
* @author $Author$
* @version $Rev$
* @ConQAT.Rating RED Hash: C365E7C32968869DFCEF1D6C7E09FE75
*/
public class FunctionalRequirementEditor<T extends Requirement> extends AspectEditorBase<T> {
/** The edited functional specification. */
private FunctionalSpecification funcSpec;
/** Default text displayed in the functional component table. */
private static final String CLICK_TO_ADD_A_NEW_FUNCTIONALCOMPONENT =
"Click to add a new functional component";
/**
* The tree viewer displaying the functional component. Only used as a table, but we use trees
* because it does
* not cost anything.
*/
private TreeViewer viewer;
/** The text styled handler for editing support. */
private Supplier<TextStyledTextActionHandler> getTextStyledTextActionHandler;
/** Top level element for the edited object. */
private ITopLevelElement top;
/** {@inheritDoc} */
@Override
protected void createAspectSection() {
EList<IModelElementSpecification> specs = editedObject.getSpecifications();
funcSpec = pickFirstInstanceOf(FunctionalSpecification.class, specs);
addFunctionalSpecificationSection(funcSpec);
}
/** Section for mode definition. */
private Composite addFunctionalSpecificationSection(FunctionalSpecification ms) {
Composite funcSection =
createNewSection("Functional Component",
"This requirement defines the following functional component:");
funcSection.setLayout(new GridLayout(1, false));
viewer = new TreeViewer(funcSection, SWT.BORDER | SWT.FULL_SELECTION);
Tree tree = viewer.getTree();
GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).minSize(300, 300)
.applyTo(tree);
tree.setLinesVisible(true);
tree.setHeaderVisible(true);
TreeViewerColumn nameColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn trclmnMode = nameColumn.getColumn();
trclmnMode.setWidth(300);
trclmnMode.setText("Name");
nameColumn.setLabelProvider(new ColumnLabelProvider() {
/** {@inheritDoc} */
@Override
public String getText(Object element) {
if(element instanceof FakeChild) {
return "Click to add a functional component..";
}
return funcSpec.getFunctionalComponent().get((Integer)element).getName();
}
});
nameColumn.setEditingSupport(createNameEditingSupport(viewer, nameColumn));
// TreeViewerColumn ioColumn = new TreeViewerColumn(viewer, SWT.NONE);
// TreeColumn ioColType = ioColumn.getColumn();
// ioColType.setWidth(120);
// ioColType.setText("Input/Output");
// ioColumn.setLabelProvider(new ColumnLabelProvider() {
// /** {@inheritDoc} */
// @Override
// public String getText(Object element) {
// return getIOName(element);
// }
// });
// ioColumn.setEditingSupport(createFunctionalSpecificationSupport(viewer, ioColumn));
TreeViewerColumn typeColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn trColType = typeColumn.getColumn();
trColType.setWidth(100);
trColType.setText("Type");
typeColumn.setLabelProvider(new ColumnLabelProvider() {
/** {@inheritDoc} */
@Override
public String getText(Object element) {
String txt = "";
if(element instanceof FunctionalComponent) {
IType type = ((FunctionalComponent)element).getComponentType();
txt = type == null ? "" : type.toString();
}
return txt;
}
});
typeColumn.setEditingSupport(createTypeEditingSupport(funcSpec.getFunctionalComponent(),
top, viewer, typeColumn));
viewer.setContentProvider(new TreeContentProviderBase() {
@Override
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof List<?>) {
List<Object> range = new ArrayList<Object>();
range.add(new FakeChild());
range.addAll(IntStream.rangeClosed(0, ms.getFunctionalComponent().size() - 1)
.boxed().collect(Collectors.toList()));
return range.toArray();
}
return new Object[0];
}
});
viewer.getControl().addKeyListener(new ViewerKeyAdapter());
viewer.setInput(funcSpec.getFunctionalComponent());
return funcSection;
}
/** Gets the string representation of the I/O information of a given functional component. */
private String getIOName(Object elt) {
String txt = "";
if(elt instanceof FunctionalComponent) {
txt = ((FunctionalComponent)elt).isOutput() ? "Input" : "Output";
}
return txt;
}
/** Fake child used to add new elements. */
private static class FakeChild {
// Nothing to implement: just a marker class
}
/**
* Checks if the name is empty or already exists among current modes, if so displays an error
* message and return true, otherwise returns false.
*/
private boolean emptyOrAlreadyExists(String name) {
if(name.equals("") || name.equals(CLICK_TO_ADD_A_NEW_FUNCTIONALCOMPONENT)) {
Status status =
new Status(ERROR, ToolingBaseUIActivator.PLUGIN_ID, 0,
"Functional Component name is not valid.", null);
openError(Display.getCurrent().getActiveShell(), "Error", null, status);
return true;
}
List<String> functionalCompNames =
funcSpec.getFunctionalComponent().stream().map(c -> c.getName().toLowerCase())
.collect(Collectors.toList());
if(functionalCompNames.contains(name.toLowerCase()) ||
name.toLowerCase().equals(CLICK_TO_ADD_A_NEW_FUNCTIONALCOMPONENT)) {
Status status =
new Status(ERROR, ToolingBaseUIActivator.PLUGIN_ID, 0,
"A Functional Component with this name already exists.", null);
openError(Display.getCurrent().getActiveShell(), "Error", null, status);
return true;
}
return false;
}
/** {@link EditingSupport} for the name column. */
private EditingSupport createNameEditingSupport(TreeViewer viewer,
TreeViewerColumn funcCompColumn) {
top = IPersistencyService.getInstance().getTopLevelElementFor(getEditedObject());
return new EditingSupport(funcCompColumn.getViewer()) {
@Override
protected void setValue(Object element, Object value) {
if(element instanceof Integer) {
FunctionalComponent funcComp =
funcSpec.getFunctionalComponent().get((Integer)element);
if(funcComp.getName().equals(value)) {
return;
}
top.runAsCommand(() -> {
funcComp.setName((String)value);
viewer.refresh();
});
} else {
if(!emptyOrAlreadyExists((String)value)) {
top.runAsCommand(() -> {
FunctionalComponent newFuncComp =
MiraFactory.eINSTANCE.createFunctionalComponent();
newFuncComp.setName((String)value);
funcSpec.getFunctionalComponent().add(newFuncComp);
viewer.refresh();
});
}
}
}
@Override
protected Object getValue(Object element) {
return element instanceof Integer ? funcSpec.getFunctionalComponent().get(
(Integer)element) : "";
}
@Override
protected CellEditor getCellEditor(Object element) {
return new TextCellEditorWithTextStyledTextActionHandler(
getTextStyledTextActionHandler(), (Composite)getViewer().getControl());
}
@Override
protected boolean canEdit(Object element) {
return true;
}
};
}
/** {@link EditingSupport} for the type column. */
private EditingSupport createTypeEditingSupport(List<FunctionalComponent> functionalComponent,
ITopLevelElement top, TreeViewer viewer, TreeViewerColumn typeColumn) {
return new EditingSupport(typeColumn.getViewer()) {
@Override
protected void setValue(Object element, Object value) {
IType t;
for(FunctionalComponent functionalComp : functionalComponent) {
try {
t = new StringToTypeConverter(functionalComp).convert(value);
} catch(ParseException e) {
t = null;
}
final IType typeToSet = t;
top.runAsCommand(() -> {
((FunctionalComponent)element).setComponentType(typeToSet);
viewer.refresh();
});
}
}
@Override
protected Object getValue(Object element) {
return new TypeToStringConverter().convert(((FunctionalComponent)element)
.getComponentType());
}
@Override
protected CellEditor getCellEditor(Object element) {
return new TextCellEditorWithTextStyledTextActionHandler(
getTextStyledTextActionHandler.get(), (Composite)getViewer().getControl());
}
@Override
protected boolean canEdit(Object element) {
return element instanceof FunctionalComponent;
}
};
}
/** Key adapter to deal with copy/paste/delete/... done through the keyboard. */
public class ViewerKeyAdapter extends KeyAdapter {
/** Constructor. */
public ViewerKeyAdapter() {
}
/** {@inheritDoc} */
@Override
public void keyReleased(KeyEvent e) {
if(e.keyCode == SWT.DEL) {
Integer modeIdx =
SelectionUtils.checkAndPickFirst(viewer.getSelection(), Integer.class);
if(modeIdx != null) {
top.runAsCommand(() -> {
funcSpec.getFunctionalComponent().remove(modeIdx.intValue());
});
viewer.refresh();
}
} else if((e.stateMask & SWT.CTRL) != 0 && e.keyCode == 0x7A) {
IActionService.getInstance().runGlobalUndoAction();
} else if((e.stateMask & SWT.CTRL) != 0 && e.keyCode == 0x79) {
IActionService.getInstance().runGlobalRedoAction();
}
}
}
/** {@inheritDoc} */
@Override
protected List<IModelElementSpecification> getElementsToDelete() {
ArrayList<IModelElementSpecification> res = new ArrayList<>();
res.addAll(pickInstanceOf(FunctionalSpecification.class, editedObject.getSpecifications()));
return res;
}
}
......@@ -163,6 +163,7 @@ public class ParameterDefinitionEditor<T extends Requirement> extends AspectEdit
});
}
});
return parameterSection;
}
......
......@@ -54,9 +54,20 @@ public class SignalDefinitionEditor<T extends Requirement> extends AspectEditorB
Composite signalSection =
createNewSection("Signals", "This requirement defines the following signals:");
signalSection.setLayout(new GridLayout(1, false));
// Composite associationSection =
// createNewSection(
// "This Section will provide list of associated Functional Requirements:",
// "Associated Functional Requirement(s):");
// associationSection.setLayout(new GridLayout(1, false));
// createFunctionalRequirementEdit(associationSection);
// createFunctionalRequirementEdit();
SignalsViewer viewer =
new SignalsViewer(signalSection, scs, () -> getTextStyledTextActionHandler());
viewer.getViewer().setInput(scs.getSignals());
return signalSection;
}
......@@ -68,4 +79,25 @@ public class SignalDefinitionEditor<T extends Requirement> extends AspectEditorB
editedObject.getSpecifications()));
return res;
}
/** Create a single line field of a associated functional requirement. */
/** Edit requirement ID. */
// private void createFunctionalRequirementEdit() {
// Composite funcReqcomposite =
// createNewSection(
// "This Section will provide list of associated Functional Requirements:",
// "Associated Functional Requirement(s):");
// funcReqcomposite.setLayout(new GridLayout(2, false));
// Label funcReqInputLabel = toolkit.createLabel(funcReqcomposite, "Id ", SWT.READ_ONLY);
// singleLineLabelFactory.applyTo(funcReqInputLabel);
//
// Text funcReqInput = toolkit.createText(funcReqcomposite, "", SWT.BORDER);
// singleLineInputFactory.applyTo(funcReqInput);
// funcReqInput.setData(DECORATION_KEY,
// new ControlDecoration(funcReqInput, SWT.LEFT | SWT.TOP));
// performComplexTextBinding(dbc, funcReqInput,
// observeValue(editedObject, SIGNAL__ASSIGNED_TO), null, null, null, null);
// registeredTextFields.add(funcReqInput);
// }
}
......@@ -109,12 +109,10 @@ public class SignalsViewer extends FilteredTree {
.applyTo(tree);
tree.setLinesVisible(true);
tree.setHeaderVisible(true);
TreeViewerColumn nameColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn trclmnName = nameColumn.getColumn();
trclmnName.setWidth(300);
trclmnName.setText("Name");
nameColumn.setLabelProvider(new ColumnLabelProvider() {
/** {@inheritDoc} */
@Override
......@@ -124,7 +122,6 @@ public class SignalsViewer extends FilteredTree {
});
nameColumn.setEditingSupport(createNameEditingSupport(signalsContainer, top, viewer,
nameColumn));
TreeViewerColumn ioColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn ioColType = ioColumn.getColumn();
ioColType.setWidth(120);
......@@ -136,23 +133,6 @@ public class SignalsViewer extends FilteredTree {
return getIOName(element);
}
});
ioColumn.setEditingSupport(createIOEditingSupport(top, viewer, ioColumn));
// adding InitialValueColumn
TreeViewerColumn initialValueColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn initValColType = initialValueColumn.getColumn();
initValColType.setWidth(120);
initValColType.setText("Initial-Value");
initialValueColumn.setLabelProvider(new ColumnLabelProvider() {
/** {@inheritDoc} */
@Override
public String getText(Object element) {
return getInitialValue(element);
}
});
initialValueColumn.setEditingSupport(createInitialValueEditingSupport(top, viewer,
initialValueColumn));
TreeViewerColumn typeColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn trColType = typeColumn.getColumn();
trColType.setWidth(100);
......@@ -171,12 +151,51 @@ public class SignalsViewer extends FilteredTree {
});
typeColumn.setEditingSupport(createTypeEditingSupport(signalsContainer, top, viewer,
typeColumn));
ioColumn.setEditingSupport(createIOEditingSupport(top, viewer, ioColumn));
// adding InitialValueColumn
TreeViewerColumn initialValueColumn = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn initValColType = initialValueColumn.getColumn();
initValColType.setWidth(120);
initValColType.setText("Initial Value");
initialValueColumn.setLabelProvider(new ColumnLabelProvider() {
/** {@inheritDoc} */
@Override
public String getText(Object element) {
return getInitialValue(element);
}
});
initialValueColumn.setEditingSupport(createInitialValueEditingSupport(top, viewer,
initialValueColumn));
// adding rangeColumnFrom
TreeViewerColumn rangeValueColumnFrom = new TreeViewerColumn(viewer, SWT.NONE);
TreeColumn rangeColumnTypeFrom = rangeValueColumnFrom.getColumn();
rangeColumnTypeFrom.setText("Range (From)");
rangeColumnTypeFrom.setWidth(120);
rangeValueColumnFrom.setLabelProvider(new ColumnLabelProvider() {