2014-02-02 22:53:09 +01:00
|
|
|
local setmetatable = setmetatable
|
|
|
|
local beautiful = require( "beautiful" )
|
|
|
|
local color = require( "gears.color" )
|
|
|
|
local cairo = require( "lgi" ).cairo
|
|
|
|
local wibox = require( "wibox" )
|
2014-02-05 05:29:38 +01:00
|
|
|
local checkbox = require( "radical.widgets.checkbox" )
|
|
|
|
local fkey = require( "radical.widgets.fkey" )
|
2014-03-13 06:14:52 +01:00
|
|
|
local underlay = require( "radical.widgets.underlay" )
|
|
|
|
local theme = require( "radical.theme" )
|
2014-10-18 05:52:26 +02:00
|
|
|
local util = require( "awful.util" )
|
2016-02-11 07:36:50 +01:00
|
|
|
local margins2 = require( "radical.margins")
|
|
|
|
local shape = require( "gears.shape" )
|
|
|
|
local surface = require( "gears.surface" )
|
2014-02-02 22:53:09 +01:00
|
|
|
|
|
|
|
local module = {}
|
|
|
|
|
|
|
|
|
|
|
|
-- Add [F1], [F2] ... to items
|
|
|
|
function module:setup_fkey(item,data)
|
2014-03-05 06:12:48 +01:00
|
|
|
item.set_f_key = function(_,value)
|
2014-02-02 22:53:09 +01:00
|
|
|
item._internal.has_changed = true
|
|
|
|
item._internal.f_key = value
|
|
|
|
data:remove_key_hook("F"..value)
|
|
|
|
data:add_key_hook({}, "F"..value , "press", function()
|
2014-04-09 05:38:31 +02:00
|
|
|
item.button1(data,menu)
|
2014-02-02 22:53:09 +01:00
|
|
|
data.visible = false
|
|
|
|
end)
|
|
|
|
end
|
2014-03-05 06:12:48 +01:00
|
|
|
item.get_f_key = function() return item._internal.f_key end
|
2014-02-02 22:53:09 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Like an overlay, but under
|
2016-01-12 09:33:38 +01:00
|
|
|
function module.paint_underlay(data,item,cr,width,height, name)
|
|
|
|
name = name or "underlay"
|
2014-02-02 22:53:09 +01:00
|
|
|
cr:save()
|
2014-03-13 06:14:52 +01:00
|
|
|
local state = item.state or {}
|
|
|
|
local current_state = state._current_key or nil
|
|
|
|
local state_name = theme.colors_by_id[current_state] or ""
|
2016-01-12 09:33:38 +01:00
|
|
|
|
|
|
|
local bg_color = item[name.."_bg_"..state_name] or data[name.."_bg_"..state_name] or data[name.."_bg"]
|
|
|
|
local style = item[name.."_style" ] or data[name.."_style" ]
|
|
|
|
local alpha = item[name.."_alpha" ] or data[name.."_alpha" ]
|
|
|
|
local align = item[name.."_align" ] or data[name.."_align" ]
|
|
|
|
|
|
|
|
local udl = underlay.draw(item[name],{style=data.underlay_style,height=height,bg=bg_color, style = style})
|
|
|
|
|
|
|
|
if align == "center" then
|
|
|
|
local offset = (width-udl:get_width()-6)/2
|
|
|
|
cr:set_source_surface(udl,3 + offset)
|
|
|
|
else
|
|
|
|
cr:set_source_surface(udl,width-udl:get_width()-3)
|
|
|
|
end
|
|
|
|
cr:paint_with_alpha(data[name.."_alpha"])
|
2014-02-02 22:53:09 +01:00
|
|
|
cr:restore()
|
|
|
|
end
|
|
|
|
|
2016-01-12 09:33:38 +01:00
|
|
|
function module.after_draw_children(self, context, cr, width, height)
|
|
|
|
if self._item.overlay then
|
|
|
|
module.paint_underlay(self._data, self._item, cr, width, height, "overlay")
|
|
|
|
end
|
|
|
|
|
|
|
|
if self._item.overlay_draw then
|
|
|
|
self._item.overlay_draw(context,self._item,cr,width,height)
|
|
|
|
end
|
2016-02-11 07:36:50 +01:00
|
|
|
|
|
|
|
-- Draw the border, if any
|
|
|
|
if self._after_draw_children then
|
|
|
|
self._after_draw_children(self, context, cr, width, height)
|
|
|
|
end
|
2016-01-12 09:33:38 +01:00
|
|
|
end
|
|
|
|
|
2014-02-20 04:09:19 +01:00
|
|
|
-- Apply icon transformation
|
|
|
|
function module.set_icon(self,image)
|
|
|
|
if self._data.icon_transformation then
|
2014-03-17 04:46:23 +01:00
|
|
|
self._item._original_icon = image
|
2014-02-20 04:09:19 +01:00
|
|
|
image = self._data.icon_transformation(image,self._data,self._item)
|
|
|
|
end
|
|
|
|
wibox.widget.imagebox.set_image(self,image)
|
|
|
|
end
|
|
|
|
|
2014-02-02 22:53:09 +01:00
|
|
|
-- Setup the item icon
|
|
|
|
function module:setup_icon(item,data)
|
|
|
|
local icon = wibox.widget.imagebox()
|
2014-02-20 04:09:19 +01:00
|
|
|
icon._data = data
|
|
|
|
icon._item = item
|
|
|
|
icon.set_image = module.set_icon
|
2014-02-02 22:53:09 +01:00
|
|
|
if item.icon then
|
|
|
|
icon:set_image(item.icon)
|
|
|
|
end
|
|
|
|
|
2014-03-05 06:12:48 +01:00
|
|
|
item.set_icon = function (_,value)
|
2014-02-02 22:53:09 +01:00
|
|
|
icon:set_image(value)
|
|
|
|
end
|
|
|
|
return icon
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Show the checkbox
|
|
|
|
function module:setup_checked(item,data)
|
|
|
|
if item.checkable then
|
2014-03-05 06:12:48 +01:00
|
|
|
item.get_checked = function()
|
2014-02-02 22:53:09 +01:00
|
|
|
if type(item._private_data.checked) == "function" then
|
2014-11-15 05:46:06 +01:00
|
|
|
return item._private_data.checked(data,item)
|
2014-02-02 22:53:09 +01:00
|
|
|
else
|
|
|
|
return item._private_data.checked
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local ck = wibox.widget.imagebox()
|
|
|
|
ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked())
|
2014-03-05 06:12:48 +01:00
|
|
|
item.set_checked = function (_,value)
|
2014-02-02 22:53:09 +01:00
|
|
|
item._private_data.checked = value
|
|
|
|
ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked())
|
|
|
|
item._internal.has_changed = true
|
|
|
|
end
|
|
|
|
return ck
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-09 06:54:59 +01:00
|
|
|
-- Setup hover
|
|
|
|
function module:setup_hover(item,data)
|
2014-03-05 06:12:48 +01:00
|
|
|
item.set_hover = function(_,value)
|
2014-02-09 06:54:59 +01:00
|
|
|
local item_style = item.item_style or data.item_style
|
2014-03-13 06:14:52 +01:00
|
|
|
item.state[-1] = value and true or nil
|
2014-03-02 22:28:30 +01:00
|
|
|
item_style(item,{})
|
2014-02-09 06:54:59 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-05 05:29:38 +01:00
|
|
|
-- Create sub_menu arrows
|
|
|
|
local sub_arrow = nil
|
|
|
|
function module:setup_sub_menu_arrow(item,data)
|
2014-08-08 08:02:37 +02:00
|
|
|
if (item._private_data.sub_menu_f or item._private_data.sub_menu_m) and not data.disable_submenu_icon then
|
2014-02-05 05:29:38 +01:00
|
|
|
if not sub_arrow then
|
|
|
|
sub_arrow = wibox.widget.imagebox() --TODO, make global
|
2015-12-29 11:19:23 +01:00
|
|
|
sub_arrow.fit = function(box, context,w, h) return (sub_arrow._image and sub_arrow._image:get_width() or 0),item.height end
|
2016-02-11 07:36:50 +01:00
|
|
|
|
|
|
|
if beautiful.menu_submenu_icon then
|
|
|
|
sub_arrow:set_image( beautiful.menu_submenu_icon )
|
|
|
|
else
|
|
|
|
local h = data.item_height
|
|
|
|
sub_arrow:set_image(surface.load_from_shape(7, h,
|
|
|
|
shape.transform(shape.isosceles_triangle) : rotate_at(3.5,h/2,math.pi/2),
|
|
|
|
beautiful.menu_fg_normal or beautiful.menu_fg or beautiful.fg_normal
|
|
|
|
))
|
|
|
|
end
|
2014-02-05 05:29:38 +01:00
|
|
|
end
|
|
|
|
return sub_arrow
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-02-16 20:46:10 +01:00
|
|
|
-- Proxy all events to the parent
|
|
|
|
function module.setup_event(data,item,widget)
|
|
|
|
local widget = widget or item.widget
|
2014-02-17 05:55:44 +01:00
|
|
|
|
|
|
|
-- Setup data signals
|
2014-10-05 23:54:55 +02:00
|
|
|
widget:connect_signal("button::press",function(_,__,___,id,mod,geo)
|
2014-02-16 20:46:10 +01:00
|
|
|
local mods_invert = {}
|
|
|
|
for k,v in ipairs(mod) do
|
|
|
|
mods_invert[v] = i
|
|
|
|
end
|
2014-04-09 05:38:31 +02:00
|
|
|
|
|
|
|
item.state[4] = true
|
2014-10-05 23:54:55 +02:00
|
|
|
data:emit_signal("button::press",item,id,mods_invert,geo)
|
|
|
|
item:emit_signal("button::press",data,id,mods_invert,geo)
|
2014-02-16 20:46:10 +01:00
|
|
|
end)
|
2014-07-28 05:49:14 +02:00
|
|
|
widget:connect_signal("button::release",function(wdg,__,___,id,mod,geo)
|
2014-02-16 20:46:10 +01:00
|
|
|
local mods_invert = {}
|
|
|
|
for k,v in ipairs(mod) do
|
|
|
|
mods_invert[v] = i
|
|
|
|
end
|
2014-04-09 05:38:31 +02:00
|
|
|
item.state[4] = nil
|
2014-07-28 05:49:14 +02:00
|
|
|
data:emit_signal("button::release",item,id,mods_invert,geo)
|
|
|
|
item:emit_signal("button::release",data,id,mods_invert,geo)
|
2014-02-16 20:46:10 +01:00
|
|
|
end)
|
2014-10-05 23:54:55 +02:00
|
|
|
widget:connect_signal("mouse::enter",function(b,mod,geo)
|
|
|
|
data:emit_signal("mouse::enter",item,mod,geo)
|
|
|
|
item:emit_signal("mouse::enter",data,mod,geo)
|
2014-02-16 20:46:10 +01:00
|
|
|
end)
|
2014-10-05 23:54:55 +02:00
|
|
|
widget:connect_signal("mouse::leave",function(b,mod,geo)
|
|
|
|
data:emit_signal("mouse::leave",item,mod,geo)
|
|
|
|
item:emit_signal("mouse::leave",data,mod,geo)
|
2014-02-16 20:46:10 +01:00
|
|
|
end)
|
2014-04-09 05:38:31 +02:00
|
|
|
|
|
|
|
-- Always tracking mouse::move is expensive, only do it when necessary
|
|
|
|
-- local function conn(b,t)
|
|
|
|
-- item:emit_signal("mouse::move",item)
|
|
|
|
-- end
|
|
|
|
-- item:connect_signal("connection",function(_,name,count)
|
|
|
|
-- if name == "mouse::move" then
|
|
|
|
-- widget:connect_signal("mouse::move",conn)
|
|
|
|
-- end
|
|
|
|
-- end)
|
|
|
|
-- item:connect_signal("disconnection",function(_,name,count)
|
|
|
|
-- if count == 0 then
|
|
|
|
-- widget:connect_signal("mouse::move",conn)
|
|
|
|
-- end
|
|
|
|
-- end)
|
2014-02-16 20:46:10 +01:00
|
|
|
end
|
|
|
|
|
2014-02-02 22:53:09 +01:00
|
|
|
-- Use all the space, let "align_fit" compute the right size
|
2015-12-29 11:19:23 +01:00
|
|
|
local function textbox_fit(box,context,w,h)
|
2014-02-02 22:53:09 +01:00
|
|
|
return w,h
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Force the width or compute the minimum space
|
2015-12-29 11:19:23 +01:00
|
|
|
local function align_fit(box,context,w,h)
|
2014-10-18 05:52:26 +02:00
|
|
|
local mar = util.table.join(box._data.item_style.margins,box._data.default_item_margins)
|
2014-02-02 22:53:09 +01:00
|
|
|
if box._item.width then return box._item.width - box._data.item_style.margins.LEFT - box._data.item_style.margins.RIGHT,h end
|
2015-12-29 11:19:23 +01:00
|
|
|
return box.first:fit(context,w,h)+wibox.widget.textbox.fit(box.second,context,w,h)+box.third:fit(context,w,h),h
|
2014-02-02 22:53:09 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Create the actual widget
|
|
|
|
local function create_item(item,data,args)
|
|
|
|
|
|
|
|
-- F keys
|
|
|
|
module:setup_fkey(item,data)
|
|
|
|
|
|
|
|
-- Icon
|
2014-02-05 05:29:38 +01:00
|
|
|
local icon = module:setup_icon(item,data)
|
2014-08-08 08:02:37 +02:00
|
|
|
icon.fit = function(...)
|
|
|
|
local w,h = wibox.widget.imagebox.fit(...)
|
|
|
|
return w+3,h
|
|
|
|
end
|
2016-02-11 10:21:10 +01:00
|
|
|
|
2014-12-25 07:10:55 +01:00
|
|
|
if data.icon_per_state == true then
|
|
|
|
item:connect_signal("state::changed",function(i,d,st)
|
|
|
|
if item._original_icon and data.icon_transformation then
|
|
|
|
wibox.widget.imagebox.set_image(icon,data.icon_transformation(item._original_icon,data,item))
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
2014-02-02 22:53:09 +01:00
|
|
|
|
|
|
|
-- Text
|
|
|
|
local tb = wibox.widget.textbox()
|
2014-02-07 05:47:24 +01:00
|
|
|
tb.fit = data._internal.text_fit or textbox_fit
|
2015-12-29 11:19:23 +01:00
|
|
|
tb.draw = function(self, context, cr, width, height)
|
2014-02-02 22:53:09 +01:00
|
|
|
if item.underlay then
|
|
|
|
module.paint_underlay(data,item,cr,width,height)
|
|
|
|
end
|
2015-12-29 11:19:23 +01:00
|
|
|
wibox.widget.textbox.draw(self, context, cr, width, height)
|
2014-02-02 22:53:09 +01:00
|
|
|
end
|
|
|
|
tb:set_text(item.text)
|
2014-03-05 06:12:48 +01:00
|
|
|
item.set_text = function (_,value)
|
2014-02-09 09:04:02 +01:00
|
|
|
if data.disable_markup then
|
|
|
|
tb:set_text(value)
|
|
|
|
else
|
|
|
|
tb:set_markup(value)
|
|
|
|
end
|
|
|
|
item._private_data.text = value
|
|
|
|
end
|
2014-02-02 22:53:09 +01:00
|
|
|
|
2014-02-09 06:54:59 +01:00
|
|
|
-- Hover
|
|
|
|
module:setup_hover(item,data)
|
|
|
|
|
2014-02-13 05:09:55 +01:00
|
|
|
-- Overlay
|
2014-03-05 06:12:48 +01:00
|
|
|
item.set_overlay = function(_,value)
|
2014-02-13 05:09:55 +01:00
|
|
|
item._private_data.overlay = value
|
|
|
|
item.widget:emit_signal("widget::updated")
|
|
|
|
end
|
|
|
|
|
2016-02-11 10:21:10 +01:00
|
|
|
-- Define the item layout
|
|
|
|
item.widget = wibox.widget.base.make_widget_declarative {
|
|
|
|
-- Widgets
|
|
|
|
{
|
|
|
|
-- Widget
|
|
|
|
{
|
|
|
|
-- This is where the content is placed
|
|
|
|
|
|
|
|
-- Widgets
|
|
|
|
{
|
|
|
|
-- The prefixes
|
|
|
|
|
|
|
|
-- Widget
|
|
|
|
data.fkeys_prefix and fkey(data,item) or nil,
|
|
|
|
icon ,
|
|
|
|
args.prefix_widget ,
|
|
|
|
|
|
|
|
-- Attributes
|
|
|
|
layout = wibox.layout.fixed.horizontal
|
|
|
|
},
|
|
|
|
tb,
|
|
|
|
{
|
|
|
|
-- Suffixes
|
|
|
|
|
|
|
|
-- Widget
|
|
|
|
module:setup_checked(item,data) ,
|
|
|
|
module:setup_sub_menu_arrow(item,data),
|
|
|
|
args.suffix_widget ,
|
|
|
|
|
|
|
|
-- Attributes
|
|
|
|
layout = wibox.layout.fixed.horizontal
|
|
|
|
},
|
|
|
|
|
|
|
|
-- Attributes
|
|
|
|
_item = item ,
|
|
|
|
_data = data ,
|
|
|
|
id = "main_align" ,
|
|
|
|
layout = wibox.layout.align.horizontal,
|
|
|
|
},
|
|
|
|
|
|
|
|
-- Attributes
|
|
|
|
id = "main_margin" ,
|
|
|
|
layout = wibox.layout.margin,
|
|
|
|
},
|
|
|
|
|
|
|
|
-- Attributes
|
|
|
|
fg = item._private_data.fg ,
|
|
|
|
tooltip = item.tooltip ,
|
|
|
|
_item = item ,
|
|
|
|
_data = data ,
|
|
|
|
widget = wibox.widget.background,
|
|
|
|
}
|
|
|
|
|
|
|
|
-- Make some widgets easier to access
|
|
|
|
item._internal.margin_w = item.widget:get_children_by_id("main_margin")[1]
|
|
|
|
item._internal.align = item.widget:get_children_by_id("main_align" )[1]
|
|
|
|
|
|
|
|
-- Override some methods
|
|
|
|
item.widget._after_draw_children = item.widget.after_draw_children
|
|
|
|
item.widget.after_draw_children = module.after_draw_children
|
|
|
|
item._internal.align.fit = data._internal.align_fit or align_fit
|
|
|
|
item._internal.text_w = tb
|
|
|
|
item._internal.icon_w = icon
|
|
|
|
|
|
|
|
-- Export the margin
|
|
|
|
local mrgns = margins2(
|
|
|
|
item._internal.margin_w,
|
|
|
|
util.table.join(
|
|
|
|
(item.item_style or data.item_style).margins,data.default_item_margins
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
function item:get_margins()
|
|
|
|
return mrgns
|
|
|
|
end
|
2014-03-02 22:28:30 +01:00
|
|
|
|
2016-02-11 10:21:10 +01:00
|
|
|
-- Draw
|
|
|
|
local item_style = item.style or data.item_style
|
|
|
|
item_style(item,{})
|
2014-02-16 03:57:07 +01:00
|
|
|
|
2014-03-28 07:13:12 +01:00
|
|
|
-- Setup dynamic underlay
|
2016-02-11 10:21:10 +01:00
|
|
|
item:connect_signal("underlay::changed",function(_,udl)
|
|
|
|
item.widget:emit_signal("widget::updated")
|
|
|
|
end)
|
2014-03-02 22:28:30 +01:00
|
|
|
|
2016-02-11 10:21:10 +01:00
|
|
|
-- Setup events
|
|
|
|
module.setup_event(data,item)
|
2016-01-12 09:33:38 +01:00
|
|
|
|
2016-02-11 10:21:10 +01:00
|
|
|
return item.widget
|
2014-02-02 22:53:09 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
return setmetatable(module, { __call = function(_, ...) return create_item(...) end })
|
2016-02-11 10:21:10 +01:00
|
|
|
-- kate: space-indent on; indent-width 4; replace-tabs on;
|