Major
#27105
Dynamic subscription to model events through UI elements
Currently, only components can react 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 depends on the component reacting to the change and updating the control's model. However, for this to happen, the component must be aware of all models represented in its context.
Enhancement
A tl:Control should be able to use a subject object directly as a model and produce a representation for it, for example. In return, the contrl should be able to react independently to changes in the represented subject object and update its representation.
New API
- tl:FrameScope gets a method getModelScope() that returns a tl:ModelScope.
- A tl:ModelScope provides methods to subscribe to tl:ModelChangeEvent notifications.
- A model event receiver must implement the tl:ModelListener interface.
Code Migration
Updates for TLObjects
Components will only be notified about the creation, modification and deletion of TLObjects if they subscribe to it. For this purpose there are the following hooks in tl:LayoutComponent:
- getObjectsToObserve(): The component is informed about changes and deletions of these objects.
- getTypesToObserve(): The component will be informed about all instances of these types and their derivatives. (creation, modification, deletion)
- observeAllTypes(): When a component needs to be informed about everything. This should only be used if absolutely necessary, as it creates unnecessary load.
- All components are automatically registered as listeners for their model(getModel()). If a component has one or more TLObjects "wrapped" 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 get updates, will not update itself, and will display outdated data when these TLObjects are modified or deleted.
- If a component should not be migrated, then observeAllTypes() can be overridden with return true;. Then it will be informed about 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 should 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 have correctly configured which types they contain. Otherwise they will no longer get model events and will not update.
- Derivatives of TreeModelBuilder and AbstractTreeGridBuilder must override the getTypesToObserve() method if they use persistent objects in their tree.
- GridBuilder.receiveModelCreatedEvent(...) was replaced by handleTLObjectCreations(...)
Other changes
- If a class overrides ModelEventAdapter.receiveAnyModelEvent(...), it must be adjusted. This method is no longer called for Model Created, Modified and Deleted. But if it is needed, the three related methods must be overridden and call receiveAnyModelEvent there.
- DynamicModelService.Config.getDefaultFactory() (i.e. Property default-factory) was removed. It was no longer used. Usages in .config.xml files must be removed.
- The ModelEventReveiver (sic) interface was deleted.
- MainLayout.GlobalConfig.getEventForwarderClass() (i.e. Property eventForwarderClass) was replaced by getEventForwarder().
- The ModelEventForwarder class became an interface. In addition, several methods were removed.
- It is no longer possible to detect if an event came from its own session. If event from own session should be handled specially, the command that causes this change must also take care of this special handling.
- ModelEventForwarder.SENDER_IN_OTHER_SESSION has been deleted.
- ExpressionSelectorComponent.isFromOwnSession(...) has been deleted.
- TreeTableComponent.getQualifiedTypeNames() has been replaced by getTypes().
- The following methods were removed:
- MainLayout.doBroadcastModelEvent(LayoutComponent, Object, Object, int)
- TLMainLayout.broadcastEvent(Collection, Object, LayoutComponent, int)
- TLMainLayout.doBroadcastModelEvent(LayoutComponent, Object, Object, int)
- The com.top_logic.layout.component.model.ModelChangeEvent class has been deprecated. Instead, com.top_logic.model.listen.ModelChangeEvent should be used.
Test
- test.com.top_logic.mig.html.layout.TestGlobalModelEventForwarder