Embed Sirius Components
Need to bring the Sirius Components runtime into your own application? This guide summarizes the core APIs that must be implemented, how to dispatch operations, and how to extend the runtime with your own handlers or widgets.
1. Start integrating Sirius Components
In order to start integrating Sirius Components in your application, you must understand the role of core concepts such as IEditingContext, IEditingContextEventProcessor, and IRepresentationEventProcessor.
Your application must connect to the IEditingContextEventProcessorRegistry, which manages the various IEditingContext instances manipulated at runtime.
Sirius Components expects implementations of two mandatory services:
-
IEditingContextSearchService— loads anIEditingContextthat can later be manipulated by Sirius Components. The service may fetch data from a database or any other persistence mechanism. TheIEditingContextmust simply provide a unique identifier; the concrete implementation is left to you. -
IEditingContextPersistenceService— saves changes made to theIEditingContext. When working purely in memory (no persistence), this service can be a no-op. With a database-backed application, persist the new state of the editing context in this implementation.
2. Perform changes on the IEditingContext
Changes are performed through a simple API composed of IInput, IPayload, and IEditingContextEventHandler.
When you want to execute an operation already supported by Sirius Components, instantiate the matching IInput (for example CreateChildInput) and send it to the IEditingContextEventProcessorRegistry#dispatchEvent.
The registry finds or creates the relevant IEditingContextEventProcessor and lets an IEditingContextEventHandler perform the change described by the input.
Once the operation completes, the handler returns an IPayload to the caller (subscribed through the returned Mono<IPayload>).
You can also contribute your own IInput/IPayload types and matching handlers to perform domain-specific changes on the editing context.
The only constraint is that the id of the IPayload is a correlation identifier and must be the same as the id of the IInput that triggered the operation.
3. Create a custom IEditingContextEventHandler
The IEditingContextEventHandler API follows a pattern reused in several parts of Sirius Components: you can register multiple handlers and we will ask them if they can handle specific data, invoking the first one that responds positively.
Inside your custom handler, use the provided IEditingContext and IInput to decide whether you want to process the request.
If you do, the handle method also receives two Reactor sinks: One<IPayload> payloadSink and Many<ChangeDescription> changeDescriptionSink.
Use payloadSink to emit a response payload (for example a CreateRepresentationSuccessPayload), and changeDescriptionSink to describe what changed so that the rest of the runtime reacts properly.
For instance:
changeDescriptionSink.tryEmitNext(new ChangeDescription(ChangeKind.SEMANTIC_CHANGE, editingContext.getId(), input));
This semantic change triggers a refresh of every impacted representation and requests the editing context to be saved, so the original operation can both update the data and refresh the UI.
4. Add support for a new kind of widget in forms
When you need a brand-new form widget you must extend both the backend and the frontend. The high-level steps are summarised below; the custom widget guide contains an end-to-end example.
4.1. Backend (packages/forms/backend)
-
Create the concrete POJO (with a builder) in
org.eclipse.sirius.components.forms, extendingAbstractWidget. -
Create the description (with a builder) in
org.eclipse.sirius.components.forms.description. -
Add the props POJO (with a builder) in
org.eclipse.sirius.components.forms.elements. -
Implement the component and its props in
org.eclipse.sirius.components.forms.components. -
Update
org.eclipse.sirius.components.forms.renderer(FormComponentPropsValidator,FormElementFactory, andFormInstancePropsValidator) to account for the new widget. -
Add the corresponding branch in
WidgetComponent#render().
In sirius-components-collaborative-forms add support for the widget in form.graphqls by declaring the new GraphQL type and mutations (type XXX implements Widget { … }, editXXX mutation, payloads, etc.).
Add DTOs in org.eclipse.sirius.components.collaborative.forms.dto, handlers in org.eclipse.sirius.components.collaborative.forms.handlers, and the mutation data fetcher in org.eclipse.sirius.components.forms.graphql.datafetchers.mutation.
If the widget must be compatible with Sirius Desktop/EEF properties/forms, update WidgetDescriptionConverter in sirius-components-compatibility.
For default properties, tweak PropertiesDefaultDescriptionProvider in sirius-components-compatibility-emf if needed for early manual validation.
4.2. Frontend (packages/forms/frontend/sirius-components-forms)
-
Add the widget type and fields in
src/form/FormEventFragments.ts, plus the matching TypeScript types insrc/form/FormEventFragments.types.tsandsrc/form/Form.types.ts. -
In
src/properties/PropertySection.tsx, add the type predicate and rendering branch. -
Implement the React component in
src/properties/propertysectionsto display the widget.
4.3. Form Description Editor support
Backend (sirius-components-formdescriptioneditors):
-
Add a
casemethod for the new widget kind inViewFormDescriptionEditorConverterSwitch. -
If the widget exposes style attributes that can be computed statically for the live preview, add a
*StyleProviderinorg.eclipse.sirius.components.formdescriptioneditors.componentsand use it in the switch.
Frontend (packages/formdescriptioneditors/frontend/sirius-components-formdescriptioneditors):
-
Implement the React preview component (see
ButtonWidget.tsxfor an example). -
Register the widget type in
FormDescriptionEditorRepresentation.types.tsand updateisKindinWidgetOperations.tsx. -
Add support for the new widget in
WidgetEntry.tsxandWidgetEntry.types.ts.
4.4. View DSL support
-
Extend
sirius-components-view/src/main/resources/model/view.ecorewith aWidgetDescriptionsub-class representing your widget and regenerate. -
Update
collectNewChildDescriptorsinFormDescriptionItemProviderso that the widget is proposed with useful defaults. -
Provide an SVG icon for the widget in
sirius-components-view-editand return it in the widget item provider’sgetImage:/** @generated NOT */ @Override public Object getImage(Object object) { return this.overlayImage(object, this.getResourceLocator().getImage("full/obj16/RichTextDescription.svg")); } -
Extend
ViewFormDescriptionConverterSwitchwithcaseMyNewWidgetDescriptionto convert the View model element into the runtimeWidgetDescription.