text_box.lua 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. setup_layout(t_box, width, height)
  92. --Generate Background (background widget)
  93. if data[t_box].background_color then
  94. helpers.draw_rounded_corners_rectangle( cr,
  95. 0,
  96. 0,
  97. width,
  98. height,
  99. props.background_color,
  100. props.rounded_size)
  101. end
  102. --Draw nothing, or filled ( value background)
  103. if data[t_box].text_background_color then
  104. --draw rounded corner rectangle
  105. helpers.draw_rounded_corners_rectangle( cr,
  106. props.h_margin,
  107. props.v_margin,
  108. width - props.h_margin,
  109. height - props.v_margin,
  110. props.text_background_color,
  111. props.rounded_size,
  112. props.background_text_border
  113. )
  114. end
  115. local x, y = 0
  116. x = width / 2 - logical.width / 2
  117. y = height / 2 - logical.height / 2
  118. cr:move_to(x, y)
  119. cr:show_layout(layout)
  120. end
  121. function text_box:fit( width, height)
  122. setup_layout(self, width, height)
  123. local _, logical = self._layout:get_pixel_extents()
  124. if logical.width == 0 or logical.height == 0 then
  125. return 0, 0
  126. end
  127. return logical.width, logical.height
  128. end
  129. --- Add a text to the t_box.
  130. -- @usage myt_box:set_text(a_text)
  131. -- @param t_box The t_box.
  132. -- @param string a string.
  133. local function set_text(t_box, string)
  134. if not t_box then return end
  135. local text = string or ""
  136. data[t_box].text = text
  137. t_box._layout.text = text
  138. t_box:emit_signal("widget::updated")
  139. return t_box
  140. end
  141. --- Set the t_box height.
  142. -- @param height The height to set.
  143. function text_box:set_height( height)
  144. if height >= 5 then
  145. data[self].height = height
  146. self:emit_signal("widget::updated")
  147. end
  148. return self
  149. end
  150. --- Set the t_box width.
  151. -- @param width The width to set.
  152. function text_box:set_width( width)
  153. if width >= 5 then
  154. data[self].width = width
  155. self:emit_signal("widget::updated")
  156. end
  157. return self
  158. end
  159. -- Build properties function
  160. for _, prop in ipairs(properties) do
  161. if not text_box["set_" .. prop] then
  162. text_box["set_" .. prop] = function(t_box, value)
  163. data[t_box][prop] = value
  164. t_box:emit_signal("widget::updated")
  165. return t_box
  166. end
  167. end
  168. end
  169. --- Create a t_box widget.
  170. -- @param args Standard widget() arguments. You should add width and height
  171. -- key to set t_box geometry.
  172. -- @return A t_box widget.
  173. function text_box.new(args)
  174. local args = args or {}
  175. local width = args.width or 5
  176. local height = args.height or 5
  177. if width < 5 or height < 5 then return end
  178. local t_box = base.make_widget()
  179. data[t_box] = {}
  180. data[t_box].text = args.text or ""
  181. for _, v in ipairs(properties) do
  182. data[t_box][v] = args[v]
  183. end
  184. data[t_box].height = height
  185. data[t_box].width = width
  186. local ctx = pangocairo.font_map_get_default():create_context()
  187. t_box._layout = pango.Layout.new(ctx)
  188. -- Set methods
  189. t_box.set_text = set_text
  190. t_box.draw = draw
  191. t_box.fit = text_box.fit
  192. for _, prop in ipairs(properties) do
  193. t_box["set_" .. prop] = text_box["set_" .. prop]
  194. end
  195. return t_box
  196. end
  197. function text_box.mt:__call(...)
  198. return text_box.new(...)
  199. end
  200. return setmetatable(text_box, text_box.mt)