Skip to content

Commit

Permalink
[1988] Add support for optional help text on widgets
Browse files Browse the repository at this point in the history
Bug: #1988
Signed-off-by: Pierre-Charles David <pierre-charles.david@obeo.fr>
  • Loading branch information
pcdavid authored and sbegaudeau committed Jun 19, 2023
1 parent 1a6446d commit 8ae7820
Show file tree
Hide file tree
Showing 186 changed files with 4,334 additions and 540 deletions.
9 changes: 7 additions & 2 deletions CHANGELOG.adoc
Expand Up @@ -5,12 +5,13 @@
=== Shapes

- Add disable / enable concept for widgets
- Add support for Help Expressions in Form widgets
- Add new custom widget to edit single and multi-valued references
- Add support for Help Expressions in Form widgets

=== Architectural decision records

- [ADR-103] Improves the existing feedback messages capability
- [ADR-104] Add support for Help Expressions in Form widgets

=== Breaking changes

Expand Down Expand Up @@ -44,7 +45,11 @@ image:doc/screenshots/feedbackMessages.png[Feedback messages,30%,30%]
There is an example of the `IFeedbackMessageService` interface usage in `DomainAttributeServices`.
Note that in the end, the message list will be the only way to return info in payload, the single message will be removed.
- https://github.com/eclipse-sirius/sirius-components/issues/2010[#2010] [diagram] Add a palette on node with the alternate diagram rendering.

- https://github.com/eclipse-sirius/sirius-components/issues/1988[#1988] All Form widgets can now define (if relevant) a dynamically computed "help text".
Widgets which define such a help text have a new "?" icon next to their labels; the actual help text is accessible as a tooltip on this icon.
For View-based widgets, this materializes as an AQL `helpExpression`.
The help text can include multiple lines (separated by `\n`), but no text formatting.
:image:doc/images/Widget_Help_Tooltip.png[Example of a help tooltip on a widget]

== v2023.6.0

Expand Down
112 changes: 112 additions & 0 deletions doc/adrs/104_help_expressions.adoc
@@ -0,0 +1,112 @@
= ADR-104 - Add support for Help Expressions in Form widgets

== Context

In the desktop version of EEF-based properties views, widgets support an optional "Help" text which is exposed as a tooltip on widgets which define one.
This is helpful to add user-oriented documentation on the property represented by the widget.
It is not currently supported in the Sirius Components' _Form_ representation.

== Decision

All widget descriptions in the _Form_ representation (including the View-based Forms) will have an optional "help text provider".
If defined, the corresponding widget instances will have a visible "?" icon which, when hovered, will display the corresponding help text to the end-user.
The help content will be a plain text (no formatting).
It will be computed in the context of the semantic element of the widget so that the text can be adapted to the current state of the element.

== Solution

=== Backend

The overall design of the solution will follow the same approach as for completion support.

We will add a new (optional) field `Function<VariableManager, String> helpTextProvider` to the core `AbstractWidgetDescription` class:

```java
public abstract class AbstractWidgetDescription extends AbstractControlDescription {
// Added:
protected Function<VariableManager, String> helpTextProvider;

public Function<VariableManager, String> getHelpTextProvider() {
return this.helpTextProvider;
}
}
```

When a widget is rendered, this `Function<VariableManager, String>` is specialized into a plain, parameter-less `Supplier<String>` in the widget instance, with the `VariableManager` used for the rendering captured:

```java
public class CheckboxComponent implements IComponent {

@Override
public Element render() {
// ...
if (checkboxDescription.getHelpTextProvider() != null) {
checkboxElementPropsBuilder.helpTextProvider(() -> checkboxDescription.getHelpTextProvider().apply(variableManager));
}
...
}
}
```

This means the value of the help expression will *not* be evaluated as part of the widget's rendering.
In the vast majority of form renders, no help text will need to be displayed for any widget.
Computing them eagerly would incur both an additional runtime cost to each render of each form _and_ a network transfer cost for text values which will never be visible.

Instead, the evaluation of a "help expression" will be done on-demand through a new GraphQL Query:

```
type FormDescription implements RepresentationDescription {
helpText(widgetId: ID!): String
}
```

The event handler for this query will simply need to find the proper widget, and if it has a non-null `Supplier<String> getHelpTextProvider()`, invoke it.

Although the actual help expression is not evaluated at render-time, we will provide a `hasHelpText: Boolean` field for each widget in the GraphQL Schema.
This GraphQL field will be computed using a custom datafetcher:

```java
@QueryDataFetcher(type = "Widget", field = "hasHelpText")
public class WidgetHasHelpTextDataFetcher implements IDataFetcherWithFieldCoordinates<Boolean> {
@Override
public Boolean get(DataFetchingEnvironment environment) throws Exception {
AbstractWidget item = environment.getSource();
return item.getHelpTextProvider() != null;
}
}
```

This attribute will be used by the frontend to know if it should display a visual hint/icon to indicate that a help text is available for the widget.

There will be no caching of the help expression's value.
Each GraphQL Query invocation will trigger the evaluation of the expression.

=== View

In the View DSL, we will add a `helpExpression : IntepretedExpression` attribute the `WidgetDescription` _EClass_.
During the View conversion, we will create a non-null `helpTextProvider` only if the WidgetDescription has a non-null and non-blank `helpExpression`:

```java
if (viewWidgetDescription.getHelpExpression() != null && !viewWidgetDescription.getHelpExpression().isBlank()) {
builder.helpTextProvider(this.getStringValueProvider(viewWidgetDescription.getHelpExpression()));
}
```

This will allow users to clear the `helpExpression` field of a widget definition to mean "no help text".

=== Frontend

On the frontend, the Form representation will fetch the `hasHelpText` for all widgets, and use that to know if some help text is available on a given widget.
When help text is available, a "?" icon (`HelpOutlineOutlined`) will be added to the right of the widget's label text.
If the user hovers the mouse on the icon, the frontend will issue the GraphQL Query mentioned above to retrieve the proper help text, and display it inside a tooltip.

The "preview" version of all widgets displaed inside a _FormDescriptionEditor_ will also show the "?" icon if (and only if) the widget defines a non-empty help expression.
This icon will not show any toolip, it will just be a visual indication that the widget has/will have a help text at runtime.

== Status

Accepted.

== Consequences

A similar feature could be added to all our representations (diagram elements, tree items...), but this is out of scope for the moment.
Binary file added doc/images/Widget_Help_Tooltip.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 8ae7820

Please sign in to comment.