wibox: Create a container module
Previously, the "containers" were placed in layout or widget. They all have similar APIs and usage, so lets bring them together.
This commit is contained in:
parent
990beef9d0
commit
d85588babe
|
@ -17,7 +17,7 @@ Code:
|
|||
{ -- Add a background color/pattern for my_third_widget
|
||||
my_third_widget,
|
||||
bg = beautiful.bg_focus,
|
||||
widget = wibox.widget.background,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ declarative layout, or `nil`.
|
|||
* Create a `wibox.widget.textbox` with various properties
|
||||
* Force the textbox size using `wibox.layout.constraint`
|
||||
* Add a margin around another textbox
|
||||
* Add a `wibox.widget.background` (for visualization)
|
||||
* Add a `wibox.container.background` (for visualization)
|
||||
|
||||
Code:
|
||||
|
||||
|
@ -48,7 +48,7 @@ Code:
|
|||
widget = wibox.widget.textbox
|
||||
},
|
||||
bg = "#ff0000",
|
||||
widget = wibox.widget.background,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
width = 300,
|
||||
strategy = "min",
|
||||
|
@ -62,13 +62,13 @@ Code:
|
|||
widget = wibox.widget.textbox
|
||||
},
|
||||
bg = "#0000ff",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
left = 10,
|
||||
right = 10,
|
||||
top = 1,
|
||||
bottom = 2,
|
||||
layout = wibox.layout.margin
|
||||
layout = wibox.container.margin
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
}
|
||||
|
|
|
@ -82,6 +82,7 @@ file = {
|
|||
'../lib/gears/init.lua',
|
||||
'../lib/wibox/layout/init.lua',
|
||||
'../lib/wibox/widget/init.lua',
|
||||
'../lib/wibox/container/init.lua',
|
||||
|
||||
-- Ignore some parts of the widget library
|
||||
'../lib/awful/widget/init.lua',
|
||||
|
|
|
@ -195,7 +195,7 @@ local function group_label(group, color)
|
|||
)
|
||||
)
|
||||
)
|
||||
local margin = wibox.layout.margin()
|
||||
local margin = wibox.container.margin()
|
||||
margin:set_widget(textbox)
|
||||
margin:set_top(widget.group_margin)
|
||||
return margin
|
||||
|
@ -315,7 +315,7 @@ local function create_wibox(s, available_groups)
|
|||
else
|
||||
available_width_px = available_width_px - item.max_width
|
||||
end
|
||||
local column_margin = wibox.layout.margin()
|
||||
local column_margin = wibox.container.margin()
|
||||
column_margin:set_widget(item.layout)
|
||||
column_margin:set_left(widget.group_margin)
|
||||
columns:add(column_margin)
|
||||
|
|
|
@ -384,7 +384,7 @@ function menu:add(args, index)
|
|||
item.width = item.width or theme.width
|
||||
item.height = item.height or theme.height
|
||||
wibox.widget.base.check_widget(item.widget)
|
||||
item._background = wibox.widget.background()
|
||||
item._background = wibox.container.background()
|
||||
item._background:set_widget(item.widget)
|
||||
item._background:set_fg(item.theme.fg_normal)
|
||||
item._background:set_bg(item.theme.bg_normal)
|
||||
|
@ -516,7 +516,7 @@ function menu.entry(parent, args) -- luacheck: no unused args
|
|||
end, 1))
|
||||
-- Set icon if needed
|
||||
local icon, iconbox
|
||||
local margin = wibox.layout.margin()
|
||||
local margin = wibox.container.margin()
|
||||
margin:set_widget(label)
|
||||
if args.icon then
|
||||
icon = surface.load(args.icon)
|
||||
|
|
|
@ -48,7 +48,7 @@ local a_placement = require("awful.placement")
|
|||
local abutton = require("awful.button")
|
||||
local beautiful = require("beautiful")
|
||||
local textbox = require("wibox.widget.textbox")
|
||||
local background = require("wibox.widget.background")
|
||||
local background = require("wibox.container.background")
|
||||
local dpi = require("beautiful").xresources.apply_dpi
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
|
@ -265,7 +265,7 @@ tooltip.new = function(args)
|
|||
-- Add margin.
|
||||
local m_lr = args.margin_leftright or dpi(5)
|
||||
local m_tb = args.margin_topbottom or dpi(3)
|
||||
self.marginbox = wibox.layout.margin(self.background, m_lr, m_lr, m_tb, m_tb)
|
||||
self.marginbox = wibox.container.margin(self.background, m_lr, m_lr, m_tb, m_tb)
|
||||
|
||||
-- Add tooltip to objects
|
||||
if args.objects then
|
||||
|
|
|
@ -60,9 +60,9 @@ function common.list_update(w, buttons, label, data, objects)
|
|||
else
|
||||
ib = wibox.widget.imagebox()
|
||||
tb = wibox.widget.textbox()
|
||||
bgb = wibox.widget.background()
|
||||
tbm = wibox.layout.margin(tb, dpi(4), dpi(4))
|
||||
ibm = wibox.layout.margin(ib, dpi(4))
|
||||
bgb = wibox.container.background()
|
||||
tbm = wibox.container.margin(tb, dpi(4), dpi(4))
|
||||
ibm = wibox.container.margin(ib, dpi(4))
|
||||
l = wibox.layout.fixed.horizontal()
|
||||
|
||||
-- All of this is added in a fixed widget
|
||||
|
|
|
@ -230,7 +230,7 @@ end
|
|||
--
|
||||
-- @tparam[opt=2] integer level Level for `debug.getinfo(level, "S")`.
|
||||
-- Typically 2 or 3.
|
||||
-- @treturn string The module name, e.g. "wibox.widget.background".
|
||||
-- @treturn string The module name, e.g. "wibox.container.background".
|
||||
function object.modulename(level)
|
||||
return debug.getinfo(level, "S").source:gsub(".*/lib/", ""):gsub("/", "."):gsub("%.lua", "")
|
||||
end
|
||||
|
|
|
@ -522,7 +522,7 @@ function naughty.notify(args)
|
|||
|
||||
-- create textbox
|
||||
local textbox = wibox.widget.textbox()
|
||||
local marginbox = wibox.layout.margin()
|
||||
local marginbox = wibox.container.margin()
|
||||
marginbox:set_margins(margin)
|
||||
marginbox:set_widget(textbox)
|
||||
textbox:set_valign("middle")
|
||||
|
@ -538,7 +538,7 @@ function naughty.notify(args)
|
|||
if actions then
|
||||
for action, callback in pairs(actions) do
|
||||
local actiontextbox = wibox.widget.textbox()
|
||||
local actionmarginbox = wibox.layout.margin()
|
||||
local actionmarginbox = wibox.container.margin()
|
||||
actionmarginbox:set_margins(margin)
|
||||
actionmarginbox:set_widget(actiontextbox)
|
||||
actiontextbox:set_valign("middle")
|
||||
|
@ -582,7 +582,7 @@ function naughty.notify(args)
|
|||
-- if we have an icon, use it
|
||||
if icon then
|
||||
iconbox = wibox.widget.imagebox()
|
||||
iconmargin = wibox.layout.margin(iconbox, margin, margin, margin, margin)
|
||||
iconmargin = wibox.container.margin(iconbox, margin, margin, margin, margin)
|
||||
if icon_size then
|
||||
local scaled = cairo.ImageSurface(cairo.Format.ARGB32, icon_size, icon_size)
|
||||
local cr = cairo.Context(scaled)
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- A container capable of changing the background color, foreground color
|
||||
-- widget shape.
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.background
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local base = require("wibox.widget.base")
|
||||
local color = require("gears.color")
|
||||
local surface = require("gears.surface")
|
||||
local beautiful = require("beautiful")
|
||||
local cairo = require("lgi").cairo
|
||||
local setmetatable = setmetatable
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
local background = { mt = {} }
|
||||
|
||||
-- Draw this widget
|
||||
function background:draw(context, cr, width, height)
|
||||
if not self.widget or not self.widget.visible then
|
||||
return
|
||||
end
|
||||
|
||||
-- Keep the shape path in case there is a border
|
||||
self._path = nil
|
||||
|
||||
if self._shape then
|
||||
-- Only add the offset if there is something to draw
|
||||
local offset = ((self._shape_border_width and self._shape_border_color)
|
||||
and self._shape_border_width or 0) / 2
|
||||
|
||||
cr:translate(offset, offset)
|
||||
self._shape(cr, width - 2*offset, height - 2*offset, unpack(self._shape_args or {}))
|
||||
cr:translate(-offset, -offset)
|
||||
self._path = cr:copy_path()
|
||||
cr:clip()
|
||||
end
|
||||
|
||||
if self.background then
|
||||
cr:set_source(self.background)
|
||||
cr:paint()
|
||||
end
|
||||
if self.bgimage then
|
||||
if type(self.bgimage) == "function" then
|
||||
self.bgimage(context, cr, width, height,unpack(self.bgimage_args))
|
||||
else
|
||||
local pattern = cairo.Pattern.create_for_surface(self.bgimage)
|
||||
cr:set_source(pattern)
|
||||
cr:paint()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Draw the border
|
||||
function background:after_draw_children(_, cr)
|
||||
-- Draw the border
|
||||
if self._path and self._shape_border_width and self._shape_border_width > 0 then
|
||||
cr:append_path(self._path)
|
||||
cr:set_source(color(self._shape_border_color or self.foreground or beautiful.fg_normal))
|
||||
|
||||
cr:set_line_width(self._shape_border_width)
|
||||
cr:stroke()
|
||||
self._path = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Prepare drawing the children of this widget
|
||||
function background:before_draw_children(_, cr)
|
||||
if self.foreground then
|
||||
cr:set_source(self.foreground)
|
||||
end
|
||||
|
||||
-- Clip the shape
|
||||
if self._path and self._shape_clip then
|
||||
cr:append_path(self._path)
|
||||
cr:clip()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout this widget
|
||||
function background:layout(_, width, height)
|
||||
if self.widget then
|
||||
return { base.place_widget_at(self.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit this widget into the given area
|
||||
function background:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return base.fit_widget(self, context, self.widget, width, height)
|
||||
end
|
||||
|
||||
--- Set the widget that is drawn on top of the background
|
||||
-- @tparam widget widget The widget to be disaplayed inside of the background
|
||||
-- area
|
||||
function background:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
-- Get children element
|
||||
-- @treturn table The children
|
||||
function background:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function background:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set the background to use.
|
||||
--@DOC_wibox_widget_background_bg_EXAMPLE@
|
||||
-- @param bg A color string, pattern or gradient (see `gears.color`)
|
||||
function background:set_bg(bg)
|
||||
if bg then
|
||||
self.background = color(bg)
|
||||
else
|
||||
self.background = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the foreground to use.
|
||||
--@DOC_wibox_widget_background_fg_EXAMPLE@
|
||||
-- @param fg A color string, pattern or gradient (see `gears.color`)
|
||||
function background:set_fg(fg)
|
||||
if fg then
|
||||
self.foreground = color(fg)
|
||||
else
|
||||
self.foreground = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the background shape.
|
||||
--
|
||||
-- Any other arguments will be passed to the shape function
|
||||
--@DOC_wibox_widget_background_shape_EXAMPLE@
|
||||
-- @param shape A function taking a context, width and height as arguments
|
||||
function background:set_shape(shape, ...)
|
||||
self._shape = shape
|
||||
self._shape_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.container.background.set_shape` for an usage example.
|
||||
-- @tparam number width The border width
|
||||
function background:set_shape_border_width(width)
|
||||
self._shape_border_width = width
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.container.background.set_shape` for an usage example.
|
||||
-- @param[opt=self.foreground] fg The border color, pattern or gradient
|
||||
function background:set_shape_border_color(fg)
|
||||
self._shape_border_color = fg
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, make sure nothing is drawn outside of it.
|
||||
--@DOC_wibox_widget_background_clip_EXAMPLE@
|
||||
-- @tparam boolean value If the shape clip is enable
|
||||
function background:set_shape_clip(value)
|
||||
self._shape_clip = value
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the background image to use
|
||||
-- If `image` is a function, it will be called with `(context, cr, width, height)`
|
||||
-- as arguments. Any other arguments passed to this method will be appended.
|
||||
-- @param image A background image or a function
|
||||
function background:set_bgimage(image, ...)
|
||||
self.bgimage = type(image) == "function" and image or surface.load(image)
|
||||
self.bgimage_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Returns a new background layout. A background layout applies a background
|
||||
-- and foreground color to another widget.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] bg The background to use for that widget.
|
||||
-- @param[opt] shape A `gears.shape` compatible shape function
|
||||
local function new(widget, bg, shape)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(background) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret._shape = shape
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_bg(bg)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function background.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(background, background.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,140 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Lukáš Hrázký
|
||||
-- @copyright 2012 Lukáš Hrázký
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.constraint
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local math = math
|
||||
|
||||
local constraint = { mt = {} }
|
||||
|
||||
--- Layout a constraint layout
|
||||
function constraint:layout(_, width, height)
|
||||
if self.widget then
|
||||
return { base.place_widget_at(self.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
--- Fit a constraint layout into the given space
|
||||
function constraint:fit(context, width, height)
|
||||
local w, h
|
||||
if self.widget then
|
||||
w = self._strategy(width, self._width)
|
||||
h = self._strategy(height, self._height)
|
||||
|
||||
w, h = base.fit_widget(self, context, self.widget, w, h)
|
||||
else
|
||||
w, h = 0, 0
|
||||
end
|
||||
|
||||
w = self._strategy(w, self._width)
|
||||
h = self._strategy(h, self._height)
|
||||
|
||||
return w, h
|
||||
end
|
||||
|
||||
--- Set the widget that this layout adds a constraint on.
|
||||
function constraint:set_widget(widget)
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function constraint:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function constraint:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set the strategy to use for the constraining. Valid values are 'max',
|
||||
-- 'min' or 'exact'. Throws an error on invalid values.
|
||||
function constraint:set_strategy(val)
|
||||
local func = {
|
||||
min = function(real_size, limit)
|
||||
return limit and math.max(limit, real_size) or real_size
|
||||
end,
|
||||
max = function(real_size, limit)
|
||||
return limit and math.min(limit, real_size) or real_size
|
||||
end,
|
||||
exact = function(real_size, limit)
|
||||
return limit or real_size
|
||||
end
|
||||
}
|
||||
|
||||
if not func[val] then
|
||||
error("Invalid strategy for constraint layout: " .. tostring(val))
|
||||
end
|
||||
|
||||
self._strategy = func[val]
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the maximum width to val. nil for no width limit.
|
||||
function constraint:set_width(val)
|
||||
self._width = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the maximum height to val. nil for no height limit.
|
||||
function constraint:set_height(val)
|
||||
self._height = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, strategy set to "max"
|
||||
-- and the constraints set to nil.
|
||||
function constraint:reset()
|
||||
self._width = nil
|
||||
self._height = nil
|
||||
self:set_strategy("max")
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Returns a new constraint layout. This layout will constraint the size of a
|
||||
-- widget according to the strategy. Note that this will only work for layouts
|
||||
-- that respect the widget's size, eg. fixed layout. In layouts that don't
|
||||
-- (fully) respect widget's requested size, the inner widget still might get
|
||||
-- drawn with a size that does not fit the constraint, eg. in flex layout.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] strategy How to constraint the size. 'max' (default), 'min' or
|
||||
-- 'exact'.
|
||||
-- @param[opt] width The maximum width of the widget. nil for no limit.
|
||||
-- @param[opt] height The maximum height of the widget. nil for no limit.
|
||||
local function new(widget, strategy, width, height)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(constraint) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_strategy(strategy or "max")
|
||||
ret:set_width(width)
|
||||
ret:set_height(height)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function constraint.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(constraint, constraint.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,20 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- Collection of containers that can be used in widget boxes
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container
|
||||
---------------------------------------------------------------------------
|
||||
local base = require("wibox.widget.base")
|
||||
|
||||
return setmetatable({
|
||||
rotate = require("wibox.container.rotate");
|
||||
margin = require("wibox.container.margin");
|
||||
mirror = require("wibox.container.mirror");
|
||||
constraint = require("wibox.container.constraint");
|
||||
scroll = require("wibox.container.scroll");
|
||||
background = require("wibox.container.background");
|
||||
}, {__call = function(_, args) return base.make_widget_declarative(args) end})
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,198 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.margin
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local gcolor = require("gears.color")
|
||||
local cairo = require("lgi").cairo
|
||||
|
||||
local margin = { mt = {} }
|
||||
|
||||
-- Draw a margin layout
|
||||
function margin:draw(_, cr, width, height)
|
||||
local x = self.left
|
||||
local y = self.top
|
||||
local w = self.right
|
||||
local h = self.bottom
|
||||
local color = self.color
|
||||
|
||||
if not self.widget or width <= x + w or height <= y + h then
|
||||
return
|
||||
end
|
||||
|
||||
if color then
|
||||
cr:set_source(color)
|
||||
cr:rectangle(0, 0, width, height)
|
||||
cr:rectangle(x, y, width - x - w, height - y - h)
|
||||
cr:set_fill_rule(cairo.FillRule.EVEN_ODD)
|
||||
cr:fill()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout a margin layout
|
||||
function margin:layout(_, width, height)
|
||||
if self.widget then
|
||||
local x = self.left
|
||||
local y = self.top
|
||||
local w = self.right
|
||||
local h = self.bottom
|
||||
|
||||
return { base.place_widget_at(self.widget, x, y, width - x - w, height - y - h) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit a margin layout into the given space
|
||||
function margin:fit(context, width, height)
|
||||
local extra_w = self.left + self.right
|
||||
local extra_h = self.top + self.bottom
|
||||
local w, h = 0, 0
|
||||
if self.widget then
|
||||
w, h = base.fit_widget(self, context, self.widget, width - extra_w, height - extra_h)
|
||||
end
|
||||
|
||||
if self._draw_empty == false and (w == 0 or h == 0) then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return w + extra_w, h + extra_h
|
||||
end
|
||||
|
||||
--- Set the widget that this layout adds a margin on.
|
||||
function margin:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
-- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function margin:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function margin:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set all the margins to val.
|
||||
-- @tparam number val The margin value
|
||||
function margin:set_margins(val)
|
||||
if self.left == val and
|
||||
self.right == val and
|
||||
self.top == val and
|
||||
self.bottom == val then
|
||||
return
|
||||
end
|
||||
|
||||
self.left = val
|
||||
self.right = val
|
||||
self.top = val
|
||||
self.bottom = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the margins color to create a border.
|
||||
-- @param color A color used to fill the margin.
|
||||
function margin:set_color(color)
|
||||
self.color = color and gcolor(color)
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Draw the margin even if the content size is 0x0 (default: true)
|
||||
-- @tparam boolean draw_empty Draw nothing is content is 0x0 or draw the margin anyway
|
||||
function margin:set_draw_empty(draw_empty)
|
||||
self._draw_empty = draw_empty
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, the margins set to 0
|
||||
-- and the color erased
|
||||
function margin:reset()
|
||||
self:set_widget(nil)
|
||||
self:set_margins(0)
|
||||
self:set_color(nil)
|
||||
end
|
||||
|
||||
--- Set the left margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_left
|
||||
-- @class function
|
||||
|
||||
--- Set the right margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_right
|
||||
-- @class function
|
||||
|
||||
--- Set the top margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_top
|
||||
-- @class function
|
||||
|
||||
--- Set the bottom margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_bottom
|
||||
-- @class function
|
||||
|
||||
-- Create setters for each direction
|
||||
for _, v in pairs({ "left", "right", "top", "bottom" }) do
|
||||
margin["set_" .. v] = function(layout, val)
|
||||
if layout[v] == val then return end
|
||||
layout[v] = val
|
||||
layout:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a new margin layout.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] left A margin to use on the left side of the widget.
|
||||
-- @param[opt] right A margin to use on the right side of the widget.
|
||||
-- @param[opt] top A margin to use on the top side of the widget.
|
||||
-- @param[opt] bottom A margin to use on the bottom side of the widget.
|
||||
-- @param[opt] color A color for the margins.
|
||||
-- @param[opt] draw_empty whether or not to draw the margin when the content is empty
|
||||
local function new(widget, left, right, top, bottom, color, draw_empty)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(margin) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_left(left or 0)
|
||||
ret:set_right(right or 0)
|
||||
ret:set_top(top or 0)
|
||||
ret:set_bottom(bottom or 0)
|
||||
ret:set_draw_empty(draw_empty)
|
||||
|
||||
ret:set_color(color)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function margin.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(margin, margin.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,127 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author dodo
|
||||
-- @copyright 2012 dodo
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.mirror
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local error = error
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
|
||||
local mirror = { mt = {} }
|
||||
|
||||
--- Layout this layout
|
||||
function mirror:layout(_, width, height)
|
||||
if not self.widget then return end
|
||||
|
||||
local m = matrix.identity
|
||||
local t = { x = 0, y = 0 } -- translation
|
||||
local s = { x = 1, y = 1 } -- scale
|
||||
if self.horizontal then
|
||||
t.x = width
|
||||
s.x = -1
|
||||
end
|
||||
if self.vertical then
|
||||
t.y = height
|
||||
s.y = -1
|
||||
end
|
||||
m = m:translate(t.x, t.y)
|
||||
m = m:scale(s.x, s.y)
|
||||
|
||||
return { base.place_widget_via_matrix(self.widget, m, width, height) }
|
||||
end
|
||||
|
||||
--- Fit this layout into the given area
|
||||
function mirror:fit(context, ...)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return base.fit_widget(self, context, self.widget, ...)
|
||||
end
|
||||
|
||||
--- Set the widget that this layout mirrors.
|
||||
-- @param widget The widget to mirror
|
||||
function mirror:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function mirror:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function mirror:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the axes reset.
|
||||
function mirror:reset()
|
||||
self.horizontal = false
|
||||
self.vertical = false
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Set the reflection of this mirror layout.
|
||||
-- @param reflection a table which contains new values for horizontal and/or vertical (booleans)
|
||||
function mirror:set_reflection(reflection)
|
||||
if type(reflection) ~= 'table' then
|
||||
error("Invalid type of reflection for mirror layout: " ..
|
||||
type(reflection) .. " (should be a table)")
|
||||
end
|
||||
for _, ref in ipairs({"horizontal", "vertical"}) do
|
||||
if reflection[ref] ~= nil then
|
||||
self[ref] = reflection[ref]
|
||||
end
|
||||
end
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the reflection of this mirror layout.
|
||||
-- @return a table of booleans with the keys "horizontal", "vertical".
|
||||
function mirror:get_reflection()
|
||||
return { horizontal = self.horizontal, vertical = self.vertical }
|
||||
end
|
||||
|
||||
--- Returns a new mirror layout. A mirror layout mirrors a given widget. Use
|
||||
-- :set_widget() to set the widget and
|
||||
-- :set_horizontal() and :set_vertical() for the direction.
|
||||
-- horizontal and vertical are by default false which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] reflection A table describing the reflection to apply.
|
||||
local function new(widget, reflection)
|
||||
local ret = base.make_widget()
|
||||
ret.horizontal = false
|
||||
ret.vertical = false
|
||||
|
||||
for k, v in pairs(mirror) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_reflection(reflection or {})
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function mirror.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(mirror, mirror.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,137 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.rotate
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local error = error
|
||||
local pairs = pairs
|
||||
local pi = math.pi
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local tostring = tostring
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
|
||||
local rotate = { mt = {} }
|
||||
|
||||
local function transform(layout, width, height)
|
||||
local dir = layout:get_direction()
|
||||
if dir == "east" or dir == "west" then
|
||||
return height, width
|
||||
end
|
||||
return width, height
|
||||
end
|
||||
|
||||
--- Layout this layout
|
||||
function rotate:layout(_, width, height)
|
||||
if not self.widget or not self.widget.visible then
|
||||
return
|
||||
end
|
||||
|
||||
local dir = self:get_direction()
|
||||
|
||||
local m = matrix.identity
|
||||
if dir == "west" then
|
||||
m = m:rotate(pi / 2)
|
||||
m = m:translate(0, -width)
|
||||
elseif dir == "south" then
|
||||
m = m:rotate(pi)
|
||||
m = m:translate(-width, -height)
|
||||
elseif dir == "east" then
|
||||
m = m:rotate(3 * pi / 2)
|
||||
m = m:translate(-height, 0)
|
||||
end
|
||||
|
||||
-- Since we rotated, we might have to swap width and height.
|
||||
-- transform() does that for us.
|
||||
return { base.place_widget_via_matrix(self.widget, m, transform(self, width, height)) }
|
||||
end
|
||||
|
||||
--- Fit this layout into the given area
|
||||
function rotate:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return transform(self, base.fit_widget(self, context, self.widget, transform(self, width, height)))
|
||||
end
|
||||
|
||||
--- Set the widget that this layout rotates.
|
||||
function rotate:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function rotate:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function rotate:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the rotation reset.
|
||||
function rotate:reset()
|
||||
self.direction = nil
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Set the direction of this rotating layout. Valid values are "north", "east",
|
||||
-- "south" and "west". On an invalid value, this function will throw an error.
|
||||
function rotate:set_direction(dir)
|
||||
local allowed = {
|
||||
north = true,
|
||||
east = true,
|
||||
south = true,
|
||||
west = true
|
||||
}
|
||||
|
||||
if not allowed[dir] then
|
||||
error("Invalid direction for rotate layout: " .. tostring(dir))
|
||||
end
|
||||
|
||||
self.direction = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the direction of this rotating layout
|
||||
function rotate:get_direction()
|
||||
return self.direction or "north"
|
||||
end
|
||||
|
||||
--- Returns a new rotate layout. A rotate layout rotates a given widget. Use
|
||||
-- :set_widget() to set the widget and :set_direction() for the direction.
|
||||
-- The default direction is "north" which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] dir The direction to rotate to.
|
||||
local function new(widget, dir)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(rotate) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_direction(dir or "north")
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function rotate.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(rotate, rotate.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -0,0 +1,509 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- @author Uli Schlachter (based on ideas from Saleur Geoffrey)
|
||||
-- @copyright 2015 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.container.scroll
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local cache = require("gears.cache")
|
||||
local timer = require("gears.timer")
|
||||
local hierarchy = require("wibox.hierarchy")
|
||||
local base = require("wibox.widget.base")
|
||||
local lgi = require("lgi")
|
||||
local GLib = lgi.GLib
|
||||
|
||||
local scroll = {}
|
||||
local scroll_mt = { __index = scroll }
|
||||
local _need_scroll_redraw
|
||||
|
||||
-- "Strip" a context so that we can use it for our own drawing
|
||||
local function cleanup_context(context)
|
||||
local skip = { wibox = true, drawable = true, client = true, position = true }
|
||||
local res = {}
|
||||
for k, v in pairs(context) do
|
||||
if not skip[k] then
|
||||
res[k] = v
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- Create a hierarchy (and some more stuff) for drawing the given widget. This
|
||||
-- allows "some stuff" to be re-used instead of re-created all the time.
|
||||
local hierarchy_cache = cache.new(function(context, widget, width, height)
|
||||
context = cleanup_context(context)
|
||||
local layouts = setmetatable({}, { __mode = "k" })
|
||||
|
||||
-- Create a widget hierarchy and update when needed
|
||||
local hier
|
||||
local function do_pending_updates(layout)
|
||||
layouts[layout] = true
|
||||
hier:update(context, widget, width, height, nil)
|
||||
end
|
||||
local function emit(signal)
|
||||
-- Make the scroll layouts redraw
|
||||
for w in pairs(layouts) do
|
||||
w:emit_signal(signal)
|
||||
end
|
||||
end
|
||||
local function redraw_callback()
|
||||
emit("widget::redraw_needed")
|
||||
end
|
||||
local function layout_callback()
|
||||
emit("widget::redraw_needed")
|
||||
emit("widget::layout_changed")
|
||||
end
|
||||
hier = hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, nil)
|
||||
|
||||
return hier, do_pending_updates, context
|
||||
end)
|
||||
|
||||
--- Calculate all the information needed for scrolling.
|
||||
-- @param self The instance of the scrolling layout.
|
||||
-- @param context A widget context under which we are fit/drawn.
|
||||
-- @param width The available width
|
||||
-- @param height The available height
|
||||
-- @return A table with the following entries
|
||||
-- @field fit_width The width that should be returned from :fit
|
||||
-- @field fit_height The height that should be returned from :fit
|
||||
-- @field surface_width The width for showing the child widget
|
||||
-- @field surface_height The height for showing the child widget
|
||||
-- @field first_x The x offset for drawing the child the first time
|
||||
-- @field first_y The y offset for drawing the child the first time
|
||||
-- @field[opt] second_x The x offset for drawing the child the second time
|
||||
-- @field[opt] second_y The y offset for drawing the child the second time
|
||||
-- @field hierarchy The wibox.hierarchy instance representing "everything"
|
||||
-- @field context The widget context for drawing the hierarchy
|
||||
local function calculate_info(self, context, width, height)
|
||||
local result = {}
|
||||
assert(self.widget)
|
||||
|
||||
-- First, get the size of the widget (and the size of extra space)
|
||||
local surface_width, surface_height = width, height
|
||||
local extra_width, extra_height, extra = 0, 0, self.expand and self.extra_space or 0
|
||||
local w, h
|
||||
if self.dir == "h" then
|
||||
w, h = base.fit_widget(self, context, self.widget, self.space_for_scrolling, height)
|
||||
surface_width = w
|
||||
extra_width = extra
|
||||
else
|
||||
w, h = base.fit_widget(self, context, self.widget, width, self.space_for_scrolling)
|
||||
surface_height = h
|
||||
extra_height = extra
|
||||
end
|
||||
result.fit_width, result.fit_height = w, h
|
||||
if self.dir == "h" then
|
||||
if self.max_size then
|
||||
result.fit_width = math.min(w, self.max_size)
|
||||
end
|
||||
else
|
||||
if self.max_size then
|
||||
result.fit_height = math.min(h, self.max_size)
|
||||
end
|
||||
end
|
||||
if w > width or h > height then
|
||||
-- There is less space available than we need, we have to scroll
|
||||
_need_scroll_redraw(self)
|
||||
|
||||
surface_width, surface_height = surface_width + extra_width, surface_height + extra_height
|
||||
|
||||
local x, y = 0, 0
|
||||
local function get_scroll_offset(size, visible_size)
|
||||
return self.step_function(self.timer:elapsed(), size, visible_size, self.speed, self.extra_space)
|
||||
end
|
||||
if self.dir == "h" then
|
||||
x = -get_scroll_offset(surface_width - extra, width)
|
||||
else
|
||||
y = -get_scroll_offset(surface_height - extra, height)
|
||||
end
|
||||
result.first_x, result.first_y = x, y
|
||||
-- Was the extra space already included elsewhere?
|
||||
local extra_spacer = self.expand and 0 or self.extra_space
|
||||
if self.dir == "h" then
|
||||
x = x + surface_width + extra_spacer
|
||||
else
|
||||
y = y + surface_height + extra_spacer
|
||||
end
|
||||
result.second_x, result.second_y = x, y
|
||||
else
|
||||
result.first_x, result.first_y = 0, 0
|
||||
end
|
||||
result.surface_width, result.surface_height = surface_width, surface_height
|
||||
|
||||
-- Get the hierarchy and subscribe ourselves to updates
|
||||
local hier, do_pending_updates, ctx = hierarchy_cache:get(context,
|
||||
self.widget, surface_width, surface_height)
|
||||
result.hierarchy = hier
|
||||
result.context = ctx
|
||||
do_pending_updates(self)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Draw this scrolling layout.
|
||||
-- @param context The context in which we are drawn.
|
||||
-- @param cr The cairo context to draw to.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:draw(context, cr, width, height)
|
||||
if not self.widget then
|
||||
return
|
||||
end
|
||||
|
||||
local info = calculate_info(self, context, width, height)
|
||||
|
||||
-- Draw the first instance of the child
|
||||
cr:save()
|
||||
cr:translate(info.first_x, info.first_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
cr:restore()
|
||||
|
||||
-- If there is one, draw the second instance (same code as above, minus the
|
||||
-- clip)
|
||||
if info.second_x and info.second_y then
|
||||
cr:translate(info.second_x, info.second_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
end
|
||||
end
|
||||
|
||||
--- Fit the scroll layout into the given space.
|
||||
-- @param context The context in which we are fit.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
local info = calculate_info(self, context, width, height)
|
||||
return info.fit_width, info.fit_height
|
||||
end
|
||||
|
||||
-- Internal function used for triggering redraws for scrolling.
|
||||
-- The purpose is to start a timer for redrawing the widget for scrolling.
|
||||
-- Redrawing works by simply emitting the `widget::redraw_needed` signal.
|
||||
-- Pausing is implemented in this function: We just don't start a timer.
|
||||
-- This function must be idempotent (calling it multiple times right after
|
||||
-- another does not make a difference).
|
||||
_need_scroll_redraw = function(self)
|
||||
if not self.paused and not self.scroll_timer then
|
||||
self.scroll_timer = timer.start_new(1 / self.fps, function()
|
||||
self.scroll_timer = nil
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- Pause the scrolling animation.
|
||||
-- @see continue
|
||||
function scroll:pause()
|
||||
if self.paused then
|
||||
return
|
||||
end
|
||||
self.paused = true
|
||||
self.timer:stop()
|
||||
end
|
||||
|
||||
--- Continue the scrolling animation.
|
||||
-- @see pause
|
||||
function scroll:continue()
|
||||
if not self.paused then
|
||||
return
|
||||
end
|
||||
self.paused = false
|
||||
self.timer:continue()
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Reset the scrolling state to its initial condition.
|
||||
-- For must scroll step functions, the effect of this function should be to
|
||||
-- display the widget without any scrolling applied.
|
||||
-- This function does not undo the effect of @{pause}.
|
||||
function scroll:reset_scrolling()
|
||||
self.timer:start()
|
||||
if self.paused then
|
||||
self.timer:stop()
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the direction in which this widget scroll.
|
||||
-- @param dir Either "h" for horizontal scrolling or "v" for vertical scrolling
|
||||
function scroll:set_direction(dir)
|
||||
if dir == self.dir then
|
||||
return
|
||||
end
|
||||
if dir ~= "h" and dir ~= "v" then
|
||||
error("Invalid direction, can only be 'h' or 'v'")
|
||||
end
|
||||
self.dir = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the widget which we scroll.
|
||||
-- @tparam widget widget The widget that we should display
|
||||
function scroll:set_widget(widget)
|
||||
if widget == self.widget then
|
||||
return
|
||||
end
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function scroll:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function scroll:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Specify the expand mode that is used for extra space.
|
||||
-- @tparam boolean expand If true, the widget is expanded to include the extra
|
||||
-- space. If false, the extra space is simply left empty.
|
||||
-- @see set_extra_space
|
||||
function scroll:set_expand(expand)
|
||||
if expand == self.expand then
|
||||
return
|
||||
end
|
||||
self.expand = expand
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the number of frames per second that this widget should draw.
|
||||
-- @tparam number fps The number of frames per second
|
||||
function scroll:set_fps(fps)
|
||||
if fps == self.fps then
|
||||
return
|
||||
end
|
||||
self.fps = fps
|
||||
-- No signal needed: If we are scrolling, the next redraw will apply the new
|
||||
-- FPS, else it obviously doesn't make a difference.
|
||||
end
|
||||
|
||||
--- Set the amount of extra space that should be included in the scrolling. This
|
||||
-- extra space will likely be left empty between repetitions of the widgets.
|
||||
-- @tparam number extra_space The amount of extra space
|
||||
-- @see set_expand
|
||||
function scroll:set_extra_space(extra_space)
|
||||
if extra_space == self.extra_space then
|
||||
return
|
||||
end
|
||||
self.extra_space = extra_space
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the speed of the scrolling animation. The exact meaning depends on the
|
||||
-- step function that is used, but for the simplest step functions, this will be
|
||||
-- in pixels per second.
|
||||
-- @tparam number speed The speed for the animation
|
||||
function scroll:set_speed(speed)
|
||||
if speed == self.speed then
|
||||
return
|
||||
end
|
||||
self.speed = speed
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the maximum size of this widget in the direction set by
|
||||
-- @{set_direction}. If the child widget is smaller than this size, no scrolling
|
||||
-- is done. If the child widget is larger, then only this size will be visible
|
||||
-- and the rest is made visible via scrolling.
|
||||
-- @tparam number max_size The maximum size of this widget or nil for unlimited.
|
||||
function scroll:set_max_size(max_size)
|
||||
if max_size == self.max_size then
|
||||
return
|
||||
end
|
||||
self.max_size = max_size
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the step function that determines the exact behaviour of the scrolling
|
||||
-- animation.
|
||||
-- The step function is called with five arguments:
|
||||
--
|
||||
-- * The time in seconds since the state of the animation
|
||||
-- * The size of the child widget
|
||||
-- * The size of the visible part of the widget
|
||||
-- * The speed of the animation. This should have a linear effect on this
|
||||
-- function's behaviour.
|
||||
-- * The extra space configured by @{set_extra_space}. This was not yet added to
|
||||
-- the size of the child widget, but should likely be added to it in most
|
||||
-- cases.
|
||||
--
|
||||
-- The step function should return a single number. This number is the offset at
|
||||
-- which the widget is drawn and should be between 0 and `size+extra_space`.
|
||||
-- @tparam function step_function A step function.
|
||||
-- @see step_functions
|
||||
function scroll:set_step_function(step_function)
|
||||
-- Call the step functions once to see if it works
|
||||
step_function(0, 42, 10, 10, 5)
|
||||
if step_function == self.step_function then
|
||||
return
|
||||
end
|
||||
self.step_function = step_function
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set an upper limit for the space for scrolling.
|
||||
-- This restricts the child widget's maximal size.
|
||||
-- @tparam number space_for_scrolling The space for scrolling
|
||||
function scroll:set_space_for_scrolling(space_for_scrolling)
|
||||
if space_for_scrolling == self.space_for_scrolling then
|
||||
return
|
||||
end
|
||||
self.space_for_scrolling = space_for_scrolling
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
local function get_layout(dir, widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
local ret = base.make_widget()
|
||||
|
||||
ret.paused = false
|
||||
ret.timer = GLib.Timer()
|
||||
ret.scroll_timer = nil
|
||||
|
||||
setmetatable(ret, scroll_mt)
|
||||
|
||||
ret:set_direction(dir)
|
||||
ret:set_widget(widget)
|
||||
ret:set_fps(fps or 20)
|
||||
ret:set_speed(speed or 10)
|
||||
ret:set_extra_space(extra_space or 0)
|
||||
ret:set_expand(expand)
|
||||
ret:set_max_size(max_size)
|
||||
ret:set_step_function(step_function or scroll.step_functions.linear_increase)
|
||||
ret:set_space_for_scrolling(space_for_scrolling or 2^1024)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Get a new horizontal scrolling layout.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.horizontal(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("h", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- Get a new vertical scrolling layout.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.vertical(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("v", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- A selection of step functions
|
||||
-- @see set_step_function
|
||||
scroll.step_functions = {}
|
||||
|
||||
--- A step function that scrolls the widget in an increasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_increase(elapsed, size, _, speed, extra_space)
|
||||
return (elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget in an decreasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_decrease(elapsed, size, _, speed, extra_space)
|
||||
return (-elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is constant.
|
||||
function scroll.step_functions.linear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
state = state <= 1 and state or 2 - state
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle.
|
||||
function scroll.step_functions.nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle. At both ends the widget stands still for a moment.
|
||||
function scroll.step_functions.waiting_nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/5 or state > 4/5 then
|
||||
-- One fifth of time, nothing moves
|
||||
state = state < 1/5 and 0 or 1
|
||||
else
|
||||
state = (state - 1/5) * 5/3
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
return scroll
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
@ -24,6 +24,7 @@ local base = require("wibox.widget.base")
|
|||
-- wibox
|
||||
local wibox = { mt = {}, object = {} }
|
||||
wibox.layout = require("wibox.layout")
|
||||
wibox.container = require("wibox.container")
|
||||
wibox.widget = require("wibox.widget")
|
||||
wibox.drawable = require("wibox.drawable")
|
||||
wibox.hierarchy = require("wibox.hierarchy")
|
||||
|
|
|
@ -1,140 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.`
|
||||
--
|
||||
-- @author Lukáš Hrázký
|
||||
-- @copyright 2012 Lukáš Hrázký
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.constraint
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local math = math
|
||||
local util = require("awful.util")
|
||||
|
||||
local constraint = { mt = {} }
|
||||
|
||||
--- Layout a constraint layout
|
||||
function constraint:layout(_, width, height)
|
||||
if self.widget then
|
||||
return { base.place_widget_at(self.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
--- Fit a constraint layout into the given space
|
||||
function constraint:fit(context, width, height)
|
||||
local w, h
|
||||
if self.widget then
|
||||
w = self._strategy(width, self._width)
|
||||
h = self._strategy(height, self._height)
|
||||
|
||||
w, h = base.fit_widget(self, context, self.widget, w, h)
|
||||
else
|
||||
w, h = 0, 0
|
||||
end
|
||||
|
||||
w = self._strategy(w, self._width)
|
||||
h = self._strategy(h, self._height)
|
||||
|
||||
return w, h
|
||||
end
|
||||
|
||||
--- Set the widget that this layout adds a constraint on.
|
||||
function constraint:set_widget(widget)
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function constraint:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function constraint:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set the strategy to use for the constraining. Valid values are 'max',
|
||||
-- 'min' or 'exact'. Throws an error on invalid values.
|
||||
function constraint:set_strategy(val)
|
||||
local func = {
|
||||
min = function(real_size, limit)
|
||||
return limit and math.max(limit, real_size) or real_size
|
||||
end,
|
||||
max = function(real_size, limit)
|
||||
return limit and math.min(limit, real_size) or real_size
|
||||
end,
|
||||
exact = function(real_size, limit)
|
||||
return limit or real_size
|
||||
end
|
||||
}
|
||||
|
||||
if not func[val] then
|
||||
error("Invalid strategy for constraint layout: " .. tostring(val))
|
||||
end
|
||||
|
||||
self._strategy = func[val]
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the maximum width to val. nil for no width limit.
|
||||
function constraint:set_width(val)
|
||||
self._width = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the maximum height to val. nil for no height limit.
|
||||
function constraint:set_height(val)
|
||||
self._height = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, strategy set to "max"
|
||||
-- and the constraints set to nil.
|
||||
function constraint:reset()
|
||||
self._width = nil
|
||||
self._height = nil
|
||||
self:set_strategy("max")
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Returns a new constraint layout. This layout will constraint the size of a
|
||||
-- widget according to the strategy. Note that this will only work for layouts
|
||||
-- that respect the widget's size, eg. fixed layout. In layouts that don't
|
||||
-- (fully) respect widget's requested size, the inner widget still might get
|
||||
-- drawn with a size that does not fit the constraint, eg. in flex layout.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] strategy How to constraint the size. 'max' (default), 'min' or
|
||||
-- 'exact'.
|
||||
-- @param[opt] width The maximum width of the widget. nil for no limit.
|
||||
-- @param[opt] height The maximum height of the widget. nil for no limit.
|
||||
local function new(widget, strategy, width, height)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(constraint) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_strategy(strategy or "max")
|
||||
ret:set_width(width)
|
||||
ret:set_height(height)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function constraint.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(constraint, constraint.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.constraint"),
|
||||
"wibox.layout.constraint",
|
||||
"wibox.container.constraint"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,198 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.margin`
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.margin
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local gcolor = require("gears.color")
|
||||
local cairo = require("lgi").cairo
|
||||
local util = require("awful.util")
|
||||
|
||||
local margin = { mt = {} }
|
||||
|
||||
-- Draw a margin layout
|
||||
function margin:draw(_, cr, width, height)
|
||||
local x = self.left
|
||||
local y = self.top
|
||||
local w = self.right
|
||||
local h = self.bottom
|
||||
local color = self.color
|
||||
|
||||
if not self.widget or width <= x + w or height <= y + h then
|
||||
return
|
||||
end
|
||||
|
||||
if color then
|
||||
cr:set_source(color)
|
||||
cr:rectangle(0, 0, width, height)
|
||||
cr:rectangle(x, y, width - x - w, height - y - h)
|
||||
cr:set_fill_rule(cairo.FillRule.EVEN_ODD)
|
||||
cr:fill()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout a margin layout
|
||||
function margin:layout(_, width, height)
|
||||
if self.widget then
|
||||
local x = self.left
|
||||
local y = self.top
|
||||
local w = self.right
|
||||
local h = self.bottom
|
||||
|
||||
return { base.place_widget_at(self.widget, x, y, width - x - w, height - y - h) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit a margin layout into the given space
|
||||
function margin:fit(context, width, height)
|
||||
local extra_w = self.left + self.right
|
||||
local extra_h = self.top + self.bottom
|
||||
local w, h = 0, 0
|
||||
if self.widget then
|
||||
w, h = base.fit_widget(self, context, self.widget, width - extra_w, height - extra_h)
|
||||
end
|
||||
|
||||
if self._draw_empty == false and (w == 0 or h == 0) then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return w + extra_w, h + extra_h
|
||||
end
|
||||
|
||||
--- Set the widget that this layout adds a margin on.
|
||||
function margin:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
-- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function margin:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function margin:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set all the margins to val.
|
||||
-- @tparam number val The margin value
|
||||
function margin:set_margins(val)
|
||||
if self.left == val and
|
||||
self.right == val and
|
||||
self.top == val and
|
||||
self.bottom == val then
|
||||
return
|
||||
end
|
||||
|
||||
self.left = val
|
||||
self.right = val
|
||||
self.top = val
|
||||
self.bottom = val
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the margins color to create a border.
|
||||
-- @param color A color used to fill the margin.
|
||||
function margin:set_color(color)
|
||||
self.color = color and gcolor(color)
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Draw the margin even if the content size is 0x0 (default: true)
|
||||
-- @tparam boolean draw_empty Draw nothing is content is 0x0 or draw the margin anyway
|
||||
function margin:set_draw_empty(draw_empty)
|
||||
self._draw_empty = draw_empty
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be unreferenced, the margins set to 0
|
||||
-- and the color erased
|
||||
function margin:reset()
|
||||
self:set_widget(nil)
|
||||
self:set_margins(0)
|
||||
self:set_color(nil)
|
||||
end
|
||||
|
||||
--- Set the left margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_left
|
||||
-- @class function
|
||||
|
||||
--- Set the right margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_right
|
||||
-- @class function
|
||||
|
||||
--- Set the top margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_top
|
||||
-- @class function
|
||||
|
||||
--- Set the bottom margin that this layout adds to its widget.
|
||||
-- @param layout The layout you are modifying.
|
||||
-- @param margin The new margin to use.
|
||||
-- @name set_bottom
|
||||
-- @class function
|
||||
|
||||
-- Create setters for each direction
|
||||
for _, v in pairs({ "left", "right", "top", "bottom" }) do
|
||||
margin["set_" .. v] = function(layout, val)
|
||||
if layout[v] == val then return end
|
||||
layout[v] = val
|
||||
layout:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a new margin layout.
|
||||
-- @param[opt] widget A widget to use.
|
||||
-- @param[opt] left A margin to use on the left side of the widget.
|
||||
-- @param[opt] right A margin to use on the right side of the widget.
|
||||
-- @param[opt] top A margin to use on the top side of the widget.
|
||||
-- @param[opt] bottom A margin to use on the bottom side of the widget.
|
||||
-- @param[opt] color A color for the margins.
|
||||
-- @param[opt] draw_empty whether or not to draw the margin when the content is empty
|
||||
local function new(widget, left, right, top, bottom, color, draw_empty)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(margin) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_left(left or 0)
|
||||
ret:set_right(right or 0)
|
||||
ret:set_top(top or 0)
|
||||
ret:set_bottom(bottom or 0)
|
||||
ret:set_draw_empty(draw_empty)
|
||||
|
||||
ret:set_color(color)
|
||||
|
||||
if widget then
|
||||
ret:set_widget(widget)
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function margin.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(margin, margin.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.margin"),
|
||||
"wibox.layout.margin",
|
||||
"wibox.container.margin"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,127 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.mirror`
|
||||
--
|
||||
-- @author dodo
|
||||
-- @copyright 2012 dodo
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.mirror
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local type = type
|
||||
local error = error
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local setmetatable = setmetatable
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
local util = require("awful.util")
|
||||
|
||||
local mirror = { mt = {} }
|
||||
|
||||
--- Layout this layout
|
||||
function mirror:layout(_, width, height)
|
||||
if not self.widget then return end
|
||||
|
||||
local m = matrix.identity
|
||||
local t = { x = 0, y = 0 } -- translation
|
||||
local s = { x = 1, y = 1 } -- scale
|
||||
if self.horizontal then
|
||||
t.x = width
|
||||
s.x = -1
|
||||
end
|
||||
if self.vertical then
|
||||
t.y = height
|
||||
s.y = -1
|
||||
end
|
||||
m = m:translate(t.x, t.y)
|
||||
m = m:scale(s.x, s.y)
|
||||
|
||||
return { base.place_widget_via_matrix(self.widget, m, width, height) }
|
||||
end
|
||||
|
||||
--- Fit this layout into the given area
|
||||
function mirror:fit(context, ...)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return base.fit_widget(self, context, self.widget, ...)
|
||||
end
|
||||
|
||||
--- Set the widget that this layout mirrors.
|
||||
-- @param widget The widget to mirror
|
||||
function mirror:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function mirror:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function mirror:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the axes reset.
|
||||
function mirror:reset()
|
||||
self.horizontal = false
|
||||
self.vertical = false
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Set the reflection of this mirror layout.
|
||||
-- @param reflection a table which contains new values for horizontal and/or vertical (booleans)
|
||||
function mirror:set_reflection(reflection)
|
||||
if type(reflection) ~= 'table' then
|
||||
error("Invalid type of reflection for mirror layout: " ..
|
||||
type(reflection) .. " (should be a table)")
|
||||
end
|
||||
for _, ref in ipairs({"horizontal", "vertical"}) do
|
||||
if reflection[ref] ~= nil then
|
||||
self[ref] = reflection[ref]
|
||||
end
|
||||
end
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the reflection of this mirror layout.
|
||||
-- @return a table of booleans with the keys "horizontal", "vertical".
|
||||
function mirror:get_reflection()
|
||||
return { horizontal = self.horizontal, vertical = self.vertical }
|
||||
end
|
||||
|
||||
--- Returns a new mirror layout. A mirror layout mirrors a given widget. Use
|
||||
-- :set_widget() to set the widget and
|
||||
-- :set_horizontal() and :set_vertical() for the direction.
|
||||
-- horizontal and vertical are by default false which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] reflection A table describing the reflection to apply.
|
||||
local function new(widget, reflection)
|
||||
local ret = base.make_widget()
|
||||
ret.horizontal = false
|
||||
ret.vertical = false
|
||||
|
||||
for k, v in pairs(mirror) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_reflection(reflection or {})
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function mirror.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(mirror, mirror.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.mirror"),
|
||||
"wibox.layout.mirror",
|
||||
"wibox.container.mirror"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,137 +1,18 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.rotate`
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.rotate
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local error = error
|
||||
local pairs = pairs
|
||||
local pi = math.pi
|
||||
local type = type
|
||||
local setmetatable = setmetatable
|
||||
local tostring = tostring
|
||||
local base = require("wibox.widget.base")
|
||||
local matrix = require("gears.matrix")
|
||||
local util = require("awful.util")
|
||||
|
||||
local rotate = { mt = {} }
|
||||
|
||||
local function transform(layout, width, height)
|
||||
local dir = layout:get_direction()
|
||||
if dir == "east" or dir == "west" then
|
||||
return height, width
|
||||
end
|
||||
return width, height
|
||||
end
|
||||
|
||||
--- Layout this layout
|
||||
function rotate:layout(_, width, height)
|
||||
if not self.widget or not self.widget.visible then
|
||||
return
|
||||
end
|
||||
|
||||
local dir = self:get_direction()
|
||||
|
||||
local m = matrix.identity
|
||||
if dir == "west" then
|
||||
m = m:rotate(pi / 2)
|
||||
m = m:translate(0, -width)
|
||||
elseif dir == "south" then
|
||||
m = m:rotate(pi)
|
||||
m = m:translate(-width, -height)
|
||||
elseif dir == "east" then
|
||||
m = m:rotate(3 * pi / 2)
|
||||
m = m:translate(-height, 0)
|
||||
end
|
||||
|
||||
-- Since we rotated, we might have to swap width and height.
|
||||
-- transform() does that for us.
|
||||
return { base.place_widget_via_matrix(self.widget, m, transform(self, width, height)) }
|
||||
end
|
||||
|
||||
--- Fit this layout into the given area
|
||||
function rotate:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
return transform(self, base.fit_widget(self, context, self.widget, transform(self, width, height)))
|
||||
end
|
||||
|
||||
--- Set the widget that this layout rotates.
|
||||
function rotate:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function rotate:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function rotate:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Reset this layout. The widget will be removed and the rotation reset.
|
||||
function rotate:reset()
|
||||
self.direction = nil
|
||||
self:set_widget(nil)
|
||||
end
|
||||
|
||||
--- Set the direction of this rotating layout. Valid values are "north", "east",
|
||||
-- "south" and "west". On an invalid value, this function will throw an error.
|
||||
function rotate:set_direction(dir)
|
||||
local allowed = {
|
||||
north = true,
|
||||
east = true,
|
||||
south = true,
|
||||
west = true
|
||||
}
|
||||
|
||||
if not allowed[dir] then
|
||||
error("Invalid direction for rotate layout: " .. tostring(dir))
|
||||
end
|
||||
|
||||
self.direction = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Get the direction of this rotating layout
|
||||
function rotate:get_direction()
|
||||
return self.direction or "north"
|
||||
end
|
||||
|
||||
--- Returns a new rotate layout. A rotate layout rotates a given widget. Use
|
||||
-- :set_widget() to set the widget and :set_direction() for the direction.
|
||||
-- The default direction is "north" which doesn't change anything.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] dir The direction to rotate to.
|
||||
local function new(widget, dir)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(rotate) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_direction(dir or "north")
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function rotate.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(rotate, rotate.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.rotate"),
|
||||
"wibox.layout.rotate",
|
||||
"wibox.container.rotate"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,509 +1,17 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- This class has been moved to `wibox.container.scroll`
|
||||
--
|
||||
-- @author Uli Schlachter (based on ideas from Saleur Geoffrey)
|
||||
-- @copyright 2015 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.layout.scroll
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
|
||||
local cache = require("gears.cache")
|
||||
local timer = require("gears.timer")
|
||||
local hierarchy = require("wibox.hierarchy")
|
||||
local base = require("wibox.widget.base")
|
||||
local lgi = require("lgi")
|
||||
local GLib = lgi.GLib
|
||||
|
||||
local scroll = {}
|
||||
local scroll_mt = { __index = scroll }
|
||||
local _need_scroll_redraw
|
||||
|
||||
-- "Strip" a context so that we can use it for our own drawing
|
||||
local function cleanup_context(context)
|
||||
local skip = { wibox = true, drawable = true, client = true, position = true }
|
||||
local res = {}
|
||||
for k, v in pairs(context) do
|
||||
if not skip[k] then
|
||||
res[k] = v
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
-- Create a hierarchy (and some more stuff) for drawing the given widget. This
|
||||
-- allows "some stuff" to be re-used instead of re-created all the time.
|
||||
local hierarchy_cache = cache.new(function(context, widget, width, height)
|
||||
context = cleanup_context(context)
|
||||
local layouts = setmetatable({}, { __mode = "k" })
|
||||
|
||||
-- Create a widget hierarchy and update when needed
|
||||
local hier
|
||||
local function do_pending_updates(layout)
|
||||
layouts[layout] = true
|
||||
hier:update(context, widget, width, height, nil)
|
||||
end
|
||||
local function emit(signal)
|
||||
-- Make the scroll layouts redraw
|
||||
for w in pairs(layouts) do
|
||||
w:emit_signal(signal)
|
||||
end
|
||||
end
|
||||
local function redraw_callback()
|
||||
emit("widget::redraw_needed")
|
||||
end
|
||||
local function layout_callback()
|
||||
emit("widget::redraw_needed")
|
||||
emit("widget::layout_changed")
|
||||
end
|
||||
hier = hierarchy.new(context, widget, width, height, redraw_callback, layout_callback, nil)
|
||||
|
||||
return hier, do_pending_updates, context
|
||||
end)
|
||||
|
||||
--- Calculate all the information needed for scrolling.
|
||||
-- @param self The instance of the scrolling layout.
|
||||
-- @param context A widget context under which we are fit/drawn.
|
||||
-- @param width The available width
|
||||
-- @param height The available height
|
||||
-- @return A table with the following entries
|
||||
-- @field fit_width The width that should be returned from :fit
|
||||
-- @field fit_height The height that should be returned from :fit
|
||||
-- @field surface_width The width for showing the child widget
|
||||
-- @field surface_height The height for showing the child widget
|
||||
-- @field first_x The x offset for drawing the child the first time
|
||||
-- @field first_y The y offset for drawing the child the first time
|
||||
-- @field[opt] second_x The x offset for drawing the child the second time
|
||||
-- @field[opt] second_y The y offset for drawing the child the second time
|
||||
-- @field hierarchy The wibox.hierarchy instance representing "everything"
|
||||
-- @field context The widget context for drawing the hierarchy
|
||||
local function calculate_info(self, context, width, height)
|
||||
local result = {}
|
||||
assert(self.widget)
|
||||
|
||||
-- First, get the size of the widget (and the size of extra space)
|
||||
local surface_width, surface_height = width, height
|
||||
local extra_width, extra_height, extra = 0, 0, self.expand and self.extra_space or 0
|
||||
local w, h
|
||||
if self.dir == "h" then
|
||||
w, h = base.fit_widget(self, context, self.widget, self.space_for_scrolling, height)
|
||||
surface_width = w
|
||||
extra_width = extra
|
||||
else
|
||||
w, h = base.fit_widget(self, context, self.widget, width, self.space_for_scrolling)
|
||||
surface_height = h
|
||||
extra_height = extra
|
||||
end
|
||||
result.fit_width, result.fit_height = w, h
|
||||
if self.dir == "h" then
|
||||
if self.max_size then
|
||||
result.fit_width = math.min(w, self.max_size)
|
||||
end
|
||||
else
|
||||
if self.max_size then
|
||||
result.fit_height = math.min(h, self.max_size)
|
||||
end
|
||||
end
|
||||
if w > width or h > height then
|
||||
-- There is less space available than we need, we have to scroll
|
||||
_need_scroll_redraw(self)
|
||||
|
||||
surface_width, surface_height = surface_width + extra_width, surface_height + extra_height
|
||||
|
||||
local x, y = 0, 0
|
||||
local function get_scroll_offset(size, visible_size)
|
||||
return self.step_function(self.timer:elapsed(), size, visible_size, self.speed, self.extra_space)
|
||||
end
|
||||
if self.dir == "h" then
|
||||
x = -get_scroll_offset(surface_width - extra, width)
|
||||
else
|
||||
y = -get_scroll_offset(surface_height - extra, height)
|
||||
end
|
||||
result.first_x, result.first_y = x, y
|
||||
-- Was the extra space already included elsewhere?
|
||||
local extra_spacer = self.expand and 0 or self.extra_space
|
||||
if self.dir == "h" then
|
||||
x = x + surface_width + extra_spacer
|
||||
else
|
||||
y = y + surface_height + extra_spacer
|
||||
end
|
||||
result.second_x, result.second_y = x, y
|
||||
else
|
||||
result.first_x, result.first_y = 0, 0
|
||||
end
|
||||
result.surface_width, result.surface_height = surface_width, surface_height
|
||||
|
||||
-- Get the hierarchy and subscribe ourselves to updates
|
||||
local hier, do_pending_updates, ctx = hierarchy_cache:get(context,
|
||||
self.widget, surface_width, surface_height)
|
||||
result.hierarchy = hier
|
||||
result.context = ctx
|
||||
do_pending_updates(self)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
--- Draw this scrolling layout.
|
||||
-- @param context The context in which we are drawn.
|
||||
-- @param cr The cairo context to draw to.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:draw(context, cr, width, height)
|
||||
if not self.widget then
|
||||
return
|
||||
end
|
||||
|
||||
local info = calculate_info(self, context, width, height)
|
||||
|
||||
-- Draw the first instance of the child
|
||||
cr:save()
|
||||
cr:translate(info.first_x, info.first_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
cr:restore()
|
||||
|
||||
-- If there is one, draw the second instance (same code as above, minus the
|
||||
-- clip)
|
||||
if info.second_x and info.second_y then
|
||||
cr:translate(info.second_x, info.second_y)
|
||||
cr:rectangle(0, 0, info.surface_width, info.surface_height)
|
||||
cr:clip()
|
||||
info.hierarchy:draw(info.context, cr)
|
||||
end
|
||||
end
|
||||
|
||||
--- Fit the scroll layout into the given space.
|
||||
-- @param context The context in which we are fit.
|
||||
-- @param width The available width.
|
||||
-- @param height The available height.
|
||||
function scroll:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
local info = calculate_info(self, context, width, height)
|
||||
return info.fit_width, info.fit_height
|
||||
end
|
||||
|
||||
-- Internal function used for triggering redraws for scrolling.
|
||||
-- The purpose is to start a timer for redrawing the widget for scrolling.
|
||||
-- Redrawing works by simply emitting the `widget::redraw_needed` signal.
|
||||
-- Pausing is implemented in this function: We just don't start a timer.
|
||||
-- This function must be idempotent (calling it multiple times right after
|
||||
-- another does not make a difference).
|
||||
_need_scroll_redraw = function(self)
|
||||
if not self.paused and not self.scroll_timer then
|
||||
self.scroll_timer = timer.start_new(1 / self.fps, function()
|
||||
self.scroll_timer = nil
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- Pause the scrolling animation.
|
||||
-- @see continue
|
||||
function scroll:pause()
|
||||
if self.paused then
|
||||
return
|
||||
end
|
||||
self.paused = true
|
||||
self.timer:stop()
|
||||
end
|
||||
|
||||
--- Continue the scrolling animation.
|
||||
-- @see pause
|
||||
function scroll:continue()
|
||||
if not self.paused then
|
||||
return
|
||||
end
|
||||
self.paused = false
|
||||
self.timer:continue()
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Reset the scrolling state to its initial condition.
|
||||
-- For must scroll step functions, the effect of this function should be to
|
||||
-- display the widget without any scrolling applied.
|
||||
-- This function does not undo the effect of @{pause}.
|
||||
function scroll:reset_scrolling()
|
||||
self.timer:start()
|
||||
if self.paused then
|
||||
self.timer:stop()
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the direction in which this widget scroll.
|
||||
-- @param dir Either "h" for horizontal scrolling or "v" for vertical scrolling
|
||||
function scroll:set_direction(dir)
|
||||
if dir == self.dir then
|
||||
return
|
||||
end
|
||||
if dir ~= "h" and dir ~= "v" then
|
||||
error("Invalid direction, can only be 'h' or 'v'")
|
||||
end
|
||||
self.dir = dir
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the widget which we scroll.
|
||||
-- @tparam widget widget The widget that we should display
|
||||
function scroll:set_widget(widget)
|
||||
if widget == self.widget then
|
||||
return
|
||||
end
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Get the number of children element
|
||||
-- @treturn table The children
|
||||
function scroll:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
--- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function scroll:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Specify the expand mode that is used for extra space.
|
||||
-- @tparam boolean expand If true, the widget is expanded to include the extra
|
||||
-- space. If false, the extra space is simply left empty.
|
||||
-- @see set_extra_space
|
||||
function scroll:set_expand(expand)
|
||||
if expand == self.expand then
|
||||
return
|
||||
end
|
||||
self.expand = expand
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the number of frames per second that this widget should draw.
|
||||
-- @tparam number fps The number of frames per second
|
||||
function scroll:set_fps(fps)
|
||||
if fps == self.fps then
|
||||
return
|
||||
end
|
||||
self.fps = fps
|
||||
-- No signal needed: If we are scrolling, the next redraw will apply the new
|
||||
-- FPS, else it obviously doesn't make a difference.
|
||||
end
|
||||
|
||||
--- Set the amount of extra space that should be included in the scrolling. This
|
||||
-- extra space will likely be left empty between repetitions of the widgets.
|
||||
-- @tparam number extra_space The amount of extra space
|
||||
-- @see set_expand
|
||||
function scroll:set_extra_space(extra_space)
|
||||
if extra_space == self.extra_space then
|
||||
return
|
||||
end
|
||||
self.extra_space = extra_space
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the speed of the scrolling animation. The exact meaning depends on the
|
||||
-- step function that is used, but for the simplest step functions, this will be
|
||||
-- in pixels per second.
|
||||
-- @tparam number speed The speed for the animation
|
||||
function scroll:set_speed(speed)
|
||||
if speed == self.speed then
|
||||
return
|
||||
end
|
||||
self.speed = speed
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the maximum size of this widget in the direction set by
|
||||
-- @{set_direction}. If the child widget is smaller than this size, no scrolling
|
||||
-- is done. If the child widget is larger, then only this size will be visible
|
||||
-- and the rest is made visible via scrolling.
|
||||
-- @tparam number max_size The maximum size of this widget or nil for unlimited.
|
||||
function scroll:set_max_size(max_size)
|
||||
if max_size == self.max_size then
|
||||
return
|
||||
end
|
||||
self.max_size = max_size
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
--- Set the step function that determines the exact behaviour of the scrolling
|
||||
-- animation.
|
||||
-- The step function is called with five arguments:
|
||||
--
|
||||
-- * The time in seconds since the state of the animation
|
||||
-- * The size of the child widget
|
||||
-- * The size of the visible part of the widget
|
||||
-- * The speed of the animation. This should have a linear effect on this
|
||||
-- function's behaviour.
|
||||
-- * The extra space configured by @{set_extra_space}. This was not yet added to
|
||||
-- the size of the child widget, but should likely be added to it in most
|
||||
-- cases.
|
||||
--
|
||||
-- The step function should return a single number. This number is the offset at
|
||||
-- which the widget is drawn and should be between 0 and `size+extra_space`.
|
||||
-- @tparam function step_function A step function.
|
||||
-- @see step_functions
|
||||
function scroll:set_step_function(step_function)
|
||||
-- Call the step functions once to see if it works
|
||||
step_function(0, 42, 10, 10, 5)
|
||||
if step_function == self.step_function then
|
||||
return
|
||||
end
|
||||
self.step_function = step_function
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set an upper limit for the space for scrolling.
|
||||
-- This restricts the child widget's maximal size.
|
||||
-- @tparam number space_for_scrolling The space for scrolling
|
||||
function scroll:set_space_for_scrolling(space_for_scrolling)
|
||||
if space_for_scrolling == self.space_for_scrolling then
|
||||
return
|
||||
end
|
||||
self.space_for_scrolling = space_for_scrolling
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
local function get_layout(dir, widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
local ret = base.make_widget()
|
||||
|
||||
ret.paused = false
|
||||
ret.timer = GLib.Timer()
|
||||
ret.scroll_timer = nil
|
||||
|
||||
setmetatable(ret, scroll_mt)
|
||||
|
||||
ret:set_direction(dir)
|
||||
ret:set_widget(widget)
|
||||
ret:set_fps(fps or 20)
|
||||
ret:set_speed(speed or 10)
|
||||
ret:set_extra_space(extra_space or 0)
|
||||
ret:set_expand(expand)
|
||||
ret:set_max_size(max_size)
|
||||
ret:set_step_function(step_function or scroll.step_functions.linear_increase)
|
||||
ret:set_space_for_scrolling(space_for_scrolling or 2^1024)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Get a new horizontal scrolling layout.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.horizontal(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("h", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- Get a new vertical scrolling layout.
|
||||
-- @param[opt] widget The widget that should be scrolled
|
||||
-- @param[opt=20] fps The number of frames per second
|
||||
-- @param[opt=10] speed The speed of the animation
|
||||
-- @param[opt=0] extra_space The amount of extra space to include
|
||||
-- @tparam[opt=false] boolean expand Should the widget be expanded to include the
|
||||
-- extra space?
|
||||
-- @param[opt] max_size The maximum size of the child widget
|
||||
-- @param[opt=step_functions.linear_increase] step_function The step function to be used
|
||||
-- @param[opt=2^1024] space_for_scrolling The space for scrolling
|
||||
function scroll.vertical(widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
return get_layout("v", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling)
|
||||
end
|
||||
|
||||
--- A selection of step functions
|
||||
-- @see set_step_function
|
||||
scroll.step_functions = {}
|
||||
|
||||
--- A step function that scrolls the widget in an increasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_increase(elapsed, size, _, speed, extra_space)
|
||||
return (elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget in an decreasing direction with
|
||||
-- constant speed.
|
||||
function scroll.step_functions.linear_decrease(elapsed, size, _, speed, extra_space)
|
||||
return (-elapsed * speed) % (size + extra_space)
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is constant.
|
||||
function scroll.step_functions.linear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
state = state <= 1 and state or 2 - state
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle.
|
||||
function scroll.step_functions.nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
--- A step function that scrolls the widget to its end and back to its
|
||||
-- beginning, then back to its end, etc. The speed is null at the ends and
|
||||
-- maximal in the middle. At both ends the widget stands still for a moment.
|
||||
function scroll.step_functions.waiting_nonlinear_back_and_forth(elapsed, size, visible_size, speed)
|
||||
local state = ((elapsed * speed) % (2 * size)) / size
|
||||
local negate = false
|
||||
if state > 1 then
|
||||
negate = true
|
||||
state = state - 1
|
||||
end
|
||||
if state < 1/5 or state > 4/5 then
|
||||
-- One fifth of time, nothing moves
|
||||
state = state < 1/5 and 0 or 1
|
||||
else
|
||||
state = (state - 1/5) * 5/3
|
||||
if state < 1/3 then
|
||||
-- In the first 1/3rd of time, do a quadratic increase in speed
|
||||
state = 2 * state * state
|
||||
elseif state < 2/3 then
|
||||
-- In the center, do a linear increase. That means we need:
|
||||
-- If state is 1/3, result is 2/9 = 2 * 1/3 * 1/3
|
||||
-- If state is 2/3, result is 7/9 = 1 - 2 * (1 - 2/3) * (1 - 2/3)
|
||||
state = 5/3*state - 3/9
|
||||
else
|
||||
-- In the last 1/3rd of time, do a quadratic decrease in speed
|
||||
state = 1 - 2 * (1 - state) * (1 - state)
|
||||
end
|
||||
end
|
||||
if negate then
|
||||
state = 1 - state
|
||||
end
|
||||
return (size - visible_size) * state
|
||||
end
|
||||
|
||||
return scroll
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.scroll"),
|
||||
"wibox.layout.scroll",
|
||||
"wibox.container.scroll"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -1,224 +1,17 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- A container capable of changing the background color, foreground color
|
||||
-- widget shape.
|
||||
-- This class has been moved to `wibox.container.background`
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @release @AWESOME_VERSION@
|
||||
-- @classmod wibox.widget.background
|
||||
---------------------------------------------------------------------------
|
||||
local util = require("awful.util")
|
||||
|
||||
local base = require("wibox.widget.base")
|
||||
local color = require("gears.color")
|
||||
local surface = require("gears.surface")
|
||||
local beautiful = require("beautiful")
|
||||
local cairo = require("lgi").cairo
|
||||
local setmetatable = setmetatable
|
||||
local pairs = pairs
|
||||
local type = type
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
local background = { mt = {} }
|
||||
|
||||
-- Draw this widget
|
||||
function background:draw(context, cr, width, height)
|
||||
if not self.widget or not self.widget.visible then
|
||||
return
|
||||
end
|
||||
|
||||
-- Keep the shape path in case there is a border
|
||||
self._path = nil
|
||||
|
||||
if self._shape then
|
||||
-- Only add the offset if there is something to draw
|
||||
local offset = ((self._shape_border_width and self._shape_border_color)
|
||||
and self._shape_border_width or 0) / 2
|
||||
|
||||
cr:translate(offset, offset)
|
||||
self._shape(cr, width - 2*offset, height - 2*offset, unpack(self._shape_args or {}))
|
||||
cr:translate(-offset, -offset)
|
||||
self._path = cr:copy_path()
|
||||
cr:clip()
|
||||
end
|
||||
|
||||
if self.background then
|
||||
cr:set_source(self.background)
|
||||
cr:paint()
|
||||
end
|
||||
if self.bgimage then
|
||||
if type(self.bgimage) == "function" then
|
||||
self.bgimage(context, cr, width, height,unpack(self.bgimage_args))
|
||||
else
|
||||
local pattern = cairo.Pattern.create_for_surface(self.bgimage)
|
||||
cr:set_source(pattern)
|
||||
cr:paint()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Draw the border
|
||||
function background:after_draw_children(_, cr)
|
||||
-- Draw the border
|
||||
if self._path and self._shape_border_width and self._shape_border_width > 0 then
|
||||
cr:append_path(self._path)
|
||||
cr:set_source(color(self._shape_border_color or self.foreground or beautiful.fg_normal))
|
||||
|
||||
cr:set_line_width(self._shape_border_width)
|
||||
cr:stroke()
|
||||
self._path = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Prepare drawing the children of this widget
|
||||
function background:before_draw_children(_, cr)
|
||||
if self.foreground then
|
||||
cr:set_source(self.foreground)
|
||||
end
|
||||
|
||||
-- Clip the shape
|
||||
if self._path and self._shape_clip then
|
||||
cr:append_path(self._path)
|
||||
cr:clip()
|
||||
end
|
||||
end
|
||||
|
||||
-- Layout this widget
|
||||
function background:layout(_, width, height)
|
||||
if self.widget then
|
||||
return { base.place_widget_at(self.widget, 0, 0, width, height) }
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit this widget into the given area
|
||||
function background:fit(context, width, height)
|
||||
if not self.widget then
|
||||
return 0, 0
|
||||
end
|
||||
|
||||
return base.fit_widget(self, context, self.widget, width, height)
|
||||
end
|
||||
|
||||
--- Set the widget that is drawn on top of the background
|
||||
-- @tparam widget widget The widget to be disaplayed inside of the background
|
||||
-- area
|
||||
function background:set_widget(widget)
|
||||
if widget then
|
||||
base.check_widget(widget)
|
||||
end
|
||||
self.widget = widget
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
|
||||
-- Get children element
|
||||
-- @treturn table The children
|
||||
function background:get_children()
|
||||
return {self.widget}
|
||||
end
|
||||
|
||||
-- Replace the layout children
|
||||
-- This layout only accept one children, all others will be ignored
|
||||
-- @tparam table children A table composed of valid widgets
|
||||
function background:set_children(children)
|
||||
self:set_widget(children[1])
|
||||
end
|
||||
|
||||
--- Set the background to use.
|
||||
--@DOC_wibox_widget_background_bg_EXAMPLE@
|
||||
-- @param bg A color string, pattern or gradient (see `gears.color`)
|
||||
function background:set_bg(bg)
|
||||
if bg then
|
||||
self.background = color(bg)
|
||||
else
|
||||
self.background = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the foreground to use.
|
||||
--@DOC_wibox_widget_background_fg_EXAMPLE@
|
||||
-- @param fg A color string, pattern or gradient (see `gears.color`)
|
||||
function background:set_fg(fg)
|
||||
if fg then
|
||||
self.foreground = color(fg)
|
||||
else
|
||||
self.foreground = nil
|
||||
end
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the background shape.
|
||||
--
|
||||
-- Any other arguments will be passed to the shape function
|
||||
--@DOC_wibox_widget_background_shape_EXAMPLE@
|
||||
-- @param shape A function taking a context, width and height as arguments
|
||||
function background:set_shape(shape, ...)
|
||||
self._shape = shape
|
||||
self._shape_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.widget.background.set_shape` for an usage example.
|
||||
-- @tparam number width The border width
|
||||
function background:set_shape_border_width(width)
|
||||
self._shape_border_width = width
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, also draw a border.
|
||||
--
|
||||
-- See `wibox.widget.background.set_shape` for an usage example.
|
||||
-- @param[opt=self.foreground] fg The border color, pattern or gradient
|
||||
function background:set_shape_border_color(fg)
|
||||
self._shape_border_color = fg
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- When a `shape` is set, make sure nothing is drawn outside of it.
|
||||
--@DOC_wibox_widget_background_clip_EXAMPLE@
|
||||
-- @tparam boolean value If the shape clip is enable
|
||||
function background:set_shape_clip(value)
|
||||
self._shape_clip = value
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Set the background image to use
|
||||
-- If `image` is a function, it will be called with `(context, cr, width, height)`
|
||||
-- as arguments. Any other arguments passed to this method will be appended.
|
||||
-- @param image A background image or a function
|
||||
function background:set_bgimage(image, ...)
|
||||
self.bgimage = type(image) == "function" and image or surface.load(image)
|
||||
self.bgimage_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
end
|
||||
|
||||
--- Returns a new background layout. A background layout applies a background
|
||||
-- and foreground color to another widget.
|
||||
-- @param[opt] widget The widget to display.
|
||||
-- @param[opt] bg The background to use for that widget.
|
||||
-- @param[opt] shape A `gears.shape` compatible shape function
|
||||
local function new(widget, bg, shape)
|
||||
local ret = base.make_widget()
|
||||
|
||||
for k, v in pairs(background) do
|
||||
if type(v) == "function" then
|
||||
ret[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
ret._shape = shape
|
||||
|
||||
ret:set_widget(widget)
|
||||
ret:set_bg(bg)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function background.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(background, background.mt)
|
||||
return util.deprecate_class(
|
||||
require("wibox.container.background"),
|
||||
"wibox.widget.background",
|
||||
"wibox.container.background"
|
||||
)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||
|
|
|
@ -10,17 +10,17 @@ parent : setup {
|
|||
{
|
||||
text_widget,
|
||||
bg = '#ff0000',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
bg = '#00ff00',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
bg = '#0000ff',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
||||
|
|
|
@ -13,7 +13,7 @@ parent : setup {
|
|||
shape = gears.shape.circle,
|
||||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
-- To solve this, clip the content
|
||||
|
@ -25,7 +25,7 @@ parent : setup {
|
|||
shape = gears.shape.circle,
|
||||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
||||
|
|
|
@ -10,17 +10,17 @@ parent : setup {
|
|||
{
|
||||
text_widget,
|
||||
fg = '#ff0000',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
fg = '#00ff00',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
text_widget,
|
||||
fg = '#0000ff',
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
||||
|
|
|
@ -14,7 +14,7 @@ parent : setup {
|
|||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
shape_border_width = beautiful.border_width,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
-- To solve this, use a margin
|
||||
|
@ -27,13 +27,13 @@ parent : setup {
|
|||
right = 10,
|
||||
top = 3,
|
||||
bottom = 3,
|
||||
widget = wibox.layout.margin
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
shape = gears.shape.hexagon,
|
||||
bg = beautiful.bg_normal,
|
||||
shape_border_color = beautiful.border_color,
|
||||
shape_border_width = beautiful.border_width,
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
spacing = 10,
|
||||
layout = wibox.layout.fixed.vertical
|
||||
|
|
|
@ -30,14 +30,14 @@ table.insert(steps, function()
|
|||
widget = wibox.widget.textbox,
|
||||
},
|
||||
bg = "#ff0000",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
{
|
||||
widget = button,
|
||||
},
|
||||
bg = "#ff00ff",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
{
|
||||
{
|
||||
|
@ -45,7 +45,7 @@ table.insert(steps, function()
|
|||
widget = wibox.widget.textbox,
|
||||
},
|
||||
bg = "#0000ff",
|
||||
widget = wibox.widget.background
|
||||
widget = wibox.container.background
|
||||
},
|
||||
layout = wibox.layout.flex.vertical
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue