141 lines
4.3 KiB
Lua
141 lines
4.3 KiB
Lua
local setmetatable = setmetatable
|
|
local unpack = unpack or table.unpack
|
|
local beautiful = require( "beautiful" )
|
|
local color = require( "gears.color" )
|
|
local cairo = require( "lgi" ).cairo
|
|
local base = require( "radical.base" )
|
|
local shape = require( "gears.shape" )
|
|
|
|
local module = {
|
|
margins = {
|
|
BOTTOM = 10,
|
|
TOP = 10,
|
|
LEFT = 0 ,
|
|
RIGHT = 0 ,
|
|
}
|
|
}
|
|
|
|
-- Matrix rotation per direction
|
|
local angles = {
|
|
top = math.pi , -- 180
|
|
bottom = 0 , -- 0
|
|
left = math.pi/2 , -- 90
|
|
right = 3*math.pi/2 , -- 270
|
|
}
|
|
|
|
-- If width and height need to be swapped
|
|
local swaps = {
|
|
top = false,
|
|
bottom= false,
|
|
right = true ,
|
|
left = true ,
|
|
}
|
|
|
|
local invert = {
|
|
top = "bottom",
|
|
bottom = "top" ,
|
|
right = "left" , --FIXME this is wrong
|
|
left = "right" , --FIXME this is wrong
|
|
}
|
|
|
|
-- Constants
|
|
local radius = 10
|
|
local arrow_height = 13
|
|
|
|
-- Generate the arrow position
|
|
local function gen_arrow_x(data,direction, width, height)
|
|
local at = data.arrow_type
|
|
local par_center_x = data.wibox.width/2
|
|
|
|
if at == base.arrow_type.PRETTY or not at then
|
|
if direction == "left" then
|
|
data._arrow_x = data._internal.w.height -20 - (data.arrow_x_orig or 20)
|
|
elseif direction == "right" then
|
|
--TODO
|
|
elseif direction == "bottom" then
|
|
data._arrow_x = width -20 - (data.arrow_x_orig or 20)
|
|
if par_center_x >= 0 then
|
|
data._arrow_x = width - (par_center_x - 0) - arrow_height
|
|
end
|
|
elseif direction == "top" then
|
|
--TODO
|
|
end
|
|
elseif at == base.arrow_type.CENTERED then
|
|
if direction == "left" or direction == "right" then
|
|
data._arrow_x = height/2 - arrow_height
|
|
else
|
|
data._arrow_x = width/2 - arrow_height
|
|
end
|
|
end
|
|
end
|
|
|
|
local function update_margins(data, pos)
|
|
-- Set the margins correctly
|
|
if data._internal.margin then
|
|
data.margins.left = module.margins.LEFT
|
|
data.margins.right = module.margins.RIGHT
|
|
data.margins.top = module.margins.TOP
|
|
data.margins.bottom = module.margins.BOTTOM
|
|
|
|
-- Add enough room for the arrow
|
|
if pos and data.arrow_type ~= base.arrow_type.NONE then
|
|
data.margins[invert[pos]] = data.margins[invert[pos]] + arrow_height
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Generate a rounded cairo path with the arrow
|
|
local function draw_roundedrect_path(cr, width, height, radius, data, position)
|
|
if data.arrow_type == base.arrow_type.NONE then
|
|
return shape.rounded_rect(cr, width, height, radius)
|
|
end
|
|
|
|
local angle, swap = angles[position], swaps[position]
|
|
|
|
-- Invert width and height to avoid distortion
|
|
if swap then
|
|
width, height = height, width
|
|
end
|
|
|
|
-- Use rounded rext for sub-menu and
|
|
local s = shape.transform(shape.infobubble)
|
|
|
|
-- Apply transformations
|
|
s = s : rotate_at(width / 2, height / 2, angle)
|
|
|
|
-- Decide where the arrow will be
|
|
gen_arrow_x(data, data.direction, width, height)
|
|
|
|
-- Forward to the real shape
|
|
local ax = swap and width - (data._arrow_x or 20) or (data._arrow_x or 20)
|
|
s(cr, width, height, radius, arrow_height, ax)
|
|
end
|
|
|
|
local function draw(data,args)
|
|
local args = args or {}
|
|
|
|
if not data._internal.arrow_setup then
|
|
data._internal.w:set_shape_border_width(data.border_width or 1)
|
|
data._internal.w:set_shape_border_color(color(beautiful.menu_outline_color or beautiful.menu_border_color or beautiful.fg_normal))
|
|
data._internal.w:set_shape(data.shape or shape.infobubble, unpack(data.shape_args or {}))
|
|
|
|
data._internal.w:connect_signal("property::position", function(_, pos)
|
|
data._internal.w:set_shape(function(cr, w, h) draw_roundedrect_path(cr, w, h, radius, data, pos) end)
|
|
update_margins(data, pos)
|
|
end)
|
|
|
|
local pos = data._internal.w.position
|
|
if pos then
|
|
data._internal.w:set_shape(function(cr, w, h) draw_roundedrect_path(cr, w, h, radius, data, data._internal.w.position) end)
|
|
end
|
|
update_margins(data, pos)
|
|
|
|
data._internal.arrow_setup = true
|
|
end
|
|
|
|
return w,w2
|
|
end
|
|
|
|
return setmetatable(module, { __call = function(_, ...) return draw(...) end })
|
|
-- kate: space-indent on; indent-width 4; replace-tabs on;
|