major
#27105
Dynamic subscription to model events through UI elements
Currently, only components can respond to model events. Each component receives all model events (individually). There is no way for a UI element (tl:Control) to react to a model change. The UI element relies on the component to react to the change and update the control’s model. To do this, however, the component must be aware of all models displayed in its context.
Improvement
A tl:Control should be able to use a business object directly as a model and, for example, generate a representation of it. In turn, the control should be able to react independently to changes in the displayed business object and update its representation.
New API
- tl:FrameScope gains a getModelScope() method, which returns a tl:ModelScope.
- A `tl:ModelScope` provides methods for subscribing to `tl:ModelChangeEvent` notifications.
- A model event listener must implement the tl:ModelListener interface.
Code Migration
Updates for TLObjects
Components are now only notified about the creation, modification, and deletion of TLObjects if they subscribe to these events. The following hooks are available in tl:LayoutComponent for this purpose:
- getObjectsToObserve(): The component is notified of changes to and deletions of these objects.
- getTypesToObserve(): The component is notified of all instances of these types and their subtypes. (Creation, modification, deletion)
- observeAllTypes(): If a component needs to be notified about everything. This should only be used when absolutely necessary, as it creates unnecessary overhead.
- All components are automatically registered as listeners for their model (getModel()). If a component has “wrapped” one or more TLObjects in its model, but the model is not simply a collection of TLObjects, then the component must override extractTLObjects(model). Otherwise, these TLObjects will not be found, the component will not be registered as a listener for them, will not receive updates, will not refresh itself, and will display outdated data if these TLObjects are modified or deleted.
- If a component is not to be migrated, observeAllTypes() can be overridden with return true;. In that case, it will be notified of everything.
- The following methods of tl:LayoutComponent have been deprecated:
- receiveModelCreatedEvent
- receiveModelChangedEvent
- receiveModelDeletedEvent
- Use the following methods instead:
- handleTLObjectCreations
- handleTLObjectUpdates
- handleTLObjectDeletions
- notifyChange (If all three types of events are to be handled in the same way.)
- The following constants in tl:ModelEventListener have been deprecated:
- MODEL_MODIFIED
- MODEL_CREATED
- MODEL_DELETED
- tl:TableComponent, tl:TreeTableComponent, and tl:GridComponent must be correctly configured to specify which types they contain. Otherwise, they will no longer receive model events and will not update.
- Subclasses of ` TreeModelBuilder ` and ` AbstractTreeGridBuilder ` must override the `getTypesToObserve() ` method if they use persistent objects in their tree.
- GridBuilder.receiveModelCreatedEvent(...) has been replaced by handleTLObjectCreations(...)
Additional Changes
- If a class overrides ModelEventAdapter.receiveAnyModelEvent(...), it must be adapted. This method is no longer called for Model Created, Modified, and Deleted events. However, if this functionality is required, the three corresponding methods must be overridden and must call receiveAnyModelEvent within them.
- DynamicModelService.Config.getDefaultFactory() (i.e., the default-factory property) has been removed. It was no longer in use. References to it in .config.xml files must be removed.
- The ModelEventReceiver (sic) interface has been removed.
- MainLayout.GlobalConfig.getEventForwarderClass() (i.e., the ` eventForwarderClass` property) has been replaced by ` getEventForwarder()`.
- The ` ModelEventForwarder ` class has been converted to an interface. In addition, several methods have been removed.
- It is no longer possible to determine whether an event originated from the current session. If events from the current session are to be handled specially, the command that causes this change must also handle this special treatment.
- ModelEventForwarder.SENDER_IN_OTHER_SESSION has been removed.
- ExpressionSelectorComponent.isFromOwnSession(...) has been removed.
- TreeTableComponent.getQualifiedTypeNames() has been replaced by getTypes().
- The following methods have been removed:
- MainLayout.doBroadcastModelEvent(LayoutComponent, Object, Object, int)
- TLMainLayout.broadcastEvent(Collection, Object, LayoutComponent, int)
- TLMainLayout.doBroadcastModelEvent(LayoutComponent, Object, Object, int)
- The class `com.top_logic.layout.component.model.ModelChangeEvent ` has been deprecated. Instead, use `com.top_logic.model.listen.ModelChangeEvent`.
Test
- test.com.top_logic.mig.html.layout.TestGlobalModelEventForwarder