Skip to content

Commit

Permalink
[4000] Add support for styled labels in view model for trees
Browse files Browse the repository at this point in the history
Bug: eclipse-sirius#4000
Signed-off-by: Jerome Gout <[email protected]>
  • Loading branch information
jerome-obeo committed Sep 17, 2024
1 parent 0d1f911 commit 7882b3c
Show file tree
Hide file tree
Showing 67 changed files with 5,055 additions and 186 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
- https://github.com/eclipse-sirius/sirius-web/issues/3882[#3882] [sirius-web] Add a new tree event to handle tree description which are not explorer-related
- https://github.com/eclipse-sirius/sirius-web/issues/3961[#3961] [sirius-web] Extend the explorer to support multiple presentations
- https://github.com/eclipse-sirius/sirius-web/issues/3856[#3856] [trees] Add tree representation in the view DSL
- https://github.com/eclipse-sirius/sirius-web/issues/4000[#4000] [trees] Add support for styled labels in view model for trees

== v2024.9.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ public final class StyledStringFragmentStyle {

private boolean struckOut;

private boolean bold;

private boolean italic;

private UnderLineStyle underlineStyle;

private BorderStyle borderStyle;
Expand Down Expand Up @@ -73,6 +77,14 @@ public boolean isStruckOut() {
return this.struckOut;
}

public boolean isBold() {
return this.bold;
}

public boolean isItalic() {
return this.italic;
}

public static Builder newStyledStringFragmentStyle() {
return new Builder();
}
Expand All @@ -86,6 +98,8 @@ public static Builder newDefaultStyledStringFragmentStyle() {
.underlineColor("")
.borderColor("")
.struckOut(false)
.bold(false)
.italic(false)
.underlineStyle(UnderLineStyle.NONE)
.borderStyle(BorderStyle.NONE);
}
Expand Down Expand Up @@ -119,6 +133,10 @@ public static final class Builder {

private boolean struckOut;

private boolean bold;

private boolean italic;

private UnderLineStyle underlineStyle;

private BorderStyle borderStyle;
Expand Down Expand Up @@ -162,6 +180,16 @@ public Builder struckOut(boolean struckOut) {
return this;
}

public Builder bold(boolean bold) {
this.bold = bold;
return this;
}

public Builder italic(boolean italic) {
this.italic = italic;
return this;
}

public Builder underlineStyle(UnderLineStyle underlineStyle) {
this.underlineStyle = Objects.requireNonNull(underlineStyle);
return this;
Expand All @@ -183,6 +211,8 @@ public StyledStringFragmentStyle build() {
styledStringFragmentStyle.struckOut = Objects.requireNonNull(this.struckOut);
styledStringFragmentStyle.underlineStyle = Objects.requireNonNull(this.underlineStyle);
styledStringFragmentStyle.borderStyle = Objects.requireNonNull(this.borderStyle);
styledStringFragmentStyle.bold = Objects.requireNonNull(this.bold);
styledStringFragmentStyle.italic = Objects.requireNonNull(this.italic);
return styledStringFragmentStyle;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ const styledLabelStyle = (gqlLabelStyle: GQLStyledStringFragmentStyle): React.CS
color: gqlLabelStyle.foregroundColor,
textDecoration: textDecorations.join(' '),
border: border.join(' '),
fontWeight: gqlLabelStyle.isBold ? 'bold' : 'normal',
fontStyle: gqlLabelStyle.isItalic ? 'italic' : 'normal',
};
return style;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export interface GQLStyledStringFragmentStyle {
borderColor: string;
borderStyle: GQLBorderStyle;
underlineStyle: GQLUnderLineStyle;
isBold: boolean;
isItalic: boolean;
}

export type GQLUnderLineStyle = 'NONE' | 'SOLID' | 'DOUBLE' | 'DOTTED' | 'DASHED' | 'WAVY';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ public StyledString convert(org.eclipse.emf.edit.provider.StyledString styledStr
}

private StyledStringFragment convertStyledStringFragment(org.eclipse.emf.edit.provider.StyledString.Fragment styledStringFragment) {
String backgroundColor = convertEmfColorToCss(styledStringFragment.getStyle().getBackgoundColor());
String foregroundColor = convertEmfColorToCss(styledStringFragment.getStyle().getForegroundColor());
String strikeoutColor = convertEmfColorToCss(styledStringFragment.getStyle().getStrikeoutColor());
String underlineColor = convertEmfColorToCss(styledStringFragment.getStyle().getUnderlineColor());
String borderColor = convertEmfColorToCss(styledStringFragment.getStyle().getBorderColor());
String backgroundColor = this.convertEmfColorToCss(styledStringFragment.getStyle().getBackgoundColor());
String foregroundColor = this.convertEmfColorToCss(styledStringFragment.getStyle().getForegroundColor());
String strikeoutColor = this.convertEmfColorToCss(styledStringFragment.getStyle().getStrikeoutColor());
String underlineColor = this.convertEmfColorToCss(styledStringFragment.getStyle().getUnderlineColor());
String borderColor = this.convertEmfColorToCss(styledStringFragment.getStyle().getBorderColor());
String font = Optional.ofNullable(styledStringFragment.getStyle().getFont()).map(URI::toString).orElse("Arial");
boolean struckOut = styledStringFragment.getStyle().isStrikedout();
UnderLineStyle underLineStyle = convertEmfUnderLineToCss(styledStringFragment.getStyle().getUnderlineStyle());
BorderStyle borderStyle = convertEmfUnderLineToCss(styledStringFragment.getStyle().getBorderStyle());
UnderLineStyle underLineStyle = this.convertEmfUnderLineToCss(styledStringFragment.getStyle().getUnderlineStyle());
BorderStyle borderStyle = this.convertEmfUnderLineToCss(styledStringFragment.getStyle().getBorderStyle());

StyledStringFragmentStyle styledStringFragmentStyle = StyledStringFragmentStyle.newStyledStringFragmentStyle()
.font(font)
Expand All @@ -63,6 +63,8 @@ private StyledStringFragment convertStyledStringFragment(org.eclipse.emf.edit.pr
.struckOut(struckOut)
.underlineStyle(underLineStyle)
.borderStyle(borderStyle)
.bold(false)
.italic(false)
.build();

return new StyledStringFragment(styledStringFragment.getString(), styledStringFragmentStyle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@
import org.eclipse.sirius.components.emf.ResourceMetadataAdapter;
import org.eclipse.sirius.components.emf.services.IDAdapter;
import org.eclipse.sirius.components.emf.services.JSONResourceFactory;
import org.eclipse.sirius.components.view.TextStyleDescription;
import org.eclipse.sirius.components.view.TextStylePalette;
import org.eclipse.sirius.components.view.View;
import org.eclipse.sirius.components.view.builder.generated.tree.TreeBuilders;
import org.eclipse.sirius.components.view.builder.generated.view.ViewBuilders;
import org.eclipse.sirius.components.view.emf.tree.ITreeIdProvider;
import org.eclipse.sirius.components.view.tree.TreeDescription;
import org.eclipse.sirius.components.view.tree.TreeItemLabelDescription;
import org.eclipse.sirius.components.view.tree.TreeItemLabelElementDescription;
import org.eclipse.sirius.emfjson.resource.JsonResource;
import org.eclipse.sirius.web.application.editingcontext.EditingContext;
import org.eclipse.sirius.web.application.studio.services.api.IStudioCapableEditingContextPredicate;
Expand All @@ -41,6 +45,14 @@ public class DomainViewTreeDescriptionProvider implements IEditingContextProcess

public static final String DOMAIN_EXPLORER_DESCRIPTION_NAME = "Domain explorer by DSL";

private static final String BLUE_ITALIC_TEXT_STYLE_NAME = "blue italic";

private static final String BROWN_BOLD_TEXT_STYLE_NAME = "brown bold";

private static final String NORMAL_TEXT_STYLE_NAME = "normal";

private static final String AQL_TRUE = "aql:true";

private static final String AQL_FALSE = "aql:false";

private static final String DOMAIN_VIEW_EXPLORER_ID = "DomainExplorer";
Expand All @@ -67,13 +79,16 @@ public void preProcess(IEditingContext editingContext) {
}

private View createView() {
var domainExplorerDescription = this.domainExplorerDescription();
var domainTextStylePalette = this.createTextStylePalette();
var domainExplorerDescription = this.domainExplorerDescription(domainTextStylePalette);

var domainView = new ViewBuilders()
.newView()
.descriptions(domainExplorerDescription)
.textStylePalettes(domainTextStylePalette)
.build();

domainView.getDescriptions().add(domainExplorerDescription);

domainView.eAllContents().forEachRemaining(eObject -> {
var id = UUID.nameUUIDFromBytes(EcoreUtil.getURI(eObject).toString().getBytes());
eObject.eAdapters().add(new IDAdapter(id));
Expand All @@ -91,7 +106,7 @@ public String getRepresentationDescriptionId() {
return this.treeIdProvider.getId(this.viewDescription);
}

private TreeDescription domainExplorerDescription() {
private TreeDescription domainExplorerDescription(TextStylePalette domainTextStylePalette) {
this.viewDescription = new TreeBuilders()
.newTreeDescription()
.name(DOMAIN_EXPLORER_DESCRIPTION_NAME)
Expand All @@ -106,11 +121,109 @@ private TreeDescription domainExplorerDescription() {
.elementsExpression("aql:editingContext.getElements()")
.childrenExpression("aql:self.getChildren(editingContext, expanded)")
.parentExpression("aql:self.getParent(editingContext, id)")
.treeItemLabelExpression("aql:self.getTreeItemLabel()")
.treeItemIdExpression("aql:self.getTreeItemId()")
.treeItemObjectExpression("aql:editingContext.getTreeItemObject(id)")
.preconditionExpression(AQL_FALSE) // -> set canCreate to false to avoid to be display in New representation menu
.treeItemLabelDescriptions(this.entityStyle(domainTextStylePalette), this.attributeStyle(domainTextStylePalette), this.defaultStyle())
.build();
return this.viewDescription;
}


private TextStylePalette createTextStylePalette() {
return new ViewBuilders()
.newTextStylePalette()
.name("Domain Text Style Palette")
.styles(this.getBrownBoldStyle(), this.getBlueItalicStyle(), this.getNormalStyle())
.build();
}

private TreeItemLabelDescription attributeStyle(TextStylePalette textStylePalette) {
return new TreeBuilders()
.newTreeItemLabelDescription()
.name("attribute style")
.preconditionExpression("aql:self.oclIsKindOf(domain::Attribute)")
.children(this.getAttributeKeyFragment(textStylePalette), this.getAttributeValueFragment(textStylePalette))
.build();
}

private TreeItemLabelDescription entityStyle(TextStylePalette textStylePalette) {
return new TreeBuilders()
.newTreeItemLabelDescription()
.name("entity style")
.preconditionExpression("aql:self.oclIsKindOf(domain::Entity)")
.children(this.getEntityKeyFragment(textStylePalette), this.getEntityValueFragment(textStylePalette))
.build();
}

private TreeItemLabelDescription defaultStyle() {
return new TreeBuilders()
.newTreeItemLabelDescription()
.name("default style")
.preconditionExpression("aql:true")
.children(new TreeBuilders()
.newTreeItemLabelFragmentDescription()
.labelExpression("aql:self.getTreeItemLabel()")
// no style specified => default one will be chosen
.build()
)
.build();
}

private TreeItemLabelElementDescription getEntityValueFragment(TextStylePalette textStylePalette) {
return new TreeBuilders().newTreeItemLabelFragmentDescription()
.labelExpression("aql:self.getTreeItemLabel()")
.style(this.getTextStyleByName(textStylePalette, NORMAL_TEXT_STYLE_NAME))
.build();
}

private TreeItemLabelElementDescription getEntityKeyFragment(TextStylePalette textStylePalette) {
return new TreeBuilders().newTreeItemLabelFragmentDescription()
.labelExpression("aql:'[Entity] '")
.style(this.getTextStyleByName(textStylePalette, BROWN_BOLD_TEXT_STYLE_NAME))
.build();
}

private TreeItemLabelElementDescription getAttributeValueFragment(TextStylePalette textStylePalette) {
return new TreeBuilders().newTreeItemLabelFragmentDescription()
.labelExpression("aql:self.name")
.style(this.getTextStyleByName(textStylePalette, NORMAL_TEXT_STYLE_NAME))
.build();
}

private TreeItemLabelElementDescription getAttributeKeyFragment(TextStylePalette textStylePalette) {
return new TreeBuilders().newTreeItemLabelFragmentDescription()
.labelExpression("aql:'[Attribute] '")
.style(this.getTextStyleByName(textStylePalette, BLUE_ITALIC_TEXT_STYLE_NAME))
.build();
}

private TextStyleDescription getBlueItalicStyle() {
return new ViewBuilders().newTextStyleDescription()
.name(BLUE_ITALIC_TEXT_STYLE_NAME)
.foregroundColorExpression("aql:'#6584e2'")
.isItalicExpression(AQL_TRUE)
.build();
}

private TextStyleDescription getBrownBoldStyle() {
return new ViewBuilders().newTextStyleDescription()
.name(BROWN_BOLD_TEXT_STYLE_NAME)
.foregroundColorExpression("aql:'#c29e00'")
.isBoldExpression(AQL_TRUE)
.build();
}

private TextStyleDescription getNormalStyle() {
return new ViewBuilders().newTextStyleDescription()
.name(NORMAL_TEXT_STYLE_NAME)
.build();
}

private TextStyleDescription getTextStyleByName(TextStylePalette textStylePalette, String styleName) {
return textStylePalette.getStyles().stream()
.filter(tsd -> tsd.getName().equals(styleName))
.findFirst()
.orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public void givenAnExplorerRepresentationWhenWeSubscribeToItsEventThenTheReprese
assertThat(tree.getChildren().get(1).getChildren()).hasSize(1);
assertThat(tree.getChildren().get(1).getChildren().get(0).getLabel().toString()).isEqualTo("buck");
assertThat(tree.getChildren().get(1).getChildren().get(0).getChildren()).hasSize(3);
assertThat(tree.getChildren().get(1).getChildren().get(0).getChildren().get(2).getLabel().toString()).isEqualTo("Human");
assertThat(tree.getChildren().get(1).getChildren().get(0).getChildren().get(2).getLabel().toString()).isEqualTo("[Entity] Human");
assertThat(tree.getChildren().get(1).getChildren().get(0).getChildren().get(2).getChildren()).hasSize(4);
assertThat(tree.getChildren().get(1).getChildren().get(0).getChildren().get(2).getChildren().get(0).getLabel().toString()).isEqualTo("superTypes");
settingId.set(tree.getChildren().get(1).getChildren().get(0).getChildren().get(2).getChildren().get(0).getId());
Expand Down
Loading

0 comments on commit 7882b3c

Please sign in to comment.