Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ It has long been unused by Sirius Web itself (since the transition to MUI).
- https://github.com/eclipse-syson/syson/issues/2237[#2237] [diagrams] Fix the item label inside `frames`, `require constraints`, and `assume constraints` compartments.
- https://github.com/eclipse-syson/syson/issues/2278[#2278] [diagrams] Display inherited behavior parameters in the _parameters_ compartment of `ActionDefinition` and `ActionUsage` graphical nodes.
- https://github.com/eclipse-syson/syson/issues/2291[#2291] [diagrams] Fix item label for constraint to show their name and expression value between braces (if present).
- https://github.com/eclipse-syson/syson/issues/2289[#2289] [details] Fix expression support for `TransitionUsage`.

=== Improvements

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ private FormDescription createDetailsViewForElement() {
pageCore.getGroups().add(this.createFeatureValuePropertiesGroup());
pageCore.getGroups().add(this.createExpressionPropertiesGroup());
pageCore.getGroups().add(this.createResultExpressionPropertiesGroup());
pageCore.getGroups().add(this.createGuardExpressionPropertiesGroup());

PageDescription pageAdvanced = FormFactory.eINSTANCE.createPageDescription();
pageAdvanced.setName("SysON-DetailsView-Advanced");
Expand All @@ -208,49 +209,23 @@ private FormDescription createDetailsViewForElement() {
}

/**
* Creates a group to display the value of an Expression.
* Creates a group to display the value of an actual Expression (selected directly).
*
* @return a {@link GroupDescription}
*/
private GroupDescription createExpressionPropertiesGroup() {
GroupDescription group = FormFactory.eINSTANCE.createGroupDescription();
group.setDisplayMode(GroupDisplayMode.LIST);
group.setName("Expression Value");
group.setLabelExpression("");
group.setSemanticCandidatesExpression(ServiceMethod.of0(DetailsViewService::getExpression).aqlSelf());

TextAreaDescription expressionWidget = FormFactory.eINSTANCE.createTextAreaDescription();
expressionWidget.setName("Expression");
expressionWidget.setLabelExpression(CUSTOM_EXPRESSION_WIDGET_KEY);
expressionWidget.setValueExpression(ServiceMethod.of0(DetailsViewService::getExpressionTextualRepresentation).aqlSelf());
expressionWidget.setIsEnabledExpression(AQLConstants.AQL_FALSE);

group.getChildren().add(expressionWidget);

return group;
return this.createExpressionPropertiesGroup(ServiceMethod.of0(DetailsViewService::getExpression).aqlSelf(),
ServiceMethod.of0(DetailsViewService::getExpressionTextualRepresentation).aqlSelf());
}

/**
* Creates a group to display the value of a Feature or FeatureValue.
* Creates a group to display the Expression defining the value of a Feature or FeatureValue.
*
* @return a {@link GroupDescription}
*/
private GroupDescription createFeatureValuePropertiesGroup() {
GroupDescription group = FormFactory.eINSTANCE.createGroupDescription();
group.setDisplayMode(GroupDisplayMode.LIST);
group.setName("Value");
group.setLabelExpression("");
group.setSemanticCandidatesExpression(ServiceMethod.of0(DetailsViewService::getFeatureValue).aqlSelf());

TextAreaDescription expressionWidget = FormFactory.eINSTANCE.createTextAreaDescription();
expressionWidget.setName("ValueExpression");
expressionWidget.setLabelExpression(CUSTOM_EXPRESSION_WIDGET_KEY);
expressionWidget.setValueExpression(ServiceMethod.of0(DetailsViewService::getValueExpressionTextualRepresentation).aqlSelf());
expressionWidget.setIsEnabledExpression(AQLConstants.AQL_FALSE);

group.getChildren().add(expressionWidget);

return group;
return this.createExpressionPropertiesGroup(ServiceMethod.of0(DetailsViewService::getFeatureValue).aqlSelf(),
ServiceMethod.of0(DetailsViewService::getValueExpressionTextualRepresentation).aqlSelf());
}

/**
Expand All @@ -259,17 +234,40 @@ private GroupDescription createFeatureValuePropertiesGroup() {
* @return a {@link GroupDescription}
*/
private GroupDescription createResultExpressionPropertiesGroup() {
return this.createExpressionPropertiesGroup(ServiceMethod.of0(DetailsViewService::getResultExpression).aqlSelf(),
ServiceMethod.of0(DetailsViewService::getResultExpressionTextualRepresentation).aqlSelf());
}

/**
* Creates a group to display the value of a guard expression.
*
* @return a {@link GroupDescription}
*/
private GroupDescription createGuardExpressionPropertiesGroup() {
return this.createExpressionPropertiesGroup(ServiceMethod.of0(DetailsViewService::getGuardExpression).aqlSelf(),
ServiceMethod.of0(DetailsViewService::getExpressionTextualRepresentation).aqlSelf());
}

/**
* Helper to create a group to display an existing expression.
*
* @param semanticCandidatesExpression
* the AQL expression to find the semantic candidate.
* @param valueExpression
* the AQL expression to render the text of the expression corresponding to the semantic candidate.
* @return a {@link GroupDescription}
*/
private GroupDescription createExpressionPropertiesGroup(String semanticCandidatesExpression, String valueExpression) {
GroupDescription group = FormFactory.eINSTANCE.createGroupDescription();
group.setDisplayMode(GroupDisplayMode.LIST);
group.setName("Result");
group.setName("Expression Value");
group.setLabelExpression("");
group.setSemanticCandidatesExpression(ServiceMethod.of0(DetailsViewService::getResultExpression).aqlSelf());
group.setSemanticCandidatesExpression(semanticCandidatesExpression);

TextAreaDescription expressionWidget = FormFactory.eINSTANCE.createTextAreaDescription();
expressionWidget.setName("ResultExpression");
LabelDescription expressionWidget = FormFactory.eINSTANCE.createLabelDescription();
expressionWidget.setName("Expression");
expressionWidget.setLabelExpression(CUSTOM_EXPRESSION_WIDGET_KEY);
expressionWidget.setValueExpression(ServiceMethod.of0(DetailsViewService::getResultExpressionTextualRepresentation).aqlSelf());
expressionWidget.setIsEnabledExpression(AQLConstants.AQL_FALSE);
expressionWidget.setValueExpression(valueExpression);

group.getChildren().add(expressionWidget);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
import org.eclipse.syson.sysml.Succession;
import org.eclipse.syson.sysml.SysmlFactory;
import org.eclipse.syson.sysml.SysmlPackage;
import org.eclipse.syson.sysml.TransitionFeatureMembership;
import org.eclipse.syson.sysml.TransitionUsage;
import org.eclipse.syson.sysml.Type;
import org.eclipse.syson.sysml.Usage;
Expand Down Expand Up @@ -651,6 +652,23 @@ public Element getResultExpression(Element self) {
return result;
}

/**
* Gets the guard expression from a {@ink TransitionUsage} or {@link TransitionFeatureMembership}.
*
* @param self
* {@ink TransitionUsage} or {@link TransitionFeatureMembership}.
* @return the corresponding guard {@link Expression} or <code>null</code>
*/
public Expression getGuardExpression(Element self) {
Expression result = null;
if (self instanceof TransitionFeatureMembership expressionMembership && expressionMembership.getOwnedMemberElement() instanceof Expression expression) {
result = expression;
} else if (self instanceof TransitionUsage transitionUsage && !transitionUsage.getGuardExpression().isEmpty()) {
result = transitionUsage.getGuardExpression().get(0);
}
return result;
}

/**
* Gets the {@link ResultExpressionMembership} from a {@link Namespace} or a {@link ResultExpressionMembership}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@

import { getCSSColor } from '@eclipse-sirius/sirius-components-core';
import {
GQLTextarea,
GQLTextfield,
getTextDecorationLineValue,
GQLLabelWidget,
LabelStyleProps,
PropertySectionComponent,
PropertySectionComponentProps,
PropertySectionLabel,
TextfieldStyleProps,
} from '@eclipse-sirius/sirius-components-forms';
import Typography from '@mui/material/Typography';

Expand All @@ -29,57 +29,24 @@ import { useState } from 'react';
import { makeStyles } from 'tss-react/mui';
import { EditSysMLExpressionModal } from './EditSysMLExpressionModal';

const useStyle = makeStyles<TextfieldStyleProps>()(
(theme, { backgroundColor, foregroundColor, fontSize, italic, bold, gridLayout }) => {
const {
gridTemplateColumns,
gridTemplateRows,
labelGridColumn,
labelGridRow,
widgetGridColumn,
widgetGridRow,
gap,
} = {
...gridLayout,
};
return {
style: {
backgroundColor: backgroundColor ? getCSSColor(backgroundColor, theme) : undefined,
color: foregroundColor ? getCSSColor(foregroundColor, theme) : undefined,
fontSize: fontSize ? fontSize : undefined,
fontStyle: italic ? 'italic' : undefined,
fontWeight: bold ? 'bold' : undefined,
},
input: {
paddingTop: theme.spacing(0.5),
paddingBottom: theme.spacing(0.5),
},
textfield: {
marginTop: theme.spacing(0.5),
marginBottom: theme.spacing(0.5),
},
formControl: {},
propertySection: {
display: 'grid',
gridTemplateColumns,
gridTemplateRows,
alignItems: 'center',
gap: gap ?? '',
},
propertySectionLabel: {
gridColumn: labelGridColumn,
gridRow: labelGridRow,
display: 'flex',
flexDirection: 'row',
gap: theme.spacing(2),
alignItems: 'center',
},
propertySectionWidget: {
gridColumn: widgetGridColumn,
gridRow: widgetGridRow,
},
};
}
const useStyle = makeStyles<LabelStyleProps>()(
(theme, { color, fontSize, italic, bold, underline, strikeThrough }) => ({
style: {
color: color ? getCSSColor(color, theme) : undefined,
fontSize: fontSize ? fontSize : undefined,
fontStyle: italic ? 'italic' : undefined,
fontWeight: bold ? 'bold' : undefined,
textDecorationLine: getTextDecorationLineValue(underline, strikeThrough),
verticalAlign: 'baseline',
alignItems: 'center',
display: 'flex',
},
propertySection: {
display: 'flex',
flexDirection: 'row',
gap: theme.spacing(2),
},
})
);

// Extracts the UUID from the string of the form "details://?objectIds=[c5f78f3a-8b39-4cb0-903a-cedd8e6e71f6]" if it contains a single UUID, otherwise returns null.
Expand All @@ -93,20 +60,18 @@ type ExpressionPropertySectionState = {
state: 'idle' | 'modal';
};

export const ExpressionPropertySection: PropertySectionComponent<GQLTextfield | GQLTextarea> = ({
export const ExpressionPropertySection: PropertySectionComponent<GQLLabelWidget> = ({
editingContextId,
formId,
widget,
}: PropertySectionComponentProps<GQLTextfield | GQLTextarea>) => {
const props: TextfieldStyleProps = {
backgroundColor: widget.style?.backgroundColor ?? null,
foregroundColor: widget.style?.foregroundColor ?? null,
}: PropertySectionComponentProps<GQLLabelWidget>) => {
const props: LabelStyleProps = {
color: widget.style?.color ?? null,
fontSize: widget.style?.fontSize ?? null,
italic: widget.style?.italic ?? null,
bold: widget.style?.bold ?? null,
underline: widget.style?.underline ?? null,
strikeThrough: widget.style?.strikeThrough ?? null,
gridLayout: widget.style?.widgetGridLayout ?? null,
};
const { classes } = useStyle(props);
const [state, setState] = useState<ExpressionPropertySectionState>({
Expand Down Expand Up @@ -137,7 +102,7 @@ export const ExpressionPropertySection: PropertySectionComponent<GQLTextfield |
const widgetForLabel = { ...widget, label: labelOverride };
return (
<div>
<div className={classes.propertySectionLabel}>
<div className={classes.propertySection}>
<PropertySectionLabel editingContextId={editingContextId} formId={formId} widget={widgetForLabel} />
</div>
<div style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ sysONExtensionRegistry.putData(widgetContributionExtensionPoint, {
previewComponent: () => null,
component: (widget: GQLWidget): PropertySectionComponent<GQLWidget> | null => {
let propertySectionComponent: PropertySectionComponent<GQLWidget> | null = null;
if (widget.__typename == 'Textarea' && widget.label.startsWith('syson:expression-value-widget')) {
if (widget.__typename == 'LabelWidget' && widget.label.startsWith('syson:expression-value-widget')) {
propertySectionComponent = ExpressionPropertySection as PropertySectionComponent<GQLWidget>;
}
return propertySectionComponent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,5 +110,19 @@ describe('Details View Tests', () => {
cy.getByTestId('details-expression-value').should('have.text', '80 [SI::centimetre]');
});
});

context('When we select a TransitionUsage with a guard Expression', () => {
beforeEach(() => {
explorer.select('Drive Batmobile');
explorer.expand('Drive Batmobile');
// The TransitionUsage is anonymous so select the closest named item and move down using the keyboard
explorer.select('scanEnvironment');
cy.getByTestId('scanEnvironment').type('{downArrow}{downArrow}{downArrow}');
});
it("Then the Details view shows the child expression's textual value", () => {
cy.getByTestId('details-expression-value').should('exist');
cy.getByTestId('details-expression-value').should('have.text', 'scanEnvironment.status == StatusKind::safe');
});
});
});
});
Loading