widgets: Add text widget

Automatic text scaling to fill an area
This commit is contained in:
Emmanuel Lepage Vallee 2016-06-27 02:11:41 -04:00
parent 825ff024ef
commit eaa389bd5f
2 changed files with 136 additions and 9 deletions

126
widgets/constrainedtext.lua Normal file
View File

@ -0,0 +1,126 @@
local color = require( "gears.color" )
local pango = require( "lgi" ).Pango
local pangocairo = require( "lgi" ).PangoCairo
local wibox = require( "wibox" )
local beautiful = require( "beautiful" )
local scale = pango.SCALE
local function setup_dpi(box, dpi)
if box._private.dpi ~= dpi then
box._private.dpi = dpi
box._private.ctx:set_resolution(dpi)
box._private.layout:context_changed()
end
end
--- Setup a pango layout for the given textbox and dpi
local function setup_layout(box, width, height, dpi)
-- box._private.layout.width = pango.units_from_double(width) --FIXME...
box._private.layout.height = pango.units_from_double(height)
setup_dpi(box, dpi)
end
local function fit(self, context,width,height)
setup_layout(self, width, height, context.dpi)
-- Compute the optimal font size
local padding = self._private.padding or 0
local tm = self._private.top_margin or 0
height = math.max(0, height - tm)
local min = math.min(width, height)
local font_size = math.max(0, min - 2*padding)
if self._private.force_text then
self._private.layout.text = self._private.force_text
end
self._private.desc:set_size( font_size * scale )
self._private.layout:set_font_description(self._private.desc)
local _, geo = self._private.layout:get_pixel_extents()
if self._private.force_text then
self._private.layout.text = self._private.text
end
return math.min(geo.width, width), math.min(geo.height + tm, height)
end
local function draw(self, context, cr, width, height)
-- Some layouts never call fit()...
fit(self, context, width, height)
cr:update_layout(self._private.layout)
local _, geo = self._private.layout:get_pixel_extents()
local tm = self._private.top_margin or 0
local size = math.min(width, height - tm)
-- Translate the canvas to center the text
local dy = ( size - geo.height )/2 - geo.y + tm
local dx = ( size - geo.width )/2 - geo.x
cr:move_to(0, dy)
-- Show the text
cr:show_layout(self._private.layout)
end
local function set_text(self, text)
if tostring(text):len() == 1 then text = text.."_" end--FIXME...
self._private.layout.text = text
self._private.text = text
self:emit_signal("widget::redraw_needed")
self:emit_signal("widget::layout_changed")
end
local function set_padding(self, padding)
self._private.padding = padding
self:emit_signal("widget::redraw_needed")
self:emit_signal("widget::layout_changed")
end
local function set_top_margin(self, margin)
self._private.top_margin = margin or 0
self:emit_signal("widget::redraw_needed")
self:emit_signal("widget::layout_changed")
end
local function set_width_for_text(self, text)
self._private.force_text = text
self:emit_signal("widget::redraw_needed")
self:emit_signal("widget::layout_changed")
end
local function new(text, padding, top_margin)
local wdg = wibox.widget.base.empty_widget()
-- Add the basic functions
rawset(wdg, "draw" , draw )
rawset(wdg, "fit" , fit )
rawset(wdg, "set_padding" , set_padding )
rawset(wdg, "set_top_margin" , set_top_margin )
rawset(wdg, "set_text" , set_text )
rawset(wdg, "set_width_for_text", set_width_for_text )
-- Create the pango objects
local pango_crx = pangocairo.font_map_get_default():create_context()
local pango_l = pango.Layout.new(pango_crx)
local desc = pango.FontDescription()
pango_l:set_alignment("CENTER")
desc:set_family( "Verdana" )
desc:set_weight( pango.Weight.BOLD )
wdg._private.layout = pango_l
wdg._private.desc = desc
wdg._private.ctx = pango_crx
wdg:emit_signal("widget::layout_changed")
if text then set_text (wdg, text ) end
if padding then set_padding (wdg, padding ) end
if top_margin then set_top_margin(wdg, top_margin) end
return wdg
end
return setmetatable({}, { __call = function(_, ...) return new(...) end })

View File

@ -8,4 +8,5 @@ return {
piechart = require( "radical.widgets.piechart" ),
separator = require( "radical.widgets.separator" ),
infoshapes = require( "radical.widgets.infoshapes" ),
constrainedtext = require( "radical.widgets.constrainedtext" ),
}