From 1a72280ccb5cb5c2134f4b4e0cea4701cb75a72b Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Tue, 31 Dec 2013 00:01:02 -0500 Subject: [PATCH] Add tooltip module --- impl/alttab.lua | 2 - tooltip.lua | 139 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 tooltip.lua diff --git a/impl/alttab.lua b/impl/alttab.lua index 1544231..a927333 100644 --- a/impl/alttab.lua +++ b/impl/alttab.lua @@ -138,5 +138,3 @@ end return setmetatable(module, { __call = function(_, ...) return new(...) end }) -- kate: space-indent on; indent-width 2; replace-tabs on; -rn new(...) end }) --- kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/tooltip.lua b/tooltip.lua new file mode 100644 index 0000000..ec9afec --- /dev/null +++ b/tooltip.lua @@ -0,0 +1,139 @@ +local setmetatable,math = setmetatable,math +local beautiful = require( "beautiful" ) +local wibox = require( "wibox" ) +local cairo = require( "lgi" ).cairo +local capi = { screen = screen , + mouse = mouse } +local module={} + +local function get_direction(args) + if not args.parent or not args.parent.drawable then return "bottom" end + local drawable_geom = args.parent.drawable.drawable.geometry(args.parent.drawable.drawable) + if args.parent.y+args.parent.height < drawable_geom.height then --Vertical wibox + if drawable_geom.x > capi.screen[capi.mouse.screen].geometry.width - (drawable_geom.x+drawable_geom.width) then + return "left" + else + return "right" + end + else --Horizontal wibox + if drawable_geom.y > capi.screen[capi.mouse.screen].geometry.height - (drawable_geom.y+drawable_geom.height) then + return "top" + else + return "bottom" + end + end +end + +local function rel_parent(w,args2,args) + if args2 and args2.parent then + local drawable_geom = args2.parent.drawable.drawable.geometry(args2.parent.drawable.drawable) + if (args.direction == "left") or (args.direction == "right") then + return {x=drawable_geom.x+((args.direction == "left") and - w.width or drawable_geom.width),y=drawable_geom.y+args2.parent.y+args2.parent.height/2-w.height/2} + else + return {x=drawable_geom.x+args2.parent.x-w.width/2 + args2.parent.width/2,y=(args.direction == "top") and drawable_geom.y-w.height or drawable_geom.y+drawable_geom.height} + end + end + return {} +end + +local function new(widget,text, args) + local args,data = args or {},{} + + local function hide_tooltip() + if data.wibox then + data.wibox.visible = false + if data.drawable then + data.drawable:disconnect_signal("mouse::leave",hide_tooltip) + data.drawable = nil + end + end + end + + function data:hide() hide_tooltip() end + + function data:showToolTip(show,args2) + local args2 = args2 or args or {} + args.direction = args.direction or get_direction(args2) + if not data.wibox then + local vertical,textw = (args.direction == "left") or (args.direction == "right"),wibox.widget.textbox() + textw.align = "center" + textw:set_markup("".. text .."") + local w,extents = wibox({position="free"}),textw._layout:get_pixel_extents() + extents.width = extents.width + 60 + w.visible = false + w.width = extents.width + w.height = vertical and 20 or 25 + w.ontop = true + w:set_bg(beautiful.tooltip_bg or beautiful.bg_normal or "") + + local img = cairo.ImageSurface(cairo.Format.A1, extents.width, vertical and 20 or 25) + local cr = cairo.Context(img) + --Clear the surface + cr:set_source_rgba( 0, 0, 0, 0 ) + cr:paint() + + --Draw the corner + cr:set_source_rgba( 1, 1, 1, 1 ) + if not (vertical) then + cr:arc(20-(vertical and 5 or 0), 20/2 + (5), 20/2 - 1,0,2*math.pi) + end + cr:arc(extents.width-20+(2*(vertical and 5 or 0)), 20/2 + (vertical and 0 or 5), 20/2 - 1,0,2*math.pi) + + --Draw arrow + if not (vertical) then + for i=0,(5) do + cr:rectangle(extents.width/2 - 5 + i ,5-i, 1, i) + cr:rectangle(extents.width/2 + 5 - i ,5-i, 1, i) + end + else + for i=0,(12) do + cr:rectangle(i, (20/2) - i, i, i*2) + end + end + cr:rectangle(20-((vertical) and 5 or 0),vertical and 0 or 5, extents.width-40+((vertical) and 14 or 0 ), 20) + cr:fill() + local l,m = wibox.layout.fixed.horizontal(),wibox.layout.margin(textw) + m:set_left ( 30 ) + m:set_right ( 10 ) + m:set_bottom ( not vertical and ((args.direction == "top") and 4 or -4) or 0 ) + l:add(m) + l:fill_space(true) + w:set_widget(l) + w:set_fg(beautiful.fg_normal) + + if args.direction == "left" or args.direction == "top" then --Mirror + local matrix,pattern = cairo.Matrix(),cairo.Pattern.create_for_surface(img) + cairo.Matrix.init_rotate(matrix,math.pi) + matrix:translate(-extents.width,-((vertical) and 20 or 25)) + pattern:set_matrix(matrix) + local img2 = cairo.ImageSurface(cairo.Format.A1, extents.width, vertical and 20 or 25) + local cr2 = cairo.Context(img2) + cr2:set_source(pattern) + cr2:paint() + img = img2 + end + w.shape_bounding = img._native + + w:connect_signal("mouse::leave",hide_tooltip) + data.wibox = w + end + if data.wibox then + local relative_to_parent = rel_parent(data.wibox,args2,args) + data.wibox.x = args2.x or args.x or relative_to_parent.x or capi.mouse.coords().x - data.wibox.width/2 -5 + data.wibox.y = args2.y or args.y or relative_to_parent.y or ((not vertical) and capi.screen[capi.mouse.screen].geometry.height - 16 - 25 or 16) + data.wibox.visible = true + if args2.parent and args2.parent.drawable and data.drawable ~= args2.parent.drawable then + data.drawable = args2.parent.drawable + data.drawable:connect_signal("mouse::leave",hide_tooltip) + end + end + data.text = text + end + widget:connect_signal("mouse::enter" , function(widget,geometry) data:showToolTip( true , {parent=geometry}) end) + widget:connect_signal("mouse::leave" , hide_tooltip) + widget:connect_signal("button::press" , hide_tooltip) + return data +end + +return setmetatable(module, { __call = function(_, ...) return new(...) end }) +-- kate: space-indent on; indent-width 2; replace-tabs on;