Closed focustense closed 1 month ago
It probably makes sense to consider #6 as a dependency of this one. While it's possible to mock it up in unit tests, it's hard to be completely certain that any arbitrary design for an asset-loading dependency will be entirely compatible with what SMAPI wants. And in any case, #6 has more immediate importance since it's the whole basis of the mod's API.
The big daddy of features that makes any UI framework maintainable in the long run is composability: the ability to define lower-level "components" and collect them into higher level "layouts".
StardewUI has many widgets that help perform these roles:
CheckBox
,ScrollableView
,Button
and so on. However, it's not possible (or rather, not reasonably practical) to have to extendIView
through the API. Users of the framework API are not going to have access toWrapperView
or necessarily even know how to use it if they did.The solution to this is includes, AKA components, user controls, etc. And StardewUI's model of this should ideally be based on assets; that is, any asset name you could pass into
IViewEngine.CreateMenuFromMarkup
can also be used as the target of an include. This way there is no obscure knowledge required to use it, and we get hot reload and other useful features for free - a major advantage over the web framework situation where there's no invalidation system and they have to be reloaded from the server.While the implementation is bound to be tricky, the specification is really very simple:
That is, "create a new view using the markup in the MyView asset, and assign its context to the
Prop
property of the current context". The context macro (described in #3) is of course optional but probably going to be needed most of the time for included views, since they'll be designed to work with a particular context type.This is a real element that can be combined into repeaters, conditionals, etc. The simplest way to implement it will be to create an actual view type for it, e.g. a
class IncludedView : WrapperView
which loads the specified asset in itsCreateView
. This is, in fact, almost exactly what theDocumentView
already does, except that it depends on an already-loaded document whereas the included view needs to encapsulate the loading logic as well, as well as any invalidation for hot reloads.I think we can kill two birds with one stone here and simply refactor the
DocumentView
to handle loading and invalidation. That way, theDocumentMenu
also gets hot reload for free, whereas currently hot reload is just a theoretical possibility and not actually implemented.