Merge pull request #638 from Elv13/upstream_shape_api

Upstream shape api
This commit is contained in:
Emmanuel Lepage Vallée 2016-01-18 17:51:58 -05:00
commit 72d3065937
5 changed files with 118 additions and 2 deletions

View File

@ -17,6 +17,7 @@ return
timer = require("gears.timer"); timer = require("gears.timer");
cache = require("gears.cache"); cache = require("gears.cache");
matrix = require("gears.matrix"); matrix = require("gears.matrix");
shape = require("gears.shape");
} }
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80 -- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

58
lib/gears/shape.lua Normal file
View File

@ -0,0 +1,58 @@
---------------------------------------------------------------------------
--- Module dedicated to gather common shape painters.
--
-- It add the concept of "shape" to Awesome. A shape can be applied to a
-- background, a margin, a mask or a drawable shape bounding.
--
-- The functions exposed by this module always take a context as first
-- parameter followed by the widget and height and additional parameters.
--
-- The functions provided by this module only create a path in the content.
-- to actually draw the content, use cr:fill(), cr:mask(), cr:slip() or
-- cr:stroke()
--
-- In many case, it is necessary to apply the shape using a transformation
-- such as a rotation. The preferred way to do this is to wrap the function
-- in another function calling `cr:rotate()` (or any other transformation
-- matrix)
--
-- @author Emmanuel Lepage Vallee
-- @copyright 2011-2016 Emmanuel Lepage Vallee
-- @release @AWESOME_VERSION@
-- @module gears.shape
---------------------------------------------------------------------------
local module = {}
--- Add a rounded rectangle to the current path
-- @note If the radius is bigger than either half side, it will be reduced
-- @param cr A cairo content
-- @param width The rectangle width
-- @param height The rectangle height
-- @param radius the corner radius
function module.rounded_rect(cr, width, height, radius)
if width / 2 < radius then
radius = width / 2
end
if height / 2 < radius then
radius = height / 2
end
cr:arc( radius , radius , radius, math.pi , 3*(math.pi/2) )
cr:arc( width-radius, radius , radius, 3*(math.pi/2), math.pi*2 )
cr:arc( width-radius, height-radius, radius, math.pi*2 , math.pi/2 )
cr:arc( radius , height-radius, radius, math.pi/2 , math.pi )
cr:close_path()
end
--- Add a rectangle delimited by 2 180 degree arcs to the path
-- @param cr A cairo content
-- @param width The rectangle width
-- @param height The rectangle height
function module.rounded_bar(cr, width, height)
module.rounded_rect(cr, width, height, height / 2)
end
return module

View File

@ -152,6 +152,32 @@ function surface.duplicate_surface(s)
return result return result
end end
--- Apply a shape to a client or a wibox.
--
-- If the wibox or client size change, this function need to be called
-- again.
-- @param draw A wibox or a client
-- @param shape or gears.shape function or a custom function with a context,
-- width and height as parameter.
-- @param[opt] Any additional parameters will be passed to the shape function
function surface.apply_shape_bounding(draw, shape, ...)
local geo = draw:geometry()
local img = cairo.ImageSurface(cairo.Format.A1, geo.width, geo.height)
local cr = cairo.Context(img)
cr:set_operator(cairo.Operator.CLEAR)
cr:set_source_rgba(0,0,0,1)
cr:paint()
cr:set_operator(cairo.Operator.SOURCE)
cr:set_source_rgba(1,1,1,1)
shape(cr, geo.width, geo.height, ...)
cr:fill()
draw.shape_bounding = img._native
end
return setmetatable(surface, surface.mt) return setmetatable(surface, surface.mt)

View File

@ -55,6 +55,11 @@ function margin:fit(context, width, height)
if self.widget then if self.widget then
w, h = base.fit_widget(self, context, self.widget, width - extra_w, height - extra_h) w, h = base.fit_widget(self, context, self.widget, width - extra_w, height - extra_h)
end end
if self._draw_empty == false and (w == 0 or h == 0) then
return 0, 0
end
return w + extra_w, h + extra_h return w + extra_w, h + extra_h
end end
@ -82,6 +87,13 @@ function margin:set_color(color)
self:emit_signal("widget::redraw_needed") self:emit_signal("widget::redraw_needed")
end 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 --- Reset this layout. The widget will be unreferenced, the margins set to 0
-- and the color erased -- and the color erased
function margin:reset() function margin:reset()
@ -129,7 +141,8 @@ end
-- @param[opt] top A margin to use on the top 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] bottom A margin to use on the bottom side of the widget.
-- @param[opt] color A color for the margins. -- @param[opt] color A color for the margins.
local function new(widget, left, right, top, bottom, color) -- @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() local ret = base.make_widget()
for k, v in pairs(margin) do for k, v in pairs(margin) do
@ -142,6 +155,7 @@ local function new(widget, left, right, top, bottom, color)
ret:set_right(right or 0) ret:set_right(right or 0)
ret:set_top(top or 0) ret:set_top(top or 0)
ret:set_bottom(bottom or 0) ret:set_bottom(bottom or 0)
ret:set_draw_empty(draw_empty)
ret:set_color(color) ret:set_color(color)

View File

@ -21,6 +21,11 @@ function background:draw(context, cr, width, height)
return return
end end
if self._shape then
self._shape(cr, width, height, unpack(self._shape_args or {}))
cr:clip()
end
if self.background then if self.background then
cr:set_source(self.background) cr:set_source(self.background)
cr:paint() cr:paint()
@ -84,6 +89,15 @@ function background:set_fg(fg)
self:emit_signal("widget::redraw_needed") self:emit_signal("widget::redraw_needed")
end end
--- Set the background shape
-- @param shape A function taking a context, width and height as arguments
-- Any other arguments will be passed to the shape function
function background:set_shape(shape, ...)
ret._shape = shape
ret._shape_args = {...}
self:emit_signal("widget::redraw_needed")
end
--- Set the background image to use --- Set the background image to use
function background:set_bgimage(image) function background:set_bgimage(image)
self.bgimage = surface.load(image) self.bgimage = surface.load(image)
@ -94,7 +108,8 @@ end
-- and foreground color to another widget. -- and foreground color to another widget.
-- @param[opt] widget The widget to display. -- @param[opt] widget The widget to display.
-- @param[opt] bg The background to use for that widget. -- @param[opt] bg The background to use for that widget.
local function new(widget, bg) -- @param[opt] shape A `gears.shape` compatible shape function
local function new(widget, bg, shape)
local ret = base.make_widget() local ret = base.make_widget()
for k, v in pairs(background) do for k, v in pairs(background) do
@ -103,6 +118,8 @@ local function new(widget, bg)
end end
end end
ret._shape = shape
ret:set_widget(widget) ret:set_widget(widget)
ret:set_bg(bg) ret:set_bg(bg)