text_box.lua 8.2 KB

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