User Objects in the @Model
We often get questions about a specific limitation of our ViewModels: The classes generated by the @Model annotation don’t allow custom inheritance. This means they cannot subclass an existing class or implement an interface. And more important, also the @Properties of the class can only be primitives, Strings, Enums or @Models.
These questions often come up, when somebody is porting an application from Swing or JavaFX to DukeScript. So our first example will model a typical scenario: We have a menu bar in our existing application. Each menu item typically has some MenuAction assigned that will be called when the user selects it. Let’s assume that in our original application these MenuActions implement an interface:
In DukeScript we cannot add a MenuAction Property, so one way to deal with it would be to create a registry that keeps references to the actions:
But that’s ugly. We don’t want to set up registries like that for everything and keep Actions and their ids in sync. A better way to deal with it is the “instance” attribute of the @Model annotation. It allows you to keep private state for the instance of your generated Model (MenuItem) in the class that defines it (MenuItemVMD):
Notice how we’re no longer using static methods. This is because now we create one instance of MenuItemVMD per MenuItem. So every instance of MenuItem can now store it’s private state in an instance of MenuItemVMD. The @ModelOperation annotation generates a new method in the MenuItem. Now you can set the MenuAction like this:
Our second example is a Tree structure. Let’s assume we have a ViewModel for that:
Again we can now add methods that act directly on the userObject without any indirection or mapping involved.