2013-05-11 21:02:42 +02:00
|
|
|
local setmetatable = setmetatable
|
2016-02-21 08:34:05 +01:00
|
|
|
local unpack = unpack or table.unpack
|
|
|
|
local beautiful = require( "beautiful" )
|
|
|
|
local color = require( "gears.color" )
|
|
|
|
local base = require( "radical.base" )
|
|
|
|
local shape = require( "gears.shape" )
|
2013-05-11 21:02:42 +02:00
|
|
|
|
|
|
|
local module = {
|
2016-02-21 08:34:05 +01:00
|
|
|
margins = {
|
|
|
|
BOTTOM = 10,
|
|
|
|
TOP = 10,
|
|
|
|
LEFT = 0 ,
|
|
|
|
RIGHT = 0 ,
|
|
|
|
}
|
2013-05-11 21:02:42 +02:00
|
|
|
}
|
|
|
|
|
2014-10-11 09:10:55 +02:00
|
|
|
-- Matrix rotation per direction
|
|
|
|
local angles = {
|
2016-02-21 08:34:05 +01:00
|
|
|
top = math.pi , -- 180
|
|
|
|
bottom = 0 , -- 0
|
|
|
|
left = math.pi/2 , -- 90
|
|
|
|
right = 3*math.pi/2 , -- 270
|
2014-10-11 09:10:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
-- If width and height need to be swapped
|
|
|
|
local swaps = {
|
2016-02-21 08:34:05 +01:00
|
|
|
top = false,
|
|
|
|
bottom= false,
|
|
|
|
right = true ,
|
|
|
|
left = true ,
|
2014-10-11 09:10:55 +02:00
|
|
|
}
|
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
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
|
|
|
|
|
2016-02-11 07:36:50 +01:00
|
|
|
-- Generate the arrow position
|
2016-03-15 08:55:20 +01:00
|
|
|
local function gen_arrow_x(data, direction, width, height)
|
2016-02-21 08:34:05 +01:00
|
|
|
local at = data.arrow_type
|
|
|
|
|
2016-06-24 06:46:41 +02:00
|
|
|
local pg = data.parent_geometry
|
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
if at == base.arrow_type.PRETTY or not at then
|
|
|
|
if direction == "left" then
|
|
|
|
--TODO
|
2016-03-15 08:55:20 +01:00
|
|
|
elseif direction == "right" then
|
2016-06-24 06:46:41 +02:00
|
|
|
data._internal.w:set_yoffset(-(20) + arrow_height)
|
2016-02-21 08:34:05 +01:00
|
|
|
elseif direction == "bottom" then
|
2016-06-24 06:46:41 +02:00
|
|
|
data._internal.w:set_xoffset(-(20) - arrow_height)
|
2016-02-21 08:34:05 +01:00
|
|
|
elseif direction == "top" then
|
2016-03-15 08:55:20 +01:00
|
|
|
data._internal.w:set_xoffset(-data._internal.w.width + (20) + arrow_height)
|
2016-02-21 08:34:05 +01:00
|
|
|
end
|
|
|
|
elseif at == base.arrow_type.CENTERED then
|
|
|
|
if direction == "left" or direction == "right" then
|
|
|
|
data._arrow_x = height/2 - arrow_height
|
2016-03-15 08:55:20 +01:00
|
|
|
data._internal.w:set_yoffset(data._internal.w.height/2 - arrow_height)
|
2016-02-21 08:34:05 +01:00
|
|
|
else
|
|
|
|
data._arrow_x = width/2 - arrow_height
|
2016-06-24 06:46:41 +02:00
|
|
|
if pg then
|
|
|
|
data._internal.w:set_xoffset(-data._internal.w.width/2 + arrow_height + pg.width/2)
|
|
|
|
else
|
|
|
|
data._internal.w:set_xoffset(data._internal.w.width/2 - arrow_height)
|
|
|
|
end
|
2016-02-21 08:34:05 +01:00
|
|
|
end
|
2014-10-06 00:01:54 +02:00
|
|
|
end
|
2014-03-27 04:21:42 +01:00
|
|
|
end
|
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
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
|
2016-02-11 07:36:50 +01:00
|
|
|
end
|
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
-- Generate a rounded cairo path with the arrow
|
2016-06-24 22:53:47 +02:00
|
|
|
local function draw_roundedrect_path(cr, width, height, rad, data, direction)
|
2016-03-15 08:55:20 +01:00
|
|
|
direction = direction or "right"
|
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
if data.arrow_type == base.arrow_type.NONE then
|
2016-03-15 08:55:20 +01:00
|
|
|
if direction == "left" then
|
2016-06-24 22:53:47 +02:00
|
|
|
data._internal.w:set_yoffset(-rad)
|
2016-03-15 08:55:20 +01:00
|
|
|
elseif direction == "right" then
|
2016-06-24 22:53:47 +02:00
|
|
|
data._internal.w:set_yoffset(rad)
|
2016-03-15 08:55:20 +01:00
|
|
|
end
|
2016-06-24 22:53:47 +02:00
|
|
|
return shape.rounded_rect(cr, width, height, rad)
|
2016-02-21 08:34:05 +01:00
|
|
|
end
|
2014-10-06 00:01:54 +02:00
|
|
|
|
2016-03-15 08:55:20 +01:00
|
|
|
local angle, swap = angles[direction], swaps[direction]
|
2014-03-24 00:00:43 +01:00
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
-- Invert width and height to avoid distortion
|
|
|
|
if swap then
|
|
|
|
width, height = height, width
|
2014-10-06 00:01:54 +02:00
|
|
|
end
|
2014-06-01 05:45:46 +02:00
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
-- Use rounded rext for sub-menu and
|
|
|
|
local s = shape.transform(shape.infobubble)
|
2014-10-11 09:10:55 +02:00
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
-- Apply transformations
|
|
|
|
s = s : rotate_at(width / 2, height / 2, angle)
|
2016-02-11 07:36:50 +01:00
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
-- Decide where the arrow will be
|
|
|
|
gen_arrow_x(data, data.direction, width, height)
|
2014-10-11 09:10:55 +02:00
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
-- Forward to the real shape
|
2016-06-24 22:53:47 +02:00
|
|
|
local ax = swap and width - (data._arrow_x or 20)-arrow_height - rad or (data._arrow_x or 20)
|
|
|
|
s(cr, width, height, rad, arrow_height, ax)
|
2014-10-11 09:10:55 +02:00
|
|
|
end
|
|
|
|
|
2016-06-24 22:53:47 +02:00
|
|
|
local function draw(data)
|
2016-02-11 07:36:50 +01:00
|
|
|
|
2016-02-21 08:34:05 +01:00
|
|
|
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 {}))
|
2016-02-11 07:36:50 +01:00
|
|
|
|
2016-03-15 08:55:20 +01:00
|
|
|
data._internal.w:connect_signal("property::direction", function(_, dir)
|
|
|
|
data.direction = dir
|
2016-08-09 22:37:52 +02:00
|
|
|
data._internal.w:set_shape(function(cr, w, h) draw_roundedrect_path(cr, w, h, data.radius or radius, data, dir) end)
|
2016-03-15 08:55:20 +01:00
|
|
|
update_margins(data, dir)
|
2016-02-21 08:34:05 +01:00
|
|
|
end)
|
2013-05-11 21:02:42 +02:00
|
|
|
|
2016-03-15 08:55:20 +01:00
|
|
|
-- local dir = data._internal.w.position
|
|
|
|
-- if dir then
|
|
|
|
-- data._internal.w:set_shape(function(cr, w, h) draw_roundedrect_path(cr, w, h, radius, data, data._internal.w.position) end)
|
|
|
|
-- end
|
2016-06-24 22:53:47 +02:00
|
|
|
update_margins(data, nil)
|
2016-02-21 08:34:05 +01:00
|
|
|
|
|
|
|
data._internal.arrow_setup = true
|
|
|
|
end
|
2013-05-11 21:02:42 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return setmetatable(module, { __call = function(_, ...) return draw(...) end })
|
2016-02-21 08:34:05 +01:00
|
|
|
-- kate: space-indent on; indent-width 4; replace-tabs on;
|