Widgets: Also add a context argument to :fit()

Together with the context argument to :draw(), this even allows widgets to have
DPI-dependant size.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2015-08-08 13:43:35 +02:00
parent 88b98789a0
commit 1ebc34b5e9
18 changed files with 42 additions and 38 deletions

View File

@ -83,7 +83,7 @@ end
local function set_geometry(self) local function set_geometry(self)
local my_geo = self.wibox:geometry() local my_geo = self.wibox:geometry()
-- calculate width / height -- calculate width / height
local n_w, n_h = self.textbox:fit(-1, -1) local n_w, n_h = self.textbox:fit(nil, -1, -1) -- Hack! :(
n_w = n_w + self.marginbox.left + self.marginbox.right n_w = n_w + self.marginbox.left + self.marginbox.right
n_h = n_h + self.marginbox.top + self.marginbox.bottom n_h = n_h + self.marginbox.top + self.marginbox.bottom
if my_geo.width ~= n_w or my_geo.height ~= n_h then if my_geo.width ~= n_w or my_geo.height ~= n_h then

View File

@ -158,7 +158,7 @@ function graph.draw(_graph, context, cr, width, height)
end end
end end
function graph.fit(_graph, width, height) function graph.fit(_graph)
return data[_graph].width, data[_graph].height return data[_graph].width, data[_graph].height
end end

View File

@ -154,7 +154,7 @@ function progressbar.draw(pbar, context, cr, width, height)
end end
end end
function progressbar.fit(pbar, width, height) function progressbar.fit(pbar)
return data[pbar].width, data[pbar].height return data[pbar].width, data[pbar].height
end end

View File

@ -526,7 +526,7 @@ function naughty.notify(args)
actiontextbox:set_font(font) actiontextbox:set_font(font)
actiontextbox:set_markup(string.format('<b>%s</b>', action)) actiontextbox:set_markup(string.format('<b>%s</b>', action))
-- calculate the height and width -- calculate the height and width
local w, h = actiontextbox:fit(-1, -1) local w, h = actiontextbox:fit(nil, -1, -1) -- Hack! :(
local height = h + 2 * margin local height = h + 2 * margin
local width = w + 2 * margin local width = w + 2 * margin
@ -596,7 +596,7 @@ function naughty.notify(args)
-- calculate the height -- calculate the height
if not height then if not height then
local w, h = textbox:fit(-1, -1) local w, h = textbox:fit(nil, -1, -1) -- Hack! :-(
if iconbox and icon_h + 2 * margin > h + 2 * margin then if iconbox and icon_h + 2 * margin > h + 2 * margin then
height = icon_h + 2 * margin height = icon_h + 2 * margin
else else
@ -608,7 +608,7 @@ function naughty.notify(args)
-- calculate the width -- calculate the width
if not width then if not width then
local w, h = textbox:fit(-1, -1) local w, h = textbox:fit(nil, -1, -1) -- Hack! :-(
width = w + (iconbox and icon_w + 2 * margin or 0) + 2 * margin width = w + (iconbox and icon_w + 2 * margin or 0) + 2 * margin
end end

View File

@ -37,7 +37,7 @@ function align:draw(context, cr, width, height)
-- if the second widget doesn't exist, we will prioritise the first one -- if the second widget doesn't exist, we will prioritise the first one
-- instead -- instead
if self._expand ~= "inside" and self.second then if self._expand ~= "inside" and self.second then
local w, h = base.fit_widget(self.second, width, height) local w, h = base.fit_widget(context, self.second, width, height)
local size_second = self.dir == "y" and h or w local size_second = self.dir == "y" and h or w
-- if all the space is taken, skip the rest, and draw just the middle -- if all the space is taken, skip the rest, and draw just the middle
-- widget -- widget
@ -57,7 +57,7 @@ function align:draw(context, cr, width, height)
-- into the remaining space -- into the remaining space
if self._expand ~= "outside" then if self._expand ~= "outside" then
if self.dir == "y" then if self.dir == "y" then
_, h = base.fit_widget(self.first, width, size_remains) _, h = base.fit_widget(context, self.first, width, size_remains)
size_first = h size_first = h
-- for "inside", the third widget will get a chance to use the -- for "inside", the third widget will get a chance to use the
-- remaining space, then the middle widget. For "none" we give -- remaining space, then the middle widget. For "none" we give
@ -68,7 +68,7 @@ function align:draw(context, cr, width, height)
size_remains = size_remains - h size_remains = size_remains - h
end end
else else
w, _ = base.fit_widget(self.first, size_remains, height) w, _ = base.fit_widget(context, self.first, size_remains, height)
size_first = w size_first = w
if self._expand == "inside" or not self.second then if self._expand == "inside" or not self.second then
size_remains = size_remains - w size_remains = size_remains - w
@ -88,13 +88,13 @@ function align:draw(context, cr, width, height)
local w, h, _ = width, height, nil local w, h, _ = width, height, nil
if self._expand ~= "outside" then if self._expand ~= "outside" then
if self.dir == "y" then if self.dir == "y" then
_, h = base.fit_widget(self.third, width, size_remains) _, h = base.fit_widget(context, self.third, width, size_remains)
-- give the middle widget the rest of the space for "inside" mode -- give the middle widget the rest of the space for "inside" mode
if self._expand == "inside" then if self._expand == "inside" then
size_remains = size_remains - h size_remains = size_remains - h
end end
else else
w, _ = base.fit_widget(self.third, size_remains, height) w, _ = base.fit_widget(context, self.third, size_remains, height)
if self._expand == "inside" then if self._expand == "inside" then
size_remains = size_remains - w size_remains = size_remains - w
end end
@ -123,10 +123,10 @@ function align:draw(context, cr, width, height)
end end
else else
if self.dir == "y" then if self.dir == "y" then
_, h = base.fit_widget(self.second, width, size_remains) _, h = base.fit_widget(context, self.second, width, size_remains)
y = floor( (height - h)/2 ) y = floor( (height - h)/2 )
else else
w, _ = base.fit_widget(self.second, width, size_remains) w, _ = base.fit_widget(context, self.second, width, size_remains)
x = floor( (width -w)/2 ) x = floor( (width -w)/2 )
end end
end end
@ -166,14 +166,15 @@ 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 -- ask for the sum of the sizes of its sub-widgets in its direction
-- and the largest sized sub widget in the other direction. -- and the largest sized sub widget in the other direction.
-- @param context The context in which we are fit.
-- @param orig_width The available width. -- @param orig_width The available width.
-- @param orig_height The available height. -- @param orig_height The available height.
function align:fit(orig_width, orig_height) function align:fit(context, orig_width, orig_height)
local used_in_dir = 0 local used_in_dir = 0
local used_in_other = 0 local used_in_other = 0
for k, v in pairs{self.first, self.second, self.third} do for k, v in pairs{self.first, self.second, self.third} do
local w, h = base.fit_widget(v, orig_width, orig_height) local w, h = base.fit_widget(context, v, orig_width, orig_height)
local max = self.dir == "y" and w or h local max = self.dir == "y" and w or h
if max > used_in_other then if max > used_in_other then

View File

@ -29,11 +29,12 @@ function base.rect_to_device_geometry(cr, x, y, width, height)
end end
--- Fit a widget for the given available width and height --- Fit a widget for the given available width and height
-- @param context The context in which we are fit.
-- @param widget The widget to fit (this uses widget:fit(width, height)). -- @param widget The widget to fit (this uses widget:fit(width, height)).
-- @param width The available width for the widget -- @param width The available width for the widget
-- @param height The available height for the widget -- @param height The available height for the widget
-- @return The width and height that the widget wants to use -- @return The width and height that the widget wants to use
function base.fit_widget(widget, width, height) function base.fit_widget(context, widget, width, height)
if not widget.visible then if not widget.visible then
return 0, 0 return 0, 0
end end
@ -41,7 +42,7 @@ function base.fit_widget(widget, width, height)
local width = math.max(0, width) local width = math.max(0, width)
local height = math.max(0, height) local height = math.max(0, height)
return widget._fit_geometry_cache:get(width, height) return widget._fit_geometry_cache:get(context, width, height)
end end
--- Draw a widget via a cairo context --- Draw a widget via a cairo context

View File

@ -24,13 +24,13 @@ function constraint:draw(context, cr, width, height)
end end
--- Fit a constraint layout into the given space --- Fit a constraint layout into the given space
function constraint:fit(width, height) function constraint:fit(context, width, height)
local w, h local w, h
if self.widget then if self.widget then
w = self._strategy(width, self._width) w = self._strategy(width, self._width)
h = self._strategy(height, self._height) h = self._strategy(height, self._height)
w, h = base.fit_widget(self.widget, w, h) w, h = base.fit_widget(context, self.widget, w, h)
else else
w, h = 0, 0 w, h = 0, 0
end end

View File

@ -28,7 +28,7 @@ function fixed:draw(context, cr, width, height)
x, y = 0, pos x, y = 0, pos
w, h = width, height - pos w, h = width, height - pos
if k ~= #self.widgets or not self._fill_space then if k ~= #self.widgets or not self._fill_space then
_, h = base.fit_widget(v, w, h); _, h = base.fit_widget(context, v, w, h);
end end
pos = pos + h + spacing pos = pos + h + spacing
in_dir = h in_dir = h
@ -36,7 +36,7 @@ function fixed:draw(context, cr, width, height)
x, y = pos, 0 x, y = pos, 0
w, h = width - pos, height w, h = width - pos, height
if k ~= #self.widgets or not self._fill_space then if k ~= #self.widgets or not self._fill_space then
w, _ = base.fit_widget(v, w, h); w, _ = base.fit_widget(context, v, w, h);
end end
pos = pos + w + spacing pos = pos + w + spacing
in_dir = w in_dir = w
@ -59,14 +59,15 @@ function fixed:add(widget)
end end
--- Fit the fixed layout into the given space --- Fit the fixed layout into the given space
-- @param context The context in which we are fit.
-- @param orig_width The available width. -- @param orig_width The available width.
-- @param orig_height The available height. -- @param orig_height The available height.
function fixed:fit(orig_width, orig_height) function fixed:fit(context, orig_width, orig_height)
local width, height = orig_width, orig_height local width, height = orig_width, orig_height
local used_in_dir, used_max = 0, 0 local used_in_dir, used_max = 0, 0
for k, v in pairs(self.widgets) do for k, v in pairs(self.widgets) do
local w, h = base.fit_widget(v, width, height) local w, h = base.fit_widget(context, v, width, height)
local in_dir, max local in_dir, max
if self.dir == "y" then if self.dir == "y" then
max, in_dir = w, h max, in_dir = w, h

View File

@ -75,9 +75,10 @@ function flex:set_max_widget_size(val)
end end
--- Fit the flex layout into the given space. --- Fit the flex layout into the given space.
-- @param context The context in which we are fit.
-- @param orig_width The available width. -- @param orig_width The available width.
-- @param orig_height The available height. -- @param orig_height The available height.
function flex:fit(orig_width, orig_height) function flex:fit(context, orig_width, orig_height)
local used_in_dir = 0 local used_in_dir = 0
local used_in_other = 0 local used_in_other = 0
@ -86,7 +87,7 @@ function flex:fit(orig_width, orig_height)
local sub_width = self.dir == "y" and orig_width or floor(orig_width / #self.widgets) local sub_width = self.dir == "y" and orig_width or floor(orig_width / #self.widgets)
for k, v in pairs(self.widgets) do for k, v in pairs(self.widgets) do
local w, h = base.fit_widget(v, sub_width, sub_height) local w, h = base.fit_widget(context, v, sub_width, sub_height)
local max = self.dir == "y" and w or h local max = self.dir == "y" and w or h
if max > used_in_other then if max > used_in_other then

View File

@ -41,12 +41,12 @@ function margin:draw(context, cr, width, height)
end end
--- Fit a margin layout into the given space --- Fit a margin layout into the given space
function margin:fit(width, height) function margin:fit(context, width, height)
local extra_w = self.left + self.right local extra_w = self.left + self.right
local extra_h = self.top + self.bottom local extra_h = self.top + self.bottom
local w, h = 0, 0 local w, h = 0, 0
if self.widget then if self.widget then
w, h = base.fit_widget(self.widget, width - extra_w, height - extra_h) w, h = base.fit_widget(context, self.widget, width - extra_w, height - extra_h)
end end
return w + extra_w, h + extra_h return w + extra_w, h + extra_h
end end

View File

@ -45,11 +45,11 @@ function mirror:draw(context, cr, width, height)
end end
--- Fit this layout into the given area --- Fit this layout into the given area
function mirror:fit(...) function mirror:fit(context, ...)
if not self.widget then if not self.widget then
return 0, 0 return 0, 0
end end
return base.fit_widget(self.widget, ...) return base.fit_widget(context, self.widget, ...)
end end
--- Set the widget that this layout mirrors. --- Set the widget that this layout mirrors.

View File

@ -49,11 +49,11 @@ function rotate:draw(context, cr, width, height)
end end
--- Fit this layout into the given area --- Fit this layout into the given area
function rotate:fit(width, height) function rotate:fit(context, width, height)
if not self.widget then if not self.widget then
return 0, 0 return 0, 0
end end
return transform(self, base.fit_widget(self.widget, transform(self, width, height))) return transform(self, base.fit_widget(context, self.widget, transform(self, width, height)))
end end
--- Set the widget that this layout rotates. --- Set the widget that this layout rotates.

View File

@ -47,12 +47,12 @@ function background:draw(context, cr, width, height)
end end
--- Fit this widget into the given area --- Fit this widget into the given area
function background:fit(width, height) function background:fit(context, width, height)
if not self.widget then if not self.widget then
return 0, 0 return 0, 0
end end
return self.widget:fit(width, height) return layout_base.fit_widget(context, self.widget, width, height)
end end
--- Set the widget that is drawn on top of the background --- Set the widget that is drawn on top of the background

View File

@ -142,7 +142,7 @@ function base.check_widget(widget)
debug.assert(type(widget[func]) == "function", func .. " is not a function") debug.assert(type(widget[func]) == "function", func .. " is not a function")
end end
local width, height = widget:fit(0, 0) local width, height = widget:fit({}, 0, 0)
debug.assert(type(width) == "number") debug.assert(type(width) == "number")
debug.assert(type(height) == "number") debug.assert(type(height) == "number")
end end

View File

@ -39,7 +39,7 @@ function imagebox:draw(context, cr, width, height)
end end
--- Fit the imagebox into the given geometry --- Fit the imagebox into the given geometry
function imagebox:fit(width, height) function imagebox:fit(context, width, height)
if not self._image then if not self._image then
return 0, 0 return 0, 0
end end

View File

@ -45,7 +45,7 @@ function systray:draw(context, cr, width, height)
base, is_rotated, bg, reverse, spacing) base, is_rotated, bg, reverse, spacing)
end end
function systray:fit(width, height) function systray:fit(context, width, height)
local num_entries = capi.awesome.systray() local num_entries = capi.awesome.systray()
local base = base_size local base = base_size
local spacing = beautiful.systray_icon_spacing or 0 local spacing = beautiful.systray_icon_spacing or 0

View File

@ -42,7 +42,7 @@ function textbox:draw(context, cr, width, height)
end end
--- Fit the given textbox --- Fit the given textbox
function textbox:fit(width, height) function textbox:fit(context, width, height)
setup_layout(self, width, height) setup_layout(self, width, height)
local ink, logical = self._layout:get_pixel_extents() local ink, logical = self._layout:get_pixel_extents()

View File

@ -35,7 +35,7 @@ local function widget_fit(state, arguments)
local widget = arguments[1] local widget = arguments[1]
local given = arguments[2] local given = arguments[2]
local expected = arguments[3] local expected = arguments[3]
local w, h = widget:fit(given[1], given[2]) local w, h = widget:fit({ "fake context" }, given[1], given[2])
local fits = expected[1] == w and expected[2] == h local fits = expected[1] == w and expected[2] == h
if state.mod == fits then if state.mod == fits then