add overflow widget from PR #3309 in awesomewm
This commit is contained in:
616
awesome/src/lib/overflow_widget/overflow.lua
Normal file
616
awesome/src/lib/overflow_widget/overflow.lua
Normal file
@@ -0,0 +1,616 @@
|
|||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- A layout that allows its children to take more space than what's available
|
||||||
|
-- in the surrounding container. If the content does exceed the available
|
||||||
|
-- size, a scrollbar is added and scrolling behavior enabled.
|
||||||
|
--
|
||||||
|
--@DOC_wibox_layout_defaults_overflow_EXAMPLE@
|
||||||
|
-- @author Lucas Schwiderski
|
||||||
|
-- @copyright 2021 Lucas Schwiderski
|
||||||
|
-- @layoutmod wibox.layout.overflow
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local base = require('wibox.widget.base')
|
||||||
|
local fixed = require('wibox.layout.fixed')
|
||||||
|
local separator = require('wibox.widget.separator')
|
||||||
|
local gtable = require('gears.table')
|
||||||
|
local gshape = require('gears.shape')
|
||||||
|
local gobject = require('gears.object')
|
||||||
|
local mousegrabber = mousegrabber
|
||||||
|
|
||||||
|
local overflow = { mt = {} }
|
||||||
|
|
||||||
|
-- Determine the required space to draw the layout's children and, if necessary,
|
||||||
|
-- the scrollbar.
|
||||||
|
function overflow:fit(context, orig_width, orig_height)
|
||||||
|
local widgets = self._private.widgets
|
||||||
|
local num_widgets = #widgets
|
||||||
|
if num_widgets < 1 then
|
||||||
|
return 0, 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local width, height = orig_width, orig_height
|
||||||
|
local scrollbar_width = self._private.scrollbar_width
|
||||||
|
local scrollbar_enabled = self._private.scrollbar_enabled
|
||||||
|
local used_in_dir, used_max = 0, 0
|
||||||
|
local is_y = self._private.dir == "y"
|
||||||
|
local avail_in_dir = is_y and orig_height or orig_width
|
||||||
|
|
||||||
|
-- Set the direction covered by scrolling to the maximum value
|
||||||
|
-- to allow widgets to take as much space as they want.
|
||||||
|
if is_y then
|
||||||
|
height = math.huge
|
||||||
|
else
|
||||||
|
width = math.huge
|
||||||
|
end
|
||||||
|
|
||||||
|
-- First, determine widget sizes.
|
||||||
|
-- Only when the content doesn't fit and needs scrolling should
|
||||||
|
-- we reduce content size to make space for a scrollbar.
|
||||||
|
for _, widget in pairs(widgets) do
|
||||||
|
local w, h = base.fit_widget(self, context, widget, width, height)
|
||||||
|
|
||||||
|
if is_y then
|
||||||
|
used_max = math.max(used_max, w)
|
||||||
|
used_in_dir = used_in_dir + h
|
||||||
|
else
|
||||||
|
used_in_dir = used_in_dir + w
|
||||||
|
used_max = math.max(used_max, h)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local spacing = self._private.spacing * (num_widgets - 1)
|
||||||
|
used_in_dir = used_in_dir + spacing
|
||||||
|
|
||||||
|
local need_scrollbar = used_in_dir > avail_in_dir and scrollbar_enabled
|
||||||
|
|
||||||
|
-- If the direction perpendicular to scrolling (e.g. width in vertical
|
||||||
|
-- scrolling) is not fully covered by any of the widgets, we can add our
|
||||||
|
-- scrollbar width to that value. Otherwise widget size will be reduced
|
||||||
|
-- during `layout` to make space for the scrollbar.
|
||||||
|
if need_scrollbar
|
||||||
|
and (
|
||||||
|
(is_y and used_max < orig_width)
|
||||||
|
or (not is_y and used_max < orig_height)
|
||||||
|
) then
|
||||||
|
used_max = used_max + scrollbar_width
|
||||||
|
end
|
||||||
|
|
||||||
|
if is_y then
|
||||||
|
return used_max, used_in_dir
|
||||||
|
else
|
||||||
|
return used_in_dir, used_max
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Layout children, scrollbar and spacing widgets.
|
||||||
|
-- Only those widgets that are currently visible will be placed.
|
||||||
|
function overflow:layout(context, orig_width, orig_height)
|
||||||
|
local result = {}
|
||||||
|
local is_y = self._private.dir == "y"
|
||||||
|
local widgets = self._private.widgets
|
||||||
|
local avail_in_dir = is_y and orig_height or orig_width
|
||||||
|
local scrollbar_width = self._private.scrollbar_width
|
||||||
|
local scrollbar_enabled = self._private.scrollbar_enabled
|
||||||
|
local scrollbar_position = self._private.scrollbar_position
|
||||||
|
local width, height = orig_width, orig_height
|
||||||
|
local widget_x, widget_y = 0, 0
|
||||||
|
local used_in_dir, used_max = 0, 0
|
||||||
|
|
||||||
|
-- Set the direction covered by scrolling to the maximum value
|
||||||
|
-- to allow widgets to take as much space as they want.
|
||||||
|
if is_y then
|
||||||
|
height = math.huge
|
||||||
|
else
|
||||||
|
width = math.huge
|
||||||
|
end
|
||||||
|
|
||||||
|
-- First, determine widget sizes.
|
||||||
|
-- Only when the content doesn't fit and needs scrolling should
|
||||||
|
-- we reduce content size to make space for a scrollbar.
|
||||||
|
for _, widget in pairs(widgets) do
|
||||||
|
local w, h = base.fit_widget(self, context, widget, width, height)
|
||||||
|
|
||||||
|
if is_y then
|
||||||
|
used_max = math.max(used_max, w)
|
||||||
|
used_in_dir = used_in_dir + h
|
||||||
|
else
|
||||||
|
used_in_dir = used_in_dir + w
|
||||||
|
used_max = math.max(used_max, h)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
used_in_dir = used_in_dir + self._private.spacing * (#widgets - 1)
|
||||||
|
|
||||||
|
-- Save size for scrolling behavior
|
||||||
|
self._private.avail_in_dir = avail_in_dir
|
||||||
|
self._private.used_in_dir = used_in_dir
|
||||||
|
|
||||||
|
local need_scrollbar = used_in_dir > avail_in_dir and scrollbar_enabled
|
||||||
|
|
||||||
|
local scroll_position = self._private.position
|
||||||
|
|
||||||
|
if need_scrollbar then
|
||||||
|
local scrollbar_widget = self._private.scrollbar_widget
|
||||||
|
local bar_x, bar_y = 0, 0
|
||||||
|
local bar_w, bar_h
|
||||||
|
-- The percentage of how much of the content can be visible within
|
||||||
|
-- the available space
|
||||||
|
local visible_percent = avail_in_dir / used_in_dir
|
||||||
|
-- Make scrollbar length reflect `visible_percent`
|
||||||
|
-- TODO: Apply a default minimum length
|
||||||
|
local bar_length = math.floor(visible_percent * avail_in_dir)
|
||||||
|
local bar_pos = (avail_in_dir - bar_length) * self._private.position
|
||||||
|
|
||||||
|
if is_y then
|
||||||
|
bar_w, bar_h = base.fit_widget(self, context, scrollbar_widget, scrollbar_width, bar_length)
|
||||||
|
bar_y = bar_pos
|
||||||
|
|
||||||
|
if scrollbar_position == "left" then
|
||||||
|
widget_x = widget_x + bar_w
|
||||||
|
elseif scrollbar_position == "right" then
|
||||||
|
bar_x = orig_width - bar_w
|
||||||
|
end
|
||||||
|
|
||||||
|
self._private.bar_length = bar_h
|
||||||
|
|
||||||
|
width = width - bar_w
|
||||||
|
else
|
||||||
|
bar_w, bar_h = base.fit_widget(self, context, scrollbar_widget, bar_length, scrollbar_width)
|
||||||
|
bar_x = bar_pos
|
||||||
|
|
||||||
|
if scrollbar_position == "top" then
|
||||||
|
widget_y = widget_y + bar_h
|
||||||
|
elseif scrollbar_position == "bottom" then
|
||||||
|
bar_y = orig_height - bar_h
|
||||||
|
end
|
||||||
|
|
||||||
|
self._private.bar_length = bar_w
|
||||||
|
|
||||||
|
height = height - bar_h
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(result, base.place_widget_at(
|
||||||
|
scrollbar_widget,
|
||||||
|
math.floor(bar_x),
|
||||||
|
math.floor(bar_y),
|
||||||
|
math.floor(bar_w),
|
||||||
|
math.floor(bar_h)
|
||||||
|
))
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos, spacing = 0, self._private.spacing
|
||||||
|
local interval = used_in_dir - avail_in_dir
|
||||||
|
|
||||||
|
local spacing_widget = self._private.spacing_widget
|
||||||
|
if spacing_widget then
|
||||||
|
if is_y then
|
||||||
|
local _
|
||||||
|
_, spacing = base.fit_widget(self, context, spacing_widget, width, spacing)
|
||||||
|
else
|
||||||
|
spacing = base.fit_widget(self, context, spacing_widget, spacing, height)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, w in pairs(widgets) do
|
||||||
|
local content_x, content_y
|
||||||
|
local content_w, content_h = base.fit_widget(self, context, w, width, height)
|
||||||
|
|
||||||
|
-- When scrolling down, the content itself moves up -> substract
|
||||||
|
local scrolled_pos = pos - (scroll_position * interval)
|
||||||
|
|
||||||
|
-- Stop processing completely once we're passed the visible portion
|
||||||
|
if scrolled_pos > avail_in_dir then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
if is_y then
|
||||||
|
content_x, content_y = widget_x, scrolled_pos
|
||||||
|
pos = pos + content_h + spacing
|
||||||
|
|
||||||
|
if self._private.fill_space then
|
||||||
|
content_w = width
|
||||||
|
end
|
||||||
|
else
|
||||||
|
content_x, content_y = scrolled_pos, widget_y
|
||||||
|
pos = pos + content_w + spacing
|
||||||
|
|
||||||
|
if self._private.fill_space then
|
||||||
|
content_h = height
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local is_in_view = is_y
|
||||||
|
and (scrolled_pos + content_h > 0)
|
||||||
|
or (scrolled_pos + content_w > 0)
|
||||||
|
|
||||||
|
if is_in_view then
|
||||||
|
-- Add the spacing widget, but not before the first widget
|
||||||
|
if i > 1 and spacing_widget then
|
||||||
|
table.insert(result, base.place_widget_at(
|
||||||
|
spacing_widget,
|
||||||
|
-- The way how spacing is added for regular widgets
|
||||||
|
-- and the `spacing_widget` is disconnected:
|
||||||
|
-- The offset for regular widgets is added to `pos` one
|
||||||
|
-- iteration _before_ the one where the widget is actually
|
||||||
|
-- placed.
|
||||||
|
-- Because of that, the placement for the spacing widget
|
||||||
|
-- needs to substract that offset to be placed right after
|
||||||
|
-- the previous regular widget.
|
||||||
|
math.floor(is_y and content_x or (content_x - spacing)),
|
||||||
|
math.floor(is_y and (content_y - spacing) or content_y),
|
||||||
|
math.floor(is_y and content_w or spacing),
|
||||||
|
math.floor(is_y and spacing or content_h)
|
||||||
|
))
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(result, base.place_widget_at(
|
||||||
|
w,
|
||||||
|
math.floor(content_x),
|
||||||
|
math.floor(content_y),
|
||||||
|
math.floor(content_w),
|
||||||
|
math.floor(content_h)
|
||||||
|
))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
function overflow:before_draw_children(_, cr, width, height)
|
||||||
|
-- Clip drawing for children to the space we're allowed to draw in
|
||||||
|
cr:rectangle(0, 0, width, height)
|
||||||
|
cr:clip()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The amount of units to advance per scroll event.
|
||||||
|
-- This affects calls to `scroll` and the default mouse wheel handler.
|
||||||
|
--
|
||||||
|
-- The default is `10`.
|
||||||
|
--
|
||||||
|
-- @property step
|
||||||
|
-- @tparam number step The step size.
|
||||||
|
-- @see set_step
|
||||||
|
|
||||||
|
--- Set the step size.
|
||||||
|
--
|
||||||
|
-- @method overflow:set_step
|
||||||
|
-- @tparam number step The step size.
|
||||||
|
-- @see step
|
||||||
|
function overflow:set_step(step)
|
||||||
|
self._private.step = step
|
||||||
|
-- We don't need to emit enything here, since changing step only really
|
||||||
|
-- takes effect the next time the user scrolls
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Scroll the layout's content by `amount * step`.
|
||||||
|
-- A positive amount scroll down/right, a negative amount scrolls up/left.
|
||||||
|
--
|
||||||
|
-- @method overflow:scroll
|
||||||
|
-- @tparam number amount The amount to scroll by.
|
||||||
|
-- @emits property::overflow::position
|
||||||
|
-- @emitstparam property::overflow::position number position The new position.
|
||||||
|
-- @emits widget::layout_changed
|
||||||
|
-- @emits widget::redraw_needed
|
||||||
|
-- @see step
|
||||||
|
function overflow:scroll(amount)
|
||||||
|
if amount == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local interval = self._private.used_in_dir
|
||||||
|
local delta = self._private.step / interval
|
||||||
|
|
||||||
|
local pos = self._private.position + (delta * amount)
|
||||||
|
self:set_position(pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The scroll position.
|
||||||
|
-- The position is represented as a fraction from `0` to `1`.
|
||||||
|
--
|
||||||
|
-- @property position
|
||||||
|
-- @tparam number position The position.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @see set_position
|
||||||
|
|
||||||
|
--- Set the current scroll position.
|
||||||
|
--
|
||||||
|
-- @method overflow:set_position
|
||||||
|
-- @tparam number position The new position.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @emits widget::layout_changed
|
||||||
|
-- @emits widget::redraw_needed
|
||||||
|
-- @see position
|
||||||
|
function overflow:set_position(pos)
|
||||||
|
local current = self._private.position
|
||||||
|
local interval = self._private.used_in_dir - self._private.avail_in_dir
|
||||||
|
if current == pos
|
||||||
|
-- the content takes less space than what is available, i.e. everything
|
||||||
|
-- is already visible
|
||||||
|
or interval <= 0
|
||||||
|
-- the position is out of range
|
||||||
|
or (current <= 0 and pos < 0)
|
||||||
|
or (current >= 1 and pos > 1) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self._private.position = math.min(1, math.max(pos, 0))
|
||||||
|
|
||||||
|
self:emit_signal("widget::layout_changed")
|
||||||
|
self:emit_signal("property::position", pos)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the current scroll position.
|
||||||
|
--
|
||||||
|
-- @method overflow:get_position
|
||||||
|
-- @treturn number position The current position.
|
||||||
|
-- @see position
|
||||||
|
function overflow:get_position()
|
||||||
|
return self._private.position
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The scrollbar width.
|
||||||
|
-- For horizontal scrollbars, this is the scrollbar height
|
||||||
|
--
|
||||||
|
-- The default is `5`.
|
||||||
|
--
|
||||||
|
--@DOC_wibox_layout_overflow_scrollbar_width_EXAMPLE@
|
||||||
|
--
|
||||||
|
-- @property scrollbar_width
|
||||||
|
-- @tparam number scrollbar_width The scrollbar width.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @see set_scrollbar_width
|
||||||
|
|
||||||
|
--- Set the scrollbar width.
|
||||||
|
--
|
||||||
|
-- @method overflow:set_scrollbar_width
|
||||||
|
-- @tparam number scrollbar_width The new scrollbar width.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @emits widget::layout_changed
|
||||||
|
-- @emits widget::redraw_needed
|
||||||
|
-- @see scrollbar_width
|
||||||
|
function overflow:set_scrollbar_width(width)
|
||||||
|
if self._private.scrollbar_width == width then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self._private.scrollbar_width = width
|
||||||
|
|
||||||
|
self:emit_signal("widget::layout_changed")
|
||||||
|
self:emit_signal("property::scrollbar_width", width)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The scrollbar position.
|
||||||
|
--
|
||||||
|
-- For horizontal scrollbars, this can be `"top"` or `"bottom"`,
|
||||||
|
-- for vertical scrollbars this can be `"left"` or `"right"`.
|
||||||
|
-- The default is `"left"`/`"bottom"`.
|
||||||
|
--
|
||||||
|
--@DOC_wibox_layout_overflow_scrollbar_position_EXAMPLE@
|
||||||
|
--
|
||||||
|
-- @property scrollbar_position
|
||||||
|
-- @tparam string scrollbar_position The scrollbar position.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @see set_scrollbar_position
|
||||||
|
|
||||||
|
--- Set the scrollbar position.
|
||||||
|
--
|
||||||
|
-- @method overflow:set_scrollbar_position
|
||||||
|
-- @tparam string scrollbar_position The new scrollbar position.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @emits widget::layout_changed
|
||||||
|
-- @emits widget::redraw_needed
|
||||||
|
-- @see scrollbar_position
|
||||||
|
function overflow:set_scrollbar_position(position)
|
||||||
|
if self._private.scrollbar_position == position then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self._private.scrollbar_position = position
|
||||||
|
|
||||||
|
self:emit_signal("widget::layout_changed")
|
||||||
|
self:emit_signal("property::scrollbar_position", position)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The scrollbar visibility.
|
||||||
|
-- If this is set to `false`, no scrollbar will be rendered, even if the layout's
|
||||||
|
-- content overflows. Mouse wheel scrolling will work regardless.
|
||||||
|
--
|
||||||
|
-- The default is `true`.
|
||||||
|
--
|
||||||
|
-- @property scrollbar_enabled
|
||||||
|
-- @tparam boolean scrollbar_enabled The scrollbar visibility.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @see set_scrollbar_enabled
|
||||||
|
|
||||||
|
--- Enable or disable the scrollbar visibility.
|
||||||
|
--
|
||||||
|
-- @method overflow:set_scrollbar_enabled
|
||||||
|
-- @tparam boolean scrollbar_enabled The new scrollbar visibility.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @emits widget::layout_changed
|
||||||
|
-- @emits widget::redraw_needed
|
||||||
|
-- @see scrollbar_enabled
|
||||||
|
function overflow:set_scrollbar_enabled(enabled)
|
||||||
|
if self._private.scrollbar_enabled == enabled then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self._private.scrollbar_enabled = enabled
|
||||||
|
|
||||||
|
self:emit_signal("widget::layout_changed")
|
||||||
|
self:emit_signal("property::scrollbar_enabled", enabled)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Wraps a callback function for `mousegrabber` that is capable of
|
||||||
|
-- updating the scroll position.
|
||||||
|
local function build_grabber(container)
|
||||||
|
local is_y = container._private.dir == "y"
|
||||||
|
local bar_interval = container._private.avail_in_dir - container._private.bar_length
|
||||||
|
local start_pos = container._private.position * bar_interval
|
||||||
|
local coords = mouse.coords()
|
||||||
|
local start = is_y and coords.y or coords.x
|
||||||
|
|
||||||
|
return function(mouse)
|
||||||
|
if not mouse.buttons[1] then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local pos = is_y and mouse.y or mouse.x
|
||||||
|
container:set_position((start_pos + (pos - start)) / bar_interval)
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Applies a mouse button signal using `build_grabber` to a scrollbar widget.
|
||||||
|
local function apply_scrollbar_mouse_signal(container, w)
|
||||||
|
w:connect_signal('button::press', function(_, _, _, button_id)
|
||||||
|
if button_id ~= 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
mousegrabber.run(build_grabber(container), "fleur")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- The scrollbar widget.
|
||||||
|
-- This widget is rendered as the scrollbar element.
|
||||||
|
--
|
||||||
|
-- The default is `awful.widget.separator{ shape = gears.shape.rectangle }`.
|
||||||
|
--
|
||||||
|
--@DOC_wibox_layout_overflow_scrollbar_widget_EXAMPLE@
|
||||||
|
--
|
||||||
|
-- @property scrollbar_widget
|
||||||
|
-- @tparam widget scrollbar_widget The scrollbar widget.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @see set_scrollbar_widget
|
||||||
|
|
||||||
|
--- Set the scrollbar widget.
|
||||||
|
--
|
||||||
|
-- This will also apply the mouse button handler.
|
||||||
|
--
|
||||||
|
-- @method overflow:set_scrollbar_widget
|
||||||
|
-- @tparam widget scrollbar_widget The new scrollbar widget.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @emits widget::layout_changed
|
||||||
|
-- @see scrollbar_widget
|
||||||
|
function overflow:set_scrollbar_widget(widget)
|
||||||
|
local w = base.make_widget_from_value(widget)
|
||||||
|
|
||||||
|
apply_scrollbar_mouse_signal(self, w)
|
||||||
|
|
||||||
|
self._private.scrollbar_widget = w
|
||||||
|
|
||||||
|
self:emit_signal("widget::layout_changed")
|
||||||
|
self:emit_signal("property::scrollbar_widget", widget)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function new(dir, ...)
|
||||||
|
local ret = fixed[dir](...)
|
||||||
|
|
||||||
|
gtable.crush(ret, overflow, true)
|
||||||
|
ret.widget_name = gobject.modulename(2)
|
||||||
|
|
||||||
|
-- Manually set the position here. We don't know the bounding size yet.
|
||||||
|
ret._private.position = 0
|
||||||
|
|
||||||
|
-- Apply defaults. Bypass setters to avoid signals.
|
||||||
|
ret._private.step = 10
|
||||||
|
ret._private.fill_space = true
|
||||||
|
ret._private.scrollbar_width = 5
|
||||||
|
ret._private.scrollbar_enabled = true
|
||||||
|
ret._private.scrollbar_position = dir == "vertical" and "right" or "bottom"
|
||||||
|
|
||||||
|
local scrollbar_widget = separator({ shape = gshape.rectangle })
|
||||||
|
apply_scrollbar_mouse_signal(ret, scrollbar_widget)
|
||||||
|
ret._private.scrollbar_widget = scrollbar_widget
|
||||||
|
|
||||||
|
ret:connect_signal('button::press', function(self, _, _, button)
|
||||||
|
if button == 4 then
|
||||||
|
if self.scroll_speed == nil or self.scroll_speed <= 0 then
|
||||||
|
self:scroll(-1)
|
||||||
|
else
|
||||||
|
self:scroll(-1 * self.scroll_speed)
|
||||||
|
end
|
||||||
|
elseif button == 5 then
|
||||||
|
if self.scroll_speed == nil or self.scroll_speed <= 0 then
|
||||||
|
self:scroll(1)
|
||||||
|
else
|
||||||
|
self:scroll(1 * self.scroll_speed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a new horizontal overflow layout.
|
||||||
|
-- Child widgets are placed similar to `wibox.layout.fixed`, except that
|
||||||
|
-- they may take as much width as they want. If the total width of all child
|
||||||
|
-- widgets exceeds the width available whithin the layout's outer container
|
||||||
|
-- a scrollbar will be added and scrolling behavior enabled.
|
||||||
|
-- @tparam widget ... Widgets that should be added to the layout.
|
||||||
|
-- @constructorfct wibox.layout.overflow.horizontal
|
||||||
|
function overflow.horizontal(...)
|
||||||
|
return new("horizontal", ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a new vertical overflow layout.
|
||||||
|
-- Child widgets are placed similar to `wibox.layout.fixed`, except that
|
||||||
|
-- they may take as much height as they want. If the total height of all child
|
||||||
|
-- widgets exceeds the height available whithin the layout's outer container
|
||||||
|
-- a scrollbar will be added and scrolling behavior enabled.
|
||||||
|
-- @tparam widget ... Widgets that should be added to the layout.
|
||||||
|
-- @constructorfct wibox.layout.fixed.horizontal
|
||||||
|
function overflow.vertical(...)
|
||||||
|
return new("vertical", ...)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add spacing between each layout widgets.
|
||||||
|
--
|
||||||
|
-- This behaves just like in `wibox.layout.fixed`:
|
||||||
|
--
|
||||||
|
--@DOC_wibox_layout_fixed_spacing_EXAMPLE@
|
||||||
|
--
|
||||||
|
-- @property spacing
|
||||||
|
-- @tparam number spacing Spacing between widgets.
|
||||||
|
-- @propemits true false
|
||||||
|
-- @see wibox.layout.fixed
|
||||||
|
|
||||||
|
|
||||||
|
--- The widget used to fill the spacing between the layout elements.
|
||||||
|
-- By default, no widget is used.
|
||||||
|
--
|
||||||
|
-- This behaves just like in `wibox.layout.fixed`:
|
||||||
|
--
|
||||||
|
--@DOC_wibox_layout_fixed_spacing_widget_EXAMPLE@
|
||||||
|
--
|
||||||
|
-- @property spacing_widget
|
||||||
|
-- @tparam widget spacing_widget
|
||||||
|
-- @propemits true false
|
||||||
|
-- @see wibox.layout.fixed
|
||||||
|
|
||||||
|
|
||||||
|
--- Set the layout's fill_space property.
|
||||||
|
--
|
||||||
|
-- If this property is `true`, widgets
|
||||||
|
-- take all space in the non-scrolling directing (e.g. `width` for vertical
|
||||||
|
-- scrolling). If `false`, they will only take as much as they need for their
|
||||||
|
-- content.
|
||||||
|
--
|
||||||
|
-- The default is `true`.
|
||||||
|
--
|
||||||
|
--@DOC_wibox_layout_overflow_fill_space_EXAMPLE@
|
||||||
|
--
|
||||||
|
-- @property fill_space
|
||||||
|
-- @tparam boolean fill_space
|
||||||
|
-- @propemits true false
|
||||||
|
|
||||||
|
|
||||||
|
--@DOC_fixed_COMMON@
|
||||||
|
|
||||||
|
--@DOC_widget_COMMON@
|
||||||
|
|
||||||
|
--@DOC_object_COMMON@
|
||||||
|
|
||||||
|
return setmetatable(overflow, overflow.mt)
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
@@ -15,7 +15,7 @@ local icondir = awful.util.getdir("config") .. "src/assets/icons/notifications/"
|
|||||||
|
|
||||||
local nl = {}
|
local nl = {}
|
||||||
|
|
||||||
nl.notification_list = { layout = wibox.layout.fixed.vertical, spacing = dpi(20) }
|
nl.notification_list = { layout = require("src.lib.overflow_widget.overflow").vertical, scrollbar_width = 0, scroll_speed = 10, spacing = dpi(20) }
|
||||||
|
|
||||||
-- @param {table} notification
|
-- @param {table} notification
|
||||||
-- @return {widget} notifications_list
|
-- @return {widget} notifications_list
|
||||||
|
|||||||
Reference in New Issue
Block a user