From 3f0d218f721b21c2e58927002051ee50b9531ed3 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 27 May 2016 23:24:03 -0400 Subject: [PATCH 01/68] util.table.crush: Optionally use rawset --- lib/awful/util.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/awful/util.lua b/lib/awful/util.lua index 18587522..866f9e4f 100644 --- a/lib/awful/util.lua +++ b/lib/awful/util.lua @@ -336,13 +336,22 @@ function util.table.join(...) return ret end ---- Override elements in the first table by the one in the second +--- Override elements in the first table by the one in the second. +-- +-- Note that this method doesn't copy entries found in `__index`. -- @tparam table t the table to be overriden -- @tparam table set the table used to override members of `t` +-- @tparam[opt=false] boolean raw Use rawset (avoid the metatable) -- @treturn table t (for convenience) -function util.table.crush(t, set) - for k, v in pairs(set) do - t[k] = v +function util.table.crush(t, set, raw) + if raw then + for k, v in pairs(set) do + rawset(t, k, v) + end + else + for k, v in pairs(set) do + t[k] = v + end end return t From 990beef9d0fca7c93fe053a9550bcce39122ada2 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 22 May 2016 23:34:59 -0400 Subject: [PATCH 02/68] util: Add a class deprecation function. --- lib/awful/util.lua | 30 ++++++++++++++++++++++++++++++ lib/awful/wibox.lua | 21 +-------------------- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/awful/util.lua b/lib/awful/util.lua index 866f9e4f..488dbacf 100644 --- a/lib/awful/util.lua +++ b/lib/awful/util.lua @@ -60,6 +60,36 @@ function util.deprecate(see) gears_debug.print_warning(msg .. ".\n" .. tb) end +--- Create a class proxy with deprecation messages. +-- This is useful when a class has moved somewhere else. +-- @tparam table fallback The new class +-- @tparam string old_name The old class name +-- @tparam string new_name The new class name +-- @treturn table A proxy class. +function util.deprecate_class(fallback, old_name, new_name) + local message = old_name.." has been renamed to "..new_name + + local function call(_,...) + util.deprecate(message) + + return fallback(...) + end + + local function index(_, k) + util.deprecate(message) + + return fallback[k] + end + + local function newindex(_, k, v) + util.deprecate(message) + + fallback[k] = v + end + + return setmetatable({}, {__call = call, __index = index, __newindex = newindex}) +end + --- Get a valid color for Pango markup -- @param color The color. -- @tparam string fallback The color to return if the first is invalid. (default: black) diff --git a/lib/awful/wibox.lua b/lib/awful/wibox.lua index 276b9f38..f56b38f5 100644 --- a/lib/awful/wibox.lua +++ b/lib/awful/wibox.lua @@ -7,26 +7,7 @@ -- @module awful.wibox --------------------------------------------------------------------------- local util = require("awful.util") -local wibar = require("awful.wibar") -local function call(_,...) - util.deprecate("awful.wibox has been renamed to awful.wibar") - - return wibar(...) -end - -local function index(_, k) - util.deprecate("awful.wibox has been renamed to awful.wibar") - - return wibar[k] -end - -local function newindex(_, k, v) - util.deprecate("awful.wibox has been renamed to awful.wibar") - - wibar[k] = v -end - -return setmetatable({}, {__call = call, __index = index, __newindex = newindex}) +return util.deprecate_class(require("awful.wibar"), "awful.wibox", "awful.wibar") -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From d85588babec7e06b8663702e681d858f03ca80b6 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sun, 22 May 2016 23:56:45 -0400 Subject: [PATCH 03/68] 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. --- docs/03-declarative-layout.md | 10 +- docs/config.ld | 1 + lib/awful/hotkeys_popup/widget.lua | 4 +- lib/awful/menu.lua | 4 +- lib/awful/tooltip.lua | 4 +- lib/awful/widget/common.lua | 6 +- lib/gears/object.lua | 2 +- lib/naughty/core.lua | 6 +- lib/wibox/container/background.lua | 224 ++++++++ lib/wibox/container/constraint.lua | 140 +++++ lib/wibox/container/init.lua | 20 + lib/wibox/container/margin.lua | 198 +++++++ lib/wibox/container/mirror.lua | 127 +++++ lib/wibox/container/rotate.lua | 137 +++++ lib/wibox/container/scroll.lua | 509 ++++++++++++++++++ lib/wibox/init.lua | 1 + lib/wibox/layout/constraint.lua | 138 +---- lib/wibox/layout/margin.lua | 196 +------ lib/wibox/layout/mirror.lua | 125 +---- lib/wibox/layout/rotate.lua | 135 +---- lib/wibox/layout/scroll.lua | 508 +---------------- lib/wibox/widget/background.lua | 223 +------- tests/examples/wibox/widget/background/bg.lua | 6 +- .../examples/wibox/widget/background/clip.lua | 4 +- tests/examples/wibox/widget/background/fg.lua | 6 +- .../wibox/widget/background/shape.lua | 6 +- tests/test-awful-widget-button.lua | 6 +- 27 files changed, 1437 insertions(+), 1309 deletions(-) create mode 100644 lib/wibox/container/background.lua create mode 100644 lib/wibox/container/constraint.lua create mode 100644 lib/wibox/container/init.lua create mode 100644 lib/wibox/container/margin.lua create mode 100644 lib/wibox/container/mirror.lua create mode 100644 lib/wibox/container/rotate.lua create mode 100644 lib/wibox/container/scroll.lua diff --git a/docs/03-declarative-layout.md b/docs/03-declarative-layout.md index be88a215..e29308a2 100644 --- a/docs/03-declarative-layout.md +++ b/docs/03-declarative-layout.md @@ -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, } diff --git a/docs/config.ld b/docs/config.ld index 6d4f140d..a6d1a629 100644 --- a/docs/config.ld +++ b/docs/config.ld @@ -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', diff --git a/lib/awful/hotkeys_popup/widget.lua b/lib/awful/hotkeys_popup/widget.lua index 85d61076..3a9f0be4 100644 --- a/lib/awful/hotkeys_popup/widget.lua +++ b/lib/awful/hotkeys_popup/widget.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) diff --git a/lib/awful/menu.lua b/lib/awful/menu.lua index 0dc62269..663b7704 100644 --- a/lib/awful/menu.lua +++ b/lib/awful/menu.lua @@ -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) diff --git a/lib/awful/tooltip.lua b/lib/awful/tooltip.lua index 6c37aead..57b37699 100644 --- a/lib/awful/tooltip.lua +++ b/lib/awful/tooltip.lua @@ -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 diff --git a/lib/awful/widget/common.lua b/lib/awful/widget/common.lua index cfe18b7d..78f57172 100644 --- a/lib/awful/widget/common.lua +++ b/lib/awful/widget/common.lua @@ -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 diff --git a/lib/gears/object.lua b/lib/gears/object.lua index 85bfcc3c..c65582ed 100644 --- a/lib/gears/object.lua +++ b/lib/gears/object.lua @@ -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 diff --git a/lib/naughty/core.lua b/lib/naughty/core.lua index 24f7c960..3aa74558 100644 --- a/lib/naughty/core.lua +++ b/lib/naughty/core.lua @@ -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) diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua new file mode 100644 index 00000000..7c0ac815 --- /dev/null +++ b/lib/wibox/container/background.lua @@ -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 diff --git a/lib/wibox/container/constraint.lua b/lib/wibox/container/constraint.lua new file mode 100644 index 00000000..deeec7f6 --- /dev/null +++ b/lib/wibox/container/constraint.lua @@ -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 diff --git a/lib/wibox/container/init.lua b/lib/wibox/container/init.lua new file mode 100644 index 00000000..b5cd7b37 --- /dev/null +++ b/lib/wibox/container/init.lua @@ -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 diff --git a/lib/wibox/container/margin.lua b/lib/wibox/container/margin.lua new file mode 100644 index 00000000..4f47c51d --- /dev/null +++ b/lib/wibox/container/margin.lua @@ -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 diff --git a/lib/wibox/container/mirror.lua b/lib/wibox/container/mirror.lua new file mode 100644 index 00000000..7bacfaa2 --- /dev/null +++ b/lib/wibox/container/mirror.lua @@ -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 diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua new file mode 100644 index 00000000..fb3c434b --- /dev/null +++ b/lib/wibox/container/rotate.lua @@ -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 diff --git a/lib/wibox/container/scroll.lua b/lib/wibox/container/scroll.lua new file mode 100644 index 00000000..b7433d0a --- /dev/null +++ b/lib/wibox/container/scroll.lua @@ -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 diff --git a/lib/wibox/init.lua b/lib/wibox/init.lua index a87d1a22..e4f4fdf1 100644 --- a/lib/wibox/init.lua +++ b/lib/wibox/init.lua @@ -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") diff --git a/lib/wibox/layout/constraint.lua b/lib/wibox/layout/constraint.lua index e355e5e4..d6c07df3 100644 --- a/lib/wibox/layout/constraint.lua +++ b/lib/wibox/layout/constraint.lua @@ -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 diff --git a/lib/wibox/layout/margin.lua b/lib/wibox/layout/margin.lua index 11448bc0..279d754f 100644 --- a/lib/wibox/layout/margin.lua +++ b/lib/wibox/layout/margin.lua @@ -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 diff --git a/lib/wibox/layout/mirror.lua b/lib/wibox/layout/mirror.lua index 2d19385f..40283b67 100644 --- a/lib/wibox/layout/mirror.lua +++ b/lib/wibox/layout/mirror.lua @@ -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 diff --git a/lib/wibox/layout/rotate.lua b/lib/wibox/layout/rotate.lua index 46e60b8e..56883d7d 100644 --- a/lib/wibox/layout/rotate.lua +++ b/lib/wibox/layout/rotate.lua @@ -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 diff --git a/lib/wibox/layout/scroll.lua b/lib/wibox/layout/scroll.lua index 850fee4b..a576a292 100644 --- a/lib/wibox/layout/scroll.lua +++ b/lib/wibox/layout/scroll.lua @@ -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 diff --git a/lib/wibox/widget/background.lua b/lib/wibox/widget/background.lua index de8e88c5..70a2af32 100644 --- a/lib/wibox/widget/background.lua +++ b/lib/wibox/widget/background.lua @@ -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 diff --git a/tests/examples/wibox/widget/background/bg.lua b/tests/examples/wibox/widget/background/bg.lua index f6562a6c..9ef3e959 100644 --- a/tests/examples/wibox/widget/background/bg.lua +++ b/tests/examples/wibox/widget/background/bg.lua @@ -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 diff --git a/tests/examples/wibox/widget/background/clip.lua b/tests/examples/wibox/widget/background/clip.lua index 15bdb15e..8184f866 100644 --- a/tests/examples/wibox/widget/background/clip.lua +++ b/tests/examples/wibox/widget/background/clip.lua @@ -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 diff --git a/tests/examples/wibox/widget/background/fg.lua b/tests/examples/wibox/widget/background/fg.lua index 98a889c5..8e3c9450 100644 --- a/tests/examples/wibox/widget/background/fg.lua +++ b/tests/examples/wibox/widget/background/fg.lua @@ -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 diff --git a/tests/examples/wibox/widget/background/shape.lua b/tests/examples/wibox/widget/background/shape.lua index e8c16361..139bb1ca 100644 --- a/tests/examples/wibox/widget/background/shape.lua +++ b/tests/examples/wibox/widget/background/shape.lua @@ -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 diff --git a/tests/test-awful-widget-button.lua b/tests/test-awful-widget-button.lua index e35ac451..f0cff928 100644 --- a/tests/test-awful-widget-button.lua +++ b/tests/test-awful-widget-button.lua @@ -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 } From feb3833fd1d8632c287ddff01628ec7f79e7e18f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 00:09:57 -0400 Subject: [PATCH 04/68] doc: Move the background examples to the container suit --- lib/wibox/container/background.lua | 8 ++++---- .../wibox/{widget => container}/background/bg.lua | 0 .../wibox/{widget => container}/background/clip.lua | 0 .../wibox/{widget => container}/background/fg.lua | 0 .../wibox/{widget => container}/background/shape.lua | 0 5 files changed, 4 insertions(+), 4 deletions(-) rename tests/examples/wibox/{widget => container}/background/bg.lua (100%) rename tests/examples/wibox/{widget => container}/background/clip.lua (100%) rename tests/examples/wibox/{widget => container}/background/fg.lua (100%) rename tests/examples/wibox/{widget => container}/background/shape.lua (100%) diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua index 7c0ac815..a8286889 100644 --- a/lib/wibox/container/background.lua +++ b/lib/wibox/container/background.lua @@ -123,7 +123,7 @@ function background:set_children(children) end --- Set the background to use. ---@DOC_wibox_widget_background_bg_EXAMPLE@ +--@DOC_wibox_container_background_bg_EXAMPLE@ -- @param bg A color string, pattern or gradient (see `gears.color`) function background:set_bg(bg) if bg then @@ -135,7 +135,7 @@ function background:set_bg(bg) end --- Set the foreground to use. ---@DOC_wibox_widget_background_fg_EXAMPLE@ +--@DOC_wibox_container_background_fg_EXAMPLE@ -- @param fg A color string, pattern or gradient (see `gears.color`) function background:set_fg(fg) if fg then @@ -149,7 +149,7 @@ end --- Set the background shape. -- -- Any other arguments will be passed to the shape function ---@DOC_wibox_widget_background_shape_EXAMPLE@ +--@DOC_wibox_container_background_shape_EXAMPLE@ -- @param shape A function taking a context, width and height as arguments function background:set_shape(shape, ...) self._shape = shape @@ -176,7 +176,7 @@ function background:set_shape_border_color(fg) end --- When a `shape` is set, make sure nothing is drawn outside of it. ---@DOC_wibox_widget_background_clip_EXAMPLE@ +--@DOC_wibox_container_background_clip_EXAMPLE@ -- @tparam boolean value If the shape clip is enable function background:set_shape_clip(value) self._shape_clip = value diff --git a/tests/examples/wibox/widget/background/bg.lua b/tests/examples/wibox/container/background/bg.lua similarity index 100% rename from tests/examples/wibox/widget/background/bg.lua rename to tests/examples/wibox/container/background/bg.lua diff --git a/tests/examples/wibox/widget/background/clip.lua b/tests/examples/wibox/container/background/clip.lua similarity index 100% rename from tests/examples/wibox/widget/background/clip.lua rename to tests/examples/wibox/container/background/clip.lua diff --git a/tests/examples/wibox/widget/background/fg.lua b/tests/examples/wibox/container/background/fg.lua similarity index 100% rename from tests/examples/wibox/widget/background/fg.lua rename to tests/examples/wibox/container/background/fg.lua diff --git a/tests/examples/wibox/widget/background/shape.lua b/tests/examples/wibox/container/background/shape.lua similarity index 100% rename from tests/examples/wibox/widget/background/shape.lua rename to tests/examples/wibox/container/background/shape.lua From 44a4eca40e1106bea2fa812108949e4580b74a26 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 00:26:13 -0400 Subject: [PATCH 05/68] doc: Port the shape images to the doc example system --- awesomeConfig.cmake | 3 -- docs/generate_examples.cmake | 51 ------------------- lib/gears/shape.lua | 32 ++++++------ tests/{ => examples/gears}/shape/arrow.lua | 0 tests/{ => examples/gears}/shape/circle.lua | 0 tests/{ => examples/gears}/shape/cross.lua | 0 tests/{ => examples/gears}/shape/hexagon.lua | 0 .../{ => examples/gears}/shape/infobubble.lua | 0 .../gears}/shape/isosceles_triangle.lua | 0 tests/{ => examples/gears}/shape/losange.lua | 0 tests/{ => examples/gears}/shape/octogon.lua | 0 .../gears}/shape/parallelogram.lua | 0 .../gears}/shape/partially_rounded_rect.lua | 0 .../{ => examples/gears}/shape/powerline.lua | 0 .../gears}/shape/radial_progress.lua | 0 .../{ => examples/gears}/shape/rectangle.lua | 0 .../gears}/shape/rectangular_tag.lua | 0 .../gears}/shape/rounded_bar.lua | 0 .../gears}/shape/rounded_rect.lua | 0 .../gears/shape/template.lua} | 2 +- 20 files changed, 17 insertions(+), 71 deletions(-) delete mode 100644 docs/generate_examples.cmake rename tests/{ => examples/gears}/shape/arrow.lua (100%) rename tests/{ => examples/gears}/shape/circle.lua (100%) rename tests/{ => examples/gears}/shape/cross.lua (100%) rename tests/{ => examples/gears}/shape/hexagon.lua (100%) rename tests/{ => examples/gears}/shape/infobubble.lua (100%) rename tests/{ => examples/gears}/shape/isosceles_triangle.lua (100%) rename tests/{ => examples/gears}/shape/losange.lua (100%) rename tests/{ => examples/gears}/shape/octogon.lua (100%) rename tests/{ => examples/gears}/shape/parallelogram.lua (100%) rename tests/{ => examples/gears}/shape/partially_rounded_rect.lua (100%) rename tests/{ => examples/gears}/shape/powerline.lua (100%) rename tests/{ => examples/gears}/shape/radial_progress.lua (100%) rename tests/{ => examples/gears}/shape/rectangle.lua (100%) rename tests/{ => examples/gears}/shape/rectangular_tag.lua (100%) rename tests/{ => examples/gears}/shape/rounded_bar.lua (100%) rename tests/{ => examples/gears}/shape/rounded_rect.lua (100%) rename tests/{shape/test-shape.lua => examples/gears/shape/template.lua} (96%) diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake index 83f0f5bf..7f2fd5d1 100644 --- a/awesomeConfig.cmake +++ b/awesomeConfig.cmake @@ -300,9 +300,6 @@ if(GENERATE_DOC) # Load the common documentation include(docs/load_ldoc.cmake) - # Generate some images and examples - include(docs/generate_examples.cmake) - # Use `include`, rather than `add_subdirectory`, to keep the variables # The file is a valid CMakeLists.txt and can be executed directly if only # the image artefacts are needed. diff --git a/docs/generate_examples.cmake b/docs/generate_examples.cmake deleted file mode 100644 index bb2d0716..00000000 --- a/docs/generate_examples.cmake +++ /dev/null @@ -1,51 +0,0 @@ - -# Get and update the LUA_PATH so the scripts can be executed without Awesome -execute_process(COMMAND lua -e print\(package.path\) OUTPUT_VARIABLE LUA_PATH_) -set(ENV{LUA_PATH} "${SOURCE_DIR}/lib/?;${SOURCE_DIR}/lib/?.lua;${LUA_PATH_}") - -file(MAKE_DIRECTORY "${BUILD_DIR}/doc/images") - -set(ENV{BUILD_DIRECTORY} "${BUILD_DIR}/") -set(ENV{AWESOME_LIB_DIR} "${SOURCE_DIR}/lib/") - -# -# Shape API -# -foreach (SHAPE_NAME "circle" "arrow" "rounded_rect" "hexagon" "infobubble" - "powerline" "isosceles_triangle" "cross" "octogon" "parallelogram" - "losange" "partially_rounded_rect" "radial_progress" "rounded_bar" - "rectangle" "rectangular_tag") - set(SHAPE_FILE "${SOURCE_DIR}/tests/shape/${SHAPE_NAME}.lua") - set(SHAPE_SVG "${BUILD_DIR}/doc/images/shape_${SHAPE_NAME}.svg") - - # Generate some SVG for the documentation and load the examples for the doc - execute_process( - COMMAND lua ${SOURCE_DIR}/tests/shape/test-shape.lua ${SHAPE_FILE} ${SHAPE_SVG} ${SOURCE_DIR}/.luacov - ERROR_VARIABLE SHAPE_ERROR - ) - - if (NOT SHAPE_ERROR STREQUAL "") - message(${SHAPE_ERROR}) - message(FATAL_ERROR ${SHAPE_NAME} " SVG generation failed, bye") - endif() - - # Set the SVG paths for the doc - set(SHAPE_${SHAPE_NAME}_SVG "../images/shape_${SHAPE_NAME}.svg") - - # Use the .lua as code example - file(READ ${SHAPE_FILE} SHAPE_EXAMPLE) - STRING(REGEX REPLACE "\n" ";" SHAPE_EXAMPLE "${SHAPE_EXAMPLE}") - SET(SHAPE_COMMENTED - "![Shape example](../images/shape_${SHAPE_NAME}.svg)\n--\n-- @usage" - ) - foreach (EXAMPLE_FILE ${SHAPE_EXAMPLE}) - if(NOT EXAMPLE_FILE MATCHES "^.+--DOC_HIDE$") - SET(SHAPE_COMMENTED ${SHAPE_COMMENTED}\n--${EXAMPLE_FILE}) - endif() - endforeach() - - set(SHAPE_${SHAPE_NAME}_EXAMPLE ${SHAPE_COMMENTED}) - -endforeach() - -# vim: filetype=cmake:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80:foldmethod=marker diff --git a/lib/gears/shape.lua b/lib/gears/shape.lua index f6c0d468..a7de80c4 100644 --- a/lib/gears/shape.lua +++ b/lib/gears/shape.lua @@ -28,7 +28,7 @@ local module = {} --- Add a rounded rectangle to the current path. -- Note: If the radius is bigger than either half side, it will be reduced. -- --- @SHAPE_rounded_rect_EXAMPLE@ +-- @DOC_gears_shape_rounded_rect_EXAMPLE@ -- -- @param cr A cairo content -- @tparam number width The rectangle width @@ -53,7 +53,7 @@ end --- Add a rectangle delimited by 2 180 degree arcs to the path. -- --- @SHAPE_rounded_bar_EXAMPLE@ +-- @DOC_gears_shape_rounded_bar_EXAMPLE@ -- -- @param cr A cairo content -- @param width The rectangle width @@ -64,7 +64,7 @@ end --- A rounded rect with only some of the corners rounded. -- --- @SHAPE_partially_rounded_rect_EXAMPLE@ +-- @DOC_gears_shape_partially_rounded_rect_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -117,7 +117,7 @@ end --- A rounded rectangle with a triangle at the top. -- --- @SHAPE_infobubble_EXAMPLE@ +-- @DOC_gears_shape_infobubble_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -152,7 +152,7 @@ end --- A rectangle terminated by an arrow. -- --- @SHAPE_rectangular_tag_EXAMPLE@ +-- @DOC_gears_shape_rectangular_tag_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -179,7 +179,7 @@ end --- A simple arrow shape. -- --- @SHAPE_arrow_EXAMPLE@ +-- @DOC_gears_shape_arrow_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -206,7 +206,7 @@ end --- A squeezed hexagon filling the rectangle. -- --- @SHAPE_hexagon_EXAMPLE@ +-- @DOC_gears_shape_hexagon_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -224,7 +224,7 @@ end --- Double arrow popularized by the vim-powerline module. -- --- @SHAPE_powerline_EXAMPLE@ +-- @DOC_gears_shape_powerline_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -252,7 +252,7 @@ end --- An isosceles triangle. -- --- @SHAPE_isosceles_triangle_EXAMPLE@ +-- @DOC_gears_shape_isosceles_triangle_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -266,7 +266,7 @@ end --- A cross (**+**) symbol. -- --- @SHAPE_cross_EXAMPLE@ +-- @DOC_gears_shape_cross_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -293,7 +293,7 @@ end --- A similar shape to the `rounded_rect`, but with sharp corners. -- --- @SHAPE_octogon_EXAMPLE@ +-- @DOC_gears_shape_octogon_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -316,7 +316,7 @@ end --- A circle shape. -- --- @SHAPE_circle_EXAMPLE@ +-- @DOC_gears_shape_circle_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -329,7 +329,7 @@ end --- A simple rectangle. -- --- @SHAPE_rectangle_EXAMPLE@ +-- @DOC_gears_shape_rectangle_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -341,7 +341,7 @@ end --- A diagonal parallelogram with the bottom left corner at x=0 and top right -- at x=width. -- --- @SHAPE_parallelogram_EXAMPLE@ +-- @DOC_gears_shape_parallelogram_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -358,7 +358,7 @@ end --- A losange. -- --- @SHAPE_losange_EXAMPLE@ +-- @DOC_gears_shape_losange_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number width The shape width @@ -377,7 +377,7 @@ end -- Note that this shape is not closed and thus filling it doesn't make much -- sense. -- --- @SHAPE_radial_progress_EXAMPLE@ +-- @DOC_gears_shape_radial_progress_EXAMPLE@ -- -- @param cr A cairo context -- @tparam number w The shape width diff --git a/tests/shape/arrow.lua b/tests/examples/gears/shape/arrow.lua similarity index 100% rename from tests/shape/arrow.lua rename to tests/examples/gears/shape/arrow.lua diff --git a/tests/shape/circle.lua b/tests/examples/gears/shape/circle.lua similarity index 100% rename from tests/shape/circle.lua rename to tests/examples/gears/shape/circle.lua diff --git a/tests/shape/cross.lua b/tests/examples/gears/shape/cross.lua similarity index 100% rename from tests/shape/cross.lua rename to tests/examples/gears/shape/cross.lua diff --git a/tests/shape/hexagon.lua b/tests/examples/gears/shape/hexagon.lua similarity index 100% rename from tests/shape/hexagon.lua rename to tests/examples/gears/shape/hexagon.lua diff --git a/tests/shape/infobubble.lua b/tests/examples/gears/shape/infobubble.lua similarity index 100% rename from tests/shape/infobubble.lua rename to tests/examples/gears/shape/infobubble.lua diff --git a/tests/shape/isosceles_triangle.lua b/tests/examples/gears/shape/isosceles_triangle.lua similarity index 100% rename from tests/shape/isosceles_triangle.lua rename to tests/examples/gears/shape/isosceles_triangle.lua diff --git a/tests/shape/losange.lua b/tests/examples/gears/shape/losange.lua similarity index 100% rename from tests/shape/losange.lua rename to tests/examples/gears/shape/losange.lua diff --git a/tests/shape/octogon.lua b/tests/examples/gears/shape/octogon.lua similarity index 100% rename from tests/shape/octogon.lua rename to tests/examples/gears/shape/octogon.lua diff --git a/tests/shape/parallelogram.lua b/tests/examples/gears/shape/parallelogram.lua similarity index 100% rename from tests/shape/parallelogram.lua rename to tests/examples/gears/shape/parallelogram.lua diff --git a/tests/shape/partially_rounded_rect.lua b/tests/examples/gears/shape/partially_rounded_rect.lua similarity index 100% rename from tests/shape/partially_rounded_rect.lua rename to tests/examples/gears/shape/partially_rounded_rect.lua diff --git a/tests/shape/powerline.lua b/tests/examples/gears/shape/powerline.lua similarity index 100% rename from tests/shape/powerline.lua rename to tests/examples/gears/shape/powerline.lua diff --git a/tests/shape/radial_progress.lua b/tests/examples/gears/shape/radial_progress.lua similarity index 100% rename from tests/shape/radial_progress.lua rename to tests/examples/gears/shape/radial_progress.lua diff --git a/tests/shape/rectangle.lua b/tests/examples/gears/shape/rectangle.lua similarity index 100% rename from tests/shape/rectangle.lua rename to tests/examples/gears/shape/rectangle.lua diff --git a/tests/shape/rectangular_tag.lua b/tests/examples/gears/shape/rectangular_tag.lua similarity index 100% rename from tests/shape/rectangular_tag.lua rename to tests/examples/gears/shape/rectangular_tag.lua diff --git a/tests/shape/rounded_bar.lua b/tests/examples/gears/shape/rounded_bar.lua similarity index 100% rename from tests/shape/rounded_bar.lua rename to tests/examples/gears/shape/rounded_bar.lua diff --git a/tests/shape/rounded_rect.lua b/tests/examples/gears/shape/rounded_rect.lua similarity index 100% rename from tests/shape/rounded_rect.lua rename to tests/examples/gears/shape/rounded_rect.lua diff --git a/tests/shape/test-shape.lua b/tests/examples/gears/shape/template.lua similarity index 96% rename from tests/shape/test-shape.lua rename to tests/examples/gears/shape/template.lua index b15cbab0..86fcc467 100644 --- a/tests/shape/test-shape.lua +++ b/tests/examples/gears/shape/template.lua @@ -30,7 +30,7 @@ local function show(cr, skip_fill) cr:clip() end -local cr = get_surface(svgpath) +local cr = get_surface(svgpath..".svg") cr:translate(3,3) loadfile(filepath)(shape, cr, show) From ae0d306114920e5f26c204f475c823dd277bf55e Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 00:46:01 -0400 Subject: [PATCH 06/68] textclock: Move to wibox.widget It doesn't depend on `awful`, so it doesn't belong in `awful`. --- awesomerc.lua | 2 +- lib/awful/tooltip.lua | 2 +- lib/awful/widget/textclock.lua | 51 +++++--------------------------- lib/wibox/widget/init.lua | 1 + lib/wibox/widget/textclock.lua | 53 ++++++++++++++++++++++++++++++++++ tests/_wibox_helper.lua | 2 +- tests/test-leaks.lua | 2 +- 7 files changed, 66 insertions(+), 47 deletions(-) create mode 100644 lib/wibox/widget/textclock.lua diff --git a/awesomerc.lua b/awesomerc.lua index c50fb151..d7132042 100755 --- a/awesomerc.lua +++ b/awesomerc.lua @@ -115,7 +115,7 @@ mykeyboardlayout = awful.widget.keyboardlayout() -- {{{ Wibox -- Create a textclock widget -mytextclock = awful.widget.textclock() +mytextclock = wibox.widget.textclock() -- Create a wibox for each screen and add it mywibox = {} diff --git a/lib/awful/tooltip.lua b/lib/awful/tooltip.lua index 57b37699..6f44e47d 100644 --- a/lib/awful/tooltip.lua +++ b/lib/awful/tooltip.lua @@ -10,7 +10,7 @@ -- How to create a tooltip? -- --- -- --- myclock = awful.widget.textclock({}, "%T", 1) +-- myclock = wibox.widget.textclock({}, "%T", 1) -- myclock_t = awful.tooltip({ -- objects = { myclock }, -- timer_function = function() diff --git a/lib/awful/widget/textclock.lua b/lib/awful/widget/textclock.lua index a4a0f90c..74cf949d 100644 --- a/lib/awful/widget/textclock.lua +++ b/lib/awful/widget/textclock.lua @@ -1,52 +1,17 @@ --------------------------------------------------------------------------- ---- Text clock widget. +-- This widget has moved to `wibox.widget.textclock` -- -- @author Julien Danjou <julien@danjou.info> --- @copyright 2009 Julien Danjou +-- @copyright 2008-2009 Julien Danjou -- @release @AWESOME_VERSION@ -- @classmod awful.widget.textclock --------------------------------------------------------------------------- +local util = require("awful.util") -local setmetatable = setmetatable -local os = os -local textbox = require("wibox.widget.textbox") -local timer = require("gears.timer") -local DateTime = require("lgi").GLib.DateTime - -local textclock = { mt = {} } - ---- This lowers the timeout so that it occurs "correctly". For example, a timeout --- of 60 is rounded so that it occurs the next time the clock reads ":00 seconds". -local function calc_timeout(real_timeout) - return real_timeout - os.time() % real_timeout -end - ---- Create a textclock widget. It draws the time it is in a textbox. --- --- @param format The time format. Default is " %a %b %d, %H:%M ". --- @param timeout How often update the time. Default is 60. --- @return A textbox widget. -function textclock.new(format, timeout) - format = format or " %a %b %d, %H:%M " - timeout = timeout or 60 - - local w = textbox() - local t - function w._textclock_update_cb() - w:set_markup(DateTime.new_now_local():format(format)) - t.timeout = calc_timeout(timeout) - t:again() - return true -- Continue the timer - end - t = timer.weak_start_new(timeout, w._textclock_update_cb) - t:emit_signal("timeout") - return w -end - -function textclock.mt:__call(...) - return textclock.new(...) -end - -return setmetatable(textclock, textclock.mt) +return util.deprecate_class( + require("wibox.widget.textclock"), + "awful.widget.textclock", + "wibox.widget.textclock" +) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/wibox/widget/init.lua b/lib/wibox/widget/init.lua index 5283fb4e..0fb702d8 100644 --- a/lib/wibox/widget/init.lua +++ b/lib/wibox/widget/init.lua @@ -12,6 +12,7 @@ return setmetatable({ imagebox = require("wibox.widget.imagebox"); background = require("wibox.widget.background"); systray = require("wibox.widget.systray"); + textclock = require("wibox.widget.textclock"); }, {__call = function(_, args) return base.make_widget_declarative(args) end}) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/wibox/widget/textclock.lua b/lib/wibox/widget/textclock.lua new file mode 100644 index 00000000..aec44521 --- /dev/null +++ b/lib/wibox/widget/textclock.lua @@ -0,0 +1,53 @@ +--------------------------------------------------------------------------- +--- Text clock widget. +-- +-- @author Julien Danjou <julien@danjou.info> +-- @copyright 2009 Julien Danjou +-- @release @AWESOME_VERSION@ +-- @classmod wibox.widget.textclock +--------------------------------------------------------------------------- + +local setmetatable = setmetatable +local os = os +local textbox = require("wibox.widget.textbox") +local timer = require("gears.timer") +local DateTime = require("lgi").GLib.DateTime + +local textclock = { mt = {} } + +--- This lowers the timeout so that it occurs "correctly". For example, a timeout +-- of 60 is rounded so that it occurs the next time the clock reads ":00 seconds". +local function calc_timeout(real_timeout) + return real_timeout - os.time() % real_timeout +end + +--- Create a textclock widget. It draws the time it is in a textbox. +-- +-- @tparam[opt=" %a %b %d, %H:%M "] string format The time format. +-- @tparam[opt=60] number timeout How often update the time (in seconds). +-- @treturn table A textbox widget. +-- @function wibox.widget.textclock +function textclock.new(format, timeout) + format = format or " %a %b %d, %H:%M " + timeout = timeout or 60 + + local w = textbox() + local t + function w._textclock_update_cb() + w:set_markup(DateTime.new_now_local():format(format)) + t.timeout = calc_timeout(timeout) + t:again() + return true -- Continue the timer + end + t = timer.weak_start_new(timeout, w._textclock_update_cb) + t:emit_signal("timeout") + return w +end + +function textclock.mt:__call(...) + return textclock.new(...) +end + +return setmetatable(textclock, textclock.mt) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/tests/_wibox_helper.lua b/tests/_wibox_helper.lua index d21ebbfe..5c7afdc2 100644 --- a/tests/_wibox_helper.lua +++ b/tests/_wibox_helper.lua @@ -13,7 +13,7 @@ return { create_wibox = function() -- Widgets that are aligned to the right local right_layout = wibox.layout.fixed.horizontal() - local textclock = awful.widget.textclock() + local textclock = wibox.widget.textclock() right_layout:add(textclock) right_layout:add(awful.widget.layoutbox(1)) diff --git a/tests/test-leaks.lua b/tests/test-leaks.lua index 725ed169..6977189c 100644 --- a/tests/test-leaks.lua +++ b/tests/test-leaks.lua @@ -63,7 +63,7 @@ collectable(wibox.layout.align.horizontal()) -- Then some random widgets from awful collectable(awful.widget.launcher({ image = cairo.ImageSurface(cairo.Format.ARGB32, 20, 20), command = "bash" })) collectable(awful.widget.prompt()) -collectable(awful.widget.textclock()) +collectable(wibox.widget.textclock()) collectable(awful.widget.layoutbox(1)) -- Some widgets do things via timer.delayed_call From 6493cbee76517b84416ea8ec515f3547fe5af58a Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 01:22:35 -0400 Subject: [PATCH 07/68] progressbar: Move to `wibox.widget` --- lib/awful/widget/progressbar.lua | 227 +----------------------------- lib/wibox/widget/init.lua | 1 + lib/wibox/widget/progressbar.lua | 230 +++++++++++++++++++++++++++++++ 3 files changed, 238 insertions(+), 220 deletions(-) create mode 100644 lib/wibox/widget/progressbar.lua diff --git a/lib/awful/widget/progressbar.lua b/lib/awful/widget/progressbar.lua index 4eb5ccbf..123869ad 100644 --- a/lib/awful/widget/progressbar.lua +++ b/lib/awful/widget/progressbar.lua @@ -1,230 +1,17 @@ --------------------------------------------------------------------------- ---- A progressbar widget. +--- This module has been moved to `wibox.widget.progressbar` -- -- @author Julien Danjou <julien@danjou.info> -- @copyright 2009 Julien Danjou -- @release @AWESOME_VERSION@ -- @classmod awful.widget.progressbar --------------------------------------------------------------------------- +local util = require("awful.util") -local setmetatable = setmetatable -local ipairs = ipairs -local math = math -local base = require("wibox.widget.base") -local color = require("gears.color") - -local progressbar = { mt = {} } - -local data = setmetatable({}, { __mode = "k" }) - ---- Set the progressbar border color. --- If the value is nil, no border will be drawn. --- --- @function set_border_color --- @param progressbar The progressbar. --- @param color The border color to set. - ---- Set the progressbar foreground color. --- --- @function set_color --- @param progressbar The progressbar. --- @param color The progressbar color. - ---- Set the progressbar background color. --- --- @function set_background_color --- @param progressbar The progressbar. --- @param color The progressbar background color. - ---- Set the progressbar to draw vertically. Default is false. --- --- @function set_vertical --- @param progressbar The progressbar. --- @param vertical A boolean value. - ---- Set the progressbar to draw ticks. Default is false. --- --- @function set_ticks --- @param progressbar The progressbar. --- @param ticks A boolean value. - ---- Set the progressbar ticks gap. --- --- @function set_ticks_gap --- @param progressbar The progressbar. --- @param value The value. - ---- Set the progressbar ticks size. --- --- @function set_ticks_size --- @param progressbar The progressbar. --- @param value The value. - ---- Set the maximum value the progressbar should handle. --- --- @function set_max_value --- @param progressbar The progressbar. --- @param value The value. - -local properties = { "width", "height", "border_color", - "color", "background_color", - "vertical", "value", "max_value", - "ticks", "ticks_gap", "ticks_size" } - -function progressbar.draw(pbar, _, cr, width, height) - local ticks_gap = data[pbar].ticks_gap or 1 - local ticks_size = data[pbar].ticks_size or 4 - - -- We want one pixel wide lines - cr:set_line_width(1) - - local value = data[pbar].value - local max_value = data[pbar].max_value - if value >= 0 then - value = value / max_value - end - - local over_drawn_width = width - local over_drawn_height = height - local border_width = 0 - if data[pbar].border_color then - -- Draw border - cr:rectangle(0.5, 0.5, width - 1, height - 1) - cr:set_source(color(data[pbar].border_color)) - cr:stroke() - - over_drawn_width = width - 2 -- remove 2 for borders - over_drawn_height = height - 2 -- remove 2 for borders - border_width = 1 - end - - cr:rectangle(border_width, border_width, - over_drawn_width, over_drawn_height) - cr:set_source(color(data[pbar].color or "#ff0000")) - cr:fill() - - -- Cover the part that is not set with a rectangle - if data[pbar].vertical then - local rel_height = over_drawn_height * (1 - value) - cr:rectangle(border_width, - border_width, - over_drawn_width, - rel_height) - cr:set_source(color(data[pbar].background_color or "#000000aa")) - cr:fill() - - -- Place smaller pieces over the gradient if ticks are enabled - if data[pbar].ticks then - for i=0, height / (ticks_size+ticks_gap)-border_width do - local rel_offset = over_drawn_height / 1 - (ticks_size+ticks_gap) * i - - if rel_offset >= rel_height then - cr:rectangle(border_width, - rel_offset, - over_drawn_width, - ticks_gap) - end - end - cr:set_source(color(data[pbar].background_color or "#000000aa")) - cr:fill() - end - else - local rel_x = over_drawn_width * value - cr:rectangle(border_width + rel_x, - border_width, - over_drawn_width - rel_x, - over_drawn_height) - cr:set_source(color(data[pbar].background_color or "#000000aa")) - cr:fill() - - if data[pbar].ticks then - for i=0, width / (ticks_size+ticks_gap)-border_width do - local rel_offset = over_drawn_width / 1 - (ticks_size+ticks_gap) * i - - if rel_offset <= rel_x then - cr:rectangle(rel_offset, - border_width, - ticks_gap, - over_drawn_height) - end - end - cr:set_source(color(data[pbar].background_color or "#000000aa")) - cr:fill() - end - end -end - -function progressbar.fit(pbar) - return data[pbar].width, data[pbar].height -end - ---- Set the progressbar value. --- @param value The progress bar value between 0 and 1. -function progressbar:set_value(value) - value = value or 0 - local max_value = data[self].max_value - data[self].value = math.min(max_value, math.max(0, value)) - self:emit_signal("widget::redraw_needed") - return self -end - ---- Set the progressbar height. --- @param height The height to set. -function progressbar:set_height(height) - data[self].height = height - self:emit_signal("widget::layout_changed") - return self -end - ---- Set the progressbar width. --- @param width The width to set. -function progressbar:set_width(width) - data[self].width = width - self:emit_signal("widget::layout_changed") - return self -end - --- Build properties function -for _, prop in ipairs(properties) do - if not progressbar["set_" .. prop] then - progressbar["set_" .. prop] = function(pbar, value) - data[pbar][prop] = value - pbar:emit_signal("widget::redraw_needed") - return pbar - end - end -end - ---- Create a progressbar widget. --- @param args Standard widget() arguments. You should add width and height --- key to set progressbar geometry. --- @return A progressbar widget. -function progressbar.new(args) - args = args or {} - local width = args.width or 100 - local height = args.height or 20 - - args.type = "imagebox" - - local pbar = base.make_widget() - - data[pbar] = { width = width, height = height, value = 0, max_value = 1 } - - -- Set methods - for _, prop in ipairs(properties) do - pbar["set_" .. prop] = progressbar["set_" .. prop] - end - - pbar.draw = progressbar.draw - pbar.fit = progressbar.fit - - return pbar -end - -function progressbar.mt:__call(...) - return progressbar.new(...) -end - -return setmetatable(progressbar, progressbar.mt) +return util.deprecate_class( + require("wibox.widget.progressbar"), + "awful.widget.progressbar", + "wibox.widget.progressbar" +) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/wibox/widget/init.lua b/lib/wibox/widget/init.lua index 0fb702d8..63a9c660 100644 --- a/lib/wibox/widget/init.lua +++ b/lib/wibox/widget/init.lua @@ -13,6 +13,7 @@ return setmetatable({ background = require("wibox.widget.background"); systray = require("wibox.widget.systray"); textclock = require("wibox.widget.textclock"); + progressbar = require("wibox.widget.progressbar"); }, {__call = function(_, args) return base.make_widget_declarative(args) end}) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/wibox/widget/progressbar.lua b/lib/wibox/widget/progressbar.lua new file mode 100644 index 00000000..a73ac917 --- /dev/null +++ b/lib/wibox/widget/progressbar.lua @@ -0,0 +1,230 @@ +--------------------------------------------------------------------------- +--- A progressbar widget. +-- +-- @author Julien Danjou <julien@danjou.info> +-- @copyright 2009 Julien Danjou +-- @release @AWESOME_VERSION@ +-- @classmod wibox.widget.progressbar +--------------------------------------------------------------------------- + +local setmetatable = setmetatable +local ipairs = ipairs +local math = math +local base = require("wibox.widget.base") +local color = require("gears.color") + +local progressbar = { mt = {} } + +local data = setmetatable({}, { __mode = "k" }) + +--- Set the progressbar border color. +-- If the value is nil, no border will be drawn. +-- +-- @function set_border_color +-- @param progressbar The progressbar. +-- @param color The border color to set. + +--- Set the progressbar foreground color. +-- +-- @function set_color +-- @param progressbar The progressbar. +-- @param color The progressbar color. + +--- Set the progressbar background color. +-- +-- @function set_background_color +-- @param progressbar The progressbar. +-- @param color The progressbar background color. + +--- Set the progressbar to draw vertically. Default is false. +-- +-- @function set_vertical +-- @param progressbar The progressbar. +-- @param vertical A boolean value. + +--- Set the progressbar to draw ticks. Default is false. +-- +-- @function set_ticks +-- @param progressbar The progressbar. +-- @param ticks A boolean value. + +--- Set the progressbar ticks gap. +-- +-- @function set_ticks_gap +-- @param progressbar The progressbar. +-- @param value The value. + +--- Set the progressbar ticks size. +-- +-- @function set_ticks_size +-- @param progressbar The progressbar. +-- @param value The value. + +--- Set the maximum value the progressbar should handle. +-- +-- @function set_max_value +-- @param progressbar The progressbar. +-- @param value The value. + +local properties = { "width", "height", "border_color", + "color", "background_color", + "vertical", "value", "max_value", + "ticks", "ticks_gap", "ticks_size" } + +function progressbar.draw(pbar, _, cr, width, height) + local ticks_gap = data[pbar].ticks_gap or 1 + local ticks_size = data[pbar].ticks_size or 4 + + -- We want one pixel wide lines + cr:set_line_width(1) + + local value = data[pbar].value + local max_value = data[pbar].max_value + if value >= 0 then + value = value / max_value + end + + local over_drawn_width = width + local over_drawn_height = height + local border_width = 0 + if data[pbar].border_color then + -- Draw border + cr:rectangle(0.5, 0.5, width - 1, height - 1) + cr:set_source(color(data[pbar].border_color)) + cr:stroke() + + over_drawn_width = width - 2 -- remove 2 for borders + over_drawn_height = height - 2 -- remove 2 for borders + border_width = 1 + end + + cr:rectangle(border_width, border_width, + over_drawn_width, over_drawn_height) + cr:set_source(color(data[pbar].color or "#ff0000")) + cr:fill() + + -- Cover the part that is not set with a rectangle + if data[pbar].vertical then + local rel_height = over_drawn_height * (1 - value) + cr:rectangle(border_width, + border_width, + over_drawn_width, + rel_height) + cr:set_source(color(data[pbar].background_color or "#000000aa")) + cr:fill() + + -- Place smaller pieces over the gradient if ticks are enabled + if data[pbar].ticks then + for i=0, height / (ticks_size+ticks_gap)-border_width do + local rel_offset = over_drawn_height / 1 - (ticks_size+ticks_gap) * i + + if rel_offset >= rel_height then + cr:rectangle(border_width, + rel_offset, + over_drawn_width, + ticks_gap) + end + end + cr:set_source(color(data[pbar].background_color or "#000000aa")) + cr:fill() + end + else + local rel_x = over_drawn_width * value + cr:rectangle(border_width + rel_x, + border_width, + over_drawn_width - rel_x, + over_drawn_height) + cr:set_source(color(data[pbar].background_color or "#000000aa")) + cr:fill() + + if data[pbar].ticks then + for i=0, width / (ticks_size+ticks_gap)-border_width do + local rel_offset = over_drawn_width / 1 - (ticks_size+ticks_gap) * i + + if rel_offset <= rel_x then + cr:rectangle(rel_offset, + border_width, + ticks_gap, + over_drawn_height) + end + end + cr:set_source(color(data[pbar].background_color or "#000000aa")) + cr:fill() + end + end +end + +function progressbar.fit(pbar) + return data[pbar].width, data[pbar].height +end + +--- Set the progressbar value. +-- @param value The progress bar value between 0 and 1. +function progressbar:set_value(value) + value = value or 0 + local max_value = data[self].max_value + data[self].value = math.min(max_value, math.max(0, value)) + self:emit_signal("widget::redraw_needed") + return self +end + +--- Set the progressbar height. +-- @param height The height to set. +function progressbar:set_height(height) + data[self].height = height + self:emit_signal("widget::layout_changed") + return self +end + +--- Set the progressbar width. +-- @param width The width to set. +function progressbar:set_width(width) + data[self].width = width + self:emit_signal("widget::layout_changed") + return self +end + +-- Build properties function +for _, prop in ipairs(properties) do + if not progressbar["set_" .. prop] then + progressbar["set_" .. prop] = function(pbar, value) + data[pbar][prop] = value + pbar:emit_signal("widget::redraw_needed") + return pbar + end + end +end + +--- Create a progressbar widget. +-- @param args Standard widget() arguments. You should add width and height +-- key to set progressbar geometry. +-- @return A progressbar widget. +function progressbar.new(args) + args = args or {} + local width = args.width or 100 + local height = args.height or 20 + + args.type = "imagebox" + + local pbar = base.make_widget() + + data[pbar] = { width = width, height = height, value = 0, max_value = 1 } + + -- Set methods + for _, prop in ipairs(properties) do + pbar["set_" .. prop] = progressbar["set_" .. prop] + end + + pbar.draw = progressbar.draw + pbar.fit = progressbar.fit + + return pbar +end + +function progressbar.mt:__call(...) + return progressbar.new(...) +end + +return setmetatable(progressbar, progressbar.mt) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From f9c9e11d11ca1339cfea614f167a303b7a6d72cb Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 01:30:44 -0400 Subject: [PATCH 08/68] graph: Move to wibox.widget --- lib/awful/widget/graph.lua | 276 +----------------------------------- lib/wibox/widget/graph.lua | 279 +++++++++++++++++++++++++++++++++++++ lib/wibox/widget/init.lua | 1 + 3 files changed, 287 insertions(+), 269 deletions(-) create mode 100644 lib/wibox/widget/graph.lua diff --git a/lib/awful/widget/graph.lua b/lib/awful/widget/graph.lua index 828a0509..3679a770 100644 --- a/lib/awful/widget/graph.lua +++ b/lib/awful/widget/graph.lua @@ -1,279 +1,17 @@ --------------------------------------------------------------------------- ---- A graph widget. +--- This module has been moved to `wibox.widget.graph` -- -- @author Julien Danjou <julien@danjou.info> -- @copyright 2009 Julien Danjou -- @release @AWESOME_VERSION@ -- @classmod awful.widget.graph --------------------------------------------------------------------------- +local util = require("awful.util") -local setmetatable = setmetatable -local ipairs = ipairs -local math = math -local table = table -local type = type -local color = require("gears.color") -local base = require("wibox.widget.base") - -local graph = { mt = {} } - ---- Set the graph border color. --- If the value is nil, no border will be drawn. --- --- @function set_border_color --- @param graph The graph. --- @param color The border color to set. - ---- Set the graph foreground color. --- --- @function set_color --- @param graph The graph. --- @param color The graph color. --- @see gears.color.create_pattern - ---- Set the graph background color. --- --- @function set_background_color --- @param graph The graph. --- @param color The graph background color. - ---- Set the maximum value the graph should handle. --- If "scale" is also set, the graph never scales up below this value, but it --- automatically scales down to make all data fit. --- --- @function set_max_value --- @param graph The graph. --- @param value The value. - ---- Set the graph to automatically scale its values. Default is false. --- --- @function set_scale --- @param graph The graph. --- @param scale A boolean value - ---- Set the graph to draw stacks. Default is false. --- --- @function set_stack --- @param graph The graph. --- @param stack A boolean value. - ---- Set the graph stacking colors. Order matters. --- --- @function set_stack_colors --- @param graph The graph. --- @param stack_colors A table with stacking colors. - -local properties = { "width", "height", "border_color", "stack", - "stack_colors", "color", "background_color", - "max_value", "scale" } - -function graph.draw(_graph, _, cr, width, height) - local max_value = _graph._data.max_value - local values = _graph._data.values - - cr:set_line_width(1) - - -- Draw the background first - cr:set_source(color(_graph._data.background_color or "#000000aa")) - cr:paint() - - -- Account for the border width - cr:save() - if _graph._data.border_color then - cr:translate(1, 1) - width, height = width - 2, height - 2 - end - - -- Draw a stacked graph - if _graph._data.stack then - - if _graph._data.scale then - for _, v in ipairs(values) do - for _, sv in ipairs(v) do - if sv > max_value then - max_value = sv - end - end - end - end - - for i = 0, width do - local rel_i = 0 - local rel_x = i + 0.5 - - if _graph._data.stack_colors then - for idx, col in ipairs(_graph._data.stack_colors) do - local stack_values = values[idx] - if stack_values and i < #stack_values then - local value = stack_values[#stack_values - i] + rel_i - cr:move_to(rel_x, height * (1 - (rel_i / max_value))) - cr:line_to(rel_x, height * (1 - (value / max_value))) - cr:set_source(color(col or "#ff0000")) - cr:stroke() - rel_i = value - end - end - end - end - else - if _graph._data.scale then - for _, v in ipairs(values) do - if v > max_value then - max_value = v - end - end - end - - -- Draw the background on no value - if #values ~= 0 then - -- Draw reverse - for i = 0, #values - 1 do - local value = values[#values - i] - if value >= 0 then - value = value / max_value - cr:move_to(i + 0.5, height * (1 - value)) - cr:line_to(i + 0.5, height) - end - end - cr:set_source(color(_graph._data.color or "#ff0000")) - cr:stroke() - end - - end - - -- Undo the cr:translate() for the border - cr:restore() - - -- Draw the border last so that it overlaps already drawn values - if _graph._data.border_color then - -- We decremented these by two above - width, height = width + 2, height + 2 - - -- Draw the border - cr:rectangle(0.5, 0.5, width - 1, height - 1) - cr:set_source(color(_graph._data.border_color or "#ffffff")) - cr:stroke() - end -end - -function graph.fit(_graph) - return _graph._data.width, _graph._data.height -end - ---- Add a value to the graph --- --- @param value The value to be added to the graph --- @param group The stack color group index. -function graph:add_value(value, group) - value = value or 0 - local values = self._data.values - local max_value = self._data.max_value - value = math.max(0, value) - if not self._data.scale then - value = math.min(max_value, value) - end - - if self._data.stack and group then - if not self._data.values[group] - or type(self._data.values[group]) ~= "table" - then - self._data.values[group] = {} - end - values = self._data.values[group] - end - table.insert(values, value) - - local border_width = 0 - if self._data.border_color then border_width = 2 end - - -- Ensure we never have more data than we can draw - while #values > self._data.width - border_width do - table.remove(values, 1) - end - - self:emit_signal("widget::redraw_needed") - return self -end - ---- Clear the graph. -function graph:clear() - self._data.values = {} - self:emit_signal("widget::redraw_needed") - return self -end - ---- Set the graph height. --- @param height The height to set. -function graph:set_height(height) - if height >= 5 then - self._data.height = height - self:emit_signal("widget::layout_changed") - end - return self -end - ---- Set the graph width. --- @param width The width to set. -function graph:set_width(width) - if width >= 5 then - self._data.width = width - self:emit_signal("widget::layout_changed") - end - return self -end - --- Build properties function -for _, prop in ipairs(properties) do - if not graph["set_" .. prop] then - graph["set_" .. prop] = function(_graph, value) - if _graph._data[prop] ~= value then - _graph._data[prop] = value - _graph:emit_signal("widget::redraw_needed") - end - return _graph - end - end - if not graph["get_" .. prop] then - graph["get_" .. prop] = function(_graph) - return _graph._data[prop] - end - end -end - ---- Create a graph widget. --- @param args Standard widget() arguments. You should add width and height --- key to set graph geometry. --- @return A graph widget. -function graph.new(args) - args = args or {} - - local width = args.width or 100 - local height = args.height or 20 - - if width < 5 or height < 5 then return end - - local _graph = base.make_widget() - - _graph._data = { width = width, height = height, values = {}, max_value = 1 } - - -- Set methods - _graph.add_value = graph["add_value"] - _graph.clear = graph["clear"] - _graph.draw = graph.draw - _graph.fit = graph.fit - - for _, prop in ipairs(properties) do - _graph["set_" .. prop] = graph["set_" .. prop] - _graph["get_" .. prop] = graph["get_" .. prop] - end - - return _graph -end - -function graph.mt:__call(...) - return graph.new(...) -end - -return setmetatable(graph, graph.mt) +return util.deprecate_class( + require("wibox.widget.graph"), + "awful.widget.graph", + "wibox.widget.graph" +) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/wibox/widget/graph.lua b/lib/wibox/widget/graph.lua new file mode 100644 index 00000000..1ac6c547 --- /dev/null +++ b/lib/wibox/widget/graph.lua @@ -0,0 +1,279 @@ +--------------------------------------------------------------------------- +--- A graph widget. +-- +-- @author Julien Danjou <julien@danjou.info> +-- @copyright 2009 Julien Danjou +-- @release @AWESOME_VERSION@ +-- @classmod wibox.widget.graph +--------------------------------------------------------------------------- + +local setmetatable = setmetatable +local ipairs = ipairs +local math = math +local table = table +local type = type +local color = require("gears.color") +local base = require("wibox.widget.base") + +local graph = { mt = {} } + +--- Set the graph border color. +-- If the value is nil, no border will be drawn. +-- +-- @function set_border_color +-- @param graph The graph. +-- @param color The border color to set. + +--- Set the graph foreground color. +-- +-- @function set_color +-- @param graph The graph. +-- @param color The graph color. +-- @see gears.color.create_pattern + +--- Set the graph background color. +-- +-- @function set_background_color +-- @param graph The graph. +-- @param color The graph background color. + +--- Set the maximum value the graph should handle. +-- If "scale" is also set, the graph never scales up below this value, but it +-- automatically scales down to make all data fit. +-- +-- @function set_max_value +-- @param graph The graph. +-- @param value The value. + +--- Set the graph to automatically scale its values. Default is false. +-- +-- @function set_scale +-- @param graph The graph. +-- @param scale A boolean value + +--- Set the graph to draw stacks. Default is false. +-- +-- @function set_stack +-- @param graph The graph. +-- @param stack A boolean value. + +--- Set the graph stacking colors. Order matters. +-- +-- @function set_stack_colors +-- @param graph The graph. +-- @param stack_colors A table with stacking colors. + +local properties = { "width", "height", "border_color", "stack", + "stack_colors", "color", "background_color", + "max_value", "scale" } + +function graph.draw(_graph, _, cr, width, height) + local max_value = _graph._data.max_value + local values = _graph._data.values + + cr:set_line_width(1) + + -- Draw the background first + cr:set_source(color(_graph._data.background_color or "#000000aa")) + cr:paint() + + -- Account for the border width + cr:save() + if _graph._data.border_color then + cr:translate(1, 1) + width, height = width - 2, height - 2 + end + + -- Draw a stacked graph + if _graph._data.stack then + + if _graph._data.scale then + for _, v in ipairs(values) do + for _, sv in ipairs(v) do + if sv > max_value then + max_value = sv + end + end + end + end + + for i = 0, width do + local rel_i = 0 + local rel_x = i + 0.5 + + if _graph._data.stack_colors then + for idx, col in ipairs(_graph._data.stack_colors) do + local stack_values = values[idx] + if stack_values and i < #stack_values then + local value = stack_values[#stack_values - i] + rel_i + cr:move_to(rel_x, height * (1 - (rel_i / max_value))) + cr:line_to(rel_x, height * (1 - (value / max_value))) + cr:set_source(color(col or "#ff0000")) + cr:stroke() + rel_i = value + end + end + end + end + else + if _graph._data.scale then + for _, v in ipairs(values) do + if v > max_value then + max_value = v + end + end + end + + -- Draw the background on no value + if #values ~= 0 then + -- Draw reverse + for i = 0, #values - 1 do + local value = values[#values - i] + if value >= 0 then + value = value / max_value + cr:move_to(i + 0.5, height * (1 - value)) + cr:line_to(i + 0.5, height) + end + end + cr:set_source(color(_graph._data.color or "#ff0000")) + cr:stroke() + end + + end + + -- Undo the cr:translate() for the border + cr:restore() + + -- Draw the border last so that it overlaps already drawn values + if _graph._data.border_color then + -- We decremented these by two above + width, height = width + 2, height + 2 + + -- Draw the border + cr:rectangle(0.5, 0.5, width - 1, height - 1) + cr:set_source(color(_graph._data.border_color or "#ffffff")) + cr:stroke() + end +end + +function graph.fit(_graph) + return _graph._data.width, _graph._data.height +end + +--- Add a value to the graph +-- +-- @param value The value to be added to the graph +-- @param group The stack color group index. +function graph:add_value(value, group) + value = value or 0 + local values = self._data.values + local max_value = self._data.max_value + value = math.max(0, value) + if not self._data.scale then + value = math.min(max_value, value) + end + + if self._data.stack and group then + if not self._data.values[group] + or type(self._data.values[group]) ~= "table" + then + self._data.values[group] = {} + end + values = self._data.values[group] + end + table.insert(values, value) + + local border_width = 0 + if self._data.border_color then border_width = 2 end + + -- Ensure we never have more data than we can draw + while #values > self._data.width - border_width do + table.remove(values, 1) + end + + self:emit_signal("widget::redraw_needed") + return self +end + +--- Clear the graph. +function graph:clear() + self._data.values = {} + self:emit_signal("widget::redraw_needed") + return self +end + +--- Set the graph height. +-- @param height The height to set. +function graph:set_height(height) + if height >= 5 then + self._data.height = height + self:emit_signal("widget::layout_changed") + end + return self +end + +--- Set the graph width. +-- @param width The width to set. +function graph:set_width(width) + if width >= 5 then + self._data.width = width + self:emit_signal("widget::layout_changed") + end + return self +end + +-- Build properties function +for _, prop in ipairs(properties) do + if not graph["set_" .. prop] then + graph["set_" .. prop] = function(_graph, value) + if _graph._data[prop] ~= value then + _graph._data[prop] = value + _graph:emit_signal("widget::redraw_needed") + end + return _graph + end + end + if not graph["get_" .. prop] then + graph["get_" .. prop] = function(_graph) + return _graph._data[prop] + end + end +end + +--- Create a graph widget. +-- @param args Standard widget() arguments. You should add width and height +-- key to set graph geometry. +-- @return A graph widget. +function graph.new(args) + args = args or {} + + local width = args.width or 100 + local height = args.height or 20 + + if width < 5 or height < 5 then return end + + local _graph = base.make_widget() + + _graph._data = { width = width, height = height, values = {}, max_value = 1 } + + -- Set methods + _graph.add_value = graph["add_value"] + _graph.clear = graph["clear"] + _graph.draw = graph.draw + _graph.fit = graph.fit + + for _, prop in ipairs(properties) do + _graph["set_" .. prop] = graph["set_" .. prop] + _graph["get_" .. prop] = graph["get_" .. prop] + end + + return _graph +end + +function graph.mt:__call(...) + return graph.new(...) +end + +return setmetatable(graph, graph.mt) + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/lib/wibox/widget/init.lua b/lib/wibox/widget/init.lua index 63a9c660..4fc533cc 100644 --- a/lib/wibox/widget/init.lua +++ b/lib/wibox/widget/init.lua @@ -14,6 +14,7 @@ return setmetatable({ systray = require("wibox.widget.systray"); textclock = require("wibox.widget.textclock"); progressbar = require("wibox.widget.progressbar"); + graph = require("wibox.widget.graph"); }, {__call = function(_, args) return base.make_widget_declarative(args) end}) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From ac7ea4c70f34bdc6d124d104c185079fbfef3607 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 01:37:35 -0400 Subject: [PATCH 09/68] tests: Fix coverage data As the documentation generation insert increasingly large ammount of code into the lua files, the coverage data is getting less and less accurate. This try to fix this by only collecting such data after the `configure_file` calls are done. --- .travis.yml | 4 ++-- awesomeConfig.cmake | 10 ++++++++++ tests/examples/CMakeLists.txt | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f769b9b6..c9d81b13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -84,14 +84,14 @@ install: - travis_retry sudo luarocks install lua-discount # Instal luacov-coveralls for code coverage testing. - - if [ "$DO_COVERAGE" = "true" ]; then sudo luarocks install luacov-coveralls; fi + - if [ "$DO_COVERAGE" = "true" ]; then sudo luarocks install luacov-coveralls; else export DO_COVERAGE=0; fi # Determine custom version. - export AWESOME_VERSION="${TRAVIS_BRANCH}-g$(git rev-parse --short HEAD)" - 'if [ "$TRAVIS_PULL_REQUEST" != false ]; then AWESOME_VERSION="${AWESOME_VERSION}-PR${TRAVIS_PULL_REQUEST}"; fi' script: - - export CMAKE_ARGS="-DLUA_LIBRARY=${LUALIBRARY} -DLUA_INCLUDE_DIR=${LUAINCLUDE} -D OVERRIDE_VERSION=$AWESOME_VERSION" + - export CMAKE_ARGS="-DLUA_LIBRARY=${LUALIBRARY} -DLUA_INCLUDE_DIR=${LUAINCLUDE} -D OVERRIDE_VERSION=$AWESOME_VERSION -D DO_COVERAGE=${DO_COVERAGE}" - | if [ -n "$BUILD_IN_DIR" ]; then SOURCE_DIRECTORY="$PWD" diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake index 7f2fd5d1..a37d5710 100644 --- a/awesomeConfig.cmake +++ b/awesomeConfig.cmake @@ -346,4 +346,14 @@ foreach(file ${AWESOME_ADDITIONAL_FILES}) endforeach() #}}} +# The examples coverage need to be done again after the configure_file has +# inserted the additional code. Otherwise, the result will be off, rendering +# the coverage useless as a tool to track untested code. +if(GENERATE_DOC AND DO_COVERAGE) + message(STATUS "Running tests again with coverage") + set(USE_LCOV 1) + + include(tests/examples/CMakeLists.txt) +endif() + # vim: filetype=cmake:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80:foldmethod=marker diff --git a/tests/examples/CMakeLists.txt b/tests/examples/CMakeLists.txt index 0c40ede3..ab9511fa 100644 --- a/tests/examples/CMakeLists.txt +++ b/tests/examples/CMakeLists.txt @@ -144,11 +144,16 @@ function(run_test test_path namespace template escaped_content) get_filename_component(${test_path} TEST_FILE_NAME NAME) set(IMAGE_PATH "${IMAGE_DIR}/AUTOGEN${namespace}_${TEST_FILE_NAME}") + # Use the example testing as coverage source + if (USE_LCOV) + set(LCOV_PATH ${SOURCE_DIR}/.luacov) + endif() + # Execute the script, leave the image extension decision to the test # SVG is preferred, but PNG is better suited for some tests, like bitmap # patterns. execute_process( - COMMAND lua ${template} ${test_path} ${IMAGE_PATH} ${SOURCE_DIR}/.luacov + COMMAND lua ${template} ${test_path} ${IMAGE_PATH} ${LCOV_PATH} OUTPUT_VARIABLE TEST_OUTPUT ERROR_VARIABLE TEST_ERROR ) From fd3e27c38bab809f9f502e1fc19c3023f0ab5bfa Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 02:46:28 -0400 Subject: [PATCH 10/68] containers: Fix documentation local functions and metatable based constructors are not documented unless an explicit @function is added. Also add missing return values and fix formatting. --- lib/wibox/container/background.lua | 7 +++++-- lib/wibox/container/constraint.lua | 5 ++++- lib/wibox/container/margin.lua | 4 +++- lib/wibox/container/mirror.lua | 9 ++++++--- lib/wibox/container/rotate.lua | 5 ++++- lib/wibox/container/scroll.lua | 4 ++-- 6 files changed, 24 insertions(+), 10 deletions(-) diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua index a8286889..4942c787 100644 --- a/lib/wibox/container/background.lua +++ b/lib/wibox/container/background.lua @@ -193,11 +193,14 @@ function background:set_bgimage(image, ...) self:emit_signal("widget::redraw_needed") end ---- Returns a new background layout. A background layout applies a background --- and foreground color to another widget. +--- Returns a new background container. +-- +-- A background container 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 +-- @function wibox.container.background local function new(widget, bg, shape) local ret = base.make_widget() diff --git a/lib/wibox/container/constraint.lua b/lib/wibox/container/constraint.lua index deeec7f6..11fc82d1 100644 --- a/lib/wibox/container/constraint.lua +++ b/lib/wibox/container/constraint.lua @@ -101,7 +101,8 @@ function constraint:reset() self:set_widget(nil) end ---- Returns a new constraint layout. This layout will constraint the size of a +--- Returns a new constraint container. +-- This container 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 @@ -111,6 +112,8 @@ end -- '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. +-- @treturn table A new constraint container +-- @function wibox.container.constraint local function new(widget, strategy, width, height) local ret = base.make_widget() diff --git a/lib/wibox/container/margin.lua b/lib/wibox/container/margin.lua index 4f47c51d..8d7b9143 100644 --- a/lib/wibox/container/margin.lua +++ b/lib/wibox/container/margin.lua @@ -157,7 +157,7 @@ for _, v in pairs({ "left", "right", "top", "bottom" }) do end end ---- Returns a new margin layout. +--- Returns a new margin container. -- @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. @@ -165,6 +165,8 @@ end -- @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 +-- @treturn table A new margin container +-- @function wibox.container.margin local function new(widget, left, right, top, bottom, color, draw_empty) local ret = base.make_widget() diff --git a/lib/wibox/container/mirror.lua b/lib/wibox/container/mirror.lua index 7bacfaa2..7c419c29 100644 --- a/lib/wibox/container/mirror.lua +++ b/lib/wibox/container/mirror.lua @@ -95,12 +95,15 @@ 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. +--- Returns a new mirror container. +-- A mirror container 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. +-- @treturn table A new mirror container +-- @function wibox.container.mirror local function new(widget, reflection) local ret = base.make_widget() ret.horizontal = false diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua index fb3c434b..94665e96 100644 --- a/lib/wibox/container/rotate.lua +++ b/lib/wibox/container/rotate.lua @@ -108,11 +108,14 @@ function rotate:get_direction() return self.direction or "north" end ---- Returns a new rotate layout. A rotate layout rotates a given widget. Use +--- Returns a new rotate container. +-- A rotate container 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. +-- @treturn table A new rotate container. +-- @function wibox.container.rotate local function new(widget, dir) local ret = base.make_widget() diff --git a/lib/wibox/container/scroll.lua b/lib/wibox/container/scroll.lua index b7433d0a..c4a5f959 100644 --- a/lib/wibox/container/scroll.lua +++ b/lib/wibox/container/scroll.lua @@ -390,7 +390,7 @@ local function get_layout(dir, widget, fps, speed, extra_space, expand, max_size return ret end ---- Get a new horizontal scrolling layout. +--- Get a new horizontal scrolling container. -- @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 @@ -404,7 +404,7 @@ function scroll.horizontal(widget, fps, speed, extra_space, expand, max_size, st return get_layout("h", widget, fps, speed, extra_space, expand, max_size, step_function, space_for_scrolling) end ---- Get a new vertical scrolling layout. +--- Get a new vertical scrolling container. -- @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 From be23bf0f157f2a22fa63ce468fbb620090cea664 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 02:54:01 -0400 Subject: [PATCH 11/68] widget: Fix documentation --- lib/wibox/widget/graph.lua | 3 ++- lib/wibox/widget/imagebox.lua | 4 +++- lib/wibox/widget/progressbar.lua | 1 + lib/wibox/widget/systray.lua | 6 ++++++ lib/wibox/widget/textbox.lua | 6 +++++- 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/lib/wibox/widget/graph.lua b/lib/wibox/widget/graph.lua index 1ac6c547..ddc32b00 100644 --- a/lib/wibox/widget/graph.lua +++ b/lib/wibox/widget/graph.lua @@ -243,7 +243,8 @@ end --- Create a graph widget. -- @param args Standard widget() arguments. You should add width and height -- key to set graph geometry. --- @return A graph widget. +-- @return A new graph widget. +-- @function wibox.widget.graph function graph.new(args) args = args or {} diff --git a/lib/wibox/widget/imagebox.lua b/lib/wibox/widget/imagebox.lua index b617724c..bf63adb1 100644 --- a/lib/wibox/widget/imagebox.lua +++ b/lib/wibox/widget/imagebox.lua @@ -133,12 +133,14 @@ function imagebox:set_resize(allowed) self:emit_signal("widget::layout_changed") end ---- Returns a new imagebox +--- Returns a new imagebox. -- Any other arguments will be passed to the clip shape function -- @param image the image to display, may be nil -- @param resize_allowed If false, the image will be clipped, else it will be resized -- to fit into the available space. -- @param clip_shape A `gears.shape` compatible function +-- @treturn table A new `imagebox` +-- @function wibox.widget.imagebox local function new(image, resize_allowed, clip_shape) local ret = base.make_widget() diff --git a/lib/wibox/widget/progressbar.lua b/lib/wibox/widget/progressbar.lua index a73ac917..e96f9ace 100644 --- a/lib/wibox/widget/progressbar.lua +++ b/lib/wibox/widget/progressbar.lua @@ -199,6 +199,7 @@ end -- @param args Standard widget() arguments. You should add width and height -- key to set progressbar geometry. -- @return A progressbar widget. +-- @function wibox.widget.progressbar function progressbar.new(args) args = args or {} local width = args.width or 100 diff --git a/lib/wibox/widget/systray.lua b/lib/wibox/widget/systray.lua index 9a513204..b97e35ca 100644 --- a/lib/wibox/widget/systray.lua +++ b/lib/wibox/widget/systray.lua @@ -138,6 +138,12 @@ function systray:set_screen(s) end end +--- Create the systray widget. +-- Note that this widget can only exist once. +-- @tparam boolean revers Show in the opposite direction +-- @treturn table The new `systray` widget +-- @function wibox.widget.systray + local function new(revers) local ret = wbase.make_widget() diff --git a/lib/wibox/widget/textbox.lua b/lib/wibox/widget/textbox.lua index 89bcfc0c..4c38f61a 100644 --- a/lib/wibox/widget/textbox.lua +++ b/lib/wibox/widget/textbox.lua @@ -228,7 +228,11 @@ function textbox:set_font(font) self:emit_signal("widget::layout_changed") end --- Returns a new textbox +--- Create a new textbox. +-- @tparam[opt=""] string text The textbox content +-- @tparam[opt=false] boolean ignore_markup Ignore the pango/HTML markup +-- @treturn table A new textbox widget +-- @function wibox.widget.textbox local function new(text, ignore_markup) local ret = base.make_widget() From 9d0693ce3a8a5a75742898283b0a10802ba303ce Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 03:02:11 -0400 Subject: [PATCH 12/68] doc: Do not export draw, fit and layout methods They are used internally, users should never call them. This will make the API documentation cleaner. --- lib/wibox/container/constraint.lua | 4 ++-- lib/wibox/container/mirror.lua | 4 ++-- lib/wibox/container/rotate.lua | 4 ++-- lib/wibox/container/scroll.lua | 4 ++-- lib/wibox/layout/align.lua | 4 ++-- lib/wibox/widget/imagebox.lua | 4 ++-- lib/wibox/widget/textbox.lua | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/wibox/container/constraint.lua b/lib/wibox/container/constraint.lua index 11fc82d1..edc9d108 100644 --- a/lib/wibox/container/constraint.lua +++ b/lib/wibox/container/constraint.lua @@ -13,14 +13,14 @@ local math = math local constraint = { mt = {} } ---- Layout a constraint layout +-- 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 +-- Fit a constraint layout into the given space function constraint:fit(context, width, height) local w, h if self.widget then diff --git a/lib/wibox/container/mirror.lua b/lib/wibox/container/mirror.lua index 7c419c29..d9229050 100644 --- a/lib/wibox/container/mirror.lua +++ b/lib/wibox/container/mirror.lua @@ -15,7 +15,7 @@ local matrix = require("gears.matrix") local mirror = { mt = {} } ---- Layout this layout +-- Layout this layout function mirror:layout(_, width, height) if not self.widget then return end @@ -36,7 +36,7 @@ function mirror:layout(_, width, height) return { base.place_widget_via_matrix(self.widget, m, width, height) } end ---- Fit this layout into the given area +-- Fit this layout into the given area function mirror:fit(context, ...) if not self.widget then return 0, 0 diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua index 94665e96..5b0d9d32 100644 --- a/lib/wibox/container/rotate.lua +++ b/lib/wibox/container/rotate.lua @@ -24,7 +24,7 @@ local function transform(layout, width, height) return width, height end ---- Layout this layout +-- Layout this layout function rotate:layout(_, width, height) if not self.widget or not self.widget.visible then return @@ -49,7 +49,7 @@ function rotate:layout(_, width, height) return { base.place_widget_via_matrix(self.widget, m, transform(self, width, height)) } end ---- Fit this layout into the given area +-- Fit this layout into the given area function rotate:fit(context, width, height) if not self.widget then return 0, 0 diff --git a/lib/wibox/container/scroll.lua b/lib/wibox/container/scroll.lua index c4a5f959..38320f01 100644 --- a/lib/wibox/container/scroll.lua +++ b/lib/wibox/container/scroll.lua @@ -140,7 +140,7 @@ local function calculate_info(self, context, width, height) return result end ---- Draw this scrolling layout. +-- 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. @@ -170,7 +170,7 @@ function scroll:draw(context, cr, width, height) end end ---- Fit the scroll layout into the given space. +-- 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. diff --git a/lib/wibox/layout/align.lua b/lib/wibox/layout/align.lua index 258acb89..741d02bf 100644 --- a/lib/wibox/layout/align.lua +++ b/lib/wibox/layout/align.lua @@ -14,7 +14,7 @@ local base = require("wibox.widget.base") local align = {} ---- Calculate the layout of an align layout. +-- Calculate the layout of an align layout. -- @param context The context in which we are drawn. -- @param width The available width. -- @param height The available height. @@ -180,7 +180,7 @@ function align:set_children(children) self:set_third(children[3]) end ---- Fit the align layout into the given space. The align layout will +-- Fit the align layout into the given space. The align layout will -- ask for the sum of the sizes of its sub-widgets in its direction -- and the largest sized sub widget in the other direction. -- @param context The context in which we are fit. diff --git a/lib/wibox/widget/imagebox.lua b/lib/wibox/widget/imagebox.lua index bf63adb1..2137724c 100644 --- a/lib/wibox/widget/imagebox.lua +++ b/lib/wibox/widget/imagebox.lua @@ -15,7 +15,7 @@ local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility local imagebox = { mt = {} } ---- Draw an imagebox with the given cairo context in the given geometry. +-- Draw an imagebox with the given cairo context in the given geometry. function imagebox:draw(_, cr, width, height) if not self._image then return end if width == 0 or height == 0 then return end @@ -40,7 +40,7 @@ function imagebox:draw(_, cr, width, height) cr:paint() end ---- Fit the imagebox into the given geometry +-- Fit the imagebox into the given geometry function imagebox:fit(_, width, height) if not self._image then return 0, 0 diff --git a/lib/wibox/widget/textbox.lua b/lib/wibox/widget/textbox.lua index 4c38f61a..32e98f52 100644 --- a/lib/wibox/widget/textbox.lua +++ b/lib/wibox/widget/textbox.lua @@ -34,7 +34,7 @@ local function setup_layout(box, width, height, dpi) setup_dpi(box, dpi) end ---- Draw the given textbox on the given cairo context in the given geometry +-- Draw the given textbox on the given cairo context in the given geometry function textbox:draw(context, cr, width, height) setup_layout(self, width, height, context.dpi) cr:update_layout(self._layout) @@ -57,7 +57,7 @@ local function do_fit_return(self) return logical.width, logical.height end ---- Fit the given textbox +-- Fit the given textbox function textbox:fit(context, width, height) setup_layout(self, width, height, context.dpi) return do_fit_return(self) From 3c2aa09b8693f0b095902238f16b421bb9acfd50 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 03:13:15 -0400 Subject: [PATCH 13/68] doc: Document the beautiful vars used by the systray and textbox --- lib/wibox/widget/systray.lua | 8 ++++++++ lib/wibox/widget/textbox.lua | 3 +++ 2 files changed, 11 insertions(+) diff --git a/lib/wibox/widget/systray.lua b/lib/wibox/widget/systray.lua index b97e35ca..7bec8988 100644 --- a/lib/wibox/widget/systray.lua +++ b/lib/wibox/widget/systray.lua @@ -23,6 +23,14 @@ local base_size = nil local reverse = false local display_on_screen = "primary" +--- The systray background color. +-- @beautiful beautiful.bg_systray +-- @param string The color (string like "#ff0000" only) + +--- The systray icon spacing. +-- @beautiful beautiful.systray_icon_spacing +-- @tparam[opt=0] integer The icon spacing + local function should_display_on(s) if display_on_screen == "primary" then return s == capi.screen.primary diff --git a/lib/wibox/widget/textbox.lua b/lib/wibox/widget/textbox.lua index 32e98f52..ed4b35b0 100644 --- a/lib/wibox/widget/textbox.lua +++ b/lib/wibox/widget/textbox.lua @@ -18,6 +18,9 @@ local pairs = pairs local textbox = { mt = {} } +--- The textbox font. +-- @beautiful beautiful.font + --- Set the DPI of a Pango layout local function setup_dpi(box, dpi) if box.dpi ~= dpi then From bc2c0cfcb01dbc7e563937d4224a5e30a5f08a33 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 23 May 2016 03:43:25 -0400 Subject: [PATCH 14/68] doc: Add a wibox.container.rotate example Also fix the documentation --- lib/wibox/container/rotate.lua | 14 +++- .../examples/wibox/container/rotate/angle.lua | 66 +++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/examples/wibox/container/rotate/angle.lua diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua index 5b0d9d32..9e166f58 100644 --- a/lib/wibox/container/rotate.lua +++ b/lib/wibox/container/rotate.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- A container rotating the conained widget by 90 degrees. +-- -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ @@ -85,8 +87,16 @@ function rotate:reset() 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. +--- Set the direction of this rotating container. +-- Valid values are: +-- +-- * *north* +-- * *east* +-- * *south* +-- * *north* +-- +--@DOC_wibox_container_rotate_angle_EXAMPLE@ +-- @tparam string dir The direction function rotate:set_direction(dir) local allowed = { north = true, diff --git a/tests/examples/wibox/container/rotate/angle.lua b/tests/examples/wibox/container/rotate/angle.lua new file mode 100644 index 00000000..4fc8a063 --- /dev/null +++ b/tests/examples/wibox/container/rotate/angle.lua @@ -0,0 +1,66 @@ +local parent = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE +local gears = {shape = require("gears.shape")} --DOC_HIDE +local beautiful = require("beautiful") --DOC_HIDE + +local function create_arrow(text) --DOC_HIDE + return { --DOC_HIDE + { --DOC_HIDE + { --DOC_HIDE + text = text, --DOC_HIDE + align = "center", --DOC_HIDE + valign = "center", --DOC_HIDE + widget = wibox.widget.textbox, --DOC_HIDE + }, --DOC_HIDE + shape = gears.shape.arrow, --DOC_HIDE + bg = beautiful.bg_normal, --DOC_HIDE + shape_border_color = beautiful.border_color, --DOC_HIDE + shape_border_width = beautiful.border_width, --DOC_HIDE + widget = wibox.container.background --DOC_HIDE + }, --DOC_HIDE + strategy = 'exact', --DOC_HIDE + width = 70, --DOC_HIDE + height = 70, --DOC_HIDE + widget = wibox.container.constraint --DOC_HIDE + } --DOC_HIDE +end --DOC_HIDE + +local normal = create_arrow("Normal") + +local north = wibox.container { + create_arrow("North"), + + direction = "north", + widget = wibox.container.rotate +} + +local south = wibox.container { + create_arrow("South"), + + direction = "south", + widget = wibox.container.rotate +} + +local east = wibox.container { + create_arrow("East"), + + direction = "east", + widget = wibox.container.rotate +} + +local west = wibox.container { + create_arrow("West"), + + direction = "west", + widget = wibox.container.rotate +} + +parent : setup { --DOC_HIDE + normal, --DOC_HIDE + north, --DOC_HIDE + south, --DOC_HIDE + east, --DOC_HIDE + west, --DOC_HIDE + spacing = 10, --DOC_HIDE + layout = wibox.layout.fixed.horizontal --DOC_HIDE +} --DOC_HIDE From e57ae1789d491f25b28b72f523fb1c10f405311b Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 12:49:12 -0400 Subject: [PATCH 15/68] doc: Add a container default example template This will be implemented by each container and then grouped into a list by CMake and inserted in the widget system documentation. --- .../wibox/container/defaults/template.lua | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 tests/examples/wibox/container/defaults/template.lua diff --git a/tests/examples/wibox/container/defaults/template.lua b/tests/examples/wibox/container/defaults/template.lua new file mode 100644 index 00000000..71a2e876 --- /dev/null +++ b/tests/examples/wibox/container/defaults/template.lua @@ -0,0 +1,92 @@ +local file_path, image_path, luacovpath = ... + +-- Set the global shims +-- luacheck: globals awesome client tag drawin screen +awesome = require( "awesome" ) +client = require( "client" ) +tag = require( "tag" ) +drawin = require( "drawin" ) +screen = require( "screen" ) + +-- Force luacheck to be silent about setting those as unused globals +assert(awesome and client and tag) + +local beautiful = require( "beautiful" ) +local wibox = require( "wibox" ) +local surface = require( "gears.surface" ) +local shape = require( "gears.shape" ) + +-- If luacov is available, use it. Else, do nothing. +pcall(function() + require("luacov.runner")(luacovpath) +end) + +-- Let the test request a size and file format +local before, after = loadfile(file_path)() + +local container = wibox.widget { + { + { + { + before, + shape_border_color = beautiful.border_color, + shape_border_width = beautiful.border_width, + shape = shape.rounded_rect, + widget = wibox.container.background, + }, + strategy = 'exact', + width = 70, + height = 40, + widget = wibox.container.constraint + }, + { + { + { + text = " ", + widget = wibox.widget.textbox, + }, + bg = beautiful.bg_normal, + shape_border_color = beautiful.border_color, + shape_border_width = beautiful.border_width, + widget = wibox.container.background, + shape = shape.transform(shape.arrow) + : rotate_at(15,15,math.pi/2) + : translate(0,-8) + : scale(0.9, 0.9), + }, + strategy = 'exact', + width = 42, + height = 40, + widget = wibox.container.constraint + }, + { + { + after, + shape_border_color = beautiful.border_color, + shape_border_width = beautiful.border_width, + shape = shape.rounded_rect, + widget = wibox.container.background, + }, + strategy = 'exact', + width = 70, + height = 40, + widget = wibox.container.constraint + }, + layout = wibox.layout.align.horizontal + }, + margins = 10, + widget = wibox.container.margin, +} + +-- Emulate the event loop for 10 iterations +for _ = 1, 10 do + awesome:emit_signal("refresh") +end + +-- Get the example fallback size (the tests can return a size if the want) +local f_w, f_h = container:fit({dpi=96}, 9999, 9999) + +-- Save to the output file +local img = surface.widget_to_svg(container, image_path..".svg", f_w, f_h) +img:finish() + From ab0a9a077e347c0dcbe4b39cf2b604425fe73e0f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 12:51:08 -0400 Subject: [PATCH 16/68] doc: Add a `rotate` default screenshot --- lib/wibox/container/rotate.lua | 1 + .../wibox/container/defaults/rotate.lua | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/examples/wibox/container/defaults/rotate.lua diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua index 9e166f58..48e2a980 100644 --- a/lib/wibox/container/rotate.lua +++ b/lib/wibox/container/rotate.lua @@ -1,6 +1,7 @@ --------------------------------------------------------------------------- -- A container rotating the conained widget by 90 degrees. -- +--@DOC_wibox_container_defaults_rotate_EXAMPLE@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/container/defaults/rotate.lua b/tests/examples/wibox/container/defaults/rotate.lua new file mode 100644 index 00000000..13cf1002 --- /dev/null +++ b/tests/examples/wibox/container/defaults/rotate.lua @@ -0,0 +1,19 @@ +--DOC_HIDE_ALL +local wibox = require("wibox") + +return { + text = "Before", + align = "center", + valign = "center", + widget = wibox.widget.textbox, +}, +{ + { + text = "After", + align = "center", + valign = "center", + widget = wibox.widget.textbox, + }, + direction = "east", + widget = wibox.container.rotate +} From 46c83b400134cc76905b2ca1aced124317f4df49 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 13:34:25 -0400 Subject: [PATCH 17/68] doc: Add a `mirror` default screenshot --- lib/wibox/container/mirror.lua | 2 ++ .../wibox/container/defaults/mirror.lua | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/examples/wibox/container/defaults/mirror.lua diff --git a/lib/wibox/container/mirror.lua b/lib/wibox/container/mirror.lua index d9229050..975f57ca 100644 --- a/lib/wibox/container/mirror.lua +++ b/lib/wibox/container/mirror.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_container_defaults_mirror_EXAMPLE@ -- @author dodo -- @copyright 2012 dodo -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/container/defaults/mirror.lua b/tests/examples/wibox/container/defaults/mirror.lua new file mode 100644 index 00000000..e216c9b4 --- /dev/null +++ b/tests/examples/wibox/container/defaults/mirror.lua @@ -0,0 +1,19 @@ +--DOC_HIDE_ALL +local wibox = require("wibox") + +return { + text = "Before", + align = "center", + valign = "center", + widget = wibox.widget.textbox, +}, +{ + { + text = "After", + align = "center", + valign = "center", + widget = wibox.widget.textbox, + }, + reflection = {horizontal = true}, + widget = wibox.container.mirror +} From de7ae79c6c6045bc56db2a58968e056039bc9bb0 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 13:38:37 -0400 Subject: [PATCH 18/68] doc: Add a `background` default screenshot --- lib/wibox/container/background.lua | 2 ++ .../wibox/container/defaults/background.lua | 24 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/examples/wibox/container/defaults/background.lua diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua index 4942c787..c9609724 100644 --- a/lib/wibox/container/background.lua +++ b/lib/wibox/container/background.lua @@ -1,6 +1,8 @@ --------------------------------------------------------------------------- -- A container capable of changing the background color, foreground color -- widget shape. +-- +--@DOC_wibox_container_defaults_background_EXAMPLE@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/container/defaults/background.lua b/tests/examples/wibox/container/defaults/background.lua new file mode 100644 index 00000000..0ce04141 --- /dev/null +++ b/tests/examples/wibox/container/defaults/background.lua @@ -0,0 +1,24 @@ +--DOC_HIDE_ALL +local wibox = require("wibox") +local gears = {shape = require("gears.shape")} +local beautiful = require("beautiful") + +return { + text = "Before", + align = "center", + valign = "center", + widget = wibox.widget.textbox, +}, +{ + { + text = "After", + align = "center", + valign = "center", + widget = wibox.widget.textbox, + }, + shape = gears.shape.circle, + shape_border_width = 5, + shape_border_color = "#ff0000", + bg = beautiful.bg_highlight, + widget = wibox.container.background +} From 26cf28b23b51bfd2064c5611749b401a0f7a3659 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 13:53:21 -0400 Subject: [PATCH 19/68] doc: Add a `constraint` default screenshot --- lib/wibox/container/constraint.lua | 2 ++ .../wibox/container/defaults/constraint.lua | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 tests/examples/wibox/container/defaults/constraint.lua diff --git a/lib/wibox/container/constraint.lua b/lib/wibox/container/constraint.lua index edc9d108..4e8a976d 100644 --- a/lib/wibox/container/constraint.lua +++ b/lib/wibox/container/constraint.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_container_defaults_constraint_EXAMPLE@ -- @author Lukáš Hrázký -- @copyright 2012 Lukáš Hrázký -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/container/defaults/constraint.lua b/tests/examples/wibox/container/defaults/constraint.lua new file mode 100644 index 00000000..1d4fcb88 --- /dev/null +++ b/tests/examples/wibox/container/defaults/constraint.lua @@ -0,0 +1,27 @@ +--DOC_HIDE_ALL +local wibox = require("wibox") + +return { + text = "Some long text", + align = "center", + valign = "center", + widget = wibox.widget.textbox, +}, +{ + { + { + { + text = "Some long text", + align = "center", + valign = "center", + widget = wibox.widget.textbox, + }, + strategy = "max", + height = 8, + width = 50, + widget = wibox.container.constraint + }, + layout = wibox.layout.fixed.horizontal, + }, + layout = wibox.layout.fixed.vertical, +} From 47a471072a9268f2439fa7a3e835e55fa9530787 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 14:13:47 -0400 Subject: [PATCH 20/68] doc: Add a `margin` default screenshot --- lib/wibox/container/margin.lua | 2 + .../wibox/container/defaults/margin.lua | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/examples/wibox/container/defaults/margin.lua diff --git a/lib/wibox/container/margin.lua b/lib/wibox/container/margin.lua index 8d7b9143..70924007 100644 --- a/lib/wibox/container/margin.lua +++ b/lib/wibox/container/margin.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_container_defaults_margin_EXAMPLE@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/container/defaults/margin.lua b/tests/examples/wibox/container/defaults/margin.lua new file mode 100644 index 00000000..49505b07 --- /dev/null +++ b/tests/examples/wibox/container/defaults/margin.lua @@ -0,0 +1,54 @@ +--DOC_HIDE_ALL +local wibox = require("wibox") +local beautiful = require("beautiful") + +return { + nil, + { + nil, + { + { + text = "Before", + align = "center", + valign = "center", + widget = wibox.widget.textbox, + }, + bg = beautiful.bg_highlight, + widget = wibox.container.background + }, + nil, + expand = "none", + layout = wibox.layout.align.horizontal, + }, + nil, + expand = "none", + layout = wibox.layout.align.vertical, +}, +{ + nil, + { + nil, + { + { + { + text = "After", + align = "center", + valign = "center", + widget = wibox.widget.textbox, + }, + bg = beautiful.bg_highlight, + widget = wibox.container.background + }, + top = 5, + left = 20, + color = "#ff0000", + widget = wibox.container.margin, + }, + nil, + expand = "none", + layout = wibox.layout.align.horizontal, + }, + nil, + expand = "none", + layout = wibox.layout.align.vertical, +} From 490306a5fc006f8ced245e9fc049c52ffa0e088e Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 15:19:50 -0400 Subject: [PATCH 21/68] shape: Add default rounded_rect radius Add an arbitrary value to avoid all caller setting extra arguments. --- lib/gears/shape.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/gears/shape.lua b/lib/gears/shape.lua index a7de80c4..af1cd566 100644 --- a/lib/gears/shape.lua +++ b/lib/gears/shape.lua @@ -35,6 +35,8 @@ local module = {} -- @tparam number height The rectangle height -- @tparam number radius the corner radius function module.rounded_rect(cr, width, height, radius) + radius = radius or 10 + if width / 2 < radius then radius = width / 2 end From f1ea1c04dd55ad6763c7b673058e8e67028b2924 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 15:01:31 -0400 Subject: [PATCH 22/68] doc: Add a layout demonnstration template. Draw rectangle with optional text placed by the layout --- tests/examples/wibox/layout/template.lua | 62 ++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tests/examples/wibox/layout/template.lua diff --git a/tests/examples/wibox/layout/template.lua b/tests/examples/wibox/layout/template.lua new file mode 100644 index 00000000..567cdfb9 --- /dev/null +++ b/tests/examples/wibox/layout/template.lua @@ -0,0 +1,62 @@ +local file_path, image_path, luacovpath = ... + +-- Set the global shims +-- luacheck: globals awesome client tag drawin screen +awesome = require( "awesome" ) +client = require( "client" ) +tag = require( "tag" ) +drawin = require( "drawin" ) +screen = require( "screen" ) + +-- Force luacheck to be silent about setting those as unused globals +assert(awesome and client and tag) + +local wibox = require( "wibox" ) +local surface = require( "gears.surface" ) +local color = require( "gears.color" ) +local beautiful = require( "beautiful" ) + +-- If luacov is available, use it. Else, do nothing. +pcall(function() + require("luacov.runner")(luacovpath) +end) + +-- Create a generic rectangle widget to show layout disposition +local function generic_widget(text) + return { + { + { + draw = function(_, _, cr, width, height) + cr:set_source(color(beautiful.bg_normal)) + cr:set_line_width(3) + cr:rectangle(0, 0, width, height) + cr:fill_preserve() + cr:set_source(color(beautiful.border_color)) + cr:stroke() + end, + widget = wibox.widget.base.make_widget + }, + text and { + align = "center", + valign = "center", + text = text, + widget = wibox.widget.textbox + } or nil, + widget = wibox.layout.stack + }, + margins = 5, + widget = wibox.container.margin, + } +end + +-- Let the test request a size and file format +local widget, w, h = loadfile(file_path)(generic_widget) + +-- Emulate the event loop for 10 iterations +for _ = 1, 10 do + awesome:emit_signal("refresh") +end + +-- Save to the output file +local img = surface["widget_to_svg"](widget, image_path..".svg", w or 200, h or 30) +img:finish() From 5ba7af2be20b49c10dc50260f29b099d6e19306f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 15:02:54 -0400 Subject: [PATCH 23/68] doc: Add an align layout default screenshot --- lib/wibox/layout/align.lua | 2 ++ tests/examples/wibox/layout/defaults/align.lua | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/examples/wibox/layout/defaults/align.lua diff --git a/lib/wibox/layout/align.lua b/lib/wibox/layout/align.lua index 741d02bf..642db2a4 100644 --- a/lib/wibox/layout/align.lua +++ b/lib/wibox/layout/align.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_layout_defaults_align_EXAMPLE@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/layout/defaults/align.lua b/tests/examples/wibox/layout/defaults/align.lua new file mode 100644 index 00000000..236b5cac --- /dev/null +++ b/tests/examples/wibox/layout/defaults/align.lua @@ -0,0 +1,10 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +return --DOC_HIDE +wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + layout = wibox.layout.align.horizontal +} From 150026690cb81c44bfdd972a768c1d5dc19a88c4 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 15:17:16 -0400 Subject: [PATCH 24/68] doc: Add a fixed layout default screenshot --- lib/wibox/layout/fixed.lua | 2 ++ tests/examples/wibox/layout/defaults/fixed.lua | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/examples/wibox/layout/defaults/fixed.lua diff --git a/lib/wibox/layout/fixed.lua b/lib/wibox/layout/fixed.lua index ed3758eb..57728b58 100644 --- a/lib/wibox/layout/fixed.lua +++ b/lib/wibox/layout/fixed.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_layout_defaults_fixed_EXAMPLE@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/layout/defaults/fixed.lua b/tests/examples/wibox/layout/defaults/fixed.lua new file mode 100644 index 00000000..0b6f1f82 --- /dev/null +++ b/tests/examples/wibox/layout/defaults/fixed.lua @@ -0,0 +1,10 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +return --DOC_HIDE +wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + layout = wibox.layout.fixed.horizontal +} From 7fa56cb94c03f60bb96f9bd17b41a87d267580e9 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 15:19:18 -0400 Subject: [PATCH 25/68] doc: Add a flex layout default screenshot --- lib/wibox/layout/flex.lua | 2 ++ tests/examples/wibox/layout/defaults/flex.lua | 10 ++++++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/examples/wibox/layout/defaults/flex.lua diff --git a/lib/wibox/layout/flex.lua b/lib/wibox/layout/flex.lua index aa932292..cef6b99e 100644 --- a/lib/wibox/layout/flex.lua +++ b/lib/wibox/layout/flex.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_layout_defaults_flex_EXAMPLE@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/layout/defaults/flex.lua b/tests/examples/wibox/layout/defaults/flex.lua new file mode 100644 index 00000000..81d59cd5 --- /dev/null +++ b/tests/examples/wibox/layout/defaults/flex.lua @@ -0,0 +1,10 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +return --DOC_HIDE +wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + layout = wibox.layout.flex.horizontal +} From 163748c7820963a959e98a6cda3d813de7e27669 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 15:23:51 -0400 Subject: [PATCH 26/68] doc: Add a ratio layout default screenshot --- lib/wibox/layout/ratio.lua | 2 ++ tests/examples/wibox/layout/defaults/ratio.lua | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/examples/wibox/layout/defaults/ratio.lua diff --git a/lib/wibox/layout/ratio.lua b/lib/wibox/layout/ratio.lua index 9cfee1c3..98c5132f 100644 --- a/lib/wibox/layout/ratio.lua +++ b/lib/wibox/layout/ratio.lua @@ -2,6 +2,8 @@ --- A layout filling all the available space. Each widget is assigned a -- ratio (percentage) of the total space. Multiple methods are available to -- ajust this ratio. +-- +--@DOC_wibox_layout_defaults_ratio_EXAMPLE@ -- @author Emmanuel Lepage Vallee -- @copyright 2016 Emmanuel Lepage Vallee -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/layout/defaults/ratio.lua b/tests/examples/wibox/layout/defaults/ratio.lua new file mode 100644 index 00000000..149109a0 --- /dev/null +++ b/tests/examples/wibox/layout/defaults/ratio.lua @@ -0,0 +1,13 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +local w = wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + layout = wibox.layout.ratio.horizontal +} + +w:ajust_ratio(2, 0.44, 0.33, 0.22) + +return w --DOC_HIDE From ab40a342afea16b8b09d12130d97b623cdf9b900 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 15:27:11 -0400 Subject: [PATCH 27/68] doc: Add a stack layout default screenshot --- lib/wibox/layout/stack.lua | 1 + tests/examples/wibox/layout/defaults/stack.lua | 10 ++++++++++ 2 files changed, 11 insertions(+) create mode 100644 tests/examples/wibox/layout/defaults/stack.lua diff --git a/lib/wibox/layout/stack.lua b/lib/wibox/layout/stack.lua index 47c34f1b..a7020a62 100644 --- a/lib/wibox/layout/stack.lua +++ b/lib/wibox/layout/stack.lua @@ -8,6 +8,7 @@ -- The indices are going from 1 (the bottom of the stack) up to the top of -- the stack. The order can be changed either using `:swap` or `:raise`. -- +--@DOC_wibox_layout_defaults_stack_EXAMPLE@ -- @author Emmanuel Lepage Vallee -- @copyright 2016 Emmanuel Lepage Vallee -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/layout/defaults/stack.lua b/tests/examples/wibox/layout/defaults/stack.lua new file mode 100644 index 00000000..82887482 --- /dev/null +++ b/tests/examples/wibox/layout/defaults/stack.lua @@ -0,0 +1,10 @@ +local generic_widget = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +return --DOC_HIDE +wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + layout = wibox.layout.stack +} From de2d6fb521d397bc21391c30b4507527fc0d2da0 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 24 May 2016 15:09:10 -0400 Subject: [PATCH 28/68] doc: Add a system to auto-generate widgets list This system allow containers, widgets and layouts to be listed in the documentation with an example screenshot. It uses raw HTML due to ldoc limitations, but as it is autogenerated, it wont be user visible. --- awesomeConfig.cmake | 5 +++- docs/03-declarative-layout.md | 44 ++++++++++++++++++++++++++------ docs/widget_lists.cmake | 48 +++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 9 deletions(-) create mode 100644 docs/widget_lists.cmake diff --git a/awesomeConfig.cmake b/awesomeConfig.cmake index a37d5710..0bf2ad46 100644 --- a/awesomeConfig.cmake +++ b/awesomeConfig.cmake @@ -304,6 +304,9 @@ if(GENERATE_DOC) # The file is a valid CMakeLists.txt and can be executed directly if only # the image artefacts are needed. include(tests/examples/CMakeLists.txt) + + # Generate the widget lists + include(docs/widget_lists.cmake) endif() # {{{ Configure files @@ -342,7 +345,7 @@ set(AWESOME_ADDITIONAL_FILES foreach(file ${AWESOME_ADDITIONAL_FILES}) configure_file(${SOURCE_DIR}/${file} ${BUILD_DIR}/${file} - COPYONLY) + @ONLY) endforeach() #}}} diff --git a/docs/03-declarative-layout.md b/docs/03-declarative-layout.md index e29308a2..6c817617 100644 --- a/docs/03-declarative-layout.md +++ b/docs/03-declarative-layout.md @@ -3,7 +3,35 @@ This system provide an alternative to the system used in Awesome 3.5 and is inspired by the one once used by Awesome 3.2-3.4 and Qt QML system. -## A simple layout +## The default widgets + +### Widgets + +Awesome provide 2 collections of widgets: + + * `wibox.widget`: Generic widgets, containers and layouts + * `awful.widget`: The Awesome specific widgets + + +@DOC_widget_WIDGET_LIST@ + +### Containers + +Containers are widget wrapping another widget. It can be used to add decorations +or to modify the content of the child widget. + +@DOC_container_WIDGET_LIST@ + +### Layouts + +Layouts are collection of children widgets. They place them according to rules +and usually provide some options. + +@DOC_layout_WIDGET_LIST@ + +## Placing widgets + +### A simple layout * Display `my_first_widget` only on screen one * Add a background color to `my_third_widget` @@ -29,7 +57,7 @@ logic expression can be used as long as it return a valid widget, or a declarative layout, or `nil`. -## Define widgets inline and place them +### Define widgets inline and place them * Create a `wibox.widget.textbox` with various properties * Force the textbox size using `wibox.layout.constraint` @@ -78,7 +106,7 @@ Result: ![Example2 screenshot](../images/widgetlayout1.png) -## Use an `wibox.layout.align` layout +### Use an `wibox.layout.align` layout The `wibox.layout.align` is a little different. While most layouts will ignore any `nil` lines, the `align` layout rely on them so `left`, `middle` and `right` can be defined @@ -94,7 +122,7 @@ Code: -## Define new widgets +### Define new widgets New trivial widgets can be created directly in the layout declaration. Here is a simple circle widget: @@ -126,7 +154,7 @@ For more information about how to draw widgets, refer to the `Cairo` api: * [Pango text](https://developer.gnome.org/pango/stable/) -## Externally defined widgets and layouts +### Externally defined widgets and layouts This is useful when the widget is provided by an external module or when it requires complex manipulations which would make the declaration unreadable. @@ -146,7 +174,7 @@ Code: -## Accessing widgets +### Accessing widgets For each widget or container, it is possible to add an `identifier` attribute so the widget can be accessed later. @@ -188,7 +216,7 @@ Code: -## Extending the system +### Extending the system This system is very flexible. Each section attribute (the entries with string keys) is directly linked to the layout or widget API. When setting the @@ -221,7 +249,7 @@ used directly in the layout declaration. This example will update the textbox every 3 seconds to show the CPU usage. -## Handling sections +### Handling sections The system allows sections to be defined externally, then composed into the final layout declaration. Here is an example re-using one of the above diff --git a/docs/widget_lists.cmake b/docs/widget_lists.cmake new file mode 100644 index 00000000..b5270376 --- /dev/null +++ b/docs/widget_lists.cmake @@ -0,0 +1,48 @@ +# This file gather the different default example screenshots and create an HTML +# table. Those tables are re-used in the official documentation. + +# Ldoc wont parse the HTML content and discount tables are disabled, so here is +# some raw HTML +function(add_to_table name namespace group current_table new_table) + + set(${new_table} "${current_table}\n\ +\n\ + + ${namespace}${name} + \n\ + \n\ +\n\ +" PARENT_SCOPE) +endfunction() + +# Use the generated "defaults" images to build a list +function(generate_widget_list name) + file(GLOB ex_files RELATIVE "${SOURCE_DIR}/tests/examples/wibox/${name}/defaults" + "${SOURCE_DIR}/tests/examples/wibox/${name}/defaults/*") + + # Add the table header + set(MY_LIST "\n\ + \n\ + \n\ + \n\ + " + ) + + # Loop all examples (and assume an image exist for them) + foreach(ex_file_name ${ex_files}) + string(REGEX REPLACE "\\.lua" "" ex_file_name ${ex_file_name}) + + if(NOT ${ex_file_name} STREQUAL "template") + add_to_table(${ex_file_name} "wibox.${name}." "${name}" "${MY_LIST}" MY_LIST) + endif() + endforeach() + + # Add the table footer + set(MY_LIST "${MY_LIST}
NameExample
\n\n") + + set(DOC_${name}_WIDGET_LIST ${MY_LIST} PARENT_SCOPE) +endfunction() + +generate_widget_list( "container" ) +generate_widget_list( "layout" ) +generate_widget_list( "widget" ) From ec2cfc7be2e3ff017de3a034bed19806338f7fc4 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 16:37:04 -0400 Subject: [PATCH 29/68] doc: Add a textbox widget default screenshot --- lib/wibox/widget/textbox.lua | 2 ++ tests/examples/wibox/widget/defaults/textbox.lua | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/examples/wibox/widget/defaults/textbox.lua diff --git a/lib/wibox/widget/textbox.lua b/lib/wibox/widget/textbox.lua index ed4b35b0..3d783df6 100644 --- a/lib/wibox/widget/textbox.lua +++ b/lib/wibox/widget/textbox.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_widget_defaults_textbox_EXAMPLE@ -- @author Uli Schlachter -- @author dodo -- @copyright 2010, 2011 Uli Schlachter, dodo diff --git a/tests/examples/wibox/widget/defaults/textbox.lua b/tests/examples/wibox/widget/defaults/textbox.lua new file mode 100644 index 00000000..7de6f9d0 --- /dev/null +++ b/tests/examples/wibox/widget/defaults/textbox.lua @@ -0,0 +1,13 @@ +local parent = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +parent:add( --DOC_HIDE + +wibox.widget{ + markup = "This is a textbox!!!", + align = "center", + valign = "center", + widget = wibox.widget.textbox +} + +) --DOC_HIDE From f29eeed82e852c6722f625173e0be12b96c1aa6a Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 17:18:43 -0400 Subject: [PATCH 30/68] doc: Add a graph widget default screenshot --- lib/wibox/widget/graph.lua | 1 + .../examples/wibox/widget/defaults/graph.lua | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tests/examples/wibox/widget/defaults/graph.lua diff --git a/lib/wibox/widget/graph.lua b/lib/wibox/widget/graph.lua index ddc32b00..ac3672e3 100644 --- a/lib/wibox/widget/graph.lua +++ b/lib/wibox/widget/graph.lua @@ -1,6 +1,7 @@ --------------------------------------------------------------------------- --- A graph widget. -- +--@DOC_wibox_widget_defaults_graph_EXAMPLE@ -- @author Julien Danjou <julien@danjou.info> -- @copyright 2009 Julien Danjou -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/widget/defaults/graph.lua b/tests/examples/wibox/widget/defaults/graph.lua new file mode 100644 index 00000000..6ccd93b5 --- /dev/null +++ b/tests/examples/wibox/widget/defaults/graph.lua @@ -0,0 +1,22 @@ +local parent = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +local data = { --DOC_HIDE + 3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE + 3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE + 3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE + 3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE + 3, 5, 6,4, 11,15,19,29,17,17,14,0,0,3,1,0,0, 22, 17,7, 1,0,0,5, --DOC_HIDE +} --DOC_HIDE + +local w = --DOC_HIDE +wibox.widget { + max_value = 29, + widget = wibox.widget.graph +} + +parent:add( w ) --DOC_HIDE + +for _, v in ipairs(data) do --DOC_HIDE + w:add_value(v) --DOC_HIDE +end --DOC_HIDE From 83a9a9e67a16de6f8ed9493e13213b4d70596109 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 17:22:44 -0400 Subject: [PATCH 31/68] doc: Add a progressbar widget default screenshot --- lib/wibox/widget/progressbar.lua | 1 + tests/examples/wibox/widget/defaults/progressbar.lua | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 tests/examples/wibox/widget/defaults/progressbar.lua diff --git a/lib/wibox/widget/progressbar.lua b/lib/wibox/widget/progressbar.lua index e96f9ace..6e4b6ecf 100644 --- a/lib/wibox/widget/progressbar.lua +++ b/lib/wibox/widget/progressbar.lua @@ -1,6 +1,7 @@ --------------------------------------------------------------------------- --- A progressbar widget. -- +--@DOC_wibox_widget_defaults_progressbar_EXAMPLE@ -- @author Julien Danjou <julien@danjou.info> -- @copyright 2009 Julien Danjou -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/widget/defaults/progressbar.lua b/tests/examples/wibox/widget/defaults/progressbar.lua new file mode 100644 index 00000000..c82957ff --- /dev/null +++ b/tests/examples/wibox/widget/defaults/progressbar.lua @@ -0,0 +1,12 @@ +local parent = ... --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + +parent:add( --DOC_HIDE + +wibox.widget { + max_value = 1, + value = 0.33, + widget = wibox.widget.progressbar +} + +) --DOC_HIDE From 940a623c341e10c9a04d586fb386c8504af18586 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 17:56:10 -0400 Subject: [PATCH 32/68] shims: Add an awesome logo --- tests/examples/shims/beautiful.lua | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/examples/shims/beautiful.lua b/tests/examples/shims/beautiful.lua index 26349e97..85115ede 100644 --- a/tests/examples/shims/beautiful.lua +++ b/tests/examples/shims/beautiful.lua @@ -1,5 +1,29 @@ local lgi = require("lgi") local Pango = lgi.Pango +local cairo = lgi.cairo + +-- A simple Awesome logo +local function logo() + local img = cairo.ImageSurface.create(cairo.Format.ARGB32, 22, 22) + local cr = cairo.Context(img) + + -- Awesome default #555555 + cr:set_source_rgb(0.21568627451, 0.21568627451, 0.21568627451) + cr:paint() + + cr:set_source_rgb(1,1,1) + + cr:rectangle(0, 7, 15, 1) + cr:fill() + + cr:rectangle(15, 15, 1, 7) + cr:fill() + + cr:rectangle(8, 15, 7, 1) + cr:fill() + + return img +end -- Default theme for the documentation examples local module = { @@ -10,7 +34,9 @@ local module = { border_width = 1.5 , -- Fake resources handling - xresources = require("beautiful.xresources") + xresources = require("beautiful.xresources"), + + awesome_icon = logo() } local f = Pango.FontDescription.from_string("sans 8") From a8505ed019e3513c34d4e4b31148d926870cd7bf Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Wed, 25 May 2016 17:56:23 -0400 Subject: [PATCH 33/68] doc: Add an imagebox widget default screenshot --- lib/wibox/widget/imagebox.lua | 2 ++ tests/examples/wibox/widget/defaults/imagebox.lua | 13 +++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/examples/wibox/widget/defaults/imagebox.lua diff --git a/lib/wibox/widget/imagebox.lua b/lib/wibox/widget/imagebox.lua index 2137724c..61524061 100644 --- a/lib/wibox/widget/imagebox.lua +++ b/lib/wibox/widget/imagebox.lua @@ -1,4 +1,6 @@ --------------------------------------------------------------------------- +-- +--@DOC_wibox_widget_defaults_imagebox_EXAMPLE@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ diff --git a/tests/examples/wibox/widget/defaults/imagebox.lua b/tests/examples/wibox/widget/defaults/imagebox.lua new file mode 100644 index 00000000..9e995225 --- /dev/null +++ b/tests/examples/wibox/widget/defaults/imagebox.lua @@ -0,0 +1,13 @@ +local parent = ... --DOC_HIDE +local wibox = require( "wibox" ) --DOC_HIDE +local beautiful = require( "beautiful" ) --DOC_HIDE + +parent:add( --DOC_HIDE + +wibox.widget { + image = beautiful.awesome_icon, + resize = false, + widget = wibox.widget.imagebox +} + +) --DOC_HIDE From efcbda0a78844d53c867097d512968aa493033b1 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 00:42:07 -0400 Subject: [PATCH 34/68] widget.base: Add property support --- lib/wibox/widget/base.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index 900eb1f5..de5844c6 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -454,7 +454,7 @@ function base.make_widget_declarative(args) local w, id = drill(ids, args) - local mt = {} + local mt = getmetatable(w) or {} local orig_string = tostring(w) rawset(w, "_by_id", ids) @@ -474,9 +474,17 @@ end -- looks the same on the screen. -- @tparam[opt] string widget_name Name of the widget. If not set, it will be -- set automatically via `gears.object.modulename`. +-- @tparam[opt={}] table args Widget settings +-- @tparam[opt=false] boolean args.enable_properties Enable automatic getters and +-- setters calls. +-- @tparam[opt=nil] table args.class The widget class -- @see fit_widget -function base.make_widget(proxy, widget_name) - local ret = object() +function base.make_widget(proxy, widget_name, args) + args = args or {} + local ret = object { + enable_properties = args.enable_properties, + class = args.class, + } -- This signal is used by layouts to find out when they have to update. ret:add_signal("widget::layout_changed") @@ -547,7 +555,7 @@ function base.make_widget(proxy, widget_name) -- Add __tostring method to metatable. ret.widget_name = widget_name or object.modulename(3) - local mt = {} + local mt = getmetatable(ret) or {} local orig_string = tostring(ret) mt.__tostring = function() return string.format("%s (%s)", ret.widget_name, orig_string) From adb2f8838380c9dc6b81760071d44d6c06d8af4d Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 00:52:11 -0400 Subject: [PATCH 35/68] objects: Add a table for private elements Provide a standardized place for them rather than having each widgets use their own conventions. --- lib/wibox/widget/base.lua | 31 +++++++++++++++++++------------ spec/wibox/test_utils.lua | 5 +++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index de5844c6..7ce9ec95 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -143,12 +143,12 @@ local widget_dependencies = setmetatable({}, { __mode = "kv" }) -- Get the cache of the given kind for this widget. This returns a gears.cache -- that calls the callback of kind `kind` on the widget. local function get_cache(widget, kind) - if not widget._widget_caches[kind] then - widget._widget_caches[kind] = cache.new(function(...) + if not widget._private.widget_caches[kind] then + widget._private.widget_caches[kind] = cache.new(function(...) return protected_call(widget[kind], widget, ...) end) end - return widget._widget_caches[kind] + return widget._private.widget_caches[kind] end -- Special value to skip the dependency recording that is normally done by @@ -177,7 +177,7 @@ local clear_caches function clear_caches(widget) local deps = widget_dependencies[widget] or {} widget_dependencies[widget] = {} - widget._widget_caches = {} + widget._private.widget_caches = {} for w in pairs(deps) do clear_caches(w) end @@ -424,7 +424,11 @@ end -- Only available when the declarative system is used local function get_children_by_id(self, name) - return self._by_id[name] or {} + if rawget(self, "_private") then + return self._private.by_id[name] or {} + else + return rawget(self, "_by_id")[name] or {} + end end --- Set a declarative widget hierarchy description. @@ -503,6 +507,9 @@ function base.make_widget(proxy, widget_name, args) ret:emit_signal("widget::redraw_needed") end) + -- Create a table used to store the widgets internal data + rawset(ret, "_private", {}) + -- No buttons yet ret.widget_buttons = {} @@ -513,7 +520,7 @@ function base.make_widget(proxy, widget_name, args) ret.opacity = 1 -- Differentiate tables from widgets - ret.is_widget = true + rawset(ret, "is_widget", true) -- Size is not restricted/forced ret._forced_width = nil @@ -528,12 +535,12 @@ function base.make_widget(proxy, widget_name, args) end) if proxy then - ret.fit = function(_, context, width, height) + rawset(ret, "fit", function(_, context, width, height) return base.fit_widget(ret, context, proxy, width, height) - end - ret.layout = function(_, _, width, height) + end) + rawset(ret, "layout", function(_, _, width, height) return { base.place_widget_at(proxy, 0, 0, width, height) } - end + end) proxy:connect_signal("widget::layout_changed", function() ret:emit_signal("widget::layout_changed") end) @@ -550,11 +557,11 @@ function base.make_widget(proxy, widget_name, args) -- Add functions for k, v in pairs(base.widget) do - ret[k] = v + rawset(ret, k, v) end -- Add __tostring method to metatable. - ret.widget_name = widget_name or object.modulename(3) + rawset(ret, "widget_name", widget_name or object.modulename(3)) local mt = getmetatable(ret) or {} local orig_string = tostring(ret) mt.__tostring = function() diff --git a/spec/wibox/test_utils.lua b/spec/wibox/test_utils.lua index 04e6e0f1..47a1138a 100644 --- a/spec/wibox/test_utils.lua +++ b/spec/wibox/test_utils.lua @@ -82,11 +82,12 @@ assert:register("assertion", "widget_layout", widget_layout, "assertion.widget_l return { widget_stub = function(width, height) local w = object() + w._private = {} w:add_signal("widget::redraw_needed") w:add_signal("widget::layout_changed") w.is_widget = true - w.visible = true - w.opacity = 1 + w._private.visible = true + w._private.opacity = 1 if width or height then w.fit = function() return width or 10, height or 10 From f9e82c1f57ec43f579fe439fbffc52537be61416 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 01:18:20 -0400 Subject: [PATCH 36/68] background: Move all private attributes into _private So there is no collision when properties are enabled --- lib/wibox/container/background.lua | 82 +++++++++++++++--------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua index c9609724..3eb74f41 100644 --- a/lib/wibox/container/background.lua +++ b/lib/wibox/container/background.lua @@ -23,34 +23,34 @@ local background = { mt = {} } -- Draw this widget function background:draw(context, cr, width, height) - if not self.widget or not self.widget.visible then + if not self._private.widget or not self._private.widget.visible then return end -- Keep the shape path in case there is a border - self._path = nil + self._private.path = nil - if self._shape then + if self._private.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 + local offset = ((self._private.shape_border_width and self._private.shape_border_color) + and self._private.shape_border_width or 0) / 2 cr:translate(offset, offset) - self._shape(cr, width - 2*offset, height - 2*offset, unpack(self._shape_args or {})) + self._private.shape(cr, width - 2*offset, height - 2*offset, unpack(self._private.shape_args or {})) cr:translate(-offset, -offset) - self._path = cr:copy_path() + self._private.path = cr:copy_path() cr:clip() end - if self.background then - cr:set_source(self.background) + if self._private.background then + cr:set_source(self._private.background) cr:paint() end - if self.bgimage then - if type(self.bgimage) == "function" then - self.bgimage(context, cr, width, height,unpack(self.bgimage_args)) + if self._private.bgimage then + if type(self._private.bgimage) == "function" then + self._private.bgimage(context, cr, width, height,unpack(self._private.bgimage_args)) else - local pattern = cairo.Pattern.create_for_surface(self.bgimage) + local pattern = cairo.Pattern.create_for_surface(self._private.bgimage) cr:set_source(pattern) cr:paint() end @@ -61,43 +61,43 @@ 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)) + if self._private.path and self._private.shape_border_width and self._private.shape_border_width > 0 then + cr:append_path(self._private.path) + cr:set_source(color(self._private.shape_border_color or self._private.foreground or beautiful.fg_normal)) - cr:set_line_width(self._shape_border_width) + cr:set_line_width(self._private.shape_border_width) cr:stroke() - self._path = nil + self._private.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) + if self._private.foreground then + cr:set_source(self._private.foreground) end -- Clip the shape - if self._path and self._shape_clip then - cr:append_path(self._path) + if self._private.path and self._private.shape_clip then + cr:append_path(self._private.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) } + if self._private.widget then + return { base.place_widget_at(self._private.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 + if not self._private.widget then return 0, 0 end - return base.fit_widget(self, context, self.widget, width, height) + return base.fit_widget(self, context, self._private.widget, width, height) end --- Set the widget that is drawn on top of the background @@ -107,14 +107,14 @@ function background:set_widget(widget) if widget then base.check_widget(widget) end - self.widget = widget + self._private.widget = widget self:emit_signal("widget::layout_changed") end -- Get children element -- @treturn table The children function background:get_children() - return {self.widget} + return {self._private.widget} end -- Replace the layout children @@ -129,9 +129,9 @@ end -- @param bg A color string, pattern or gradient (see `gears.color`) function background:set_bg(bg) if bg then - self.background = color(bg) + self._private.background = color(bg) else - self.background = nil + self._private.background = nil end self:emit_signal("widget::redraw_needed") end @@ -141,9 +141,9 @@ end -- @param fg A color string, pattern or gradient (see `gears.color`) function background:set_fg(fg) if fg then - self.foreground = color(fg) + self._private.foreground = color(fg) else - self.foreground = nil + self._private.foreground = nil end self:emit_signal("widget::redraw_needed") end @@ -154,8 +154,8 @@ end --@DOC_wibox_container_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._private.shape = shape + self._private.shape_args = {...} self:emit_signal("widget::redraw_needed") end @@ -164,16 +164,16 @@ end -- 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._private.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 +-- @param[opt=self._private.foreground] fg The border color, pattern or gradient function background:set_shape_border_color(fg) - self._shape_border_color = fg + self._private.shape_border_color = fg self:emit_signal("widget::redraw_needed") end @@ -181,7 +181,7 @@ end --@DOC_wibox_container_background_clip_EXAMPLE@ -- @tparam boolean value If the shape clip is enable function background:set_shape_clip(value) - self._shape_clip = value + self._private.shape_clip = value self:emit_signal("widget::redraw_needed") end @@ -190,8 +190,8 @@ end -- 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._private.bgimage = type(image) == "function" and image or surface.load(image) + self._private.bgimage_args = {...} self:emit_signal("widget::redraw_needed") end @@ -212,7 +212,7 @@ local function new(widget, bg, shape) end end - ret._shape = shape + ret._private.shape = shape ret:set_widget(widget) ret:set_bg(bg) From c9dd32424f8310378e561377166e884c43f3a1fe Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 01:49:16 -0400 Subject: [PATCH 37/68] doc: Fix wibox.widget.base documentation It was set as `module` instead of `class` because ldoc was confused set shown the methods as functions and functions as methods. This commit set the explicit section so ldoc don't gress (wrongly) --- lib/wibox/widget/base.lua | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index 7ce9ec95..a177bad4 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -2,7 +2,7 @@ -- @author Uli Schlachter -- @copyright 2010 Uli Schlachter -- @release @AWESOME_VERSION@ --- @module wibox.widget.base +-- @classmod wibox.widget.base --------------------------------------------------------------------------- local object = require("gears.object") @@ -24,6 +24,7 @@ base.widget = {} --- Set/get a widget's buttons. -- @param _buttons The table of buttons that should bind to the widget. +-- @function buttons function base.widget:buttons(_buttons) if _buttons then self.widget_buttons = _buttons @@ -34,6 +35,7 @@ end --- Set a widget's visible property -- @tparam boolean b Wether the widget is visible at all +-- @function set_visible function base.widget:set_visible(b) if b ~= self.visible then self.visible = b @@ -46,6 +48,7 @@ end --- Set a widget's opacity -- @tparam number o The opacity to use (a number from 0 to 1). 0 is fully -- transparent while 1 is fully opaque. +-- @function set_opacity function base.widget:set_opacity(o) if o ~= self.opacity then self.opacity = o @@ -57,6 +60,7 @@ end -- @tparam number|nil s The width that the widget has. `nil` means to apply the -- default mechanism of calling the `:fit` method. A number overrides the result -- from `:fit`. +-- @function set_width function base.widget:set_width(s) if s ~= self._forced_width then self._forced_width = s @@ -68,6 +72,7 @@ end -- @tparam number|nil s The height that the widget has. `nil` means to apply the -- default mechanism of calling the `:fit` method. A number overrides the result -- from `:fit`. +-- @function set_height function base.widget:set_height(s) if s ~= self._forced_height then self._forced_height = s @@ -78,6 +83,7 @@ end --- Get all direct children widgets -- This method should be re-implemented by the relevant widgets -- @treturn table The children +-- @function get_children function base.widget:get_children() return {} end @@ -86,6 +92,7 @@ end -- The default implementation does nothing, this must be re-implemented by -- all layout and container widgets. -- @tparam table children A table composed of valid widgets +-- @function set_children function base.widget:set_children(children) -- luacheck: no unused -- Nothing on purpose end @@ -103,6 +110,7 @@ end -- Warning: This method it prone to stack overflow id the widget, or any of its -- children, contain (directly or indirectly) itself. -- @treturn table The children +-- @function get_all_children function base.widget:get_all_children() local ret = {} digg_children(ret, self) @@ -116,6 +124,7 @@ end -- @return The index -- @return The parent layout -- @return The path between "self" and "widget" +-- @function index function base.widget:index(widget, recursive, ...) local widgets = self:get_children() @@ -187,6 +196,7 @@ end --- Figure out the geometry in device coordinate space. This gives only tight -- bounds if no rotations by non-multiples of 90° are used. +-- @function wibox.widget.base.rect_to_device_geometry function base.rect_to_device_geometry(cr, x, y, width, height) return matrix.transform_rectangle(cr.matrix, x, y, width, height) end @@ -200,6 +210,7 @@ end -- @param width The available width for the widget -- @param height The available height for the widget -- @return The width and height that the widget wants to use +-- @function wibox.widget.base.fit_widget function base.fit_widget(parent, context, widget, width, height) record_dependency(parent, widget) @@ -244,6 +255,7 @@ end -- @param width The available width for the widget -- @param height The available height for the widget -- @return The result from the widget's `:layout` callback. +-- @function wibox.widget.base.layout_widget function base.layout_widget(parent, context, widget, width, height) record_dependency(parent, widget) @@ -262,6 +274,7 @@ end -- Handle a button event on a widget. This is used internally and should not be -- called directly. +-- @function wibox.widget.base.handle_button function base.handle_button(event, widget, x, y, button, modifiers, geometry) x = x or y -- luacheck: no unused local function is_any(mod) @@ -310,6 +323,7 @@ end -- @param height The height of the widget in its own coordinate system. That is, -- after applying the transformation matrix. -- @return An opaque object that can be returned from :layout() +-- @function wibox.widget.base.place_widget_via_matrix function base.place_widget_via_matrix(widget, mat, width, height) return { _widget = widget, @@ -329,6 +343,7 @@ end -- @param height The height of the widget in its own coordinate system. That is, -- after applying the transformation matrix. -- @return An opaque object that can be returned from :layout() +-- @function wibox.widget.base.place_widget_at function base.place_widget_at(widget, x, y, width, height) return base.place_widget_via_matrix(widget, matrix.create_translate(x, y), width, height) end @@ -434,6 +449,7 @@ end --- Set a declarative widget hierarchy description. -- See [The declarative layout system](../documentation/03-declarative-layout.md.html) -- @param args An array containing the widgets disposition +-- @function setup function base.widget:setup(args) local f,ids = self.set_widget or self.add or self.set_first,{} local w, id = drill(ids, args) @@ -449,6 +465,7 @@ end --- Create a widget from a declarative description -- See [The declarative layout system](../documentation/03-declarative-layout.md.html) -- @param args An array containing the widgets disposition +-- @function wibox.widget.base.make_widget_declarative function base.make_widget_declarative(args) local ids = {} @@ -483,6 +500,7 @@ end -- setters calls. -- @tparam[opt=nil] table args.class The widget class -- @see fit_widget +-- @function wibox.widget.base.make_widget function base.make_widget(proxy, widget_name, args) args = args or {} local ret = object { @@ -571,12 +589,14 @@ function base.make_widget(proxy, widget_name, args) end --- Generate an empty widget which takes no space and displays nothing +-- @function wibox.widget.base.empty_widget function base.empty_widget() return base.make_widget() end --- Do some sanity checking on widget. This function raises a lua error if -- widget is not a valid widget. +-- @function wibox.widget.base.check_widget function base.check_widget(widget) assert(type(widget) == "table", "Type should be table, but is " .. tostring(type(widget))) assert(widget.is_widget, "Argument is not a widget!") From 8d9e7aacce1b2228c26ed8c4904a32e37cc93f6e Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 01:59:20 -0400 Subject: [PATCH 38/68] doc: Add a default widget documentation. This will avoid copy/pasting. This assume the widget use the property system. --- docs/common/widget.ldoc | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 docs/common/widget.ldoc diff --git a/docs/common/widget.ldoc b/docs/common/widget.ldoc new file mode 100644 index 00000000..f76c7844 --- /dev/null +++ b/docs/common/widget.ldoc @@ -0,0 +1,41 @@ + +--- Get a widex index. +-- @param widget The widget to look for +-- @param[opt] recursive Also check sub-widgets +-- @param[opt] ... Aditional widgets to add at the end of the "path" +-- @return The index +-- @return The parent layout +-- @return The path between "self" and "widget" +-- @function index + +--- Get all direct and indirect children widgets. +-- This will scan all containers recursively to find widgets +-- Warning: This method it prone to stack overflow id the widget, or any of its +-- children, contain (directly or indirectly) itself. +-- @treturn table The children +-- @function get_all_children + +--- Set a declarative widget hierarchy description. +-- See [The declarative layout system](../documentation/03-declarative-layout.md.html) +-- @param args An array containing the widgets disposition +-- @function setup + +--- Force a widget height. +-- @property forced_height +-- @tparam number|nil height The height (`nil` for automatic) + +--- Force a widget width. +-- @property forced_width +-- @tparam number|nil width The width (`nil` for automatic) + +--- The widget opacity (transparency). +-- @property opacity +-- @tparam[opt=1] number opacity The opacity (between 0 and 1) + +--- The widget visibility. +-- @property visible +-- @param boolean + +--- Set/get a widget's buttons. +-- @param _buttons The table of buttons that should bind to the widget. +-- @function buttons From eb79b3262d2ff6d5589cea4eff7d713a3accfd07 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 02:09:18 -0400 Subject: [PATCH 39/68] background: Enable the property system --- lib/wibox/container/background.lua | 86 ++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua index 3eb74f41..da1d64f6 100644 --- a/lib/wibox/container/background.lua +++ b/lib/wibox/container/background.lua @@ -15,7 +15,6 @@ 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) @@ -100,9 +99,11 @@ function background:fit(context, width, height) return base.fit_widget(self, context, self._private.widget, width, height) end ---- Set the widget that is drawn on top of the background +--- The widget displayed in the background widget. +-- @property widget -- @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) @@ -111,6 +112,10 @@ function background:set_widget(widget) self:emit_signal("widget::layout_changed") end +function background:get_widget() + return self._private.widget +end + -- Get children element -- @treturn table The children function background:get_children() @@ -124,9 +129,12 @@ function background:set_children(children) self:set_widget(children[1]) end ---- Set the background to use. +--- The background color/pattern/gradient to use. --@DOC_wibox_container_background_bg_EXAMPLE@ --- @param bg A color string, pattern or gradient (see `gears.color`) +-- @property bg +-- @param bg A color string, pattern or gradient +-- @see gears.color + function background:set_bg(bg) if bg then self._private.background = color(bg) @@ -136,9 +144,16 @@ function background:set_bg(bg) self:emit_signal("widget::redraw_needed") end ---- Set the foreground to use. +function background:get_bg() + return self._private.background +end + +--- The foreground (text) color/pattern/gradient to use. --@DOC_wibox_container_background_fg_EXAMPLE@ --- @param fg A color string, pattern or gradient (see `gears.color`) +-- @property fg +-- @param fg A color string, pattern or gradient +-- @see gears.color + function background:set_fg(fg) if fg then self._private.foreground = color(fg) @@ -148,53 +163,98 @@ function background:set_fg(fg) self:emit_signal("widget::redraw_needed") end +function background:get_fg() + return self._private.foreground +end + +--- The background shape. +-- +-- Use `set_shape` to set additional shape paramaters. +-- +--@DOC_wibox_container_background_shape_EXAMPLE@ +-- @property shape +-- @param shape A function taking a context, width and height as arguments +-- @see gears.shape +-- @see set_shape + --- Set the background shape. -- -- Any other arguments will be passed to the shape function ---@DOC_wibox_container_background_shape_EXAMPLE@ -- @param shape A function taking a context, width and height as arguments +-- @see gears.shape +-- @see shape function background:set_shape(shape, ...) self._private.shape = shape self._private.shape_args = {...} self:emit_signal("widget::redraw_needed") end +function background:get_shape() + return self._private.shape +end + --- When a `shape` is set, also draw a border. -- --- See `wibox.container.background.set_shape` for an usage example. +-- See `wibox.container.background.shape` for an usage example. +-- @property shape_border_width -- @tparam number width The border width + function background:set_shape_border_width(width) self._private.shape_border_width = width self:emit_signal("widget::redraw_needed") end +function background:get_shape_border_width() + return self._private.shape_border_width +end + --- When a `shape` is set, also draw a border. -- --- See `wibox.container.background.set_shape` for an usage example. +-- See `wibox.container.background.shape` for an usage example. +-- @property shape_border_color -- @param[opt=self._private.foreground] fg The border color, pattern or gradient +-- @see gears.color + function background:set_shape_border_color(fg) self._private.shape_border_color = fg self:emit_signal("widget::redraw_needed") end +function background:get_shape_border_color() + return self._private.shape_border_color +end + --- When a `shape` is set, make sure nothing is drawn outside of it. --@DOC_wibox_container_background_clip_EXAMPLE@ +-- @property shape_clip -- @tparam boolean value If the shape clip is enable + function background:set_shape_clip(value) self._private.shape_clip = value self:emit_signal("widget::redraw_needed") end ---- Set the background image to use +function background:get_shape_clip() + return self._private.shape_clip or false +end + +--- 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. +-- @property bgimage -- @param image A background image or a function +-- @see gears.surface + function background:set_bgimage(image, ...) self._private.bgimage = type(image) == "function" and image or surface.load(image) self._private.bgimage_args = {...} self:emit_signal("widget::redraw_needed") end +function background:get_bgimage() + return self._private.bgimage +end + --- Returns a new background container. -- -- A background container applies a background and foreground color @@ -204,7 +264,9 @@ end -- @param[opt] shape A `gears.shape` compatible shape function -- @function wibox.container.background local function new(widget, bg, shape) - local ret = base.make_widget() + local ret = base.make_widget(nil, nil, { + enable_properties = true, + }) for k, v in pairs(background) do if type(v) == "function" then @@ -224,6 +286,8 @@ function background.mt:__call(...) return new(...) end +--@DOC_widget_COMMON@ + return setmetatable(background, background.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 542070205f34b82c3eb57e178589d63d5be32f5b Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 13:57:34 -0400 Subject: [PATCH 40/68] widget: Add proper accessors for the 'opacity' property To avoid collision with the property system and comply with the API guidelines. --- lib/wibox/hierarchy.lua | 2 +- lib/wibox/widget/base.lua | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/wibox/hierarchy.lua b/lib/wibox/hierarchy.lua index 5e6abc47..bbf961af 100644 --- a/lib/wibox/hierarchy.lua +++ b/lib/wibox/hierarchy.lua @@ -272,7 +272,7 @@ function hierarchy:draw(context, cr) -- Draw if needed if not empty_clip(cr) then - local opacity = widget.opacity + local opacity = widget:get_opacity() local function call(func, extra_arg1, extra_arg2) if not func then return end if not extra_arg2 then diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index a177bad4..04e16510 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -50,12 +50,19 @@ end -- transparent while 1 is fully opaque. -- @function set_opacity function base.widget:set_opacity(o) - if o ~= self.opacity then - self.opacity = o + if o ~= self._private.opacity then + self._private.opacity = o self:emit_signal("widget::redraw") end end +--- Get the widget opacity. +-- @treturn number The opacity (between 0 and 1) +-- @function get_opacity +function base.widget:get_opacity() + return self._private.opacity +end + --- Set the widget's width -- @tparam number|nil s The width that the widget has. `nil` means to apply the -- default mechanism of calling the `:fit` method. A number overrides the result @@ -535,7 +542,7 @@ function base.make_widget(proxy, widget_name, args) ret.visible = true -- Widget is fully opaque - ret.opacity = 1 + ret._private.opacity = 1 -- Differentiate tables from widgets rawset(ret, "is_widget", true) From c828e56b57b8601fb5fa5580487e56f0ebd18ab6 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 13:59:41 -0400 Subject: [PATCH 41/68] widget: Fix documentation --- lib/wibox/widget/base.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index 04e16510..5fd4bdd6 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -112,7 +112,7 @@ local function digg_children(ret, tlw) end end ---- Get all direct and indirect children widgets +--- Get all direct and indirect children widgets. -- This will scan all containers recursively to find widgets -- Warning: This method it prone to stack overflow id the widget, or any of its -- children, contain (directly or indirectly) itself. @@ -124,7 +124,7 @@ function base.widget:get_all_children() return ret end ---- Get a widex index +--- Get a widex index. -- @param widget The widget to look for -- @param[opt] recursive Also check sub-widgets -- @param[opt] ... Aditional widgets to add at the end of the "path" From afa17fd8f9d76910f08f0c2a5025245b07ba14d7 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 14:05:49 -0400 Subject: [PATCH 42/68] widget: Move 'widget_buttons' into _private --- lib/wibox/widget/base.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index 5fd4bdd6..887bfd6d 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -27,10 +27,10 @@ base.widget = {} -- @function buttons function base.widget:buttons(_buttons) if _buttons then - self.widget_buttons = _buttons + self._private.widget_buttons = _buttons end - return self.widget_buttons + return self._private.widget_buttons end --- Set a widget's visible property @@ -302,7 +302,7 @@ function base.handle_button(event, widget, x, y, button, modifiers, geometry) -- Find all matching button objects local matches = {} - for _, v in pairs(widget.widget_buttons) do + for _, v in pairs(widget._private.widget_buttons) do local match = true -- Is it the right button? if v.button ~= 0 and v.button ~= button then match = false end @@ -536,7 +536,7 @@ function base.make_widget(proxy, widget_name, args) rawset(ret, "_private", {}) -- No buttons yet - ret.widget_buttons = {} + ret._private.widget_buttons = {} -- Widget is visible ret.visible = true From c0eabf9d8f85e90fca9c5657e34e05f63c514319 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 14:25:07 -0400 Subject: [PATCH 43/68] widget: Move 'visible' into _private --- lib/awful/menu.lua | 4 ++-- lib/wibox/container/background.lua | 4 ++-- lib/wibox/container/rotate.lua | 2 +- lib/wibox/hierarchy.lua | 2 +- lib/wibox/widget/base.lua | 17 ++++++++++++----- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/awful/menu.lua b/lib/awful/menu.lua index 663b7704..4fff3df9 100644 --- a/lib/awful/menu.lua +++ b/lib/awful/menu.lua @@ -249,7 +249,7 @@ function menu:exec(num, opts) self.active_child:hide() end self.active_child = self.child[num] - if not self.active_child.visible then + if not self.active_child:get_visible() then self.active_child:show() end elseif type(cmd) == "string" then @@ -431,7 +431,7 @@ function menu:delete(num) local item = self.items[num] if not item then return end item.widget:disconnect_signal("mouse::enter", item._mouse) - item.widget.visible = false + item.widget:set_visible(false) table.remove(self.items, num) if self.sel == num then self:item_leave(self.sel) diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua index da1d64f6..d16c7c31 100644 --- a/lib/wibox/container/background.lua +++ b/lib/wibox/container/background.lua @@ -22,7 +22,7 @@ local background = { mt = {} } -- Draw this widget function background:draw(context, cr, width, height) - if not self._private.widget or not self._private.widget.visible then + if not self._private.widget or not self._private.widget:get_visible() then return end @@ -167,7 +167,7 @@ function background:get_fg() return self._private.foreground end ---- The background shape. +--- The background shap e. -- -- Use `set_shape` to set additional shape paramaters. -- diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua index 48e2a980..08d42e04 100644 --- a/lib/wibox/container/rotate.lua +++ b/lib/wibox/container/rotate.lua @@ -29,7 +29,7 @@ end -- Layout this layout function rotate:layout(_, width, height) - if not self.widget or not self.widget.visible then + if not self.widget or not self.widget._private.visible then return end diff --git a/lib/wibox/hierarchy.lua b/lib/wibox/hierarchy.lua index bbf961af..6ef800af 100644 --- a/lib/wibox/hierarchy.lua +++ b/lib/wibox/hierarchy.lua @@ -259,7 +259,7 @@ end -- @param cr The cairo context that is used for drawing. function hierarchy:draw(context, cr) local widget = self:get_widget() - if not widget.visible then + if not widget._private.visible then return end diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index 887bfd6d..ae023191 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -37,14 +37,21 @@ end -- @tparam boolean b Wether the widget is visible at all -- @function set_visible function base.widget:set_visible(b) - if b ~= self.visible then - self.visible = b + if b ~= self._private.visible then + self._private.visible = b self:emit_signal("widget::layout_changed") -- In case something ignored fit and drew the widget anyway self:emit_signal("widget::redraw_needed") end end +--- Get if the widget is visible. +-- @treturn boolean If the widget is visible +-- @function get_visible +function base.widget:get_visible() + return self._private.visible or false +end + --- Set a widget's opacity -- @tparam number o The opacity to use (a number from 0 to 1). 0 is fully -- transparent while 1 is fully opaque. @@ -221,7 +228,7 @@ end function base.fit_widget(parent, context, widget, width, height) record_dependency(parent, widget) - if not widget.visible then + if not widget._private.visible then return 0, 0 end @@ -266,7 +273,7 @@ end function base.layout_widget(parent, context, widget, width, height) record_dependency(parent, widget) - if not widget.visible then + if not widget._private.visible then return end @@ -539,7 +546,7 @@ function base.make_widget(proxy, widget_name, args) ret._private.widget_buttons = {} -- Widget is visible - ret.visible = true + ret._private.visible = true -- Widget is fully opaque ret._private.opacity = 1 From fdf86ba84d57cdc6905c3c4dee96ad10cfbc4e49 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 14:32:12 -0400 Subject: [PATCH 44/68] widget: Move height and width into _private --- lib/wibox/widget/base.lua | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index ae023191..ccf960dd 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -75,25 +75,47 @@ end -- default mechanism of calling the `:fit` method. A number overrides the result -- from `:fit`. -- @function set_width -function base.widget:set_width(s) - if s ~= self._forced_width then - self._forced_width = s +function base.widget:set_forced_width(s) + if s ~= self._private.forced_width then + self._private.forced_width = s self:emit_signal("widget::layout_changed") end end +--- Get the widget forced width. +-- Note that widgets instances can be placed at different places simultaneously, +-- therefore, they can have multiple width and width simultaneously. If there +-- is no forced size, then the only way to get the widget actual size is when +-- there is a `mouse::enter`, `mouse::leave` or button events. +-- @treturn nil|number The forced width (nil if automatic) +-- @function get_forced_widget +function base.widget:get_forced_width() + return self._private.forced_width +end + --- Set the widget's height -- @tparam number|nil s The height that the widget has. `nil` means to apply the -- default mechanism of calling the `:fit` method. A number overrides the result -- from `:fit`. -- @function set_height -function base.widget:set_height(s) - if s ~= self._forced_height then - self._forced_height = s +function base.widget:set_forced_height(s) + if s ~= self._private.forced_height then + self._private.forced_height = s self:emit_signal("widget::layout_changed") end end +--- Get the widget forced height. +-- Note that widgets instances can be placed at different places simultaneously, +-- therefore, they can have multiple width and height simultaneously. If there +-- is no forced size, then the only way to get the widget actual size is when +-- there is a `mouse::enter`, `mouse::leave` or button events. +-- @treturn nil|number The forced height (nil if automatic) +-- @function get_forced_height +function base.widget:get_forced_height() + return self._private.forced_height +end + --- Get all direct children widgets -- This method should be re-implemented by the relevant widgets -- @treturn table The children @@ -250,8 +272,8 @@ function base.fit_widget(parent, context, widget, width, height) end -- Apply forced size and handle nil's - w = widget._forced_width or w or 0 - h = widget._forced_height or h or 0 + w = widget._private.forced_width or w or 0 + h = widget._private.forced_height or h or 0 -- Also sanitize the output. w = math.max(0, math.min(w, width)) @@ -555,8 +577,8 @@ function base.make_widget(proxy, widget_name, args) rawset(ret, "is_widget", true) -- Size is not restricted/forced - ret._forced_width = nil - ret._forced_height = nil + ret._private.forced_width = nil + ret._private.forced_height = nil -- Make buttons work ret:connect_signal("button::press", function(...) From 9630f3c3edc0ea63502db501c569f92181db2e2b Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 14:37:58 -0400 Subject: [PATCH 45/68] widget: Move the identifier index into _private --- lib/wibox/widget/base.lua | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/wibox/widget/base.lua b/lib/wibox/widget/base.lua index ccf960dd..54a04cb9 100644 --- a/lib/wibox/widget/base.lua +++ b/lib/wibox/widget/base.lua @@ -494,7 +494,13 @@ function base.widget:setup(args) -- Avoid being dropped by wibox metatable -> drawin rawset(self, id, w) end - rawset(self, "_by_id", ids) + + if rawget(self, "_private") then + self._private.by_id = ids + else + rawset(self, "_by_id", ids) + end + rawset(self, "get_children_by_id", get_children_by_id) end @@ -514,7 +520,13 @@ function base.make_widget_declarative(args) local mt = getmetatable(w) or {} local orig_string = tostring(w) - rawset(w, "_by_id", ids) + + if rawget(w, "_private") then + w._private.by_id = ids + else + rawset(w, "_by_id", ids) + end + rawset(w, "get_children_by_id", get_children_by_id) mt.__tostring = function() From 8ac2db76bea306d5aafcbf27431f0d1f92ad84ea Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 15:05:51 -0400 Subject: [PATCH 46/68] doc: Add widgets common signals --- docs/common/widget.ldoc | 69 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/docs/common/widget.ldoc b/docs/common/widget.ldoc index f76c7844..76b24eea 100644 --- a/docs/common/widget.ldoc +++ b/docs/common/widget.ldoc @@ -39,3 +39,72 @@ --- Set/get a widget's buttons. -- @param _buttons The table of buttons that should bind to the widget. -- @function buttons + + +--- When the layout (size) change. +-- This signal is emited when the previous results of `:layout()` and `:fit()` +-- are no longer valid. +-- @signal widget::layout_changed +-- @see widget::redraw_needed + +--- When the widget content changed. +-- Unless this signal is emitted, `:layout()` and `:fit()` must return the same +-- result when called with the same arguments. In case this isn't the case, +-- use `widget::layout_changed`. +-- @signal widget::redraw_needed + +--- When a mouse button is pressed over the widget. +-- The position of the mouse press relative to the widget while geometry +-- contains the geometry of the widget relative to the wibox. +-- @signal button::press +-- @tparam table widget The widget +-- @tparam number lx The relative horizontal position. +-- @tparam number ly The relative vertical position. +-- @tparam number button The button number. +-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) +-- @tparam table geometry +-- @tparam number geometry.x The vertical position +-- @tparam number geometry.y The horizontal position +-- @tparam number geometry.width The widget +-- @tparam number geometry.height The height +-- @tparam drawable geometry.drawable The `drawable` +-- @see mouse + +--- When a mouse button is released over the widget. +-- The position of the mouse press relative to the widget while geometry +-- contains the geometry of the widget relative to the wibox. +-- @signal button::release +-- @tparam table widget The widget +-- @tparam number lx The relative horizontal position. +-- @tparam number ly The relative vertical position. +-- @tparam number button The button number. +-- @tparam table mods The modifiers (mod4, mod1 (alt), Control, Shift) +-- @tparam table geometry +-- @tparam number geometry.x The vertical position +-- @tparam number geometry.y The horizontal position +-- @tparam number geometry.width The widget +-- @tparam number geometry.height The height +-- @tparam drawable geometry.drawable The `drawable` +-- @see mouse + +--- When the mouse enter a widget. +-- @signal mouse::enter +-- @tparam table widget The widget +-- @tparam table geometry +-- @tparam number geometry.x The vertical position +-- @tparam number geometry.y The horizontal position +-- @tparam number geometry.width The widget +-- @tparam number geometry.height The height +-- @tparam drawable geometry.drawable The `drawable` +-- @see mouse + +--- When the mouse leave a widget. +-- @signal mouse::leave +-- @tparam table widget The widget +-- @tparam table geometry +-- @tparam number geometry.x The vertical position +-- @tparam number geometry.y The horizontal position +-- @tparam number geometry.width The widget +-- @tparam number geometry.height The height +-- @tparam drawable geometry.drawable The `drawable` +-- @see mouse From 8d6f82f0a31f13e88f832a68eb5f832f40f68331 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 15:08:31 -0400 Subject: [PATCH 47/68] doc: Add gears.object common documentation --- docs/common/object.ldoc | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 docs/common/object.ldoc diff --git a/docs/common/object.ldoc b/docs/common/object.ldoc new file mode 100644 index 00000000..19dfbd03 --- /dev/null +++ b/docs/common/object.ldoc @@ -0,0 +1,35 @@ + +--- Disonnect to a signal. +-- @tparam string name The name of the signal +-- @tparam function func The callback that should be disconnected +-- @see add_signal +-- @function disconnect_signal + +--- Emit a signal. +-- +-- @tparam string name The name of the signal +-- @param ... Extra arguments for the callback functions. Each connected +-- function receives the object as first argument and then any extra arguments +-- that are given to emit_signal() +-- @function emit_signal + +--- Add a signal to an object. All signals must be added before they can be used. +-- +-- @tparam string name The name of the new signal. +-- @function add_signal + +--- Connect to a signal. +-- @tparam string name The name of the signal +-- @tparam function func The callback to call when the signal is emitted +-- @see add_signal +-- @function connect_signal + +--- Connect to a signal weakly. This allows the callback function to be garbage +-- collected and automatically disconnects the signal when that happens. +-- +-- **Warning:** +-- Only use this function if you really, really, really know what you +-- are doing. +-- @tparam string name The name of the signal +-- @tparam function func The callback to call when the signal is emitted +-- @function weak_connect_signal From a5edff396c97e19082e9b1ecf832d38b39c4634f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 15:12:56 -0400 Subject: [PATCH 48/68] background: Add the common object documentation --- lib/wibox/container/background.lua | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/wibox/container/background.lua b/lib/wibox/container/background.lua index d16c7c31..6b52e986 100644 --- a/lib/wibox/container/background.lua +++ b/lib/wibox/container/background.lua @@ -14,6 +14,7 @@ local color = require("gears.color") local surface = require("gears.surface") local beautiful = require("beautiful") local cairo = require("lgi").cairo +local util = require("awful.util") local setmetatable = setmetatable local type = type local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) @@ -268,11 +269,7 @@ local function new(widget, bg, shape) enable_properties = true, }) - for k, v in pairs(background) do - if type(v) == "function" then - ret[k] = v - end - end + util.table.crush(ret, background, true) ret._private.shape = shape @@ -288,6 +285,8 @@ end --@DOC_widget_COMMON@ +--@DOC_object_COMMON@ + return setmetatable(background, background.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 832e9ed054a4a81f83858ae68d3cf10ba0e95de5 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 15:37:33 -0400 Subject: [PATCH 49/68] constraint: Enable the property system And add the missing documentation --- lib/wibox/container/constraint.lua | 74 ++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 24 deletions(-) diff --git a/lib/wibox/container/constraint.lua b/lib/wibox/container/constraint.lua index 4e8a976d..af0e5594 100644 --- a/lib/wibox/container/constraint.lua +++ b/lib/wibox/container/constraint.lua @@ -7,49 +7,55 @@ -- @classmod wibox.container.constraint --------------------------------------------------------------------------- -local pairs = pairs -local type = type local setmetatable = setmetatable local base = require("wibox.widget.base") +local util = require("awful.util") 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) } + if self._private.widget then + return { base.place_widget_at(self._private.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) + if self._private.widget then + w = self._private.strategy(width, self._private.width) + h = self._private.strategy(height, self._private.height) - w, h = base.fit_widget(self, context, self.widget, w, h) + w, h = base.fit_widget(self, context, self._private.widget, w, h) else w, h = 0, 0 end - w = self._strategy(w, self._width) - h = self._strategy(h, self._height) + w = self._private.strategy(w, self._private.width) + h = self._private.strategy(h, self._private.height) return w, h end ---- Set the widget that this layout adds a constraint on. +--- The widget to be constrained. +-- @property widget +-- @tparam widget widget The widget + function constraint:set_widget(widget) - self.widget = widget + self._private.widget = widget self:emit_signal("widget::layout_changed") end +function constraint:get_widget() + return self._private.widget +end + --- Get the number of children element -- @treturn table The children function constraint:get_children() - return {self.widget} + return {self._private.widget} end --- Replace the layout children @@ -61,6 +67,8 @@ end --- Set the strategy to use for the constraining. Valid values are 'max', -- 'min' or 'exact'. Throws an error on invalid values. +-- @property strategy + function constraint:set_strategy(val) local func = { min = function(real_size, limit) @@ -78,27 +86,45 @@ function constraint:set_strategy(val) error("Invalid strategy for constraint layout: " .. tostring(val)) end - self._strategy = func[val] + self._private.strategy = func[val] self:emit_signal("widget::layout_changed") end +function constraint:get_strategy() + return self._private.strategy +end + --- Set the maximum width to val. nil for no width limit. +-- @property height +-- @param number + function constraint:set_width(val) - self._width = val + self._private.width = val self:emit_signal("widget::layout_changed") end +function constraint:get_width() + return self._private.width +end + --- Set the maximum height to val. nil for no height limit. +-- @property width +-- @param number + function constraint:set_height(val) - self._height = val + self._private.height = val self:emit_signal("widget::layout_changed") end +function constraint:get_height() + return self._private.height +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._private.width = nil + self._private.height = nil self:set_strategy("max") self:set_widget(nil) end @@ -117,13 +143,9 @@ end -- @treturn table A new constraint container -- @function wibox.container.constraint local function new(widget, strategy, width, height) - local ret = base.make_widget() + local ret = base.make_widget(nil, nil, {enable_properties = true}) - for k, v in pairs(constraint) do - if type(v) == "function" then - ret[k] = v - end - end + util.table.crush(ret, constraint, true) ret:set_strategy(strategy or "max") ret:set_width(width) @@ -140,6 +162,10 @@ function constraint.mt:__call(...) return new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(constraint, constraint.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 8869257940c07c8654ad447dac28ec09a5ee19b0 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 16:19:48 -0400 Subject: [PATCH 50/68] margin: Enable the property system And add the missing documentation --- lib/wibox/container/margin.lua | 119 +++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 51 deletions(-) diff --git a/lib/wibox/container/margin.lua b/lib/wibox/container/margin.lua index 70924007..4508c7b4 100644 --- a/lib/wibox/container/margin.lua +++ b/lib/wibox/container/margin.lua @@ -8,23 +8,23 @@ --------------------------------------------------------------------------- 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 + local x = self._private.left + local y = self._private.top + local w = self._private.right + local h = self._private.bottom + local color = self._private.color - if not self.widget or width <= x + w or height <= y + h then + if not self._private.widget or width <= x + w or height <= y + h then return end @@ -39,45 +39,52 @@ 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 + if self._private.widget then + local x = self._private.left + local y = self._private.top + local w = self._private.right + local h = self._private.bottom - return { base.place_widget_at(self.widget, x, y, width - x - w, height - y - h) } + return { base.place_widget_at(self._private.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 extra_w = self._private.left + self._private.right + local extra_h = self._private.top + self._private.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) + if self._private.widget then + w, h = base.fit_widget(self, context, self._private.widget, width - extra_w, height - extra_h) end - if self._draw_empty == false and (w == 0 or h == 0) then + if self._private.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. +--- The widget to be wrapped the the margins. +-- @property widget +-- @tparam widget widget The widget + function margin:set_widget(widget) if widget then base.check_widget(widget) end - self.widget = widget + self._private.widget = widget self:emit_signal("widget::layout_changed") end +function margin:get_widget() + return self._private.widget +end + -- Get the number of children element -- @treturn table The children function margin:get_children() - return {self.widget} + return {self._private.widget} end -- Replace the layout children @@ -88,36 +95,50 @@ function margin:set_children(children) end --- Set all the margins to val. +-- @property margins -- @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 + if self._private.left == val and + self._private.right == val and + self._private.top == val and + self._private.bottom == val then return end - self.left = val - self.right = val - self.top = val - self.bottom = val + self._private.left = val + self._private.right = val + self._private.top = val + self._private.bottom = val self:emit_signal("widget::layout_changed") end --- Set the margins color to create a border. +-- @property color -- @param color A color used to fill the margin. + function margin:set_color(color) - self.color = color and gcolor(color) + self._private.color = color and gcolor(color) self:emit_signal("widget::redraw_needed") end +function margin:get_color() + return self._private.color +end + --- Draw the margin even if the content size is 0x0 (default: true) +-- @function draw_empty -- @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._private.draw_empty = draw_empty self:emit_signal("widget::layout_changed") end +function margin:get_draw_empty() + return self._private.draw_empty +end + --- Reset this layout. The widget will be unreferenced, the margins set to 0 -- and the color erased function margin:reset() @@ -127,36 +148,32 @@ function margin:reset() 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 +-- @property left --- 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 +-- @property right --- 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 +-- @property top --- 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 +-- @property bottom -- 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 + if layout._private[v] == val then return end + layout._private[v] = val layout:emit_signal("widget::layout_changed") end + + margin["get_" .. v] = function(layout) + return layout._private[v] + end end --- Returns a new margin container. @@ -170,13 +187,9 @@ end -- @treturn table A new margin container -- @function wibox.container.margin local function new(widget, left, right, top, bottom, color, draw_empty) - local ret = base.make_widget() + local ret = base.make_widget(nil, nil, {enable_properties = true}) - for k, v in pairs(margin) do - if type(v) == "function" then - ret[k] = v - end - end + util.table.crush(ret, margin, true) ret:set_left(left or 0) ret:set_right(right or 0) @@ -197,6 +210,10 @@ function margin.mt:__call(...) return new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(margin, margin.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From bf74ca8a8c2ec4035da3ca75afe1e5e5c3dda60c Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 16:26:50 -0400 Subject: [PATCH 51/68] mirror: Enable the property system And add the missing documentation --- lib/wibox/container/mirror.lua | 60 +++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/lib/wibox/container/mirror.lua b/lib/wibox/container/mirror.lua index 975f57ca..d00e93f2 100644 --- a/lib/wibox/container/mirror.lua +++ b/lib/wibox/container/mirror.lua @@ -9,57 +9,63 @@ 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 + if not self._private.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 + if self._private.horizontal then t.x = width s.x = -1 end - if self.vertical then + if self._private.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) } + return { base.place_widget_via_matrix(self._private.widget, m, width, height) } end -- Fit this layout into the given area function mirror:fit(context, ...) - if not self.widget then + if not self._private.widget then return 0, 0 end - return base.fit_widget(self, context, self.widget, ...) + return base.fit_widget(self, context, self._private.widget, ...) end ---- Set the widget that this layout mirrors. --- @param widget The widget to mirror +--- The widget to be reflected. +-- @property widget +-- @tparam widget widget The widget + function mirror:set_widget(widget) if widget then base.check_widget(widget) end - self.widget = widget + self._private.widget = widget self:emit_signal("widget::layout_changed") end +function mirror:get_widget() + return self._private.widget +end + --- Get the number of children element -- @treturn table The children function mirror:get_children() - return {self.widget} + return {self._private.widget} end --- Replace the layout children @@ -71,13 +77,11 @@ end --- Reset this layout. The widget will be removed and the axes reset. function mirror:reset() - self.horizontal = false - self.vertical = false + self._private.horizontal = false + self._private.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: " .. @@ -85,16 +89,20 @@ function mirror:set_reflection(reflection) end for _, ref in ipairs({"horizontal", "vertical"}) do if reflection[ref] ~= nil then - self[ref] = reflection[ref] + self._private[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". +-- @property reflection +-- @param table reflection A table of booleans with the keys "horizontal", "vertical". +-- @param boolean reflection.horizontal +-- @param boolean reflection.vertical + function mirror:get_reflection() - return { horizontal = self.horizontal, vertical = self.vertical } + return { horizontal = self._private.horizontal, vertical = self._private.vertical } end --- Returns a new mirror container. @@ -107,15 +115,11 @@ end -- @treturn table A new mirror container -- @function wibox.container.mirror local function new(widget, reflection) - local ret = base.make_widget() - ret.horizontal = false - ret.vertical = false + local ret = base.make_widget(nil, nil, {enable_properties = true}) + ret._private.horizontal = false + ret._private.vertical = false - for k, v in pairs(mirror) do - if type(v) == "function" then - ret[k] = v - end - end + util.table.crush(ret, mirror, true) ret:set_widget(widget) ret:set_reflection(reflection or {}) @@ -127,6 +131,10 @@ function mirror.mt:__call(...) return new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(mirror, mirror.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 4ffbff3a5f990fbac058326f389ff80da8475969 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 16:34:44 -0400 Subject: [PATCH 52/68] rotate: Enable the property system And add the missing documentation --- lib/wibox/container/rotate.lua | 46 ++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/wibox/container/rotate.lua b/lib/wibox/container/rotate.lua index 08d42e04..caaf4b12 100644 --- a/lib/wibox/container/rotate.lua +++ b/lib/wibox/container/rotate.lua @@ -9,13 +9,12 @@ --------------------------------------------------------------------------- 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 = {} } @@ -29,7 +28,7 @@ end -- Layout this layout function rotate:layout(_, width, height) - if not self.widget or not self.widget._private.visible then + if not self._private.widget or not self._private.widget._private.visible then return end @@ -49,30 +48,37 @@ function rotate:layout(_, width, height) -- 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)) } + return { base.place_widget_via_matrix(self._private.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 + if not self._private.widget then return 0, 0 end - return transform(self, base.fit_widget(self, context, self.widget, transform(self, width, height))) + return transform(self, base.fit_widget(self, context, self._private.widget, transform(self, width, height))) end ---- Set the widget that this layout rotates. +--- The widget to be rotated. +-- @property widget +-- @tparam widget widget The widget + function rotate:set_widget(widget) if widget then base.check_widget(widget) end - self.widget = widget + self._private.widget = widget self:emit_signal("widget::layout_changed") end +function rotate:get_widget() + return self._private.widget +end + --- Get the number of children element -- @treturn table The children function rotate:get_children() - return {self.widget} + return {self._private.widget} end --- Replace the layout children @@ -84,11 +90,15 @@ end --- Reset this layout. The widget will be removed and the rotation reset. function rotate:reset() - self.direction = nil + self._private.direction = nil self:set_widget(nil) end ---- Set the direction of this rotating container. +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + +--- The direction of this rotating container. -- Valid values are: -- -- * *north* @@ -97,7 +107,9 @@ end -- * *north* -- --@DOC_wibox_container_rotate_angle_EXAMPLE@ +-- @property direction -- @tparam string dir The direction + function rotate:set_direction(dir) local allowed = { north = true, @@ -110,13 +122,13 @@ function rotate:set_direction(dir) error("Invalid direction for rotate layout: " .. tostring(dir)) end - self.direction = dir + self._private.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" + return self._private.direction or "north" end --- Returns a new rotate container. @@ -128,13 +140,9 @@ end -- @treturn table A new rotate container. -- @function wibox.container.rotate local function new(widget, dir) - local ret = base.make_widget() + local ret = base.make_widget(nil, nil, {enable_properties = true}) - for k, v in pairs(rotate) do - if type(v) == "function" then - ret[k] = v - end - end + util.table.crush(ret, rotate, true) ret:set_widget(widget) ret:set_direction(dir or "north") From 03e2310c54ee2edf3c4bbadf09f1324b3bcc684f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 16:35:02 -0400 Subject: [PATCH 53/68] scroll: Enable the property system And add the missing documentation --- lib/wibox/container/scroll.lua | 118 ++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/lib/wibox/container/scroll.lua b/lib/wibox/container/scroll.lua index 38320f01..f18200e5 100644 --- a/lib/wibox/container/scroll.lua +++ b/lib/wibox/container/scroll.lua @@ -76,29 +76,29 @@ end) -- @field context The widget context for drawing the hierarchy local function calculate_info(self, context, width, height) local result = {} - assert(self.widget) + assert(self._private.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 extra_width, extra_height, extra = 0, 0, self._private.expand and self._private.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) + if self._private.dir == "h" then + w, h = base.fit_widget(self, context, self._private.widget, self._private.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) + w, h = base.fit_widget(self, context, self._private.widget, width, self._private.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) + if self._private.dir == "h" then + if self._private.max_size then + result.fit_width = math.min(w, self._private.max_size) end else - if self.max_size then - result.fit_height = math.min(h, self.max_size) + if self._private.max_size then + result.fit_height = math.min(h, self._private.max_size) end end if w > width or h > height then @@ -109,17 +109,17 @@ local function calculate_info(self, context, width, 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) + return self._private.step_function(self._private.timer:elapsed(), size, visible_size, self._private.speed, self._private.extra_space) end - if self.dir == "h" then + if self._private.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 + local extra_spacer = self._private.expand and 0 or self._private.extra_space + if self._private.dir == "h" then x = x + surface_width + extra_spacer else y = y + surface_height + extra_spacer @@ -132,7 +132,7 @@ local function calculate_info(self, context, width, 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) + self._private.widget, surface_width, surface_height) result.hierarchy = hier result.context = ctx do_pending_updates(self) @@ -146,7 +146,7 @@ end -- @param width The available width. -- @param height The available height. function scroll:draw(context, cr, width, height) - if not self.widget then + if not self._private.widget then return end @@ -175,7 +175,7 @@ end -- @param width The available width. -- @param height The available height. function scroll:fit(context, width, height) - if not self.widget then + if not self._private.widget then return 0, 0 end local info = calculate_info(self, context, width, height) @@ -189,9 +189,9 @@ end -- 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 + if not self._private.paused and not self._private.scroll_timer then + self._private.scroll_timer = timer.start_new(1 / self._private.fps, function() + self._private.scroll_timer = nil self:emit_signal("widget::redraw_needed") end) end @@ -200,21 +200,21 @@ end --- Pause the scrolling animation. -- @see continue function scroll:pause() - if self.paused then + if self._private.paused then return end - self.paused = true - self.timer:stop() + self._private.paused = true + self._private.timer:stop() end --- Continue the scrolling animation. -- @see pause function scroll:continue() - if not self.paused then + if not self._private.paused then return end - self.paused = false - self.timer:continue() + self._private.paused = false + self._private.timer:continue() self:emit_signal("widget::redraw_needed") end @@ -223,44 +223,50 @@ end -- 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() + self._private.timer:start() + if self._private.paused then + self._private.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 + if dir == self._private.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._private.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 +--- The widget to be scrolled. +-- @property widget +-- @tparam widget widget The widget + function scroll:set_widget(widget) - if widget == self.widget then + if widget == self._private.widget then return end if widget then base.check_widget(widget) end - self.widget = widget + self._private.widget = widget self:emit_signal("widget::layout_changed") self:emit_signal("widget::redraw_needed") end +function scroll:get_widget() + return self._private.widget +end + --- Get the number of children element -- @treturn table The children function scroll:get_children() - return {self.widget} + return {self._private.widget} end --- Replace the layout children @@ -275,20 +281,20 @@ end -- space. If false, the extra space is simply left empty. -- @see set_extra_space function scroll:set_expand(expand) - if expand == self.expand then + if expand == self._private.expand then return end - self.expand = expand + self._private.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 + if fps == self._private.fps then return end - self.fps = fps + self._private.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 @@ -298,10 +304,10 @@ end -- @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 + if extra_space == self._private.extra_space then return end - self.extra_space = extra_space + self._private.extra_space = extra_space self:emit_signal("widget::redraw_needed") end @@ -310,10 +316,10 @@ end -- in pixels per second. -- @tparam number speed The speed for the animation function scroll:set_speed(speed) - if speed == self.speed then + if speed == self._private.speed then return end - self.speed = speed + self._private.speed = speed self:emit_signal("widget::redraw_needed") end @@ -323,10 +329,10 @@ end -- 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 + if max_size == self._private.max_size then return end - self.max_size = max_size + self._private.max_size = max_size self:emit_signal("widget::layout_changed") end @@ -350,10 +356,10 @@ end 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 + if step_function == self._private.step_function then return end - self.step_function = step_function + self._private.step_function = step_function self:emit_signal("widget::redraw_needed") end @@ -361,19 +367,19 @@ end -- 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 + if space_for_scrolling == self._private.space_for_scrolling then return end - self.space_for_scrolling = space_for_scrolling + self._private.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() + local ret = base.make_widget(nil, nil, {enable_properties = true}) - ret.paused = false - ret.timer = GLib.Timer() - ret.scroll_timer = nil + ret._priavte.paused = false + ret._private.timer = GLib.Timer() + ret._private.scroll_timer = nil setmetatable(ret, scroll_mt) @@ -504,6 +510,10 @@ function scroll.step_functions.waiting_nonlinear_back_and_forth(elapsed, size, v return (size - visible_size) * state end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return scroll -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From ea16481228ab9c534fee38f6bb5c047efe500683 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 17:39:04 -0400 Subject: [PATCH 54/68] graph: Enable the property system And add the missing documentation --- lib/wibox/widget/graph.lua | 102 ++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/lib/wibox/widget/graph.lua b/lib/wibox/widget/graph.lua index ac3672e3..d1c9bfa5 100644 --- a/lib/wibox/widget/graph.lua +++ b/lib/wibox/widget/graph.lua @@ -21,47 +21,40 @@ local graph = { mt = {} } --- Set the graph border color. -- If the value is nil, no border will be drawn. -- --- @function set_border_color --- @param graph The graph. --- @param color The border color to set. +-- @property border_color +-- @tparam geats.color border_color The border color to set. --- Set the graph foreground color. -- --- @function set_color --- @param graph The graph. --- @param color The graph color. +-- @property color +-- @tparam color color The graph color. -- @see gears.color.create_pattern --- Set the graph background color. -- --- @function set_background_color --- @param graph The graph. --- @param color The graph background color. +-- @property background_color +-- @tparam gears.color background_color The graph background color. --- Set the maximum value the graph should handle. -- If "scale" is also set, the graph never scales up below this value, but it -- automatically scales down to make all data fit. -- --- @function set_max_value --- @param graph The graph. --- @param value The value. +-- @property max_value +-- @param number --- Set the graph to automatically scale its values. Default is false. -- --- @function set_scale --- @param graph The graph. --- @param scale A boolean value +-- @property scale +-- @param boolean --- Set the graph to draw stacks. Default is false. -- --- @function set_stack --- @param graph The graph. --- @param stack A boolean value. +-- @property stack +-- @param boolean --- Set the graph stacking colors. Order matters. -- --- @function set_stack_colors --- @param graph The graph. +-- @property stack_colors -- @param stack_colors A table with stacking colors. local properties = { "width", "height", "border_color", "stack", @@ -69,26 +62,26 @@ local properties = { "width", "height", "border_color", "stack", "max_value", "scale" } function graph.draw(_graph, _, cr, width, height) - local max_value = _graph._data.max_value - local values = _graph._data.values + local max_value = _graph._private.max_value + local values = _graph._private.values cr:set_line_width(1) -- Draw the background first - cr:set_source(color(_graph._data.background_color or "#000000aa")) + cr:set_source(color(_graph._private.background_color or "#000000aa")) cr:paint() -- Account for the border width cr:save() - if _graph._data.border_color then + if _graph._private.border_color then cr:translate(1, 1) width, height = width - 2, height - 2 end -- Draw a stacked graph - if _graph._data.stack then + if _graph._private.stack then - if _graph._data.scale then + if _graph._private.scale then for _, v in ipairs(values) do for _, sv in ipairs(v) do if sv > max_value then @@ -102,8 +95,8 @@ function graph.draw(_graph, _, cr, width, height) local rel_i = 0 local rel_x = i + 0.5 - if _graph._data.stack_colors then - for idx, col in ipairs(_graph._data.stack_colors) do + if _graph._private.stack_colors then + for idx, col in ipairs(_graph._private.stack_colors) do local stack_values = values[idx] if stack_values and i < #stack_values then local value = stack_values[#stack_values - i] + rel_i @@ -117,7 +110,7 @@ function graph.draw(_graph, _, cr, width, height) end end else - if _graph._data.scale then + if _graph._private.scale then for _, v in ipairs(values) do if v > max_value then max_value = v @@ -136,7 +129,7 @@ function graph.draw(_graph, _, cr, width, height) cr:line_to(i + 0.5, height) end end - cr:set_source(color(_graph._data.color or "#ff0000")) + cr:set_source(color(_graph._private.color or "#ff0000")) cr:stroke() end @@ -146,19 +139,19 @@ function graph.draw(_graph, _, cr, width, height) cr:restore() -- Draw the border last so that it overlaps already drawn values - if _graph._data.border_color then + if _graph._private.border_color then -- We decremented these by two above width, height = width + 2, height + 2 -- Draw the border cr:rectangle(0.5, 0.5, width - 1, height - 1) - cr:set_source(color(_graph._data.border_color or "#ffffff")) + cr:set_source(color(_graph._private.border_color or "#ffffff")) cr:stroke() end end function graph.fit(_graph) - return _graph._data.width, _graph._data.height + return _graph._private.width, _graph._private.height end --- Add a value to the graph @@ -167,28 +160,28 @@ end -- @param group The stack color group index. function graph:add_value(value, group) value = value or 0 - local values = self._data.values - local max_value = self._data.max_value + local values = self._private.values + local max_value = self._private.max_value value = math.max(0, value) - if not self._data.scale then + if not self._private.scale then value = math.min(max_value, value) end - if self._data.stack and group then - if not self._data.values[group] - or type(self._data.values[group]) ~= "table" + if self._private.stack and group then + if not self._private.values[group] + or type(self._private.values[group]) ~= "table" then - self._data.values[group] = {} + self._private.values[group] = {} end - values = self._data.values[group] + values = self._private.values[group] end table.insert(values, value) local border_width = 0 - if self._data.border_color then border_width = 2 end + if self._private.border_color then border_width = 2 end -- Ensure we never have more data than we can draw - while #values > self._data.width - border_width do + while #values > self._private.width - border_width do table.remove(values, 1) end @@ -198,7 +191,7 @@ end --- Clear the graph. function graph:clear() - self._data.values = {} + self._private.values = {} self:emit_signal("widget::redraw_needed") return self end @@ -207,7 +200,7 @@ end -- @param height The height to set. function graph:set_height(height) if height >= 5 then - self._data.height = height + self._private.height = height self:emit_signal("widget::layout_changed") end return self @@ -217,7 +210,7 @@ end -- @param width The width to set. function graph:set_width(width) if width >= 5 then - self._data.width = width + self._private.width = width self:emit_signal("widget::layout_changed") end return self @@ -227,8 +220,8 @@ end for _, prop in ipairs(properties) do if not graph["set_" .. prop] then graph["set_" .. prop] = function(_graph, value) - if _graph._data[prop] ~= value then - _graph._data[prop] = value + if _graph._private[prop] ~= value then + _graph._private[prop] = value _graph:emit_signal("widget::redraw_needed") end return _graph @@ -236,7 +229,7 @@ for _, prop in ipairs(properties) do end if not graph["get_" .. prop] then graph["get_" .. prop] = function(_graph) - return _graph._data[prop] + return _graph._private[prop] end end end @@ -254,9 +247,12 @@ function graph.new(args) if width < 5 or height < 5 then return end - local _graph = base.make_widget() + local _graph = base.make_widget(nil, nil, {enable_properties = true}) - _graph._data = { width = width, height = height, values = {}, max_value = 1 } + _graph._private.width = width + _graph._private.height = height + _graph._private.values = {} + _graph._private.max_value = 1 -- Set methods _graph.add_value = graph["add_value"] @@ -276,6 +272,10 @@ function graph.mt:__call(...) return graph.new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(graph, graph.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 5a0f7b7efe1fbcd2ea7997d54ae89388eb0ea2e6 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 17:39:17 -0400 Subject: [PATCH 55/68] textbox: Enable the property system And add the missing documentation --- lib/wibox/widget/textbox.lua | 115 +++++++++++++++++++++-------------- 1 file changed, 69 insertions(+), 46 deletions(-) diff --git a/lib/wibox/widget/textbox.lua b/lib/wibox/widget/textbox.lua index 3d783df6..e486d450 100644 --- a/lib/wibox/widget/textbox.lua +++ b/lib/wibox/widget/textbox.lua @@ -12,11 +12,10 @@ local base = require("wibox.widget.base") local gdebug = require("gears.debug") local beautiful = require("beautiful") local lgi = require("lgi") +local util = require("awful.util") local Pango = lgi.Pango local PangoCairo = lgi.PangoCairo -local type = type local setmetatable = setmetatable -local pairs = pairs local textbox = { mt = {} } @@ -25,37 +24,37 @@ local textbox = { mt = {} } --- Set the DPI of a Pango layout local function setup_dpi(box, dpi) - if box.dpi ~= dpi then - box.dpi = dpi - box._ctx:set_resolution(dpi) - box._layout:context_changed() + if box._private.dpi ~= dpi then + box._private.dpi = dpi + box._private.ctx:set_resolution(dpi) + box._private.layout:context_changed() end end --- Setup a pango layout for the given textbox and dpi local function setup_layout(box, width, height, dpi) - box._layout.width = Pango.units_from_double(width) - box._layout.height = Pango.units_from_double(height) + box._private.layout.width = Pango.units_from_double(width) + box._private.layout.height = Pango.units_from_double(height) setup_dpi(box, dpi) end -- Draw the given textbox on the given cairo context in the given geometry function textbox:draw(context, cr, width, height) setup_layout(self, width, height, context.dpi) - cr:update_layout(self._layout) - local _, logical = self._layout:get_pixel_extents() + cr:update_layout(self._private.layout) + local _, logical = self._private.layout:get_pixel_extents() local offset = 0 - if self._valign == "center" then + if self._private.valign == "center" then offset = (height - logical.height) / 2 - elseif self._valign == "bottom" then + elseif self._private.valign == "bottom" then offset = height - logical.height end cr:move_to(0, offset) - cr:show_layout(self._layout) + cr:show_layout(self._private.layout) end local function do_fit_return(self) - local _, logical = self._layout:get_pixel_extents() + local _, logical = self._private.layout:get_pixel_extents() if logical.width == 0 or logical.height == 0 then return 0, 0 end @@ -97,8 +96,8 @@ end function textbox:get_preferred_size_at_dpi(dpi) local max_lines = 2^20 setup_dpi(self, dpi) - self._layout.width = -1 -- no width set - self._layout.height = -max_lines -- show this many lines per paragraph + self._private.layout.width = -1 -- no width set + self._private.layout.height = -max_lines -- show this many lines per paragraph return do_fit_return(self) end @@ -111,8 +110,8 @@ end function textbox:get_height_for_width_at_dpi(width, dpi) local max_lines = 2^20 setup_dpi(self, dpi) - self._layout.width = Pango.units_from_double(width) - self._layout.height = -max_lines -- show this many lines per paragraph + self._private.layout.width = Pango.units_from_double(width) + self._private.layout.height = -max_lines -- show this many lines per paragraph local _, h = do_fit_return(self) return h end @@ -126,7 +125,7 @@ end -- @treturn[2] boolean false -- @treturn[2] string Error message explaining why the markup was invalid. function textbox:set_markup_silently(text) - if self._markup == text then + if self._private.markup == text then return true end @@ -136,9 +135,9 @@ function textbox:set_markup_silently(text) return false, parsed.message or tostring(parsed) end - self._markup = text - self._layout.text = parsed - self._layout.attributes = attr + self._private.markup = text + self._private.layout.text = parsed + self._private.layout.attributes = attr self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") return true @@ -146,9 +145,12 @@ end --- Set the text of the textbox (with -- [Pango markup](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html)). +-- @property markup -- @tparam string text The text to set. This can contain pango markup (e.g. -- `bold`). You can use `awful.util.escape` to escape -- parts of it. +-- @see text + function textbox:set_markup(text) local success, message = self:set_markup_silently(text) if not success then @@ -156,79 +158,100 @@ function textbox:set_markup(text) end end +function textbox:get_markup() + return self._private.markup +end + --- Set a textbox' text. +-- @property text -- @param text The text to display. Pango markup is ignored and shown as-is. +-- @see markup + function textbox:set_text(text) - if self._layout.text == text and self._layout.attributes == nil then + if self._private.layout.text == text and self._private.layout.attributes == nil then return end - self._markup = nil - self._layout.text = text - self._layout.attributes = nil + self._private.markup = nil + self._private.layout.text = text + self._private.layout.attributes = nil self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") end +function textbox:get_text() + return self._private.layout.text +end + --- Set a textbox' ellipsize mode. +-- @property ellipsize -- @param mode Where should long lines be shortened? "start", "middle" or "end" + function textbox:set_ellipsize(mode) local allowed = { none = "NONE", start = "START", middle = "MIDDLE", ["end"] = "END" } if allowed[mode] then - if self._layout:get_ellipsize() == allowed[mode] then + if self._private.layout:get_ellipsize() == allowed[mode] then return end - self._layout:set_ellipsize(allowed[mode]) + self._private.layout:set_ellipsize(allowed[mode]) self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") end end --- Set a textbox' wrap mode. +-- @property wrap -- @param mode Where to wrap? After "word", "char" or "word_char" + function textbox:set_wrap(mode) local allowed = { word = "WORD", char = "CHAR", word_char = "WORD_CHAR" } if allowed[mode] then - if self._layout:get_wrap() == allowed[mode] then + if self._private.layout:get_wrap() == allowed[mode] then return end - self._layout:set_wrap(allowed[mode]) + self._private.layout:set_wrap(allowed[mode]) self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") end end ---- Set a textbox' vertical alignment +--- The textbox' vertical alignment +-- @property valign -- @param mode Where should the textbox be drawn? "top", "center" or "bottom" + function textbox:set_valign(mode) local allowed = { top = true, center = true, bottom = true } if allowed[mode] then - if self._valign == mode then + if self._private.valign == mode then return end - self._valign = mode + self._private.valign = mode self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") end end ---- Set a textbox' horizontal alignment +--- Set a textbox' horizontal alignment. +-- @property align -- @param mode Where should the textbox be drawn? "left", "center" or "right" + function textbox:set_align(mode) local allowed = { left = "LEFT", center = "CENTER", right = "RIGHT" } if allowed[mode] then - if self._layout:get_alignment() == allowed[mode] then + if self._private.layout:get_alignment() == allowed[mode] then return end - self._layout:set_alignment(allowed[mode]) + self._private.layout:set_alignment(allowed[mode]) self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") end end --- Set a textbox' font +-- @property font -- @param font The font description as string + function textbox:set_font(font) - self._layout:set_font_description(beautiful.get_font(font)) + self._private.layout:set_font_description(beautiful.get_font(font)) self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") end @@ -239,17 +262,13 @@ end -- @treturn table A new textbox widget -- @function wibox.widget.textbox local function new(text, ignore_markup) - local ret = base.make_widget() + local ret = base.make_widget(nil, nil, {enable_properties = true}) - for k, v in pairs(textbox) do - if type(v) == "function" then - ret[k] = v - end - end + util.table.crush(ret, textbox, true) - ret._dpi = -1 - ret._ctx = PangoCairo.font_map_get_default():create_context() - ret._layout = Pango.Layout.new(ret._ctx) + ret._private.dpi = -1 + ret._private.ctx = PangoCairo.font_map_get_default():create_context() + ret._private.layout = Pango.Layout.new(ret._private.ctx) ret:set_ellipsize("end") ret:set_wrap("word_char") @@ -272,6 +291,10 @@ function textbox.mt.__call(_, ...) return new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(textbox, textbox.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 584a48db2fa5003cca8194030eecbf396014d6b4 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 30 May 2016 23:09:50 -0400 Subject: [PATCH 56/68] titlebar: Use _private --- lib/awful/titlebar.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/awful/titlebar.lua b/lib/awful/titlebar.lua index c44d1703..29b81f29 100644 --- a/lib/awful/titlebar.lua +++ b/lib/awful/titlebar.lua @@ -204,8 +204,8 @@ function titlebar.widget.button(c, name, selector, action) local ret = imagebox() if titlebar.enable_tooltip then - ret.tooltip = atooltip({ objects = {ret}, delay_show = 1 }) - ret.tooltip:set_text(name) + ret._private.tooltip = atooltip({ objects = {ret}, delay_show = 1 }) + ret._private.tooltip:set_text(name) end local function update() From c62ca6c66551042caa5ae56745324206499c8257 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 17:39:27 -0400 Subject: [PATCH 57/68] imagebox: Enable the property system And add the missing documentation --- lib/wibox/widget/imagebox.lua | 65 ++++++++++++++++++------------ tests/test-awful-widget-button.lua | 14 +++---- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/lib/wibox/widget/imagebox.lua b/lib/wibox/widget/imagebox.lua index 61524061..75242e8c 100644 --- a/lib/wibox/widget/imagebox.lua +++ b/lib/wibox/widget/imagebox.lua @@ -9,8 +9,8 @@ local base = require("wibox.widget.base") local surface = require("gears.surface") +local util = require("awful.util") local setmetatable = setmetatable -local pairs = pairs local type = type local print = print local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1) @@ -19,13 +19,13 @@ local imagebox = { mt = {} } -- Draw an imagebox with the given cairo context in the given geometry. function imagebox:draw(_, cr, width, height) - if not self._image then return end + if not self._private.image then return end if width == 0 or height == 0 then return end - if not self.resize_forbidden then + if not self._private.resize_forbidden then -- Let's scale the image so that it fits into (width, height) - local w = self._image:get_width() - local h = self._image:get_height() + local w = self._private.image:get_width() + local h = self._private.image:get_height() local aspect = width / w local aspect_h = height / h if aspect > aspect_h then aspect = aspect_h end @@ -34,22 +34,22 @@ function imagebox:draw(_, cr, width, height) end -- Set the clip - if self._clip_shape then - cr:clip(self._clip_shape(cr, width, height, unpack(self._clip_args))) + if self._private.clip_shape then + cr:clip(self._private.clip_shape(cr, width, height, unpack(self._private.clip_args))) end - cr:set_source_surface(self._image, 0, 0) + cr:set_source_surface(self._private.image, 0, 0) cr:paint() end -- Fit the imagebox into the given geometry function imagebox:fit(_, width, height) - if not self._image then + if not self._private.image then return 0, 0 end - local w = self._image:get_width() - local h = self._image:get_height() + local w = self._private.image:get_width() + local h = self._private.image:get_height() if w > width then h = h * width / w @@ -64,7 +64,7 @@ function imagebox:fit(_, width, height) return 0, 0 end - if not self.resize_forbidden then + if not self._private.resize_forbidden then local aspect = width / w local aspect_h = height / h @@ -78,9 +78,11 @@ function imagebox:fit(_, width, height) end --- Set an imagebox' image +-- @property image -- @param image Either a string or a cairo image surface. A string is -- interpreted as the path to a png image file. -- @return true on success, false if the image cannot be used + function imagebox:set_image(image) if type(image) == "string" then image = surface.load(image) @@ -100,19 +102,28 @@ function imagebox:set_image(image) end end - if self._image == image then + if self._private.image == image then -- The image could have been modified, so better redraw self:emit_signal("widget::redraw_needed") return end - self._image = image + self._private.image = image self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") return true end +--- Set a clip shape for this imagebox +-- A clip shape define an area where the content is displayed and one where it +-- is trimmed. +-- +-- @property clip_shape +-- @param clip_shape A `gears_shape` compatible shape function +-- @see gears.shape +-- @see set_clip_shape + --- Set a clip shape for this imagebox -- A clip shape define an area where the content is displayed and one where it -- is trimmed. @@ -120,17 +131,21 @@ end -- Any other parameters will be passed to the clip shape function -- -- @param clip_shape A `gears_shape` compatible shape function +-- @see gears.shape +-- @see clip_shape function imagebox:set_clip_shape(clip_shape, ...) - self._clip_shape = clip_shape - self._clip_args = {...} + self._private.clip_shape = clip_shape + self._private.clip_args = {...} self:emit_signal("widget::redraw_needed") end --- Should the image be resized to fit into the available space? +-- @property resize -- @param allowed If false, the image will be clipped, else it will be resized -- to fit into the available space. + function imagebox:set_resize(allowed) - self.resize_forbidden = not allowed + self._private.resize_forbidden = not allowed self:emit_signal("widget::redraw_needed") self:emit_signal("widget::layout_changed") end @@ -144,13 +159,9 @@ end -- @treturn table A new `imagebox` -- @function wibox.widget.imagebox local function new(image, resize_allowed, clip_shape) - local ret = base.make_widget() + local ret = base.make_widget(nil, nil, {enable_properties = true}) - for k, v in pairs(imagebox) do - if type(v) == "function" then - ret[k] = v - end - end + util.table.crush(ret, imagebox, true) if image then ret:set_image(image) @@ -159,8 +170,8 @@ local function new(image, resize_allowed, clip_shape) ret:set_resize(resize_allowed) end - ret._clip_shape = clip_shape - ret._clip_args = {} + ret._private.clip_shape = clip_shape + ret._private.clip_args = {} return ret end @@ -169,6 +180,10 @@ function imagebox.mt:__call(...) return new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(imagebox, imagebox.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 diff --git a/tests/test-awful-widget-button.lua b/tests/test-awful-widget-button.lua index f0cff928..ffb84e12 100644 --- a/tests/test-awful-widget-button.lua +++ b/tests/test-awful-widget-button.lua @@ -52,7 +52,7 @@ table.insert(steps, function() awful.placement.centered(w) - img = button._image + img = button._private.image assert(img) return true @@ -68,7 +68,7 @@ table.insert(steps, function() end) table.insert(steps, function() - assert(button._image ~= img) + assert(button._private.image ~= img) return true end) @@ -77,14 +77,14 @@ end) table.insert(steps, function() root.fake_input("button_release", 1) - assert(button._image ~= img) + assert(button._private.image ~= img) return true end) -- Test a button press/release outside of the widget table.insert(steps, function() - assert(button._image == img) + assert(button._private.image == img) root.fake_input("button_press", 1) @@ -92,14 +92,14 @@ table.insert(steps, function() end) table.insert(steps, function() - assert(button._image ~= img) + assert(button._private.image ~= img) return true end) table.insert(steps, function() -- just make sure the button is not released for nothing - assert(button._image ~= img) + assert(button._private.image ~= img) -- test if the button is released when the mouse move out awful.placement.right(mouse--[[, {parent = w}]]) @@ -109,7 +109,7 @@ table.insert(steps, function() end) table.insert(steps, function() - assert(button._image == img) + assert(button._private.image == img) return true end) From 18500838d95b41644cd2a77f6b9958854cdeed54 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 17:41:23 -0400 Subject: [PATCH 58/68] textclock: Add missing documentation --- lib/wibox/widget/textclock.lua | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/wibox/widget/textclock.lua b/lib/wibox/widget/textclock.lua index aec44521..221bed86 100644 --- a/lib/wibox/widget/textclock.lua +++ b/lib/wibox/widget/textclock.lua @@ -33,13 +33,13 @@ function textclock.new(format, timeout) local w = textbox() local t - function w._textclock_update_cb() + function w._private.textclock_update_cb() w:set_markup(DateTime.new_now_local():format(format)) t.timeout = calc_timeout(timeout) t:again() return true -- Continue the timer end - t = timer.weak_start_new(timeout, w._textclock_update_cb) + t = timer.weak_start_new(timeout, w._private.textclock_update_cb) t:emit_signal("timeout") return w end @@ -48,6 +48,10 @@ function textclock.mt:__call(...) return textclock.new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(textclock, textclock.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From b89fbcf940027bef766cd55839283a4d4f5759b3 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 19:41:58 -0400 Subject: [PATCH 59/68] fixed: Enable the property system And add the missing documentation --- docs/common/fixed.ldoc | 6 +-- lib/wibox/layout/fixed.lua | 82 +++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/docs/common/fixed.ldoc b/docs/common/fixed.ldoc index 4ac6b714..ce9ea846 100644 --- a/docs/common/fixed.ldoc +++ b/docs/common/fixed.ldoc @@ -29,11 +29,9 @@ -- @name swap_widgets -- @class function ---- Get all children of this layout. +--- Get all direct children of this layout. -- @param layout The layout you are modifying. --- @return a list of all widgets --- @name get_children --- @class function +-- @property children --- Reset a ratio layout. This removes all widgets from the layout. -- @param layout The layout you are modifying. diff --git a/lib/wibox/layout/fixed.lua b/lib/wibox/layout/fixed.lua index 57728b58..975c366f 100644 --- a/lib/wibox/layout/fixed.lua +++ b/lib/wibox/layout/fixed.lua @@ -23,28 +23,28 @@ local fixed = {} -- @param height The available height. function fixed:layout(context, width, height) local result = {} - local pos,spacing = 0, self._spacing + local pos,spacing = 0, self._private.spacing - for k, v in pairs(self.widgets) do + for k, v in pairs(self._private.widgets) do local x, y, w, h, _ - if self.dir == "y" then + if self._private.dir == "y" then x, y = 0, pos w, h = width, height - pos - if k ~= #self.widgets or not self._fill_space then + if k ~= #self._private.widgets or not self._private.fill_space then _, h = base.fit_widget(self, context, v, w, h); end pos = pos + h + spacing else x, y = pos, 0 w, h = width - pos, height - if k ~= #self.widgets or not self._fill_space then + if k ~= #self._private.widgets or not self._private.fill_space then w, _ = base.fit_widget(self, context, v, w, h); end pos = pos + w + spacing end - if (self.dir == "y" and pos-spacing > height) or - (self.dir ~= "y" and pos-spacing > width) then + if (self._private.dir == "y" and pos-spacing > height) or + (self._private.dir ~= "y" and pos-spacing > width) then break end table.insert(result, base.place_widget_at(v, x, y, w, h)) @@ -60,7 +60,7 @@ function fixed:add(...) assert(args.n > 0, "need at least one widget to add") for i=1, args.n do base.check_widget(args[i]) - table.insert(self.widgets, args[i]) + table.insert(self._private.widgets, args[i]) end self:emit_signal("widget::layout_changed") end @@ -70,9 +70,9 @@ end -- @tparam number index The widget index to remove -- @treturn boolean index If the operation is successful function fixed:remove(index) - if not index or index < 1 or index > #self.widgets then return false end + if not index or index < 1 or index > #self._private.widgets then return false end - table.remove(self.widgets, index) + table.remove(self._private.widgets, index) self:emit_signal("widget::layout_changed") @@ -106,14 +106,10 @@ function fixed:remove_widgets(...) return #args > (recursive and 1 or 0) and ret end ---- Get all children of this layout --- @treturn table a list of all widgets function fixed:get_children() - return self.widgets + return self._private.widgets end ---- Replace the layout children --- @tparam table children A table composed of valid widgets function fixed:set_children(children) self:reset() if #children > 0 then @@ -138,12 +134,12 @@ function fixed:replace_widget(widget, widget2, recursive) end function fixed:swap(index1, index2) - if not index1 or not index2 or index1 > #self.widgets - or index2 > #self.widgets then + if not index1 or not index2 or index1 > #self._private.widgets + or index2 > #self._private.widgets then return false end - local widget1, widget2 = self.widgets[index1], self.widgets[index2] + local widget1, widget2 = self._private.widgets[index1], self._private.widgets[index2] self:set(index1, widget2) self:set(index2, widget1) @@ -177,11 +173,11 @@ function fixed:swap_widgets(widget1, widget2, recursive) end function fixed:set(index, widget2) - if (not widget2) or (not self.widgets[index]) then return false end + if (not widget2) or (not self._private.widgets[index]) then return false end base.check_widget(widget2) - self.widgets[index] = widget2 + self._private.widgets[index] = widget2 self:emit_signal("widget::layout_changed") @@ -193,10 +189,10 @@ end -- @param widget The widget -- @treturn boolean If the operation is successful function fixed:insert(index, widget) - if not index or index < 1 or index > #self.widgets + 1 then return false end + if not index or index < 1 or index > #self._private.widgets + 1 then return false end base.check_widget(widget) - table.insert(self.widgets, index, widget) + table.insert(self._private.widgets, index, widget) self:emit_signal("widget::layout_changed") return true @@ -210,10 +206,10 @@ function fixed:fit(context, orig_width, orig_height) local width, height = orig_width, orig_height local used_in_dir, used_max = 0, 0 - for _, v in pairs(self.widgets) do + for _, v in pairs(self._private.widgets) do local w, h = base.fit_widget(self, context, v, width, height) local in_dir, max - if self.dir == "y" then + if self._private.dir == "y" then max, in_dir = w, h height = height - in_dir else @@ -226,7 +222,7 @@ function fixed:fit(context, orig_width, orig_height) used_in_dir = used_in_dir + in_dir if width <= 0 or height <= 0 then - if self.dir == "y" then + if self._private.dir == "y" then used_in_dir = orig_height else used_in_dir = orig_width @@ -235,36 +231,38 @@ function fixed:fit(context, orig_width, orig_height) end end - local spacing = self._spacing * (#self.widgets-1) + local spacing = self._private.spacing * (#self._private.widgets-1) - if self.dir == "y" then + if self._private.dir == "y" then return used_max, used_in_dir + spacing end return used_in_dir + spacing, used_max end function fixed:reset() - self.widgets = {} + self._private.widgets = {} self:emit_signal("widget::layout_changed") end --- Set the layout's fill_space property. If this property is true, the last -- widget will get all the space that is left. If this is false, the last widget -- won't be handled specially and there can be space left unused. +-- @property fill_space + function fixed:fill_space(val) - if self._fill_space ~= val then - self._fill_space = not not val + if self._private.fill_space ~= val then + self._private.fill_space = not not val self:emit_signal("widget::layout_changed") end end local function get_layout(dir, widget1, ...) - local ret = base.make_widget() + local ret = base.make_widget(nil, nil, {enable_properties = true}) - util.table.crush(ret, fixed) + util.table.crush(ret, fixed, true) - ret.dir = dir - ret.widgets = {} + ret._private.dir = dir + ret._private.widgets = {} ret:set_spacing(0) ret:fill_space(false) @@ -294,14 +292,24 @@ function fixed.vertical(...) end --- Add spacing between each layout widgets --- @param spacing Spacing between widgets. +-- @property spacing +-- @tparam number spacing Spacing between widgets. + function fixed:set_spacing(spacing) - if self._spacing ~= spacing then - self._spacing = spacing + if self._private.spacing ~= spacing then + self._private.spacing = spacing self:emit_signal("widget::layout_changed") end end +function fixed:get_spacing() + return self._private.spacing or 0 +end + +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return fixed -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 0a8bc8156dcf0b3c4bce3367c34de58333e490f5 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 19:41:58 -0400 Subject: [PATCH 60/68] align: Enable the property system And add the missing documentation --- lib/wibox/layout/align.lua | 140 +++++++++++++++++++++---------------- 1 file changed, 80 insertions(+), 60 deletions(-) diff --git a/lib/wibox/layout/align.lua b/lib/wibox/layout/align.lua index 642db2a4..7c3e45e5 100644 --- a/lib/wibox/layout/align.lua +++ b/lib/wibox/layout/align.lua @@ -32,7 +32,7 @@ function align:layout(context, width, height) -- allowed. local size_first = 0 -- start with all the space given by the parent, subtract as we go along - local size_remains = self.dir == "y" and height or width + local size_remains = self._private.dir == "y" and height or width -- This is only set & used if expand ~= "inside" and we have second width. -- It contains the size allocated to the second widget. local size_second @@ -41,84 +41,84 @@ function align:layout(context, width, height) -- if it is, we prioritize the first widget by not doing this block also, -- if the second widget doesn't exist, we will prioritise the first one -- instead - if self._expand ~= "inside" and self.second then - local w, h = base.fit_widget(self, context, self.second, width, height) - size_second = self.dir == "y" and h or w + if self._private.expand ~= "inside" and self._private.second then + local w, h = base.fit_widget(self, context, self._private.second, width, height) + size_second = self._private.dir == "y" and h or w -- if all the space is taken, skip the rest, and draw just the middle -- widget if size_second >= size_remains then - return { base.place_widget_at(self.second, 0, 0, width, height) } + return { base.place_widget_at(self._private.second, 0, 0, width, height) } else -- the middle widget is sized first, the outside widgets are given -- the remaining space if available we will draw later size_remains = floor((size_remains - size_second) / 2) end end - if self.first then + if self._private.first then local w, h, _ = width, height, nil -- we use the fit function for the "inside" and "none" modes, but -- ignore it for the "outside" mode, which will force it to expand -- into the remaining space - if self._expand ~= "outside" then - if self.dir == "y" then - _, h = base.fit_widget(self, context, self.first, width, size_remains) + if self._private.expand ~= "outside" then + if self._private.dir == "y" then + _, h = base.fit_widget(self, context, self._private.first, width, size_remains) size_first = h -- for "inside", the third widget will get a chance to use the -- remaining space, then the middle widget. For "none" we give -- the third widget the remaining space if there was no second -- widget to take up any space (as the first if block is skipped -- if this is the case) - if self._expand == "inside" or not self.second then + if self._private.expand == "inside" or not self._private.second then size_remains = size_remains - h end else - w, _ = base.fit_widget(self, context, self.first, size_remains, height) + w, _ = base.fit_widget(self, context, self._private.first, size_remains, height) size_first = w - if self._expand == "inside" or not self.second then + if self._private.expand == "inside" or not self._private.second then size_remains = size_remains - w end end else - if self.dir == "y" then + if self._private.dir == "y" then h = size_remains else w = size_remains end end - table.insert(result, base.place_widget_at(self.first, 0, 0, w, h)) + table.insert(result, base.place_widget_at(self._private.first, 0, 0, w, h)) end -- size_remains will be <= 0 if first used all the space - if self.third and size_remains > 0 then + if self._private.third and size_remains > 0 then local w, h, _ = width, height, nil - if self._expand ~= "outside" then - if self.dir == "y" then - _, h = base.fit_widget(self, context, self.third, width, size_remains) + if self._private.expand ~= "outside" then + if self._private.dir == "y" then + _, h = base.fit_widget(self, context, self._private.third, width, size_remains) -- give the middle widget the rest of the space for "inside" mode - if self._expand == "inside" then + if self._private.expand == "inside" then size_remains = size_remains - h end else - w, _ = base.fit_widget(self, context, self.third, size_remains, height) - if self._expand == "inside" then + w, _ = base.fit_widget(self, context, self._private.third, size_remains, height) + if self._private.expand == "inside" then size_remains = size_remains - w end end else - if self.dir == "y" then + if self._private.dir == "y" then h = size_remains else w = size_remains end end local x, y = width - w, height - h - table.insert(result, base.place_widget_at(self.third, x, y, w, h)) + table.insert(result, base.place_widget_at(self._private.third, x, y, w, h)) end -- here we either draw the second widget in the space set aside for it -- in the beginning, or in the remaining space, if it is "inside" - if self.second and size_remains > 0 then + if self._private.second and size_remains > 0 then local x, y, w, h = 0, 0, width, height - if self._expand == "inside" then - if self.dir == "y" then + if self._private.expand == "inside" then + if self._private.dir == "y" then h = size_remains x, y = 0, size_first else @@ -127,55 +127,69 @@ function align:layout(context, width, height) end else local _ - if self.dir == "y" then - _, h = base.fit_widget(self, context, self.second, width, size_second) + if self._private.dir == "y" then + _, h = base.fit_widget(self, context, self._private.second, width, size_second) y = floor( (height - h)/2 ) else - w, _ = base.fit_widget(self, context, self.second, size_second, height) + w, _ = base.fit_widget(self, context, self._private.second, size_second, height) x = floor( (width -w)/2 ) end end - table.insert(result, base.place_widget_at(self.second, x, y, w, h)) + table.insert(result, base.place_widget_at(self._private.second, x, y, w, h)) end return result end ---- Set the layout's first widget. This is the widget that is at the left/top +--- Set the layout's first widget. +-- This is the widget that is at the left/top +-- @property first + function align:set_first(widget) - if self.first == widget then + if self._private.first == widget then return end - self.first = widget + self._private.first = widget self:emit_signal("widget::layout_changed") end --- Set the layout's second widget. This is the centered one. +-- @property second + function align:set_second(widget) - if self.second == widget then + if self._private.second == widget then return end - self.second = widget + self._private.second = widget self:emit_signal("widget::layout_changed") end ---- Set the layout's third widget. This is the widget that is at the right/bottom +--- Set the layout's third widget. +-- This is the widget that is at the right/bottom +-- @property third + function align:set_third(widget) - if self.third == widget then + if self._private.third == widget then return end - self.third = widget + self._private.third = widget self:emit_signal("widget::layout_changed") end ---- Get all children of this layout --- @treturn table a list of all widgets -function align:get_children() - return util.from_sparse {self.first, self.second, self.third} +for _, prop in ipairs {"first", "second", "third", "expand" } do + align["get_"..prop] = function(self) + return self._private[prop] + end +end + +--- All direct children of this layout. +-- This can be used to replace all 3 widgets at once. +-- @treturn table a list of all widgets +-- @property children + +function align:get_children() + return util.from_sparse {self._private.first, self._private.second, self._private.third} end ---- Replace the layout children --- This layout only accept three children, all others will be ignored --- @tparam table children A table composed of valid widgets function align:set_children(children) self:set_first(children[1]) self:set_second(children[2]) @@ -192,18 +206,18 @@ function align:fit(context, orig_width, orig_height) local used_in_dir = 0 local used_in_other = 0 - for _, v in pairs{self.first, self.second, self.third} do + for _, v in pairs{self._private.first, self._private.second, self._private.third} do local w, h = base.fit_widget(self, context, v, orig_width, orig_height) - local max = self.dir == "y" and w or h + local max = self._private.dir == "y" and w or h if max > used_in_other then used_in_other = max end - used_in_dir = used_in_dir + (self.dir == "y" and h or w) + used_in_dir = used_in_dir + (self._private.dir == "y" and h or w) end - if self.dir == "y" then + if self._private.dir == "y" then return used_in_other, used_in_dir end return used_in_dir, used_in_other @@ -223,11 +237,13 @@ end -- * "none" - All widgets are sized using their fit function, drawn to only the -- returned space, or remaining space, whichever is smaller. Center widget -- gets priority. +-- @property expand + function align:set_expand(mode) if mode == "none" or mode == "outside" then - self._expand = mode + self._private.expand = mode else - self._expand = "inside" + self._private.expand = "inside" end self:emit_signal("widget::layout_changed") end @@ -240,12 +256,12 @@ function align:reset() end local function get_layout(dir, first, second, third) - local ret = base.make_widget() - ret.dir = dir + local ret = base.make_widget(nil, nil, {enable_properties = true}) + ret._private.dir = dir for k, v in pairs(align) do if type(v) == "function" then - ret[k] = v + rawset(ret, k, v) end end @@ -270,9 +286,9 @@ end function align.horizontal(left, middle, right) local ret = get_layout("x", left, middle, right) - ret.set_left = ret.set_first - ret.set_middle = ret.set_second - ret.set_right = ret.set_third + rawset(ret, "set_left" , ret.set_first ) + rawset(ret, "set_middle", ret.set_second ) + rawset(ret, "set_right" , ret.set_third ) return ret end @@ -287,13 +303,17 @@ end function align.vertical(top, middle, bottom) local ret = get_layout("y", top, middle, bottom) - ret.set_top = ret.set_first - ret.set_middle = ret.set_second - ret.set_bottom = ret.set_third + rawset(ret, "set_top" , ret.set_first ) + rawset(ret, "set_middle", ret.set_second ) + rawset(ret, "set_bottom", ret.set_third ) return ret end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return align -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From eddbbf7acac3270af89985a31751ab87bedf1ef7 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 19:41:58 -0400 Subject: [PATCH 61/68] ratio: Enable the property system And add the missing documentation --- lib/wibox/layout/ratio.lua | 92 ++++++++++++++++++++------------------ 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/lib/wibox/layout/ratio.lua b/lib/wibox/layout/ratio.lua index 98c5132f..072b64af 100644 --- a/lib/wibox/layout/ratio.lua +++ b/lib/wibox/layout/ratio.lua @@ -25,9 +25,9 @@ local ratio = {} local function gen_sum(self, i_s, i_e) local sum, new_w = 0,0 - for i = i_s or 1, i_e or #self.widgets do - if self._ratios[i] then - sum = sum + self._ratios[i] + for i = i_s or 1, i_e or #self._private.widgets do + if self._private.ratios[i] then + sum = sum + self._private.ratios[i] else new_w = new_w + 1 end @@ -42,24 +42,24 @@ end -- specific ratio must be enforced for a widget, it has to be done with the -- `ajust_ratio` method after each insertion or deletion local function normalize(self) - local count = #self.widgets + local count = #self._private.widgets if count == 0 then return end -- Instead of adding "if" everywhere, just handle this common case if count == 1 then - self._ratios = { 1 } + self._private.ratios = { 1 } return end local sum, new_w = gen_sum(self) - local old_count = #self.widgets - new_w + local old_count = #self._private.widgets - new_w local to_add = (sum == 0) and 1 or (sum / old_count) -- Make sure all widgets have a ratio - for i=1, #self.widgets do - if not self._ratios[i] then - self._ratios[i] = to_add + for i=1, #self._private.widgets do + if not self._private.ratios[i] then + self._private.ratios[i] = to_add end end @@ -68,9 +68,9 @@ local function normalize(self) local delta, new_sum = (1 - sum) / count,0 -- Increase or decrease each ratio so it the sum become 1 - for i=1, #self.widgets do - self._ratios[i] = self._ratios[i] + delta - new_sum = new_sum + self._ratios[i] + for i=1, #self._private.widgets do + self._private.ratios[i] = self._private.ratios[i] + delta + new_sum = new_sum + self._private.ratios[i] end -- Floating points is not an exact science, but it should still be close @@ -80,18 +80,18 @@ end function ratio:layout(_, width, height) local result = {} - local pos,spacing = 0, self._spacing + local pos,spacing = 0, self._private.spacing - for k, v in ipairs(self.widgets) do + for k, v in ipairs(self._private.widgets) do local space local x, y, w, h - if self.dir == "y" then - space = height * self._ratios[k] + if self._private.dir == "y" then + space = height * self._private.ratios[k] x, y = 0, util.round(pos) w, h = width, floor(space) else - space = width * self._ratios[k] + space = width * self._private.ratios[k] x, y = util.round(pos), 0 w, h = floor(space), height end @@ -102,8 +102,8 @@ function ratio:layout(_, width, height) -- Make sure all widgets fit in the layout, if they aren't, something -- went wrong - if (self.dir == "y" and util.round(pos) >= height) or - (self.dir ~= "y" and util.round(pos) >= width) then + if (self._private.dir == "y" and util.round(pos) >= height) or + (self._private.dir ~= "y" and util.round(pos) >= width) then break end end @@ -118,14 +118,14 @@ end -- @tparam number increment An floating point value between -1 and 1 where the -- end result is within 0 and 1 function ratio:inc_ratio(index, increment) - if #self.widgets == 1 or (not index) or (not self._ratios[index]) + if #self._private.widgets == 1 or (not index) or (not self._private.ratios[index]) or increment < -1 or increment > 1 then return end - assert(self._ratios[index]) + assert(self._private.ratios[index]) - self:set_ratio(index, self._ratios[index] + increment) + self:set_ratio(index, self._private.ratios[index] + increment) end --- Increment the ratio of the first instance of `widget` @@ -146,22 +146,22 @@ end -- @tparam number index The index of the widget to change -- @tparam number percent An floating point value between 0 and 1 function ratio:set_ratio(index, percent) - if not percent or #self.widgets == 1 or not index or not self.widgets[index] + if not percent or #self._private.widgets == 1 or not index or not self._private.widgets[index] or percent < 0 or percent > 1 then return end - local old = self._ratios[index] + local old = self._private.ratios[index] -- Remove what has to be cleared from all widget - local delta = ( (percent-old) / (#self.widgets-1) ) + local delta = ( (percent-old) / (#self._private.widgets-1) ) - for k in pairs(self.widgets) do - self._ratios[k] = self._ratios[k] - delta + for k in pairs(self._private.widgets) do + self._private.ratios[k] = self._private.ratios[k] - delta end -- Set the new ratio - self._ratios[index] = percent + self._private.ratios[index] = percent -- As some widgets may now have a slightly negative ratio, normalize again normalize(self) @@ -174,7 +174,7 @@ end -- @treturn number The index (between 0 and 1) function ratio:get_ratio(index) if not index then return end - return self._ratios[index] + return self._private.ratios[index] end --- Set the ratio of `widget` to `percent`. @@ -193,7 +193,7 @@ end -- @tparam number itself The ratio for "widget" -- @tparam number after The sum of the ratio after the widget function ratio:ajust_ratio(index, before, itself, after) - if not self.widgets[index] or not before or not itself or not after then + if not self._private.widgets[index] or not before or not itself or not after then return end @@ -204,21 +204,21 @@ function ratio:ajust_ratio(index, before, itself, after) if sum > 1.01 or sum < -0.99 then return end -- Compute the before and after offset to be applied to each widgets - local before_count, after_count = index-1, #self.widgets - index + local before_count, after_count = index-1, #self._private.widgets - index local b, a = gen_sum(self, 1, index-1), gen_sum(self, index+1) local db, da = (before - b)/before_count, (after - a)/after_count -- Apply the new ratio - self._ratios[index] = itself + self._private.ratios[index] = itself -- Equality split the delta among widgets before and after for i = 1, index -1 do - self._ratios[i] = self._ratios[i] + db + self._private.ratios[i] = self._private.ratios[i] + db end - for i = index+1, #self.widgets do - self._ratios[i] = self._ratios[i] + da + for i = index+1, #self._private.widgets do + self._private.ratios[i] = self._private.ratios[i] + da end -- Remove potential negative ratio @@ -245,7 +245,7 @@ function ratio:add(...) assert(args.n > 0, "need at least one widget to add") for i=1, args.n do base.check_widget(args[i]) - table.insert(self.widgets, args[i]) + table.insert(self._private.widgets, args[i]) end normalize(self) @@ -256,10 +256,10 @@ end -- @tparam number index The widget index to remove -- @treturn boolean index If the operation is successful function ratio:remove(index) - if not index or not self.widgets[index] then return false end + if not index or not self._private.widgets[index] then return false end - table.remove(self._ratios, index) - table.remove(self.widgets, index) + table.remove(self._private.ratios, index) + table.remove(self._private.widgets, index) normalize(self) @@ -272,11 +272,11 @@ end -- @tparam number index The position -- @param widget The widget function ratio:insert(index, widget) - if not index or index < 1 or index > #self.widgets + 1 then return false end + if not index or index < 1 or index > #self._private.widgets + 1 then return false end base.check_widget(widget) - table.insert(self.widgets, index, widget) + table.insert(self._private.widgets, index, widget) normalize(self) @@ -286,11 +286,11 @@ end local function get_layout(dir, widget1, ...) local ret = flex[dir](widget1, ...) - util.table.crush(ret, ratio) + util.table.crush(ret, ratio, true) - ret.fill_space = nil + ret._private.fill_space = nil - ret._ratios = {} + ret._private.ratios = {} return ret end @@ -309,6 +309,10 @@ function ratio.vertical(...) return get_layout("vertical", ...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return ratio -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 23729b62968c74f4bd452fcaafbb9c4ad1b71eea Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 19:41:58 -0400 Subject: [PATCH 62/68] flex: Enable the property system And add the missing documentation --- lib/wibox/layout/flex.lua | 56 ++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/lib/wibox/layout/flex.lua b/lib/wibox/layout/flex.lua index cef6b99e..3d525d3e 100644 --- a/lib/wibox/layout/flex.lua +++ b/lib/wibox/layout/flex.lua @@ -52,24 +52,24 @@ local flex = {} function flex:layout(_, width, height) local result = {} - local pos,spacing = 0, self._spacing - local num = #self.widgets + local pos,spacing = 0, self._private.spacing + local num = #self._private.widgets local total_spacing = (spacing*(num-1)) local space_per_item - if self.dir == "y" then + if self._private.dir == "y" then space_per_item = height / num - total_spacing/num else space_per_item = width / num - total_spacing/num end - if self._max_widget_size then - space_per_item = math.min(space_per_item, self._max_widget_size) + if self._private.max_widget_size then + space_per_item = math.min(space_per_item, self._private.max_widget_size) end - for _, v in pairs(self.widgets) do + for _, v in pairs(self._private.widgets) do local x, y, w, h - if self.dir == "y" then + if self._private.dir == "y" then x, y = 0, util.round(pos) w, h = width, floor(space_per_item) else @@ -81,8 +81,8 @@ function flex:layout(_, width, height) pos = pos + space_per_item + spacing - if (self.dir == "y" and pos-spacing >= height) or - (self.dir ~= "y" and pos-spacing >= width) then + if (self._private.dir == "y" and pos-spacing >= height) or + (self._private.dir ~= "y" and pos-spacing >= width) then break end end @@ -99,39 +99,41 @@ function flex:fit(context, orig_width, orig_height) local used_in_other = 0 -- Figure out the maximum size we can give out to sub-widgets - local sub_height = self.dir == "x" and orig_height or orig_height / #self.widgets - local sub_width = self.dir == "y" and orig_width or orig_width / #self.widgets + local sub_height = self._private.dir == "x" and orig_height or orig_height / #self._private.widgets + local sub_width = self._private.dir == "y" and orig_width or orig_width / #self._private.widgets - for _, v in pairs(self.widgets) do + for _, v in pairs(self._private.widgets) do local w, h = base.fit_widget(self, context, v, sub_width, sub_height) - local max = self.dir == "y" and w or h + local max = self._private.dir == "y" and w or h if max > used_in_other then used_in_other = max end - used_in_dir = used_in_dir + (self.dir == "y" and h or w) + used_in_dir = used_in_dir + (self._private.dir == "y" and h or w) end - if self._max_widget_size then + if self._private.max_widget_size then used_in_dir = math.min(used_in_dir, - #self.widgets * self._max_widget_size) + #self._private.widgets * self._private.max_widget_size) end - local spacing = self._spacing * (#self.widgets-1) + local spacing = self._private.spacing * (#self._private.widgets-1) - if self.dir == "y" then + if self._private.dir == "y" then return used_in_other, used_in_dir + spacing end return used_in_dir + spacing, used_in_other end ---- Set the maximum size the widgets in this layout will take (that is, --- maximum width for horizontal and maximum height for vertical). --- @param val The maximum size of the widget. +--- Set the maximum size the widgets in this layout will take. +--That is, maximum width for horizontal and maximum height for vertical. +-- @property max_widget_size +-- @param number + function flex:set_max_widget_size(val) - if self._max_widget_size ~= val then - self._max_widget_size = val + if self._private.max_widget_size ~= val then + self._private.max_widget_size = val self:emit_signal("widget::layout_changed") end end @@ -139,9 +141,9 @@ end local function get_layout(dir, widget1, ...) local ret = fixed[dir](widget1, ...) - util.table.crush(ret, flex) + util.table.crush(ret, flex, true) - ret.fill_space = nil + ret._private.fill_space = nil return ret end @@ -162,6 +164,10 @@ function flex.vertical(...) return get_layout("vertical", ...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return flex -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From f9ff2f4909f22f86da8c625a4e1f0412210fe4d4 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Thu, 26 May 2016 19:41:58 -0400 Subject: [PATCH 63/68] stack: Enable the property system And add the missing documentation --- lib/wibox/layout/stack.lua | 44 ++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/lib/wibox/layout/stack.lua b/lib/wibox/layout/stack.lua index a7020a62..ff33f5a0 100644 --- a/lib/wibox/layout/stack.lua +++ b/lib/wibox/layout/stack.lua @@ -53,17 +53,16 @@ local stack = {mt={}} -- @class function --- Add spacing between each layout widgets --- @param spacing Spacing between widgets. --- @name set_spacing --- @class function +-- @property spacing +-- @tparam number spacing Spacing between widgets. function stack:layout(_, width, height) local result = {} - local spacing = self._spacing + local spacing = self._private.spacing - for _, v in pairs(self.widgets) do + for _, v in pairs(self._private.widgets) do table.insert(result, base.place_widget_at(v, spacing, spacing, width - 2*spacing, height - 2*spacing)) - if self._top_only then break end + if self._private.top_only then break end end return result @@ -71,9 +70,9 @@ end function stack:fit(context, orig_width, orig_height) local max_w, max_h = 0,0 - local spacing = self._spacing + local spacing = self._private.spacing - for _, v in pairs(self.widgets) do + for _, v in pairs(self._private.widgets) do local w, h = base.fit_widget(self, context, v, orig_width, orig_height) max_w, max_h = math.max(max_w, w+2*spacing), math.max(max_h, h+2*spacing) end @@ -81,26 +80,25 @@ function stack:fit(context, orig_width, orig_height) return math.min(max_w, orig_width), math.min(max_h, orig_height) end ---- Get if only the first stack widget is drawn --- @return If the only the first stack widget is drawn -function stack:get_display_top_only() - return self._top_only +--- If only the first stack widget is drawn +-- @property top_only + +function stack:get_top_only() + return self._private.top_only end ---- Only draw the first widget of the stack, ignore others --- @tparam boolean top_only Only draw the top stack widget -function stack:set_display_top_only(top_only) - self._top_only = top_only +function stack:set_top_only(top_only) + self._private.top_only = top_only end --- Raise a widget at `index` to the top of the stack -- @tparam number index the widget index to raise function stack:raise(index) - if (not index) or self.widgets[index] then return end + if (not index) or self._private.widgets[index] then return end - local w = self.widgets[index] - table.remove(self.widgets, index) - table.insert(self.widgets, w) + local w = self._private.widgets[index] + table.remove(self._private.widgets, index) + table.insert(self._private.widgets, w) self:emit_signal("widget::layout_changed") end @@ -131,7 +129,7 @@ end local function new(...) local ret = fixed.horizontal(...) - util.table.crush(ret, stack) + util.table.crush(ret, stack, true) return ret end @@ -140,5 +138,9 @@ function stack.mt:__call(_, ...) return new(...) end +--@DOC_widget_COMMON@ + +--@DOC_object_COMMON@ + return setmetatable(stack, stack.mt) -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 From 7c00b2a55aa6f079fc96e25b5ff000bb081aea2e Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 27 May 2016 01:23:12 -0400 Subject: [PATCH 64/68] graph: Add theme options --- lib/wibox/widget/graph.lua | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/wibox/widget/graph.lua b/lib/wibox/widget/graph.lua index d1c9bfa5..802cc0c9 100644 --- a/lib/wibox/widget/graph.lua +++ b/lib/wibox/widget/graph.lua @@ -15,6 +15,7 @@ local table = table local type = type local color = require("gears.color") local base = require("wibox.widget.base") +local beautiful = require("beautiful") local graph = { mt = {} } @@ -57,6 +58,15 @@ local graph = { mt = {} } -- @property stack_colors -- @param stack_colors A table with stacking colors. +--- The graph background color. +-- @beautiful beautiful.graph_bg + +--- The graph foreground color. +-- @beautiful beautiful.graph_fg + +--- The graph border color. +-- @beautiful beautiful.graph_border_color + local properties = { "width", "height", "border_color", "stack", "stack_colors", "color", "background_color", "max_value", "scale" } @@ -68,7 +78,7 @@ function graph.draw(_graph, _, cr, width, height) cr:set_line_width(1) -- Draw the background first - cr:set_source(color(_graph._private.background_color or "#000000aa")) + cr:set_source(color(_graph._private.background_color or beautiful.graph_bg or "#000000aa")) cr:paint() -- Account for the border width @@ -102,7 +112,7 @@ function graph.draw(_graph, _, cr, width, height) local value = stack_values[#stack_values - i] + rel_i cr:move_to(rel_x, height * (1 - (rel_i / max_value))) cr:line_to(rel_x, height * (1 - (value / max_value))) - cr:set_source(color(col or "#ff0000")) + cr:set_source(color(col or beautiful.graph_fg or "#ff0000")) cr:stroke() rel_i = value end @@ -129,7 +139,7 @@ function graph.draw(_graph, _, cr, width, height) cr:line_to(i + 0.5, height) end end - cr:set_source(color(_graph._private.color or "#ff0000")) + cr:set_source(color(_graph._private.color or beautiful.graph_fg or "#ff0000")) cr:stroke() end @@ -145,7 +155,7 @@ function graph.draw(_graph, _, cr, width, height) -- Draw the border cr:rectangle(0.5, 0.5, width - 1, height - 1) - cr:set_source(color(_graph._private.border_color or "#ffffff")) + cr:set_source(color(_graph._private.border_color or beautiful.graph_border_color or "#ffffff")) cr:stroke() end end From cbe046b0db78920ece4c4809e245b5278bbac1f2 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 27 May 2016 01:26:46 -0400 Subject: [PATCH 65/68] progressbar: Add theme options --- lib/wibox/widget/progressbar.lua | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/wibox/widget/progressbar.lua b/lib/wibox/widget/progressbar.lua index 6e4b6ecf..885d7e85 100644 --- a/lib/wibox/widget/progressbar.lua +++ b/lib/wibox/widget/progressbar.lua @@ -13,6 +13,7 @@ local ipairs = ipairs local math = math local base = require("wibox.widget.base") local color = require("gears.color") +local beautiful = require("beautiful") local progressbar = { mt = {} } @@ -67,6 +68,15 @@ local data = setmetatable({}, { __mode = "k" }) -- @param progressbar The progressbar. -- @param value The value. +--- The progressbar background color. +-- @beautiful beautiful.graph_bg + +--- The progressbar foreground color. +-- @beautiful beautiful.graph_fg + +--- The progressbar border color. +-- @beautiful beautiful.graph_border_color + local properties = { "width", "height", "border_color", "color", "background_color", "vertical", "value", "max_value", @@ -88,10 +98,11 @@ function progressbar.draw(pbar, _, cr, width, height) local over_drawn_width = width local over_drawn_height = height local border_width = 0 - if data[pbar].border_color then + local col = data[pbar].border_color or beautiful.progressbar_border_color + if col then -- Draw border cr:rectangle(0.5, 0.5, width - 1, height - 1) - cr:set_source(color(data[pbar].border_color)) + cr:set_source(color(col)) cr:stroke() over_drawn_width = width - 2 -- remove 2 for borders @@ -101,7 +112,7 @@ function progressbar.draw(pbar, _, cr, width, height) cr:rectangle(border_width, border_width, over_drawn_width, over_drawn_height) - cr:set_source(color(data[pbar].color or "#ff0000")) + cr:set_source(color(data[pbar].color or beautiful.progressbar_fg or "#ff0000")) cr:fill() -- Cover the part that is not set with a rectangle @@ -111,7 +122,7 @@ function progressbar.draw(pbar, _, cr, width, height) border_width, over_drawn_width, rel_height) - cr:set_source(color(data[pbar].background_color or "#000000aa")) + cr:set_source(color(data[pbar].background_color or beautiful.progressbar_bg or "#000000aa")) cr:fill() -- Place smaller pieces over the gradient if ticks are enabled @@ -126,7 +137,7 @@ function progressbar.draw(pbar, _, cr, width, height) ticks_gap) end end - cr:set_source(color(data[pbar].background_color or "#000000aa")) + cr:set_source(color(data[pbar].background_color or beautiful.progressbar_bg or "#000000aa")) cr:fill() end else From 505db433d610e0ceb2752989c7b29d290dfcb58c Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 27 May 2016 01:28:57 -0400 Subject: [PATCH 66/68] shims: Support graph and progresssbar colors --- tests/examples/shims/beautiful.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/examples/shims/beautiful.lua b/tests/examples/shims/beautiful.lua index 85115ede..72a9a711 100644 --- a/tests/examples/shims/beautiful.lua +++ b/tests/examples/shims/beautiful.lua @@ -39,6 +39,12 @@ local module = { awesome_icon = logo() } +module.graph_bg = module.bg_normal +module.graph_fg = module.bg_highlight + +module.progressbar_bg = module.bg_normal +module.progressbar_fg = module.bg_highlight + local f = Pango.FontDescription.from_string("sans 8") function module.get_font() From 72c437a7c8add458084580d7f7f3e2f4763cb9a3 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Mon, 30 May 2016 23:12:39 -0400 Subject: [PATCH 67/68] test: Fix widget cache --- spec/wibox/test_utils.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/wibox/test_utils.lua b/spec/wibox/test_utils.lua index 47a1138a..dd895e74 100644 --- a/spec/wibox/test_utils.lua +++ b/spec/wibox/test_utils.lua @@ -93,7 +93,7 @@ return { return width or 10, height or 10 end end - w._widget_caches = {} + w._private.widget_caches = {} return w end, From 756862dff6de262e8773ca845f168e2bf9c116af Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 27 May 2016 23:22:46 -0400 Subject: [PATCH 68/68] systray: Use table.crush --- lib/wibox/widget/systray.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/wibox/widget/systray.lua b/lib/wibox/widget/systray.lua index 7bec8988..6808332f 100644 --- a/lib/wibox/widget/systray.lua +++ b/lib/wibox/widget/systray.lua @@ -7,6 +7,7 @@ local wbase = require("wibox.widget.base") local beautiful = require("beautiful") +local util = require("awful.util") local capi = { awesome = awesome, screen = screen @@ -155,9 +156,7 @@ end local function new(revers) local ret = wbase.make_widget() - for k, v in pairs(systray) do - ret[k] = v - end + util.table.crush(ret, systray, true) if revers then ret:set_reverse(true)