forked from cedlemo/blingbling
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtext_box.lua
More file actions
277 lines (236 loc) · 8.86 KB
/
text_box.lua
File metadata and controls
277 lines (236 loc) · 8.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
-- @author cedlemo
local setmetatable = setmetatable
local ipairs = ipairs
local math = math
local table = table
local type = type
local string = string
local color = require("gears.color")
local base = require("wibox.widget.base")
local helpers = require("blingbling.helpers")
local superproperties = require("blingbling.superproperties")
local lgi = require("lgi")
local pango = lgi.Pango
local pangocairo = lgi.PangoCairo
local util = require('awful.util')
---A text box.
--@module blingbling.text_box
local text_box = { mt = {} }
local data = setmetatable({}, { __mode = "k" })
---Fill all the widget with this color (default is transparent).
--@usage myt_box:set_background_color(string) -->"#rrggbbaa"
--@name set_background_color
--@class function
--@param t_box the value text box
--@param color a string "#rrggbbaa" or "#rrggbb"
---Fill the text area (text height/width + padding) background with this color (default is none).
--@usage myt_box:set_text_background_color(string) -->"#rrggbbaa"
--@name set_text_background_color
--@class function
--@param color a string "#rrggbbaa" or "#rrggbb"
---Set a border on the text area background (default is none ).
--@usage myt_box:set_text_background_border(string) -->"#rrggbbaa"
--@name set_text_background_border
--@class function
--@param color a string "#rrggbbaa" or "#rrggbb"
---Define the top and bottom margin for the text background .
--@usage myt_box:set_v_margin(integer)
--@name set_v_margin
--@class function
--@param t_box the value text box
--@param margin an integer for top and bottom margin
---Define the left and right margin for the text background.
--@usage myt_box:set_h_margin(integer)
--@name set_h_margin
--@class function
--@param t_box the value text box
--@param margin an integer for left and right margin
---Set rounded corners for background and text background.
--@usage myt_box:set_rounded_size(a) -> a in [0,1]
--@usage myt_box:set_rounded_size(b) -> b = { 0.2,0.3,0.4,0.7}
--@name set_rounded_size
--@class function
--@param t_box the value text box
--@param rounded_size float in [0,1] or a table of 4 float for each corners.
---Define the color of the text.
--@usage myt_box:set_text_color(string)
--@name set_text_color
--@class function
--@param t_box the value text box
--@param color a string "#rrggbb"
---Define the text font size.
--@usage myt_box:set_font_size(integer)
--@name set_font_size
--@class function
--@param t_box the value text box
--@param size the font size
local properties = { "width", "height", "h_margin", "v_margin",
"background_color",
"background_text_border", "text_background_color",
"rounded_size", "text_color", "font_size", "font"
}
-- Setup a pango layout for the given textbox and cairo context
local function setup_layout(t_box, width, height)
local layout = t_box._layout
layout.width = pango.units_from_double(width)
layout.height = pango.units_from_double(height)
end
local function draw( t_box, wibox, cr, width, height)
local background_color = data[t_box].background_color or superproperties.background_color
local rounded_size = data[t_box].rounded_size or superproperties.rounded_size
local text_color = data[t_box].text_color or superproperties.text_color
local text_background_color = data[t_box].text_background_color or superproperties.text_background_color
local font_size =data[t_box].font_size or superproperties.font_size
local font = data[t_box].font or superproperties.font
local text = data[t_box].text
if type(font) ~= "string" and type(font) == "table" then
font = (font.family or "Sans") ..(font.slang or "normal") ..( font.weight or "normal")
end
layout = t_box._layout
cr:update_layout(layout)
local font_desc = pango.FontDescription.from_string(font .. " " .. font_size)
layout:set_font_description(font_desc)
layout.text = text
layout:set_markup("<span color='"..text_color.."'>"..text.."</span>" )
local ink, logical = layout:get_pixel_extents()
local width = data[t_box].width > logical.width and data[t_box].width or logical.width
local height = data[t_box].height > logical.height and data[t_box].height or logical.height
local v_margin = superproperties.v_margin
if data[t_box].v_margin and data[t_box].v_margin <= height/3 then
v_margin = data[t_box].v_margin
end
local h_margin = superproperties.h_margin
if data[t_box].h_margin and data[t_box].h_margin <= width / 3 then
h_margin = data[t_box].h_margin
end
setup_layout(t_box, width, height)
--Generate Background (background widget)
if data[t_box].background_color then
helpers.draw_rounded_corners_rectangle( cr,
0,
0,
width,
height,
background_color,
rounded_size)
end
--Draw nothing, or filled ( value background)
if data[t_box].text_background_color then
--draw rounded corner rectangle
local x=h_margin
local y=v_margin
helpers.draw_rounded_corners_rectangle( cr,
x,
y,
width - h_margin,
height - v_margin,
text_background_color,
rounded_size,
background_text_border
)
end
local x_offset, y_offset = 0
if logical.width < data[t_box].width then
x_offset = (data[t_box].width - logical.width)/2
end
if logical.height < data[t_box].height then
y_offset = (data[t_box].height - logical.height)/2
end
cr:move_to(x_offset,y_offset)
cr:show_layout(layout)
end
function text_box:fit( width, height)
setup_layout(self, width, height)
local font =data[self].font or superproperties.font
local font_size =data[self].font_size or superproperties.font_size
local font_desc = pango.FontDescription.from_string(font .. " " .. font_size)
local text_color = data[self].text_color
local text = data[self].text or ""
self._layout:set_font_description(font_desc)
if text_color then
self._layout:set_markup("<span color='"..text_color.."'>"..text.."</span>" )
else
self._layout:set_markup(text)
end
local ink, logical = self._layout:get_pixel_extents()
local width, height
width = logical.width > data[self].width and logical.width or data[self].width
height = logical.height > data[self].height and logical.height or data[self].height
if logical.width == 0 or logical.height == 0 then
width = 0
height = 0
end
return width, height
end
--- Add a text to the t_box.
-- @usage myt_box:set_text(a_text)
-- @param t_box The t_box.
-- @param string a string.
local function set_text(t_box, string)
if not t_box then return end
local text = string or ""
data[t_box].text = text
t_box._layout.text = text
t_box:emit_signal("widget::updated")
return t_box
end
--- Set the t_box height.
-- @param height The height to set.
function text_box:set_height( height)
if height >= 5 then
data[self].height = height
self:emit_signal("widget::updated")
end
return self
end
--- Set the t_box width.
-- @param width The width to set.
function text_box:set_width( width)
if width >= 5 then
data[self].width = width
self:emit_signal("widget::updated")
end
return self
end
-- Build properties function
for _, prop in ipairs(properties) do
if not text_box["set_" .. prop] then
text_box["set_" .. prop] = function(t_box, value)
data[t_box][prop] = value
t_box:emit_signal("widget::updated")
return t_box
end
end
end
--- Create a t_box widget.
-- @param args Standard widget() arguments. You should add width and height
-- key to set t_box geometry.
-- @return A t_box widget.
function text_box.new(args)
local args = args or {}
local width = args.width or 5
local height = args.height or 5
if width < 5 or height < 5 then return end
local t_box = base.make_widget()
data[t_box] = {}
data[t_box].text = args.text or ""
for _, v in ipairs(properties) do
data[t_box][v] = args[v]
end
data[t_box].height = height
data[t_box].width = width
local ctx = pangocairo.font_map_get_default():create_context()
t_box._layout = pango.Layout.new(ctx)
-- Set methods
t_box.set_text = set_text
t_box.draw = draw
t_box.fit = text_box.fit
for _, prop in ipairs(properties) do
t_box["set_" .. prop] = text_box["set_" .. prop]
end
return t_box
end
function text_box.mt:__call(...)
return text_box.new(...)
end
return setmetatable(text_box, text_box.mt)