imagebox: Support a CSS file.
Before, the CSS had to be inline. Now that the border container uses this code, it makes sense to make it more flexible.
This commit is contained in:
parent
5c9ffb8ef3
commit
ab121e9ac0
|
@ -31,12 +31,17 @@ local base = require("wibox.widget.base")
|
|||
local surface = require("gears.surface")
|
||||
local gtable = require("gears.table")
|
||||
local gdebug = require("gears.debug")
|
||||
local gfs = require("gears.filesystem")
|
||||
local setmetatable = setmetatable
|
||||
local type = type
|
||||
local math = math
|
||||
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
-- Placeholder table to represent an emty stylesheet.
|
||||
-- It has to be defined here to avoid being GCed
|
||||
local empty_stylesheet = {}
|
||||
|
||||
local policies_to_extents = {
|
||||
["pad"] = cairo.Extend.PAD,
|
||||
["repeat"] = cairo.Extend.REPEAT,
|
||||
|
@ -55,18 +60,25 @@ end
|
|||
local imagebox = { mt = {} }
|
||||
|
||||
local rsvg_handle_cache = setmetatable({}, { __mode = 'k' })
|
||||
local stylesheet_cache = {}
|
||||
|
||||
--Load rsvg handle form image file
|
||||
-- @tparam string file Path to svg file.
|
||||
-- @return Rsvg handle
|
||||
-- @treturn table A table where cached data can be stored.
|
||||
function imagebox._load_rsvg_handle(file)
|
||||
function imagebox._load_rsvg_handle(file, style)
|
||||
-- Make sure this is called in the right order.
|
||||
assert((not style) or (style and stylesheet_cache[style]))
|
||||
|
||||
local style_ref = style and stylesheet_cache[style] or empty_stylesheet
|
||||
|
||||
if not Rsvg then return end
|
||||
|
||||
local cache = (rsvg_handle_cache[file] or {})["handle"]
|
||||
local bucket = rsvg_handle_cache[file] or {}
|
||||
local cache = (bucket[style_ref] or {})["handle"]
|
||||
|
||||
if cache then
|
||||
return cache, rsvg_handle_cache[file]
|
||||
return cache, bucket[style_ref]
|
||||
end
|
||||
|
||||
local handle, err
|
||||
|
@ -78,9 +90,10 @@ function imagebox._load_rsvg_handle(file)
|
|||
end
|
||||
|
||||
if not err then
|
||||
rsvg_handle_cache[file] = rsvg_handle_cache[file] or {}
|
||||
rsvg_handle_cache[file]["handle"] = handle
|
||||
return handle, rsvg_handle_cache[file]
|
||||
rsvg_handle_cache[file] = rsvg_handle_cache[file] or setmetatable({}, {__mode = "k"})
|
||||
rsvg_handle_cache[file][style_ref] = rsvg_handle_cache[file][style_ref] or {}
|
||||
rsvg_handle_cache[file][style_ref]["handle"] = handle
|
||||
return handle, rsvg_handle_cache[file][style_ref]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -117,7 +130,7 @@ end
|
|||
---@treturn boolean True if image was successfully applied
|
||||
local function load_and_apply(ib, file, image_loader, image_setter)
|
||||
local image_applied
|
||||
local object, cache = image_loader(file)
|
||||
local object, cache = image_loader(file, ib._private.stylesheet_og)
|
||||
|
||||
if object then
|
||||
image_applied = image_setter(ib, object, cache)
|
||||
|
@ -125,6 +138,38 @@ local function load_and_apply(ib, file, image_loader, image_setter)
|
|||
return image_applied
|
||||
end
|
||||
|
||||
--- Support both CSS data and filepath for the stylsheet.
|
||||
function imagebox._get_stylesheet(self, content_or_path)
|
||||
if not content_or_path then return nil end
|
||||
|
||||
-- Always set the entry because the image cache uses it.
|
||||
stylesheet_cache[content_or_path] = stylesheet_cache[content_or_path]
|
||||
or setmetatable({}, {__mode = "v"})
|
||||
|
||||
if gfs.file_readable(content_or_path) then
|
||||
local ret
|
||||
|
||||
local _, obj = next(stylesheet_cache[content_or_path])
|
||||
|
||||
if obj then
|
||||
ret = obj._private.stylesheet
|
||||
table.insert(stylesheet_cache[content_or_path], self)
|
||||
else
|
||||
local f = io.open(content_or_path, 'r')
|
||||
|
||||
if not f then return nil end
|
||||
|
||||
ret = f:read("*all")
|
||||
f:close()
|
||||
table.insert(stylesheet_cache[content_or_path], self)
|
||||
end
|
||||
|
||||
return ret
|
||||
else
|
||||
return content_or_path
|
||||
end
|
||||
end
|
||||
|
||||
---Update the cached size depending on the stylesheet and dpi.
|
||||
--
|
||||
-- It's necessary because a single RSVG handle can be used by
|
||||
|
@ -443,8 +488,7 @@ end
|
|||
-- If the image is an SVG (vector graphics), this property allows to set
|
||||
-- a CSS stylesheet. It can be used to set colors and much more.
|
||||
--
|
||||
-- Note that this property is a string, not a path. If the stylesheet is
|
||||
-- stored on disk, read the content first.
|
||||
-- The value can be either CSS data or a file path.
|
||||
--
|
||||
--@DOC_wibox_widget_imagebox_stylesheet_EXAMPLE@
|
||||
--
|
||||
|
@ -483,18 +527,47 @@ end
|
|||
-- @propemits true false
|
||||
-- @see dpi
|
||||
|
||||
for _, prop in ipairs {"stylesheet", "dpi", "auto_dpi"} do
|
||||
for _, prop in ipairs {"dpi", "auto_dpi"} do
|
||||
imagebox["set_" .. prop] = function(self, value)
|
||||
local old = self._private[prop]
|
||||
|
||||
-- It will be set in :fit and :draw. The handle is shared
|
||||
-- by multiple imagebox, so it cannot be set just once.
|
||||
self._private[prop] = value
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("property::" .. prop)
|
||||
self:emit_signal("property::" .. prop, value, old)
|
||||
end
|
||||
end
|
||||
|
||||
function imagebox:set_stylesheet(value)
|
||||
if value == self._private.stylesheet_og then return end
|
||||
|
||||
local old = self._private.stylesheet_og
|
||||
|
||||
if old and stylesheet_cache[old] then
|
||||
for k, v in ipairs(stylesheet_cache[old]) do
|
||||
if self == v then
|
||||
table.remove(stylesheet_cache[old], k)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local content = imagebox._get_stylesheet(self, value)
|
||||
|
||||
self._private.stylesheet = content
|
||||
self._private.stylesheet_og = value
|
||||
|
||||
-- Refresh the pixmap.
|
||||
self.image = self._private.original_image
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("property::stylesheet", value)
|
||||
end
|
||||
|
||||
function imagebox:set_resize(allowed)
|
||||
self._private.resize = allowed
|
||||
|
||||
|
|
Loading…
Reference in New Issue