diff --git a/docs/89-NEWS.md b/docs/89-NEWS.md index a7e5af538..78c78cea7 100644 --- a/docs/89-NEWS.md +++ b/docs/89-NEWS.md @@ -89,6 +89,9 @@ This document was last updated at commit v4.3-197-g9085ed631. * Pango 1.44 is now the oldest recommended Pango version. Older versions are still supported, but will lack the ability to use some textbox properties, mainly `wibox.widget.textbox.line_spacing_factor`. + * The `wibox.layout.grid` layout `expand`, `spacing` and `homogeneous` + property getters now return a table instead of a number. The table contains + a `horizontal` and a `vertical` key. # Awesome window manager framework version 4.3 changes diff --git a/lib/wibox/layout/grid.lua b/lib/wibox/layout/grid.lua index 9ef13ffd9..7241a3430 100644 --- a/lib/wibox/layout/grid.lua +++ b/lib/wibox/layout/grid.lua @@ -7,8 +7,14 @@ -- --@DOC_wibox_layout_grid_imperative_EXAMPLE@ -- --- Using the declarative system, widgets are automatically added next to each --- other spanning only one cell. +-- The same can be done using the declarative syntax: +-- +--@DOC_wibox_layout_grid_declarative1_EXAMPLE@ +-- +-- When `col_index` and `row_index` are not provided, the widgets are +-- automatically added next to each other spanning only one cell: +-- +--@DOC_wibox_layout_grid_declarative2_EXAMPLE@ -- --@DOC_wibox_layout_defaults_grid_EXAMPLE@ -- @author getzze @@ -24,15 +30,18 @@ local pairs = pairs local ipairs = ipairs local math = math local gtable = require("gears.table") +local gmath = require("gears.math") +local gcolor = require("gears.color") +local gdebug = require("gears.debug") local base = require("wibox.widget.base") +local cairo = require("lgi").cairo local grid = { mt = {} } local properties = { - "orientation", "superpose", - "forced_num_rows", "forced_num_cols", - "min_cols_size", "min_rows_size", - } + "orientation", "superpose", + "forced_row_count", "forced_column_count", +} local dir_properties = { "spacing", "homogeneous", "expand" } @@ -61,41 +70,72 @@ local dir_properties = { "spacing", "homogeneous", "expand" } -- @property superpose --- Force the number of rows of the layout. --- @property forced_num_rows +-- +-- Deprecated, use `row_count`. +-- +-- @deprecatedproperty forced_num_rows -- @tparam[opt=nil] number|nil forced_num_rows -- @propertytype nil Automatically determine the number of rows. -- @propertyunit rows -- @negativeallowed false -- @see forced_num_cols +-- @see row_count --- Force the number of columns of the layout. --- @property forced_num_cols +-- +-- Deprecated, use `column_count`. +-- +-- @deprecatedproperty forced_num_cols -- @tparam[opt=nil] number|nil forced_num_cols -- @propertytype nil Automatically determine the number of columns.' -- @propertyunit columns -- @negativeallowed false -- @see forced_num_rows +-- @see column_count --- Set the minimum size for the columns. -- --@DOC_wibox_layout_grid_min_size_EXAMPLE@ --- @tparam[opt=0] number min_cols_size Minimum size of the columns. --- @property min_cols_size +-- @tparam[opt=0] number minimum_column_width Minimum size of the columns. +-- @property minimum_column_width -- @propertyunit pixel -- @negativeallowed false --- @see min_rows_size +-- @see minimum_row_height + +--- Set the minimum size for the columns. +-- +-- Deprecated, use `minimum_column_width`. +-- +--@DOC_wibox_layout_grid_min_size_EXAMPLE@ +-- @tparam[opt=0] number min_cols_size Minimum size of the columns. +-- @deprecatedproperty min_cols_size +-- @propertyunit pixel +-- @negativeallowed false +-- @see minimum_row_height --- Set the minimum size for the rows. +-- @tparam[opt=0] number minimum_row_height Minimum size of the rows. +-- @property minimum_row_height +-- @propertyunit pixel +-- @negativeallowed false +-- @see min_cols_size + +--- Set the minimum size for the rows. +-- +-- Deprecated, use `minimum_row_height`. +-- -- @tparam[opt=0] number min_rows_size Minimum size of the rows. --- @property min_rows_size +-- @deprecatedproperty min_rows_size -- @propertyunit pixel -- @negativeallowed false -- @see min_cols_size --- The spacing between columns. -- +-- Deprecated, use `spacing`. +-- -- @tparam[opt=0] number horizontal_spacing --- @property horizontal_spacing +-- @deprecatedproperty horizontal_spacing -- @propertyunit pixel -- @negativeallowed false -- @see spacing @@ -103,8 +143,10 @@ local dir_properties = { "spacing", "homogeneous", "expand" } --- The spacing between rows. -- +-- Deprecated, use `spacing`. +-- -- @tparam[opt=0] number vertical_spacing --- @property vertical_spacing +-- @deprecatedproperty vertical_spacing -- @propertyunit pixel -- @negativeallowed false -- @see spacing @@ -116,23 +158,40 @@ local dir_properties = { "spacing", "homogeneous", "expand" } -- preferred `orientation`. -- --@DOC_wibox_layout_grid_spacing_EXAMPLE@ --- @tparam[opt=0] number spacing +-- +-- When a border is present, the spacing is applied on both side of the border, +-- thus is twice as large: +-- +-- @DOC_wibox_layout_grid_border_width3_EXAMPLE@ +-- -- @property spacing +-- @tparam[opt=0] number|table spacing +-- @tparam number spacing.vertical The vertical spacing. +-- @tparam number spacing.horizontal The horizontal spacing. +-- @propertytype number The same value for the `"vertical"` and `"horizontal"` +-- aspects. +-- @propertytype table Different values for the `"vertical"` and `"horizontal"` +-- aspects. +-- @propertyunit pixel -- @negativeallowed false -- @see vertical_spacing -- @see horizontal_spacing --- Controls if the columns are expanded to use all the available width. -- +-- Deprecated, use `expand`. +-- -- @tparam[opt=false] boolean horizontal_expand Expand the grid into the available space --- @property horizontal_expand +-- @deprecatedproperty horizontal_expand -- @see expand -- @see vertical_expand --- Controls if the rows are expanded to use all the available height. -- +-- Deprecated, use `expand`. +-- -- @tparam[opt=false] boolean vertical_expand Expand the grid into the available space --- @property vertical_expand +-- @deprecatedproperty vertical_expand -- @see expand -- @see horizontal_expand @@ -142,28 +201,34 @@ local dir_properties = { "spacing", "homogeneous", "expand" } -- preferred `orientation`. -- --@DOC_wibox_layout_grid_expand_EXAMPLE@ --- @tparam[opt=false] boolean expand Expand the grid into the available space -- @property expand +-- @tparam[opt=false] boolean|table expand Expand the grid into the available space +-- @tparam boolean expand.vertical The vertical expand. +-- @tparam boolean expand.horizontal The horizontal expand. +-- @propertytype number The same value for the `"vertical"` and `"horizontal"` +-- aspects. +-- @propertytype table Different values for the `"vertical"` and `"horizontal"` +-- aspects. -- @see horizontal_expand -- @see vertical_expand --- Controls if the columns all have the same width or if the width of each -- column depends on the content. -- --- see `homogeneous` +-- Deprecated, use `homogeneous` -- -- @tparam[opt=true] boolean horizontal_homogeneous All the columns have the same width. --- @property horizontal_homogeneous +-- @deprecatedproperty horizontal_homogeneous -- @see vertical_homogeneous -- @see homogeneous --- Controls if the rows all have the same height or if the height of each row -- depends on the content. -- --- see `homogeneous` +-- Deprecated, use `homogeneous` -- -- @tparam[opt=true] boolean vertical_homogeneous All the rows have the same height. --- @property vertical_homogeneous +-- @deprecatedproperty vertical_homogeneous -- @see homogeneous -- @see horizontal_homogeneous @@ -174,11 +239,38 @@ local dir_properties = { "spacing", "homogeneous", "expand" } -- by the preferred `orientation`. -- --@DOC_wibox_layout_grid_expand_EXAMPLE@ --- @tparam[opt=true] boolean homogeneous All the columns/rows have the same size. -- @property homogeneous +-- @tparam[opt=true] boolean|table homogeneous All the columns/rows have the same size. +-- @tparam boolean homogeneous.vertical The vertical homogeneous value. +-- @tparam boolean homogeneous.horizontal The horizontal homogeneous value. +-- @propertytype number The same value for the `"vertical"` and `"horizontal"` +-- aspects. +-- @propertytype table Different values for the `"vertical"` and `"horizontal"` +-- aspects. -- @see vertical_homogeneous -- @see horizontal_homogeneous +--- The number of rows. +-- +-- Unless manually set, the value will be automatically determined base on the +-- `orientation`. +-- +-- @property row_count +-- @tparam integer row_count +-- @negativeallowed false +-- @propertydefault autogenerated +-- @see forced_num_rows + +--- The number of columns. +-- +-- Unless manually set, the value will be automatically determined base on the +-- `orientation`. +-- +-- @property column_count +-- @tparam integer column_count +-- @negativeallowed false +-- @propertydefault autogenerated +-- @see forced_num_cols --- Child widget position. Return of `get_widget_position`. -- @field row Top row index @@ -250,8 +342,10 @@ local function find_widget(widgets_table, widget) end --- Get the number of rows and columns occupied by the widgets in the grid. --- @method get_dimension +-- @deprecatedmethod get_dimension -- @treturn number,number The number of rows and columns +-- @see row_count +-- @see column_count function grid:get_dimension() return self._private.num_rows, self._private.num_cols end @@ -314,6 +408,9 @@ end -- -- The widgets are assumed to span one cell. -- +-- If the widgets have a `row_index`, `col_index`, `col_span` +-- or `row_span` property, it will be honored. +-- -- @method add -- @tparam wibox.widget ... Widgets that should be added (must at least be one) -- @interface layout @@ -323,17 +420,26 @@ function grid:add(...) assert(args.n > 0, "need at least one widget to add") local row, column for i=1, args.n do + local w = args[i] -- Get the next empty coordinate to insert the widget row, column = self:get_next_empty(row, column) - self:add_widget_at(args[i], row, column, 1, 1) + self:add_widget_at( + w, + w.row_index or row, + w.col_index or column, + w.row_span or 1, + w.col_span or 1 + ) end end --- Add a widget to the grid layout at specific coordinate. -- +-- You can now use `:add {row_index = 1, col_index = 1}` instead of this method. +-- --@DOC_wibox_layout_grid_add_EXAMPLE@ -- --- @method add_widget_at +-- @deprecatedmethod add_widget_at -- @tparam wibox.widget child Widget that should be added -- @tparam number row Row number for the top left corner of the widget -- @tparam number col Column number for the top left corner of the widget @@ -642,6 +748,90 @@ function grid:remove_row(index) end +--- Add row border. +-- +-- This method allows to set the width/color or a specific row rather than use +-- the same values for all the rows. +-- +-- @DOC_wibox_layout_grid_add_row_border1_EXAMPLE@ +-- +-- @method add_row_border +-- @tparam integer index The row index. `1` is the top border (outer) border. +-- @tparam[opt=nil] integer|nil height The border height. If `nil` is passed, +-- then the `border_width.outer` will be user for index `1` and +-- `row_count + 1`, otherwise, `border_width.inner` will be used. +-- @tparam[opt={}] table args +-- @tparam[opt=nil] color args.color The border color. If `nil` is passed, +-- then the `border_color.outer` will be user for index `1` and +-- `row_count + 1`, otherwise, `border_color.inner` will be used. +-- @tparam[opt={1}] table args.dashes The dash pattern used for the line. By default, +-- it is a solid line. +-- @tparam[opt=0] number args.dash_offset If the line has `dashes`, then this is the +-- initial offset. Note that line are draw left to right and top to bottom. +-- @tparam[opt="butt"] string args.caps How the dashes ends are drawn. Either +-- `"butt"` (default), `"round"` or `"square"` +-- @noreturn +-- @see add_column_border + +--- Add column border. +-- +-- This method allows to set the width/color or a specific column rather than use +-- the same values for all the columns. +-- +-- @DOC_wibox_layout_grid_add_column_border1_EXAMPLE@ +-- +-- @method add_column_border +-- @tparam integer index The column index. `1` is the top border (outer) border. +-- @tparam[opt=nil] integer|nil height The border height. If `nil` is passed, +-- then the `border_width.outer` will be user for index `1` and +-- `column_count + 1`, otherwise, `border_width.inner` will be used. +-- @tparam[opt={}] table args +-- @tparam[opt=nil] color args.color The border color. If `nil` is passed, +-- then the `border_color.outer` will be user for index `1` and +-- `row_count + 1`, otherwise, `border_color.inner` will be used. +-- @tparam[opt={1}] table args.dashes The dash pattern used for the line. By default, +-- it is a solid line. +-- @tparam[opt=0] number args.dash_offset If the line has `dashes`, then this is the +-- initial offset. Note that line are draw left to right and top to bottom. +-- @tparam[opt="butt"] string args.caps How the dashes ends are drawn. Either +-- `"butt"` (default), `"round"` or `"square"` +-- @noreturn +-- @see add_column_border + +--- The border width. +-- +-- @DOC_wibox_layout_grid_border_width1_EXAMPLE@ +-- +-- If `add_row_border` or `add_column_border` is used, it takes precedence and +-- is drawn on top of the `border_color` mask. Using both `border_width` and +-- `add_row_border` at the same time makes little sense: +-- +-- @DOC_wibox_layout_grid_border_width2_EXAMPLE@ +-- +-- It is also possible to set the inner and outer borders separately: +-- +-- @DOC_wibox_layout_grid_border_width4_EXAMPLE@ +-- +-- @property border_width +-- @tparam[opt=0] integer|table border_width +-- @tparam integer border_width.inner +-- @tparam integer border_width.outer +-- @propertytype integer Use the same value for inner and outer borders. +-- @propertytype table Specify a different value for the inner and outer borders. +-- @negativeallowed false +-- @see border_color +-- @see add_column_border +-- @see add_row_border + +--- The border color for the table outer border. +-- @property border_color +-- @tparam[opt=0] color|table border_color +-- @tparam color border_color.inner +-- @tparam color border_color.outer +-- @propertytype color Use the same value for inner and outer borders. +-- @propertytype table Specify a different value for the inner and outer borders. +-- @see border_width + -- Return list of children function grid:get_children() local ret = {} @@ -680,30 +870,171 @@ function grid:set_min_rows_size(val) end end --- Force the number of columns of the layout. function grid:set_forced_num_cols(val) + gdebug.deprecate( + "The `.column_count = "..tostring(val).."`.", + {deprecated_in=5} + ) + self:set_column_count(val) +end + +function grid:set_forced_num_rows(val) + gdebug.deprecate( + "The `row_count = "..tostring(val).."`.", + {deprecated_in=5} + ) + self:set_row_count(val) +end + +-- Force the number of columns of the layout. +function grid:set_column_count(val) if self._private.forced_num_cols ~= val then self._private.forced_num_cols = val update_dimension(self) + self:emit_signal("property::column_count", val) self:emit_signal("widget::layout_changed") end end -- Force the number of rows of the layout. -function grid:set_forced_num_rows(val) +function grid:set_row_count(val) if self._private.forced_num_rows ~= val then self._private.forced_num_rows = val update_dimension(self) + self:emit_signal("property::row_count", val) self:emit_signal("widget::layout_changed") end end +function grid:get_row_count() + return self._private.forced_num_rows or self._private.num_rows +end + +function grid:get_column_count() + return self._private.forced_num_cols or self._private.num_cols +end + +function grid:set_minimum_column_width(val) + if self._private.min_cols_size ~= val then + self._private.min_cols_size = val + update_dimension(self) + self:emit_signal("property::minimum_column_width", val) + self:emit_signal("widget::layout_changed") + end +end + +function grid:set_minimum_row_height(val) + if self._private.min_rows_size ~= val then + self._private.min_rows_size = val + update_dimension(self) + self:emit_signal("property::minimum_column_width", val) + self:emit_signal("widget::layout_changed") + end +end + +function grid:set_min_cols_size(val) + gdebug.deprecate( + "The `.minimum_column_width = "..tostring(val).."`.", + {deprecated_in=5} + ) + self:set_minimum_column_width(val) +end + +function grid:set_min_rows_size(val) + gdebug.deprecate( + "The `.minimum_column_width = "..tostring(val).."`.", + {deprecated_in=5} + ) + self:set_minimum_row_height(val) +end + +function grid:get_minimum_column_width() + return self._private.min_cols_size +end + +function grid:get_minimum_row_height() + return self._private.min_rows_size +end + +function grid:get_min_cols_size() + return self._private.min_cols_size +end + +function grid:get_min_rows_size() + return self._private.min_rows_size +end + +function grid:set_border_width(val) + self._private.border_width = type(val) == "table" and val or { + inner = val or 0, + outer = val or 0, + } + + -- Enforce integers. Not doing so makes the masking code more complex. Also, + -- most of the time, not using integer is probably an user mistake (DPI + -- related or ratio related). + self._private.border_width.inner = gmath.round(self._private.border_width.inner) + self._private.border_width.outer = gmath.round(self._private.border_width.outer) + + -- Drawing the border takes both a lot of memory (for the cached masks) + -- and CPU, so make sure it is no-op for the 99% of cases where there is + -- no border. + self._private.has_border = self._private.border_width.inner ~= 0 + or self._private.border_width.outer ~= 0 + + self:emit_signal("property::border_width", self._private.border_width) + self:emit_signal("widget::layout_changed") +end + +function grid:set_border_color(val) + if type(val) == "table" then + self._private.border_color = { + inner = gcolor(val.inner), + outer = gcolor(val.outer), + } + else + self._private.border_color = { + inner = gcolor(val), + outer = gcolor(val), + } + end + self:emit_signal("property::border_color", self._private.border_color) + self:emit_signal("widget::redraw_needed") +end + +function grid:add_row_border(index, height, args) + self._private.has_border = true + self._private.custom_border_width.rows[index] = { + size = height, + color = args.color and gcolor(args.color), + dashes = args.dashes, + offset = args.dash_offset, + caps = args.caps, + } + + self:emit_signal("widget::layout_changed") +end + +function grid:add_column_border(index, width, args) + self._private.has_border = true + self._private.custom_border_width.cols[index] = { + size = width, + color = args.color and gcolor(args.color), + dashes = args.dashes, + offset = args.dash_offset, + caps = args.caps, + } + + self:emit_signal("widget::layout_changed") +end + -- Set the grid properties for _, prop in ipairs(properties) do if not grid["set_" .. prop] then grid["set_"..prop] = function(self, value) if self._private[prop] ~= value then self._private[prop] = value + self:emit_signal("property::"..prop, value) self:emit_signal("widget::layout_changed") end end @@ -725,26 +1056,46 @@ for _, prop in ipairs(dir_properties) do for _,dir in ipairs{"horizontal", "vertical"} do local dir_prop = dir .. "_" .. prop grid["set_"..dir_prop] = function(self, value) + gdebug.deprecate( + "The `".. dir_prop .."` property is deprecated. Use `".. prop .."`", + {deprecated_in=5} + ) if self._private[dir_prop] ~= value then self._private[dir_prop] = value self:emit_signal("widget::layout_changed") end end grid["get_"..dir_prop] = function(self) + gdebug.deprecate( + "The `".. dir_prop .."` property is deprecated. Use `".. prop .."`", + {deprecated_in=5} + ) return self._private[dir_prop] end end - -- Non-directional options grid["set_"..prop] = function(self, value) - if self._private["horizontal_"..prop] ~= value or self._private["vertical_"..prop] ~= value then - self._private["horizontal_"..prop] = value - self._private["vertical_"..prop] = value + if type(value) ~= "table" then + if self._private["horizontal_"..prop] ~= value + or self._private["vertical_"..prop] ~= value then + self._private["horizontal_"..prop] = value + self._private["vertical_"..prop] = value + self:emit_signal("property::"..prop, value) + self:emit_signal("widget::layout_changed") + end + else + self._private["horizontal_"..prop] = value.horizontal + self._private["vertical_"..prop] = value.vertical + + self:emit_signal("property::"..prop, value) self:emit_signal("widget::layout_changed") end end grid["get_"..prop] = function(self) - return self._private[self._private.orientation .. "_" .. prop] + return { + vertical = self._private["vertical_" .. prop], + horizontal = self._private["horizontal_" .. prop], + } end end @@ -779,6 +1130,41 @@ local function get_grid_sizes(self, context, orig_width, orig_height) return rows_size, cols_size end +-- All the code to get the width of a specific border. +-- +-- This table module supports partial borders and "just add a border" modes. +local function setup_border_widths(self) + self._private.border_width = {inner = 0, outer = 0} + self._private.custom_border_width = {rows = {}, cols = {}} + self._private.border_color = {} + + -- Use a metatable to get the defaults. + local function meta_border_common(custom, row_or_col) + return setmetatable({}, { + __index = function(_, k) + -- Handle custom borders. + if custom[k] then + return custom[k].size + end + + local size = self[row_or_col.."_count"] + if k == 1 or k == size + 1 then + return self._private.border_width.outer + else + return self._private.border_width.inner + end + end + }) + end + + local hfb = self._private.custom_border_width.rows + local vfb = self._private.custom_border_width.cols + + self._private.meta_borders = { + rows = meta_border_common(hfb, "row"), + cols = meta_border_common(vfb, "column"), + } +end -- Fit the grid layout into the given space. -- @param context The context in which we are fit. @@ -788,18 +1174,42 @@ function grid:fit(context, orig_width, orig_height) local width, height = orig_width, orig_height -- Calculate the space needed - local function fit_direction(dir, sizes) - local m = 0 + local function fit_direction(dir, sizes, border_widths) + local m = border_widths[1] + local space = self._private[dir .. "_spacing"] + + -- First border + m = m > 0 and m + space or m + if self._private[dir .. "_homogeneous"] then + local max = max_value(sizes) + -- all the columns/rows have the same size - m = #sizes * max_value(sizes) + (#sizes - 1) * self._private[dir .. "_spacing"] + if self._private.has_border then + + -- Not all borders are identical, so the loop is required. + for i in ipairs(sizes) do + local bw = border_widths[i+1] + + -- When there is a border, it needs the spacing on both sides. + + m = m + max + (space*(bw > 0 and 2 or 1)) + bw + end + else + -- Much simpler. + m = #sizes * max + (#sizes - 1) * space + end else -- sum the columns/rows size - for _,s in ipairs(sizes) do - m = m + s + self._private[dir .. "_spacing"] + for i, s in ipairs(sizes) do + local bw = border_widths[i+1] + + -- When there is a border, it needs the spacing on both sides. + m = m + s + (space * (bw > 0 and 2 or 1)) + bw end - m = m - self._private[dir .. "_spacing"] + end + return m end @@ -807,69 +1217,117 @@ function grid:fit(context, orig_width, orig_height) local rows_size, cols_size = get_grid_sizes(self, context, width, height) -- compute the width - local used_width_max = fit_direction("horizontal", cols_size) - local used_height_max = fit_direction("vertical", rows_size) + local borders = self._private.meta_borders + local used_width_max = fit_direction("horizontal", cols_size, borders.cols) + local used_height_max = fit_direction("vertical", rows_size, borders.rows) return used_width_max, used_height_max end --- Layout a grid layout. --- @param context The context in which we are drawn. --- @param width The available width. --- @param height The available height. -function grid:layout(context, width, height) - local result = {} +local function layout_common(self, context, width, height, h_homogeneous, v_homogeneous) + local result, areas = {}, {} local hspacing, vspacing = self._private.horizontal_spacing, self._private.vertical_spacing -- Fit matrix cells local rows_size, cols_size = get_grid_sizes(self, context, width, height) local total_expected_width, total_expected_height = sum_values(cols_size), sum_values(rows_size) + local h_bw, v_bw = self._private.meta_borders.cols, self._private.meta_borders.rows + + -- Do it once, the result wont change unless widgets are added. + if self._private.has_border and not self._private.area_cache.total_horizontal_border_width then + -- Also add the "second" spacing here. This avoid having some `if` below. + local total_h = h_bw[1] + h_bw[#cols_size+1] + 1*hspacing + local total_v = v_bw[1] + v_bw[#rows_size+1] + 1*vspacing + + for j = 1, #cols_size do + local bw = h_bw[j+1] + total_h = total_h + bw + hspacing*(bw > 0 and 1 or 0) + end + + for i = 1, #rows_size do + local bw = v_bw[i+1] + total_v = total_v + bw + vspacing*(bw > 0 and 1 or 0) + end + + self._private.area_cache.total_horizontal_border_width = total_h - h_bw[1] + self._private.area_cache.total_vertical_border_width = total_v - v_bw[1] + end + + local total_h = self._private.area_cache.total_horizontal_border_width or 0 + local total_v = self._private.area_cache.total_vertical_border_width or 0 + -- Figure out the maximum size we can give out to sub-widgets local single_width, single_height = max_value(cols_size), max_value(rows_size) + if self._private.horizontal_expand then - single_width = (width - (self._private.num_cols-1)*hspacing) / self._private.num_cols + single_width = (width - (self._private.num_cols-1)*hspacing - total_h) / self._private.num_cols end + if self._private.vertical_expand then - single_height = (height - (self._private.num_rows-1)*vspacing) / self._private.num_rows + single_height = (height - (self._private.num_rows-1)*vspacing - total_v) / self._private.num_rows end -- Calculate the position and size to place the widgets local cumul_width, cumul_height = {}, {} - local cw, ch = 0, 0 + local c_hor, c_ver = h_bw[1], v_bw[1] + + -- If there is an outer border, then it needs inner spacing too. + c_hor, c_ver = c_hor > 0 and c_hor + hspacing or 0, c_ver > 0 and c_ver + vspacing or 0 + for j = 1, #cols_size do - cumul_width[j] = cw - if self._private.horizontal_homogeneous then + cumul_width[j] = c_hor + + if h_homogeneous then cols_size[j] = math.max(self._private.min_cols_size, single_width) elseif self._private.horizontal_expand then local hpercent = self._private.num_cols * single_width * cols_size[j] / total_expected_width cols_size[j] = math.max(self._private.min_cols_size, hpercent) end - cw = cw + cols_size[j] + hspacing + + local bw = h_bw[j+1] + c_hor = c_hor + cols_size[j] + (bw > 0 and 2 or 1)*hspacing + bw end - cumul_width[#cols_size + 1] = cw + + cumul_width[#cols_size + 1] = c_hor + for i = 1, #rows_size do - cumul_height[i] = ch - if self._private.vertical_homogeneous then + cumul_height[i] = c_ver + + if v_homogeneous then rows_size[i] = math.max(self._private.min_rows_size, single_height) elseif self._private.vertical_expand then local vpercent = self._private.num_rows * single_height * rows_size[i] / total_expected_height rows_size[i] = math.max(self._private.min_rows_size, vpercent) end - ch = ch + rows_size[i] + vspacing + + local bw = v_bw[i+1] + c_ver = c_ver + rows_size[i] + (bw > 0 and 2 or 1)*vspacing + bw end - cumul_height[#rows_size + 1] = ch + + cumul_height[#rows_size + 1] = c_ver -- Place widgets local fill_space = true -- should be fill_space property? for _, v in pairs(self._private.widgets) do local x, y, w, h + + -- If there is a border, then the spacing is needed on both sides. + local col_bw, row_bw = h_bw[v.col+v.col_span], v_bw[v.row+v.row_span] + local col_spacing = hspacing * (col_bw > 0 and 2 or 1) + local row_spacing = vspacing * (row_bw > 0 and 2 or 1) + -- Round numbers to avoid decimals error, force to place tight widgets -- and avoid redraw glitches x = math.floor(cumul_width[v.col]) y = math.floor(cumul_height[v.row]) - w = math.floor(cumul_width[v.col + v.col_span] - hspacing - x) - h = math.floor(cumul_height[v.row + v.row_span] - vspacing - y) + w = math.floor(cumul_width[v.col + v.col_span] - col_spacing - x - col_bw) + h = math.floor(cumul_height[v.row + v.row_span] - row_spacing - y - row_bw) + + -- Handle large spacing and/or border_width. The grid doesn't support + -- dropping widgets. It would be very hard to implement. + w, h = math.max(0, w), math.max(0, h) + -- Recalculate the width so the last widget fits if (fill_space or self._private.horizontal_expand) and x + w > width then w = math.floor(math.max(self._private.min_cols_size, width - x)) @@ -881,11 +1339,179 @@ function grid:layout(context, width, height) -- Place the widget if it fits in the area if x + w <= width and y + h <= height then table.insert(result, base.place_widget_at(v.widget, x, y, w, h)) + table.insert(areas, { + x = x - hspacing, + y = y - vspacing, + width = w + col_spacing, + height = h + row_spacing, + }) end end - return result + + -- Sometime, the `:fit()` size and `:layout()` size are different, thus it's + -- important to say where the widget actually ends. + areas.end_x = cumul_width[#cumul_width] - hspacing + areas.end_y = cumul_height[#cumul_height] - vspacing + areas.column_count = #cols_size + areas.row_count = #rows_size + areas.cols = cumul_width + areas.rows = cumul_height + + return result, areas end +local function get_area_cache_hash(width, height) + return width*1.5+height*15 +end + +-- Layout a grid layout. +-- @param context The context in which we are drawn. +-- @param width The available width. +-- @param height The available height. +function grid:layout(context, width, height) + local l, areas = layout_common( + self, + context, + width, + height, + self._private.horizontal_homogeneous, + self._private.vertical_homogeneous + ) + + self._private.area_cache[get_area_cache_hash(width, height)] = areas + + return l +end + +local function create_border_mask(self, areas, default_color) + if areas.surface then return areas.surface end + + local meta = self._private.meta_borders + + local top, bottom = meta.rows[1], meta.rows[areas.row_count+1] + local left, right = meta.cols[1], meta.cols[areas.column_count+1] + + -- A1 is fine because :layout() aligns to pixel boundary and `border_width` + -- are integers. + local img = cairo.RecordingSurface(cairo.Content.COLOR_ALPHA, cairo.Rectangle { + x = 0, + y = 0, + width = areas.end_x + right, + height = areas.end_y + bottom + }) + local cr = cairo.Context(img) + cr:set_source(default_color) + + local bw_i, bw_o = self._private.border_width.inner, self._private.border_width.outer + + if bw_i ~= bw_o then + if bw_o then + if self._private.border_color.outer then + cr:set_source(self._private.border_color.outer) + end + + -- Clip the outside region. It cannot use `cr:set_line_width()` because + -- each border might be different. + cr:rectangle(0, 0, areas.end_x, top) + cr:rectangle(0, areas.end_y - bottom, areas.end_x, bottom) + cr:rectangle(0, top, left, areas.end_y - top - bottom) + cr:rectangle(areas.end_x - right, top, right, areas.end_y - top - bottom) + cr:clip() + cr:paint() + cr:reset_clip() + end + + cr:rectangle(left, top, areas.end_x - top - bottom, areas.end_y - left - right) + cr:clip() + else + cr:rectangle(0,0, areas.end_x, areas.end_y) + cr:clip() + end + + if bw_i then + if self._private.border_color.inner then + cr:set_source(self._private.border_color.inner) + end + cr:rectangle(0, 0, areas.end_x, areas.end_y) + cr:fill() + end + + -- Add the custom horizontal and borders. + -- This is a lifeline for users who want borders only on specific places. + -- Implementing word processing style borders would be overkill and + -- too hard to maintain. + for _, orientation in ipairs { "rows", "cols" } do + for row, args in pairs(self._private.custom_border_width[orientation]) do + local line_height = meta[orientation][row] + cr:save() + cr:rectangle(0,0, areas.end_x, areas.end_y) + cr:clip() + cr:set_line_width(line_height) + + if args.dashes then + cr:set_dash(args.dashes, #args.dashes, args.offset or 0) + end + + if args.caps then + cr:set_line_cap(cairo.LineCap[args.caps:upper()]) + end + + cr:set_source(args.color) + + -- Cairo draw the stroke equally on both side, for `line_height/2` is + -- needed. + local y = (row == 1 and line_height or areas[orientation][row] or 0) - math.ceil(line_height/2) + + if orientation == "rows" then + cr:move_to(0, y) + cr:line_to(areas.end_x, y) + else + cr:move_to(y, 0) + cr:line_to(y, areas.end_y) + end + + cr:stroke() + cr:restore() + end + end + + -- Remove the area used by widgets. This needs to be done regardless of the + -- border mode to handle row/col span. + cr:set_operator(cairo.Operator.CLEAR) + + for _, area in ipairs(areas) do + cr:rectangle(area.x, area.y, area.width, area.height) + end + + cr:fill() + + areas.surface = img + + return img +end + +-- Draw the border. +function grid:after_draw_children(ctx, cr, width, height) + if not self._private.has_border then return end + + local hash = get_area_cache_hash(width, height) + + if not self._private.area_cache[hash] then + self._private.area_cache[hash] = select(2, layout_common( + self, + ctx, + width, + height, + self._private.horizontal_homogeneous, + self._private.vertical_homogeneous + )) + end + + local areas = self._private.area_cache[hash] + + cr:set_source_surface(create_border_mask(self, areas, cr:get_source()), 0 ,0) + cr:paint() +end --- Reset the grid layout. -- Remove all widgets and reset row and column counts @@ -946,6 +1572,14 @@ local function new(orientation) ret._private.horizontal_spacing = 0 ret._private.vertical_spacing = 0 + ret._private.area_cache, ret._private.border_color = {}, {} + + ret:connect_signal("widget::layout_changed", function(self) + self._private.area_cache = {} + end) + + setup_border_widths(ret) + return ret end diff --git a/lib/wibox/widget/calendar.lua b/lib/wibox/widget/calendar.lua index 886c93703..3d1f804d6 100644 --- a/lib/wibox/widget/calendar.lua +++ b/lib/wibox/widget/calendar.lua @@ -39,6 +39,7 @@ local calendar = { mt = {} } local properties = { "date" , "font" , "spacing" , "week_numbers", "start_sunday", "long_weekdays", "fn_embed", "flex_height", + "border_width", "border_color" , } --- The calendar font. @@ -66,6 +67,12 @@ local properties = { "date" , "font" , "spacing" , "week_numbers" -- @beautiful beautiful.flex_height -- @param boolean Cells can skretch to fill the empty space. +--- Set the color for the empty space where there are no date widgets. +-- +-- This happens when the month doesn't start on a Sunday or stop on a Saturday. +-- @beautiful beautiful.calendar_empty_color +-- @param color The empty area color. + --- The calendar date. -- -- E.g.. `{day=21, month=2, year=2005}`, `{month=2, year=2005}, {year=2005}` @@ -147,6 +154,54 @@ local properties = { "date" , "font" , "spacing" , "week_numbers" -- @property flex_height -- @usebeautiful beautiful.flex_height +--- Set the calendar border width. +-- @property border_width +-- @tparam[opt=0] integer|table border_width +-- @tparam color border_width.inner The border between the cells. +-- @tparam color border_width.outer The border around the calendar. +-- @propertytype color Use the same value for inner and outer borders. +-- @propertytype table Specify a different value for the inner and outer borders. +-- @negativeallowed false +-- @see border_color +-- @see wibox.layout.grid.border_width + +--- Set the calendar border color. +-- @property border_color +-- @tparam[opt=0] color|table border_color +-- @tparam color border_color.inner The border between the cells. +-- @tparam color border_color.outer The border around the calendar. +-- @propertytype color Use the same value for inner and outer borders. +-- @propertytype table Specify a different value for the inner and outer borders. +-- @see border_width +-- @see wibox.layout.grid.border_color + +--- Set the color for the empty cells. +-- +-- @property empty_color +-- @tparam[opt=nil] color|nil empty_color +-- @usebeautiful beautiful.calendar_empty_color +-- @see empty_widget +-- @see empty_cell_mode + +--- Set a widget for the empty cells. +-- +-- @property empty_widget +-- @tparam[opt=nil] widget|nil empty_widget +-- @see empty_color +-- @see empty_cell_mode + +--- How should the cells outside of the current month should be handled. +-- +-- @property empty_cell_mode +-- @tparam[opt="merged"] string empty_cell_mode +-- @propertyvalue "merged" Merge all cells and display the `empty_widget` or +-- `empty_color`. +-- @propertyvalue "split" Display one `empty_widget` per day rather than merge +-- them. +-- @propertyvalue "rolling" Display the dates from the previous or next month. +-- @see empty_widget +-- @see empty_color + --- Make a textbox -- @tparam string text Text of the textbox -- @tparam string font Font of the text @@ -210,6 +265,14 @@ local function create_month(props, date) layout:set_forced_num_rows(num_rows) layout:set_forced_num_cols(num_columns) + if props.border_width then + layout:set_border_width(props.border_width) + end + + if props.border_color then + layout:set_border_color(props.border_color) + end + --local flags = {"header", "weekdays", "weeknumber", "normal", "focus"} local cell_date, t, i, j, w, flag, text @@ -385,6 +448,7 @@ local function get_calendar(type, date, font) ret._private.long_weekdays = beautiful.calendar_long_weekdays or false ret._private.flex_height = beautiful.calendar_flex_height or false ret._private.fn_embed = function (w, _) return w end + ret._private.empty_widget = bgcontainer(beautiful.calendar_empty_color) -- header specific ret._private.subtype = type=="year" and "monthheader" or "fullheader" diff --git a/tests/examples/awful/popup/alttab.lua b/tests/examples/awful/popup/alttab.lua index d56c17418..e6d3b82ab 100644 --- a/tests/examples/awful/popup/alttab.lua +++ b/tests/examples/awful/popup/alttab.lua @@ -27,7 +27,7 @@ local tasklist_buttons = nil --DOC_HIDE }, layout = { spacing = 5, - forced_num_rows = 2, + row_count = 2, layout = wibox.layout.grid.horizontal }, diff --git a/tests/examples/awful/popup/wiboxtypes.lua b/tests/examples/awful/popup/wiboxtypes.lua index 4c0777b5f..22bbc5262 100644 --- a/tests/examples/awful/popup/wiboxtypes.lua +++ b/tests/examples/awful/popup/wiboxtypes.lua @@ -107,9 +107,9 @@ awful.popup { filter = awful.widget.layoutlist.source.for_screen, screen = 1, base_layout = wibox.widget { - spacing = 5, - forced_num_cols = 5, - layout = wibox.layout.grid.vertical, + spacing = 5, + column_count = 5, + layout = wibox.layout.grid.vertical, }, widget_template = { { diff --git a/tests/examples/awful/screenshot/popup.lua b/tests/examples/awful/screenshot/popup.lua index 3896c4085..c075d0ff0 100644 --- a/tests/examples/awful/screenshot/popup.lua +++ b/tests/examples/awful/screenshot/popup.lua @@ -98,9 +98,9 @@ gen_client("C2") align = "center" }, layout = { - spacing = 5, - forced_num_rows = 1, - layout = wibox.layout.grid.horizontal + spacing = 5, + row_count = 1, + layout = wibox.layout.grid.horizontal }, widget_template = { { diff --git a/tests/examples/awful/widget/layoutlist/bar.lua b/tests/examples/awful/widget/layoutlist/bar.lua index a3bb6ffcd..0b37190d0 100644 --- a/tests/examples/awful/widget/layoutlist/bar.lua +++ b/tests/examples/awful/widget/layoutlist/bar.lua @@ -24,9 +24,9 @@ local beautiful = require("beautiful") --DOC_HIDE source = awful.widget.layoutlist.source.default_layouts, screen = 1, base_layout = wibox.widget { - spacing = 5, - forced_num_cols = 3, - layout = wibox.layout.grid.vertical, + spacing = 5, + column_count = 3, + layout = wibox.layout.grid.vertical, }, widget_template = { { diff --git a/tests/examples/awful/widget/layoutlist/popup.lua b/tests/examples/awful/widget/layoutlist/popup.lua index 8eddca029..695248e5f 100644 --- a/tests/examples/awful/widget/layoutlist/popup.lua +++ b/tests/examples/awful/widget/layoutlist/popup.lua @@ -12,9 +12,9 @@ local modkey = "mod4" --DOC_HIDE local ll = awful.widget.layoutlist { source = awful.widget.layoutlist.source.default_layouts, --DOC_HIDE base_layout = wibox.widget { - spacing = 5, - forced_num_cols = 5, - layout = wibox.layout.grid.vertical, + spacing = 5, + column_count = 5, + layout = wibox.layout.grid.vertical, }, widget_template = { { diff --git a/tests/examples/sequences/client/tasklist_layout1.lua b/tests/examples/sequences/client/tasklist_layout1.lua index 5619de919..9cf7f1f54 100644 --- a/tests/examples/sequences/client/tasklist_layout1.lua +++ b/tests/examples/sequences/client/tasklist_layout1.lua @@ -42,11 +42,11 @@ local s = screen[1] --DOC_NEWLINE if count > 5 and not self.is_grid then self.base_layout = wibox.widget { - forced_num_rows = 2, - homogeneous = true, - expand = true, - spacing = 2, - layout = wibox.layout.grid.horizontal + row_count = 2, + homogeneous = true, + expand = true, + spacing = 2, + layout = wibox.layout.grid.horizontal } --DOC_NEWLINE self.is_grid = true diff --git a/tests/examples/wibox/layout/defaults/grid.lua b/tests/examples/wibox/layout/defaults/grid.lua index 1e3813434..9d4f6429a 100644 --- a/tests/examples/wibox/layout/defaults/grid.lua +++ b/tests/examples/wibox/layout/defaults/grid.lua @@ -8,10 +8,10 @@ wibox.widget { generic_widget( "second" ), generic_widget( "third" ), generic_widget( "fourth" ), - forced_num_cols = 2, - forced_num_rows = 2, - homogeneous = true, - expand = true, - layout = wibox.layout.grid + column_count = 2, + row_count = 2, + homogeneous = true, + expand = true, + layout = wibox.layout.grid } , nil, 60 --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/add.lua b/tests/examples/wibox/layout/grid/add.lua index 216eeae6b..ccafe4167 100644 --- a/tests/examples/wibox/layout/grid/add.lua +++ b/tests/examples/wibox/layout/grid/add.lua @@ -6,9 +6,9 @@ local beautiful = require("beautiful") --DOC_HIDE print("l:add_widget_at(new, 1, 4, 1, 1)") --DOC_HIDE local w = generic_before_after(wibox.layout.grid, { - forced_num_cols = 3, - forced_num_rows = 2, - homogeneous = true, + column_count = 3, + row_count = 2, + homogeneous = true, }, 6, "add_widget_at", {--DOC_HIDE generic_widget("__new__",beautiful.bg_highlight) --DOC_HIDE , 1, 4, 1, 1 --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/add_column_border1.lua b/tests/examples/wibox/layout/grid/add_column_border1.lua new file mode 100644 index 000000000..ab07088db --- /dev/null +++ b/tests/examples/wibox/layout/grid/add_column_border1.lua @@ -0,0 +1,85 @@ +--DOC_GEN_IMAGE --DOC_HIDE_START +local generic_widget_ = ... +local wibox = require("wibox") +local beautiful = require("beautiful") + +local l = wibox.widget { + spacing = 10, + layout = wibox.layout.fixed.horizontal +} + +local function generic_widget(txt) + return generic_widget_(txt, nil, 0) +end + +--DOC_HIDE_END + local w = wibox.widget { + --DOC_HIDE_START + -- [...] Some widgets here. + { + text = "none", + row_index = 1, + col_index = 1, + col_span = 3, + widget = generic_widget + }, + { + text = "first", + col_span = 2, + row_index = 2, + col_index = 1, + widget = generic_widget + }, + { + text = "third", + row_index = 2, + col_index = 3, + row_span = 2, + widget = generic_widget + }, + { + text = "second", + row_index = 3, + col_index = 1, + col_span = 2, + widget = generic_widget + }, + { + text = "fourth", + row_index = 4, + col_index = 1, + widget = generic_widget + }, + { + text = "fifth", + row_index = 4, + col_index = 2, + col_span = 2, + widget = generic_widget + }, + { + text = "sixth", + row_index = 1, + col_index = 4, + row_span = 4, + widget = generic_widget + }, + --DOC_HIDE_END + homogeneous = true, + spacing = 0, + border_width = 4, + border_color = beautiful.border_color, + minimum_column_width = 10, + minimum_row_height = 10, + layout = wibox.layout.grid, + } + + --DOC_NEWLINE + w:add_column_border(1, 5 , { color = "purple" }) + w:add_column_border(2, 10, { color = "cyan" }) + w:add_column_border(3, 5 , { color = "magenta"}) + w:add_column_border(4, 5 , { color = "black" }) + w:add_column_border(5, 10, { color = "grey" }) + +l:add(w) --DOC_HIDE +return l, l:fit({dpi=96}, 9999, 9999) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/add_row_border1.lua b/tests/examples/wibox/layout/grid/add_row_border1.lua new file mode 100644 index 000000000..c00a9e6ec --- /dev/null +++ b/tests/examples/wibox/layout/grid/add_row_border1.lua @@ -0,0 +1,85 @@ +--DOC_GEN_IMAGE --DOC_HIDE_START +local generic_widget_ = ... +local wibox = require("wibox") +local beautiful = require("beautiful") + +local l = wibox.widget { + spacing = 10, + layout = wibox.layout.fixed.horizontal +} + +local function generic_widget(txt) + return generic_widget_(txt, nil, 0) +end + +--DOC_HIDE_END + local w = wibox.widget { + -- [...] Some widgets here. + --DOC_HIDE_START + { + text = "none", + row_index = 1, + col_index = 1, + col_span = 3, + widget = generic_widget + }, + { + text = "first", + col_span = 2, + row_index = 2, + col_index = 1, + widget = generic_widget + }, + { + text = "third", + row_index = 2, + col_index = 3, + row_span = 2, + widget = generic_widget + }, + { + text = "second", + row_index = 3, + col_index = 1, + col_span = 2, + widget = generic_widget + }, + { + text = "fourth", + row_index = 4, + col_index = 1, + widget = generic_widget + }, + { + text = "fifth", + row_index = 4, + col_index = 2, + col_span = 2, + widget = generic_widget + }, + { + text = "sixth", + row_index = 1, + col_index = 4, + row_span = 4, + widget = generic_widget + }, + --DOC_HIDE_END + homogeneous = true, + spacing = 0, + border_width = 4, + border_color = beautiful.border_color, + minimum_column_width = 10, + minimum_row_height = 10, + layout = wibox.layout.grid, + } + + --DOC_NEWLINE + w:add_row_border(1, 40, { color = "red" }) + w:add_row_border(2, 5 , { color = "green" , dashes = {5, 3, 10, 3}}) + w:add_row_border(3, 10, { color = "blue" , dashes = {5, 3, 10, 3}, dash_offset = 5}) + w:add_row_border(4, 30, { color = "orange", dashes = {5, 40}, caps = "round"}) + w:add_row_border(5, 10, { color = "yellow"}) + +l:add(w) --DOC_HIDE +return l, l:fit({dpi=96}, 9999, 9999) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/border_width1.lua b/tests/examples/wibox/layout/grid/border_width1.lua new file mode 100644 index 000000000..4466454be --- /dev/null +++ b/tests/examples/wibox/layout/grid/border_width1.lua @@ -0,0 +1,62 @@ +--DOC_GEN_IMAGE --DOC_HIDE_START --DOC_NO_USAGE +local generic_widget_ = ... +local wibox = require("wibox") + +local l = wibox.widget { + spacing = 10, + layout = wibox.layout.fixed.vertical +} + +local function generic_widget(txt) + return generic_widget_(txt, nil, 0) +end + +--DOC_HIDE_END + + for _, expand in ipairs { true, false } do + for _, homogeneous in ipairs { true, false } do + --DOC_HIDE_START + local row = wibox.widget { + spacing = 10, + layout = wibox.layout.fixed.horizontal + } + l:add(wibox.widget.textbox( + "`expand = "..tostring(expand).."`, `homogeneous = "..tostring(homogeneous).."`:" + )) + l:add(row) + --DOC_HIDE_END + for _, width in ipairs { 0, 1, 2, 4, 10 } do + local w = wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + generic_widget( "fourth" ), + generic_widget( "fifth" ), + generic_widget( "sixth" ), + column_count = 2, + row_count = 2, + homogeneous = homogeneous, + spacing = 10, + border_width = { + inner = width, + outer = 1.5 * width, + }, + border_color = "red", + expand = expand, + forced_height = expand and 200 or nil, + layout = wibox.layout.grid, + } + + --DOC_HIDE_START + row:add(wibox.widget { + wibox.widget.textbox(" `border_width = ".. width .."`: "), + w, + layout = wibox.layout.fixed.vertical + }) + --DOC_HIDE_END + end + end + end +--DOC_HIDE_START + +return l, l:fit({dpi=96}, 9999, 9999) diff --git a/tests/examples/wibox/layout/grid/border_width2.lua b/tests/examples/wibox/layout/grid/border_width2.lua new file mode 100644 index 000000000..672ab2484 --- /dev/null +++ b/tests/examples/wibox/layout/grid/border_width2.lua @@ -0,0 +1,91 @@ +--DOC_GEN_IMAGE --DOC_HIDE_START --DOC_NO_USAGE +local generic_widget_ = ... +local wibox = require("wibox") +local beautiful = require("beautiful") + +local l = wibox.widget { + spacing = 10, + layout = wibox.layout.fixed.horizontal +} + +local function generic_widget(txt) + return generic_widget_(txt, nil, 0) +end + +--DOC_HIDE_END + local w = wibox.widget { + --DOC_HIDE_START + -- [...] Some widgets here. + { + text = "none", + row_index = 1, + col_index = 1, + col_span = 3, + widget = generic_widget + }, + { + text = "first", + col_span = 2, + row_index = 2, + col_index = 1, + widget = generic_widget + }, + { + text = "third", + row_index = 2, + col_index = 3, + row_span = 2, + widget = generic_widget + }, + { + text = "second", + row_index = 3, + col_index = 1, + col_span = 2, + widget = generic_widget + }, + { + text = "fourth", + row_index = 4, + col_index = 1, + widget = generic_widget + }, + { + text = "fifth", + row_index = 4, + col_index = 2, + col_span = 2, + widget = generic_widget + }, + { + text = "sixth", + row_index = 1, + col_index = 4, + row_span = 4, + widget = generic_widget + }, + --DOC_HIDE_END + homogeneous = true, + spacing = 0, + border_width = 4, + border_color = beautiful.border_color, + minimum_column_width = 10, + minimum_row_height = 10, + layout = wibox.layout.grid, + } + + --DOC_NEWLINE + w:add_row_border(1, 40, { color = "red" }) + w:add_row_border(2, 5 , { color = "green" , dashes = {5, 3, 10, 3}}) + w:add_row_border(3, 10, { color = "blue" , dashes = {5, 3, 10, 3}, dash_offset = 5}) + w:add_row_border(4, 30, { color = "orange", dashes = {5, 40}, caps = "round"}) + w:add_row_border(5, 10, { color = "yellow"}) + --DOC_NEWLINE + w:add_column_border(1, 5, { color = "purple"}) + w:add_column_border(2, 10, { color = "cyan"}) + w:add_column_border(3, 5, { color = "magenta"}) + w:add_column_border(4, 5, { color = "black"}) + w:add_column_border(5, 10, { color = "grey"}) + +l:add(w) --DOC_HIDE +return l, l:fit({dpi=96}, 9999, 9999) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/border_width3.lua b/tests/examples/wibox/layout/grid/border_width3.lua new file mode 100644 index 000000000..d7bf41a92 --- /dev/null +++ b/tests/examples/wibox/layout/grid/border_width3.lua @@ -0,0 +1,40 @@ +--DOC_GEN_IMAGE --DOC_HIDE_START --DOC_NO_USAGE +local generic_widget_ = ... +local wibox = require("wibox") --DOC_HIDE + +local l = wibox.widget { + spacing = 10, + layout = wibox.layout.fixed.horizontal +} + +local function generic_widget(txt) + return generic_widget_(txt, nil, 0) +end + +--DOC_HIDE_END + for _, width in ipairs { 0, 1, 2, 4, 10 } do + local w = wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + generic_widget( "fourth" ), + column_count = 2, + row_count = 2, + homogeneous = true, + spacing = width, + border_width = 1, + border_color = "red", + layout = wibox.layout.grid, + } + + --DOC_HIDE_START + l:add(wibox.widget { + wibox.widget.textbox(" `spacing = ".. width .."`: "), + w, + layout = wibox.layout.fixed.vertical + }) + --DOC_HIDE_END + end +--DOC_HIDE_START + +return l, l:fit({dpi=96}, 9999, 9999) diff --git a/tests/examples/wibox/layout/grid/border_width4.lua b/tests/examples/wibox/layout/grid/border_width4.lua new file mode 100644 index 000000000..d65be982f --- /dev/null +++ b/tests/examples/wibox/layout/grid/border_width4.lua @@ -0,0 +1,67 @@ +--DOC_GEN_IMAGE --DOC_HIDE_START --DOC_NO_USAGE +local generic_widget_ = ... +local wibox = require("wibox") +local gears = { color = require("gears.color") } + +local l = wibox.widget { + spacing = 10, + layout = wibox.layout.fixed.horizontal +} + +local function generic_widget(txt) + return generic_widget_(txt, nil, 0) +end + +--DOC_HIDE_END + for _, width in ipairs { 0, 1, 2, 4, 10 } do + local w = wibox.widget { + generic_widget( "first" ), + generic_widget( "second" ), + generic_widget( "third" ), + generic_widget( "fourth" ), + column_count = 2, + row_count = 2, + homogeneous = true, + spacing = 10, + border_width = { + inner = width, + outer = 10 - width, + }, + border_color = { + inner = gears.color { + type = "linear", + from = { 0 , 0 }, + to = { 100, 100 }, + stops = { + { 0, "#ff0000" }, + { 1, "#ffff00" }, + } + }, + outer = gears.color { + type = "linear", + from = { 0 , 0 }, + to = { 100, 100 }, + stops = { + { 0, "#0000ff" }, + { 1, "#ff0000" }, + } + }, + }, + layout = wibox.layout.grid, + } + + --DOC_HIDE_START + l:add(wibox.widget { + wibox.widget.textbox( + "".. + "`border_width.outer = ".. (10-width) .."`\n".. + "`border_width.inner = ".. width .."`".. + ":"), + w, + layout = wibox.layout.fixed.vertical + }) + --DOC_HIDE_STOP + end +--DOC_HIDE_START + +return l, l:fit({dpi=96}, 9999, 9999) diff --git a/tests/examples/wibox/layout/grid/declarative1.lua b/tests/examples/wibox/layout/grid/declarative1.lua new file mode 100644 index 000000000..ef6306f8f --- /dev/null +++ b/tests/examples/wibox/layout/grid/declarative1.lua @@ -0,0 +1,64 @@ +--DOC_GEN_IMAGE --DOC_HIDE_START +local generic_widget = ... --DOC_NO_USAGE +local wibox = require("wibox") +local beautiful = require("beautiful") + +--DOC_HIDE_END + + local lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing " .. + "elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + +--DOC_NEWLINE + + local l = wibox.widget { + { + text = lorem, + row_index = 1, + col_index = 1, + col_span = 3, + widget = generic_widget + }, + { + text = "first", + col_span = 2, + row_index = 2, + col_index = 1, + widget = generic_widget + }, + { + text = "third", + row_index = 2, + col_index = 3, + row_span = 2, + widget = generic_widget + }, + { + text = "second", + row_index = 3, + col_index = 1, + col_span = 2, + widget = generic_widget + }, + { + text = "fourth", + row_index = 4, + col_index = 1, + widget = generic_widget + }, + { + text = "fifth", + row_index = 4, + col_index = 2, + col_span = 2, + widget = generic_widget + }, + homogeneous = true, + spacing = 5, + border_width = 1, + border_color = beautiful.border_color, + minimum_column_width = 10, + minimum_row_height = 10, + layout = wibox.layout.grid, + } + +return l, l:fit({dpi=96}, 400, 200) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/declarative2.lua b/tests/examples/wibox/layout/grid/declarative2.lua new file mode 100644 index 000000000..d652db7c9 --- /dev/null +++ b/tests/examples/wibox/layout/grid/declarative2.lua @@ -0,0 +1,18 @@ +--DOC_GEN_IMAGE --DOC_HIDE +local generic_widget = ... --DOC_NO_USAGE --DOC_HIDE +local wibox = require("wibox") --DOC_HIDE + + local l = wibox.widget { + generic_widget("first"), + generic_widget("second"), + generic_widget("third"), + generic_widget("fourth"), + generic_widget("fifth"), + column_count = 2, + spacing = 5, + minimum_column_width = 10, + minimum_row_height = 10, + layout = wibox.layout.grid, + } + +return l, l:fit({dpi=96}, 300, 200) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/expand.lua b/tests/examples/wibox/layout/grid/expand.lua index c83e8995f..d18f7cd0d 100644 --- a/tests/examples/wibox/layout/grid/expand.lua +++ b/tests/examples/wibox/layout/grid/expand.lua @@ -16,15 +16,15 @@ local w = wibox.widget { generic_widget( "-------- long 1 --------" ), generic_widget( "short 2" ), generic_widget( "-------- long 2 --------" ), - forced_num_cols = 2, - forced_num_rows = 2, - expand = false, - homogeneous = false, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + expand = false, + homogeneous = false, + layout = wibox.layout.grid, }, margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, @@ -39,15 +39,15 @@ local w = wibox.widget { generic_widget( "-------- long 1 --------" ), generic_widget( "short 2" ), generic_widget( "-------- long 2 --------" ), - forced_num_cols = 2, - forced_num_rows = 2, - expand = true, - homogeneous = false, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + expand = true, + homogeneous = false, + layout = wibox.layout.grid, }, margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, @@ -65,11 +65,11 @@ local w = wibox.widget { generic_widget( "-------- long 1 --------" ), generic_widget( "short 2" ), generic_widget( "-------- long 2 --------" ), - forced_num_cols = 2, - forced_num_rows = 2, - expand = false, - homogeneous = true, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + expand = false, + homogeneous = true, + layout = wibox.layout.grid, }, margins = 1, color = beautiful.border_color, @@ -88,11 +88,11 @@ local w = wibox.widget { generic_widget( "-------- long 1 --------" ), generic_widget( "short 2" ), generic_widget( "-------- long 2 --------" ), - forced_num_cols = 2, - forced_num_rows = 2, - expand = true, - homogeneous = true, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + expand = true, + homogeneous = true, + layout = wibox.layout.grid, }, margins = 1, color = beautiful.border_color, diff --git a/tests/examples/wibox/layout/grid/extend_column.lua b/tests/examples/wibox/layout/grid/extend_column.lua index 360e16bd4..e31471d10 100644 --- a/tests/examples/wibox/layout/grid/extend_column.lua +++ b/tests/examples/wibox/layout/grid/extend_column.lua @@ -5,8 +5,8 @@ local wibox = require("wibox") --DOC_HIDE print("l:extend_column(2)") --DOC_HIDE local w = generic_before_after(wibox.layout.grid, { - forced_num_cols = 3, - forced_num_rows = 2, - homogeneous = true, + column_count = 3, + row_count = 2, + homogeneous = true, }, 6, "extend_column", {2}) --DOC_HIDE return w, w:fit({dpi=96}, 9999, 9999) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/imperative.lua b/tests/examples/wibox/layout/grid/imperative.lua index a6f8a4659..47f550d65 100644 --- a/tests/examples/wibox/layout/grid/imperative.lua +++ b/tests/examples/wibox/layout/grid/imperative.lua @@ -11,11 +11,11 @@ local lorem = generic_widget("Lorem ipsum dolor sit amet, consectetur " .. -- "adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") --DOC_HIDE local l = wibox.widget { - homogeneous = true, - spacing = 5, - min_cols_size = 10, - min_rows_size = 10, - layout = wibox.layout.grid, + homogeneous = true, + spacing = 5, + minimum_column_width = 10, + minimum_row_height = 10, + layout = wibox.layout.grid, } l:add_widget_at(first , 2, 1, 1, 2) l:add_widget_at(second, 3, 1, 1, 2) diff --git a/tests/examples/wibox/layout/grid/insert_column.lua b/tests/examples/wibox/layout/grid/insert_column.lua index e823d7f06..60ff820aa 100644 --- a/tests/examples/wibox/layout/grid/insert_column.lua +++ b/tests/examples/wibox/layout/grid/insert_column.lua @@ -5,9 +5,9 @@ local wibox = require("wibox") --DOC_HIDE print("l:insert_column(2)") --DOC_HIDE local w = generic_before_after(wibox.layout.grid, { - forced_num_cols = 3, - forced_num_rows = 2, - homogeneous = true, + column_count = 3, + row_count = 2, + homogeneous = true, } , 6, "insert_column", {2}) --DOC_HIDE return w, w:fit({dpi=96}, 9999, 9999) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/min_size.lua b/tests/examples/wibox/layout/grid/min_size.lua index fbd736181..6adf06759 100644 --- a/tests/examples/wibox/layout/grid/min_size.lua +++ b/tests/examples/wibox/layout/grid/min_size.lua @@ -6,41 +6,41 @@ local beautiful = require("beautiful") --DOC_HIDE local w = wibox.widget { { { - markup = "min_cols_size = 0", + markup = "minimum_column_width = 0", widget = wibox.widget.textbox }, { { generic_widget( "first" ), generic_widget( "second" ), - forced_num_cols = 2, - min_cols_size = 0, - homogeneous = true, - layout = wibox.layout.grid, + column_count = 2, + minimum_column_width = 0, + homogeneous = true, + layout = wibox.layout.grid, }, margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, { { - markup = "min_cols_size = 100", + markup = "minimum_column_width = 100", widget = wibox.widget.textbox }, { { generic_widget( "first" ), generic_widget( "second" ), - forced_num_cols = 2, - min_cols_size = 100, - homogeneous = true, - layout = wibox.layout.grid, + column_count = 2, + minimum_column_width = 100, + homogeneous = true, + layout = wibox.layout.grid, }, margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, diff --git a/tests/examples/wibox/layout/grid/orientation.lua b/tests/examples/wibox/layout/grid/orientation.lua index d0274925b..aac627fc7 100644 --- a/tests/examples/wibox/layout/grid/orientation.lua +++ b/tests/examples/wibox/layout/grid/orientation.lua @@ -1,42 +1,33 @@ ---DOC_GEN_OUTPUT --DOC_GEN_IMAGE -local generic_widget = ... --DOC_HIDE_ALL -local wibox = require("wibox") --DOC_HIDE -local beautiful = require("beautiful") --DOC_HIDE +--DOC_GEN_IMAGE +local generic_widget = ... --DOC_HIDE_START +local wibox = require("wibox") +local beautiful = require("beautiful") -print([[l = wibox.layout { - forced_num_cols = 2, - forced_num_rows = 2, - homogeneous = true, - layout = wibox.layout.grid -} -l:set_orientation("vertical") -- change to "horizontal" -l:add(...)]]) --DOC_HIDE - -return --DOC_HIDE +return wibox.widget { { { markup = "orientation = 'vertical'", widget = wibox.widget.textbox }, - { - { + { --DOC_HIDE_STOP + {--DOC_HIDE_START generic_widget( "first" ), generic_widget( "second" ), generic_widget( "third" ), generic_widget( "fourth" ), generic_widget( "fifth" ), - generic_widget( "sixth" ), - forced_num_cols = 2, - forced_num_rows = 2, - orientation = "vertical", - expand = false, - homogeneous = true, - layout = wibox.layout.grid, + generic_widget( "sixth" ),--DOC_HIDE_STOP + column_count = 2, + row_count = 2, + orientation = "vertical", + expand = false, + homogeneous = true, + layout = wibox.layout.grid, }, - margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + margins = 1,--DOC_HIDE_START + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, @@ -53,19 +44,20 @@ wibox.widget { generic_widget( "fourth" ), generic_widget( "fifth" ), generic_widget( "sixth" ), - forced_num_cols = 2, - forced_num_rows = 2, - orientation = 'horizontal', - expand = false, - homogeneous = true, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + orientation = 'horizontal', + expand = false, + homogeneous = true, + layout = wibox.layout.grid, }, margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, + spacing = 5, layout = wibox.layout.fixed.horizontal } -, 300, 90 --DOC_HIDE +, 300, 90 diff --git a/tests/examples/wibox/layout/grid/orientation.output.txt b/tests/examples/wibox/layout/grid/orientation.output.txt index cb19909a7..e69de29bb 100644 --- a/tests/examples/wibox/layout/grid/orientation.output.txt +++ b/tests/examples/wibox/layout/grid/orientation.output.txt @@ -1,8 +0,0 @@ -l = wibox.layout { - forced_num_cols = 2, - forced_num_rows = 2, - homogeneous = true, - layout = wibox.layout.grid -} -l:set_orientation("vertical") -- change to "horizontal" -l:add(...) diff --git a/tests/examples/wibox/layout/grid/remove.lua b/tests/examples/wibox/layout/grid/remove.lua index c2e1fe42e..c9c54208a 100644 --- a/tests/examples/wibox/layout/grid/remove.lua +++ b/tests/examples/wibox/layout/grid/remove.lua @@ -5,9 +5,9 @@ local wibox = require("wibox") --DOC_HIDE print("l:remove_widgets_at(1,1)") --DOC_HIDE local w = generic_before_after(wibox.layout.grid, { - forced_num_cols = 3, - forced_num_rows = 2, - homogeneous = true, + column_count = 3, + row_count = 2, + homogeneous = true, }, 6, "remove_widgets_at", {1, 1}) --DOC_HIDE return w, w:fit({dpi=96}, 9999, 9999) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/remove_column.lua b/tests/examples/wibox/layout/grid/remove_column.lua index 7359e032b..bde9e45a0 100644 --- a/tests/examples/wibox/layout/grid/remove_column.lua +++ b/tests/examples/wibox/layout/grid/remove_column.lua @@ -5,9 +5,9 @@ local wibox = require("wibox") --DOC_HIDE print("l:remove_column(2)") --DOC_HIDE local w = generic_before_after(wibox.layout.grid, { - forced_num_cols = 3, - forced_num_rows = 2, - homogeneous = true, + column_count = 3, + row_count = 2, + homogeneous = true, }, 6, "remove_column", {2} --DOC_HIDE ) return w, w:fit({dpi=96}, 9999, 9999) --DOC_HIDE diff --git a/tests/examples/wibox/layout/grid/spacing.lua b/tests/examples/wibox/layout/grid/spacing.lua index 750e4c79e..d0ef0bc76 100644 --- a/tests/examples/wibox/layout/grid/spacing.lua +++ b/tests/examples/wibox/layout/grid/spacing.lua @@ -1,8 +1,12 @@ --DOC_GEN_IMAGE -local generic_widget = ... --DOC_HIDE_ALL +local generic_widget_ = ... --DOC_HIDE_ALL local wibox = require("wibox") --DOC_HIDE local beautiful = require("beautiful") --DOC_HIDE +local function generic_widget(txt) + return generic_widget_(txt, nil, 0) +end + local w = wibox.widget { { { @@ -15,16 +19,15 @@ local w = wibox.widget { generic_widget( "second" ), generic_widget( "third" ), generic_widget( "fourth" ), - forced_num_cols = 2, - forced_num_rows = 2, - homogeneous = true, - spacing = 0, - padding = 0, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + homogeneous = true, + spacing = 0, + layout = wibox.layout.grid, }, margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, @@ -39,16 +42,15 @@ local w = wibox.widget { generic_widget( "second" ), generic_widget( "third" ), generic_widget( "fourth" ), - forced_num_cols = 2, - forced_num_rows = 2, - homogeneous = true, - spacing = 10, - padding = 0, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + homogeneous = true, + spacing = 10, + layout = wibox.layout.grid, }, margins = 1, - color = beautiful.border_color, - layout = wibox.container.margin, + color = beautiful.border_color, + layout = wibox.container.margin, }, layout = wibox.layout.fixed.vertical }, diff --git a/tests/examples/wibox/layout/grid/superpose.lua b/tests/examples/wibox/layout/grid/superpose.lua index 7036882b5..88ae58849 100644 --- a/tests/examples/wibox/layout/grid/superpose.lua +++ b/tests/examples/wibox/layout/grid/superpose.lua @@ -8,11 +8,11 @@ local w = wibox.widget { generic_widget( "second" ), generic_widget( "third" ), generic_widget( "fourth" ), - forced_num_cols = 2, - forced_num_rows = 2, - superpose = true, - homogeneous = true, - layout = wibox.layout.grid, + column_count = 2, + row_count = 2, + superpose = true, + homogeneous = true, + layout = wibox.layout.grid, } w:add_widget_at( generic_widget("fifth",beautiful.bg_highlight) diff --git a/tests/examples/wibox/nwidget/icon/strategy.lua b/tests/examples/wibox/nwidget/icon/strategy.lua index f7e2563fe..5594e1945 100644 --- a/tests/examples/wibox/nwidget/icon/strategy.lua +++ b/tests/examples/wibox/nwidget/icon/strategy.lua @@ -54,9 +54,9 @@ parent:add( icons[1], icons[2], icons[3], - forced_num_rows = 2, - forced_num_cols = 3, - spacing = 5, - widget = wibox.layout.grid, + column_count = 2, + row_count = 3, + spacing = 5, + widget = wibox.layout.grid, } ) diff --git a/tests/examples/wibox/widget/defaults/calendar.lua b/tests/examples/wibox/widget/defaults/calendar.lua index 45b966b09..619bc7c28 100644 --- a/tests/examples/wibox/widget/defaults/calendar.lua +++ b/tests/examples/wibox/widget/defaults/calendar.lua @@ -14,5 +14,6 @@ beautiful.fg_focus = "#ff9800" --DOC_HIDE beautiful.bg_focus = "#b9214f" --DOC_HIDE local cal = wibox.widget.calendar.month(os.date("*t")) + cal.border_width = 1 parent:add(cal) --DOC_HIDE