Fork me on GitHub
#membrane
<
2022-03-03
>
Richie14:03:27

"Event Function - a pure function which receives the application state and an event and returns data specifying the user's intent (eg. add a new todo item to the todo list). This facilitates communication from the user to the application." "Event Handler: A pure function of an Event to Intents." from https://blog.phronemophobic.com/ui-model.html These two definitions sound the same which is a little confusing. I think the example helps since the example says that ui/mouse-down is an event function while ui/on :mouse-down is an event handler. Maybe something like "a pure function which receives the application state and an event and uses the event handler to return data specifying the user's intent." That's not great. I'd like something that shows the relationship between the two.

phronmophobic18:03:53

The difference is that the Event Function receives 2 arguments: elem and event while the Event Handler only receives event . Eg.

(defn my-event-function [elem [mx my]]
   ...)
;; vs
(defn my-event-handler [[mx my]]
   ...)
> a pure function which receives the application state and an event and uses the event handler to return data specifying the user's intent An event function need not use any helper functions. I agree that it is a little confusing. I'll try to think about how to clarify the description.

Richie19:03:15

That helps. Thanks!

Richie19:03:56

The blog introduces ui/on to help "bind" event handlers (the functions that turn events into intents). (I read through ui.cljc a little so I see that on constructs a record from the handler function and the element.) In a later example ui/on is used with a function that turns an intent into another intent.

(def add-todo-button (ui/on :mouse-down (fn [_]
                                          [[::add-todo]])
                            (ui/button "Add Todo")))

;; wrap add-todo-button
;; capture all ::add-todo intents bubbling and
;; qualify that we're adding a todo to ::work-todos
(def work-add-todo-button (ui/on ::add-todo (fn []
                                              [[::add-todo ::work-todos]])
                                 add-todo-button))

(def mpos [3 4])
(ui/mouse-down add-todo-button
               mpos) ;; [[::add-todo]]

(ui/mouse-down work-add-todo-button
               mpos) ;; [[::add-todo ::work-todos]]
This example is using on to turn [::add-todo] into [::add-todo ::work-todos]. (It doesn't "turn" anything really; it uses on to associate an event handler with the element.) I think this example is showing that you can use on to "alter intents that are getting passed back up the chain" even though -bubble is the more appropriate function. I don't understand how it works. What happens in the (ui/mouse-down work-add-todo-button mpos) call? I can imagine mouse-down calls -mouse-down which is available on the OnMouseEvent record that on constructed with the handler. Hmm. The :else case of on constructs an EventHandler whose -bubble calls -handle-event and -mouse-event calls -bubble. Ok, maybe I get the machinery now. I think there might be some friction for me since I assume that on only works with events coming into the element. There's actually a dual use with bubble that's covered next but that went over my head on my first read through. I'd like to see the example with bubble. I think the impl of bubble is straightforward and would just match on the first item of each intent vector and substitute [::add-todo] with [::add-todo ::work-todos] but I think it adds value to the blog.

Richie19:03:01

So like, it catches events on the down and intents on the way up?

phronmophobic06:03:15

> I think this example is showing that you can use on to "alter intents that are getting passed back up the chain" even though -bubble is the more appropriate function You're right that membrane.ui/on is overloaded. It can be used for input events and for bubbling. In principle, I think this is ok since membrane.ui/on is solely for convenience and there are simpler constructs to fallback to (eg. on-mouse-move, on-key-event, on-bubble, etc.). I'm not totally convinced that it's the optimal API, but I've found it convenient so far. However, I have a major bias since I'm very familiar with the full stack so your feedback is helpful. > even though -bubble is the more appropriate function The simpler construct is on-bubble rather than -bubble. Bubbling is a crucial part of the event model's API, but -bubble is an implementation detail. Bubbling could be implemented without the IBubble protocol, but there are some design tradeoffs that affect performance and extensibility (eg. adding new event types) that I haven't had time to sort through. > I'd like to see the example with bubble. I think the impl of bubble is straightforward and would just match on the first item of each intent vector and substitute [::add-todo] with [::add-todo ::work-todos] but I think it adds value to the blog. on-bubble was added after I wrote this post. Maybe it makes sense to start with examples that use the simpler constructs like on-mouse-down /`on-bubble` and introduce membrane.ui/on later as a convenient way to add event/bubble handlers. Thoughts? I've found it difficult to explain how the event model works. I want to use familiar words like bubbling, but it makes it easy for the important differences to be overlooked. I think the event model in membrane is much more straightforward than how events work in other UI libraries, but experience with existing UI libraries can make the mindset shift harder to make.

👍 1
Richie12:03:50

I also think it would be better to start with on-mouse-down/`on-bubble` and then introduce on. When I found on-mouse-down in on 's impl, it went over my head that those were part of the public api. I was so focused on the realization that on is overloaded.