membrane

zimablue 2023-09-23T19:48:28.550459Z

I agree re mouse event availability

zimablue 2023-09-23T19:50:19.120089Z

interesting related (?) problem to this, not sure if it's just my outside-the-effects-system implementation, but when you implement a click-and-drag, you can "lose" the drag if you move too fast

zimablue 2023-09-23T19:50:35.106229Z

because the event is not being passed to the element, because now the mouse is outside the bounds of the element

zimablue 2023-09-23T19:51:21.490099Z

so: click, drag right slowly, unclick => all good click, drag right quickly, (once the mouse leaves the object bounds it stops being dragged), unclick => you also lose the 'mouseup' event after

zimablue 2023-09-23T19:53:48.161979Z

I'd be curious to know whether somehow the component effect system prevents this (I'm just swap!ing an atom to change the state), my intuition is that it wouldn,t because mouse move events must be debounced somewhere in the browser stack, so you can always move the mouse fast enough that the diff between the positions of two consecutive mousemove events is greater than the distance to the edge of the object, so it's not that 'we're not redrawing fast enough/between events', but I'm not certain

phronmophobic 2023-09-23T19:55:37.218789Z

The root cause is that things like drag and drop need more context.

phronmophobic 2023-09-23T19:55:57.023339Z

They should get support from a top level component.

phronmophobic 2023-09-23T19:58:51.983999Z

There's some initial work on drag and drop https://github.com/phronmophobic/membrane/blob/master/src/membrane/alpha/component/drag_and_drop.cljc, but the key idea is that if you want to response to global mouse events, then the handler should be implemented by the top level component.

phronmophobic 2023-09-23T19:59:54.350519Z

Having a top level component that supports drag and drop can be done through functional bubbling.

phronmophobic 2023-09-23T20:02:10.498089Z

Basically, you have a child component emit a [:drag-start ...] event which the top level catches and handles. The top level component can then capture all mouse-move events and turn then into drag events until the dragging is complete (you almost never want mouse-move handlers from other elements to fire while dragging is happening).

zimablue 2023-09-23T20:07:23.475159Z

having a top level component doesn't preclude that though, could imagine eg. highlight to drop onto, which is logical and a top level handler could as you say support

👍 1
zimablue 2023-09-23T20:07:56.069229Z

it's a nice solution, does complicate/make it more involved to encapsulate those behaviours though

phronmophobic 2023-09-23T20:09:31.837349Z

I've started using it a few places and it seems pretty nice. I would like to have it as a builtin option so drag and drop can work consistently across apps (it would still be able to be enabled/disabled).

zimablue 2023-09-23T20:10:06.714449Z

another thing which is currently happening is that when I have eg. one rectangle, my drag-release moves it down and right. Now, if I click to the above-left of that element, the drag still works. I presume that this is something to do with bounds checking and maybe origin calculation

zimablue 2023-09-23T20:13:13.982809Z

I think it's because the "on" is outside (contains) the "translate" element, if the "on" was inside the "translate" I'm guessing it would work as expected

phronmophobic 2023-09-23T20:16:37.795889Z

that sounds right

zimablue 2023-09-23T20:40:48.798619Z

commuting them fixed the bounds issue but created a weird broken drag experience (very slow, flipping backwards and forwards a bit), maybe some weird thing in my code

zimablue 2023-09-23T20:40:57.426039Z

good chilled saturday investigation lol

😄 1
zimablue 2023-09-23T20:41:45.250259Z

in the original form you have the bounds issue but the drag itself is smooth, very strange that flipping them does this

zimablue 2023-09-23T22:55:45.619319Z

was my code, you can't use the same accumulation of changes in local position if the translate is outside, I forgot that the code worked on local-pos which will be different and so I shouldn't expect it to commute

zimablue 2023-09-23T22:56:01.460099Z

haven't been doing it solidly lol

phronmophobic 2023-09-23T22:58:06.732269Z

Ah, right. When I was doing drag and drop, I would typically use deltas (ie. drag distance was (dx, dy) rather than drag position is (x,y)).

phronmophobic 2023-09-23T22:58:20.081349Z

Then it doesn't really matter where the origin is.

zimablue 2023-09-23T23:00:06.131979Z

yeah so the original code recorded the first click and kept swapping in the delta from that, like (assoc (delta local-pos original-click)) but the new code (on the other side of translate) is like (update #(+ %1 (delta local-pos original-click ))), because the local position is shifting, need to accumulate changes not just bash in the delta relative to the first click

zimablue 2023-09-23T23:01:05.414679Z

interestingly, I'm not losing my events now when the mouse is slightly outside the bounds of the rect, maybe because it's 'catching up' before the next mouse-move is emitted

zimablue 2023-09-23T23:06:47.481349Z

is your new mouse-mouse-down to the original the same as mouse-move-global to the original?

phronmophobic 2023-09-23T23:12:00.135089Z

No, the change ended up being more subtle. regular mouse-down events work just like they used to. They check the bounds of the child element and only return values for clicks inside their bounds. There's now a new mouse-down-raw handler which can return values for any mouse-event it receives, but most of the time, it's similar since parent components probably still filter out events outside their bounds.

phronmophobic 2023-09-23T23:13:34.670039Z

Overall, I don't think mouse-move-global is the right solution, but it's still available for backwards compatibility. I think a better solution is to use top level components+bubbling for the cases where mouse-move-global was previously used.

zimablue 2023-09-23T23:33:35.093139Z

I see, I only just remembered it existed actually, just looking at the implementation - the relationship with has-mouse-move-global is only created in the component namespace, in terms of base protocols in membrane.ui they're not forced to be related right? Basically it will propagate down to every element by default, instead of shortcutting on a bounds check? because everything delegates to -default-mouse-move-global with that behaviour

phronmophobic 2023-09-23T23:35:47.164629Z

Yes, for mouse-move-global. It logically gets called on every element. membrane.component does some caching to speed things up, but if you'r not using membrane.component, then the mouse-move-global event is called on every element.