Improve design decisions document

This commit is contained in:
Francisco Vallarino 2021-08-13 19:59:59 -03:00
parent f5e1f29c7e
commit 523355c389

View File

@ -18,7 +18,7 @@ Users take care of storing and providing the state to the library. This is
similar to how the model's fields are associated to widgets.
The advantage is that this makes the library more functionally pure. It also
simplifies the internals and may improve performance, since the merge process
simplifies the internals and may improve performance since the merge process
could be simplified.
The disadvantage is that it requires more boilerplate from part of the user,
@ -35,7 +35,7 @@ is transparent from the user's point of view.
The disadvantages are that it makes the library more complex and less
functionally pure than the other approach. It also makes creating custom widgets
a bit more complex, since the merge process needs to be considered.
more complicated, since the merge process needs to be considered.
### What this library does
@ -50,8 +50,8 @@ Sometimes, for performance reasons, you may want to use `mergeRequired` as the
## Are themes really necessary?
While it's true that you can create a customized version of a widget by writing
a regular function, and it is in fact encouraged and used in the examples, in
some cases it is not enough.
a regular function, and it is encouraged and used in the examples, in some cases
it is not enough.
Some widgets, such as `alert` and `confirm`, are built out of nested widgets and
do not expose styling options for all their sub widgets. In this scenario,
@ -61,9 +61,9 @@ Themes also have the nice property of simplifying color scheme switching.
## Why there is not a margin property, considering border and padding do exist?
Margin used to be part of the library, but made mouse event handling more
complex. Since margin is just space outside the border, it can be emulated
by adding a wrapper widget. For example:
Margin used to be part of the library but made mouse event handling more
complex. Since margin is just space outside the border, it can be emulated by
adding a wrapper widget. For example:
```haskell
box (label "Test" `styleBasic` [padding 10, border 1 black])
@ -79,7 +79,7 @@ in handling it. With that in mind, relying on messages or regular events made
more sense.
Considering there is not broadcasting support for messages (they are sent to
a widget on a given path), restricting to the top level widget seemed clearer.
a widget on a given path), restricting to the top-level widget seemed clearer.
## Why, except for render, is the widget interface non monadic?
@ -94,24 +94,24 @@ Reader stack may have been a good idea).
## Why is the return type of Tasks and Producers IO and not MonadIO?
There were some type mismatch issues down the road plus the async library
There were some type mismatch issues down the road, plus the async library
requires using IO to launch asynchronous tasks. Maybe MonadBaseControl or
MonadUnliftIO could be used.
## Why does WidgetNode have a reference to children widget, considering the widget may not have any?
It made development of container widgets simpler. It also gave me the ability to
create utility functions that can be used across the library for inspecting the
widget node tree.
It made the development of container widgets more straightforward. It also gave
me the ability to create utility functions that can be used across the library
for inspecting the widget node tree.
## Why is the location of the optional config argument inconsistent between single and container widgets?
For single widgets having the optional config as the last argument makes sense,
since it is something extra compared to the default version.
For container widgets the usage pattern is a bit different. While splitting a
complex UI into smaller parts is necessary for maintainability, being able to
see the widget hierarchy at first glance is also useful for understanding an
For container widgets, the usage pattern is a bit different. While splitting a
complex UI into smaller parts is necessary for maintainability, seeing the
widget hierarchy at first glance is also helpful for understanding an
application. For this reason, sometimes, widgets are nested directly in their
parent instead of creating a separate list that is later provided to the parent
widget. In that scenario, having the config of the parent widget _after_ its
@ -138,13 +138,13 @@ example,
I wanted to provide a standardized interface for configuring widgets. For
example, all widgets which generate events when clicked should expose a
configuration option using the same name (in this case `onClick`). I think the
configuration option using the same name (in this case, `onClick`). I think the
only options to achieve this are typeclasses and labels, and I chose typeclasses
because I know them better.
This choice may also cause namespace issues that require using qualified
imports. I tried to avoid _reserving_ common names to reduce the number of times
this is required.
this is needed.
If you know a better option to solve this, please let me know!
@ -154,3 +154,28 @@ I needed to store references to lenses in custom data types, which is not
possible with the standard `Lens` type. The lens library provides `ALens`, which
allows for that use case. I don't think microlens has something similar, plus
I'm currently using more things from lens.
## Why nanovg? The project's repository says it's not actively maintained.
[NanoVG](https://github.com/memononen/nanovg) is an easy to use vector graphics
library that uses OpenGL, making it GPU accelerated. It provides a nice set of
drawing operations that cover all the current use cases of Monomer. When I
started the project, NanoVG was actively maintained and was a very reasonable
option.
NanoVG not being maintained is not ideal, but the feature set used by Monomer
has been stable for quite a while. It's also a kind of small library, which
makes porting it to other backends feasible (a version for Metal, which I have
not tested, can be found [here](https://github.com/ollix/MetalNanoVG)).
I have this situation on the back of my mind since I also worry at some point
Apple will discontinue OpenGL support, but it's not on my list of priorities. I
have taken a look at these options:
- [Skia](https://skia.org) has lots of features and is used by Chrome and other
major applications, but the C bindings are marked as not stable, and it does
not look like an easy to distribute library (plus compiling it takes a long
time).
- ImGui's [ImDrawList](https://github.com/ocornut/imgui/issues/1878), the option
I like the most, supports several backends and is an easy to embed library. I
haven't validated if something Monomer uses is missing.