This is a follow-up to How to make mouse events propagate to widgets in `scroll` containers?
TL;DR:
The :layout
method I implemented makes the widget draw all over the other widgets (see pictures below). How can I constrain where the :layout
method will draw my widgets and where it will allow me to interact with the children?
Longer version:
So I ended up patching the scroll
container and what I basically did was that I implemented a :layout
method, based on the offset calculations that were already made in the original scroll
container code.
This is basically what I did (I'll only put the relevant parts here):
-- this function emits signals `self._private.fps` times a second
local _need_scroll_redraw = function(self)
if not self._private.paused and not self._private.scroll_timer then
self._private.scroll_timer = timer.start_new(1 / self._private.fps, function()
self._private.scroll_timer = nil
self:emit_signal("widget::redraw_needed")
self:emit_signal("widget::layout_changed") -- this is the only
-- line that I added
-- to this function
end)
end
end
local function calculate_info(self, context, width, height)
-- this is a longer function, but in summary here we calculate the
-- ideal size that the child would like to be, we see if the child
-- is bigger than the space we have for drawing, and if it is,
-- we calculate offsets (and we call `_need_scroll_redraw` here)
-- so we later know where and how often to `:draw` and `:fit` it
end
function scroll:fit(context, width, height)
local info = calculate_info(self, context, width, height)
return info.fit_width, info.fit_height
end
function scroll:layout(context, width, height)
local result = {}
local i = calculate_info(self, context, width, height)
table.insert(result, base.place_widget_at(
self._private.widget, i.first_x, i.first_y, i.surface_width, i.surface_height
))
return result
end
-- Also, there was a `:draw` method, but I took it out entirely since
-- if I add the `:layout` method, things get drawn just fine
-- P.S: I also tried to implement what was in the `:draw` method, inside
-- the `:layout` method, so that it'll clip properly. I also tried that idea
-- with the `:before_draw_children` and `:after_draw_children` methods
-- but since I don't know how to use cairo, god knows what I wrote there,
-- but it didn't work
With the default scroll widget, my widget looks like this, but nothing I click on works:
But with the changes I made above, the widget with the rows does scroll, and I can click on each child just fine and have it react, it's just that it draws everything outside of its boundaries, and I can also click on stuff that's outside of the boundaries:
So my question is: how would I go about restricting what the :layout
method displays, to have it work the way the default scroll
layout works, but still be able to interact with the children?