awful: add tooltip module
[awesome.git] / lib / awful / tooltip.lua.in
bloba1b03e20e818af39f3b5da7faa9b5a6d20cbbf80
1 -------------------------------------------------------------------------
2 -- @author Sébastien Gross <seb•ɱɩɲʋʃ•awesome•ɑƬ•chezwam•ɖɵʈ•org&gt
3 -- @copyright 2009 Sébastien Gross
4 -- @release @AWESOME_VERSION@
5 -------------------------------------------------------------------------
7 local mouse = mouse
8 local widget = widget
9 local wibox = wibox
10 local screen = screen
11 local timer = timer
12 local a_placement = require("awful.placement")
13 local beautiful = require("beautiful")
14 local setmetatable = setmetatable
15 local ipairs = ipairs
17 --- Tooltip module for awesome objects.
18 -- A tooltip is a small hint displayed when the mouse cursor
19 -- hovers a specific item.
20 -- In awesome, a tooltip can be linked with almost any
21 -- object having a <code>add_signal()</code> method and receiving
22 -- <code>mouse::enter</code> and <code>mouse::leave</code> signals.
23 -- <p>How to create a tooltip?<br/>
24 -- <code>
25 -- myclock = awful.widget.textclock({}, "%T", 1)<br/>
26 -- myclock_t = awful.tooltip({<br/>
27 -- objects = { K },<br/>
28 -- timer_function = function()<br/>
29 -- return os.date("Today is %A %B %d %Y\nThe time is %T")<br/>
30 -- end,<br/>
31 -- })<br/>
32 -- </code>
33 -- </p>
34 -- <p>How to add the same tooltip to several objects?<br/>
35 -- <code>
36 -- myclock_t:add_to_object(obj1)<br/>
37 -- myclock_t:add_to_object(obj2)<br/>
38 -- </code>
39 -- Now the same tooltip is attached to <code>K</code>, <code>obj1</code>,
40 -- <code>obj2</code>.<br/>
41 -- </p>
42 -- <p>How to remove tooltip from many objects?<br/>
43 -- <code>
44 -- myclock_t:remove_from_object(obj1)<br/>
45 -- myclock_t:remove_from_object(obj2)<br/>
46 -- </code>
47 -- Now the same tooltip is only attached to <code>K</code>.<br/>
48 -- </p>
49 module("awful.tooltip")
51 local data = setmetatable({}, { __mode = 'k' })
53 --- Tooltip object definition.
54 -- @name tooltip
55 -- @field wibox The wibox displaying the tooltip.
56 -- @field visible True if tooltip is visible.
57 -- @class table
59 -- Tooltip private data.
60 -- @name awful.tooltip.data
61 -- @field fg tooltip foreground color.
62 -- @field font Tooltip font.
63 -- @field hide The hide() function.
64 -- @field show The show() function.
65 -- @field timer The text update timer.
66 -- @field timer_function The text update timer function.
68 -- Place to tooltip on th screen.
69 -- @param self A tooltip object.
70 local function place(self)
71 a_placement.under_mouse(self.wibox)
72 a_placement.no_offscreen(self.wibox)
73 end
75 -- Place the tooltip under the mouse.
76 -- @param self A tooltip object.
77 local function set_geometry(self)
78 local my_geo = self.wibox:geometry()
79 -- calculate width / height
80 n_s = self.wibox.widgets[1]:extents()
81 if my_geo.width ~= n_s.width or my_geo.height ~= n_s.height then
82 self.wibox:geometry(n_s)
83 place(self)
84 end
85 end
87 -- Show a tooltip.
88 -- @param self The tooltip to show.
89 local function show(self)
90 -- do nothing if the tooltip is already shown
91 if self.visible then return end
92 if data[self].timer then
93 if not data[self].timer.started then
94 -- make sure the tooltip is on the same screen as the mouse
95 self.wibox.screen = mouse.screen
96 data[self].timer_function()
97 data[self].timer:start()
98 end
99 end
100 place(self)
101 self.wibox.visible = true
102 self.visible = true
105 -- Hide a tooltip.
106 -- @param self The tooltip to hide.
107 local function hide(self)
108 -- do nothing if the tooltip is already hidden
109 if not self.visible then return end
110 if data[self].timer then
111 if data[self].timer.started then
112 data[self].timer:stop()
115 self.visible = false
116 self.wibox.visible = false
119 --- Change displayed text.
120 -- @param self The tooltip object.
121 -- @param text New tooltip text.
122 local function set_text(self, text)
123 self.wibox.widgets[1].text = '<span color="' .. data[self].fg
124 .. '" font_desc="' .. data[self].font .. '">' .. text .. "</span>"
127 --- Change the tooltip's update interval.
128 -- @param self A tooltip object.
129 -- @param timeout The timeout value.
130 local function set_timeout(self, timeout)
131 if data[self].timer then
132 data[self].timer.timeout = timeout
136 -- Load Default values.
137 -- @param self A tooltip object.
138 local function set_defaults(self)
139 self.wibox.border_width = beautiful.tooltip_border_width or beautiful.border_width or 1
140 self.wibox.border_color = beautiful.tooltip_border_color or beautiful.border_normal or "#ffcb60"
141 self.wibox.opacity = beautiful.tooltip_opacity or 1
142 self.wibox.bg = beautiful.tooltip_bg_color or beautiful.bg_focus or "#ffcb60"
143 data[self].fg = beautiful.tooltip_fg_color or beautiful.fg_focus or "#000000"
144 data[self].font = beautiful.tooltip_font or beautiful.font or "terminus 6"
147 --- Add tooltip to an object.
148 -- @param self The tooltip.
149 -- @param object An object.
150 local function add_to_object(self, object)
151 object:add_signal("mouse::enter", data[self].show)
152 object:add_signal("mouse::leave", data[self].hide)
155 --- Remove tooltip from an object.
156 -- @param self The tooltip.
157 -- @param object An object.
158 local function remove_from_object(self, object)
159 object:remove_signal("mouse::enter", data[self].show)
160 object:remove_signal("mouse::leave", data[self].hide)
164 --- Create a new tooltip and link it to a widget.
165 -- @param args Arguments for tooltip creation may containt:<br/>
166 -- <code>timeout</code>: The timeout value for update_func.<br/>
167 -- <code>timer_function</code>: A function to dynamicaly change the tooltip
168 -- text.<br/>
169 -- <code>objects</code>: A list of objects linked to the tooltip.<br/>
170 -- @return The created tooltip.
171 -- @see add_to_object
172 -- @see set_timeout
173 -- @see set_text
174 local function new(args)
175 local self = {
176 wibox = wibox({ }),
177 visible = false,
180 local my_textbox = widget({
181 type = "textbox",
182 name = "tooltip_textbox",
183 align="right"})
185 -- private data
186 data[self] = {
187 show = function() show(self) end,
188 hide = function() hide(self) end
191 -- export functions
192 self.set_text = set_text
193 self.set_timeout = set_timeout
194 self.add_to_object = add_to_object
195 self.remove_from_object = remove_from_object
197 set_defaults(self)
199 -- setup the timer action only if needed
200 if args.timer_function then
201 data[self].timer = timer { timeout = args.timeout and args.timeout or 1 }
202 data[self].timer_function = function()
203 self:set_text(args.timer_function())
204 set_geometry(self)
206 data[self].timer:add_signal("timeout", data[self].timer_function)
209 -- set tooltip properties
210 self.wibox.visible = false
211 -- Who want a non ontop tooltip ?
212 self.wibox.ontop = true
213 self.wibox.widgets = { my_textbox }
215 -- add some signals on both the tooltip and widget
216 self.wibox:add_signal("mouse::enter", data[self].hide)
218 -- Add tooltip to objects
219 if args.objects then
220 for _, object in ipairs(args.objects) do
221 self:add_to_object(object)
225 return self
228 setmetatable(_M, { __call = function(_, ...) return new(...) end })
230 -- vim: ft=lua:et:sw=4:ts=4:sts=4:enc=utf-8:tw=78