diff --git a/bar.lua b/bar.lua index 427f873..c2dc086 100644 --- a/bar.lua +++ b/bar.lua @@ -8,9 +8,11 @@ local beautiful = require( "beautiful" ) local cairo = require( "lgi" ).cairo local awful = require( "awful" ) local util = require( "awful.util" ) +local fkey = require( "radical.widgets.fkey" ) local button = require( "awful.button" ) local checkbox = require( "radical.widgets.checkbox" ) local item_style = require( "radical.item_style.arrow_alt" ) +local vertical = require( "radical.layout.vertical" ) local capi,module = { mouse = mouse , screen = screen, keygrabber = keygrabber },{} @@ -75,7 +77,22 @@ local function setup_drawable(data) data.draw = internal.margin.draw end -local function create_item(item,data) +-- Use all the space, let "align_fit" compute the right size +local function textbox_fit(box,w,h) + return w,h +end + +-- Force the width or compute the minimum space +local function align_fit(box,w,h) + if box._item.width then return box._item.width - box._data.item_style.margins.LEFT - box._data.item_style.margins.RIGHT,h end + local lw = box.first:fit(w,h) + local cw = wibox.widget.textbox.fit(box.second,w,h) + local lr = box.third:fit(w,h) + return lw+cw+lr,h +end + +-- Create the actual widget +local function create_item(item,data,args) -- Background local bg = wibox.widget.background() @@ -87,21 +104,54 @@ local function create_item(item,data) m:set_top ( data.item_style.margins.TOP ) m:set_bottom( data.item_style.margins.BOTTOM ) - -- Layout + -- Layout (left) local layout = wibox.layout.fixed.horizontal() bg:set_widget(m) - m:set_widget(layout) - -- Content - if item.icon then - local icon = wibox.widget.imagebox() - icon:set_image(item.icon) - layout:add(icon) + -- Layout (right) + local right = wibox.layout.fixed.horizontal() + + -- F keys + vertical:setup_fkey(item,data) + if data.fkeys_prefix == true then + layout:add(fkey(data,item)) + m:set_left ( 0 ) end + + -- Icon + layout:add(vertical:setup_icon(item,data)) + + -- Prefix + if args.prefix_widget then + layout:add(args.prefix_widget) + end + + -- Text local tb = wibox.widget.textbox() - layout:add(tb) + tb.fit = textbox_fit item.widget = bg - tb:set_text("bob") + tb:set_text(item.text) + + -- Checkbox + local ck = vertical:setup_checked(item,data) + if ck then + right:add(ck) + end + + -- Suffix + if args.suffix_widget then + right:add(args.suffix_widget) + end + + -- Layout (align) + local align = wibox.layout.align.horizontal() + align:set_middle( tb ) + align:set_left ( layout ) + align:set_right ( right ) + m:set_widget ( align ) + align._item = item + align._data = data + align.fit = align_fit -- Tooltip item.widget:set_tooltip(item.tooltip) @@ -116,7 +166,7 @@ end local function setup_item(data,item,args) -- Add widgets - data._internal.layout:add(create_item(item,data)) + data._internal.layout:add(create_item(item,data,args)) item.widget:connect_signal("mouse::enter", function() item.selected = true end) item.widget:connect_signal("mouse::leave", function() item.selected = false end) diff --git a/base.lua b/base.lua index 835f852..2a1ca70 100644 --- a/base.lua +++ b/base.lua @@ -124,15 +124,16 @@ local function add_item(data,args) private_data = { text = args.text or "" , height = args.height or beautiful.menu_height or 30 , + width = args.width or nil , icon = args.icon or nil , prefix = args.prefix or "" , suffix = args.suffix or "" , bg = args.bg or nil , - fg = args.fg or data.fg or beautiful.menu_fg_normal or beautiful.fg_normal, - fg_focus = args.fg_focus or data.fg_focus or beautiful.menu_fg_focus or beautiful.fg_focus , - bg_focus = args.bg_focus or data.bg_focus or beautiful.menu_bg_focus or beautiful.bg_focus , + fg = args.fg or data.fg or beautiful.menu_fg_normal or beautiful.fg_normal , + fg_focus = args.fg_focus or data.fg_focus or beautiful.menu_fg_focus or beautiful.fg_focus , + bg_focus = args.bg_focus or data.bg_focus or beautiful.menu_bg_focus or beautiful.bg_focus , sub_menu_m = (args.sub_menu and type(args.sub_menu) == "table" and args.sub_menu.is_menu) and args.sub_menu or nil, - sub_menu_f = (args.sub_menu and type(args.sub_menu) == "function") and args.sub_menu or nil, + sub_menu_f = (args.sub_menu and type(args.sub_menu) == "function") and args.sub_menu or nil , selected = false, checkable = args.checkable or (args.checked ~= nil) or false, checked = args.checked or false, @@ -400,7 +401,7 @@ local function new(args) end function data:remove_key_hook(key) - for k,v in pairs(internal.filter_hooks) do + for k,v in pairs(internal.filter_hooks or {}) do if k.key == key then internal.filter_hooks[k] = nil break diff --git a/layout/vertical.lua b/layout/vertical.lua index d2480be..4be3ce0 100644 --- a/layout/vertical.lua +++ b/layout/vertical.lua @@ -94,6 +94,90 @@ local function cache_pixmap(item) end end +function module:setup_fkey(item,data) + item._internal.set_map.f_key = function(value) + item._internal.has_changed = true + item._internal.f_key = value + data:remove_key_hook("F"..value) + data:add_key_hook({}, "F"..value , "press", function() + item.button1() + data.visible = false + end) + end + item._internal.get_map.f_key = function() return item._internal.f_key end +end + +function module:setup_checked(item,data) + if item.checkable then + item._internal.get_map.checked = function() + if type(item._private_data.checked) == "function" then + return item._private_data.checked() + else + return item._private_data.checked + end + end + local ck = wibox.widget.imagebox() + ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked()) + item._internal.set_map.checked = function (value) + 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 + +function module:setup_icon(item,data) + local icon = wibox.widget.imagebox() + icon.fit = function(...) + local w,h = wibox.widget.imagebox.fit(...) + return w+3,h + end + if item.icon then + icon:set_image(item.icon) + end + + item._internal.set_map.icon = function (value) + icon:set_image(value) + end + return icon +end + +function module:setup_text(item,data) + local text_w = wibox.widget.textbox() + + text_w.draw = function(self,w, cr, width, height) + if item.underlay then + paint_underlay(data,item,cr,width,height) + end + wibox.widget.textbox.draw(self,w, cr, width, height) + end + text_w.fit = function(self,width,height) return width,height end + + item._internal.set_map.text = function (value) + if data.disable_markup then + text_w:set_text(value) + else + text_w:set_markup(value) + end + if data.auto_resize then + local fit_w,fit_h = wibox.widget.textbox.fit(text_w,9999,9999) + local is_largest = item == data._internal.largest_item_w + item._internal.has_changed = true + if not data._internal.largest_item_w_v or data._internal.largest_item_w_v < fit_w then + data._internal.largest_item_w = item + data._internal.largest_item_w_v = fit_w + end + --TODO find new largest is item is smaller + -- if data._internal.largest_item_h_v < fit_h then + -- data._internal.largest_item_h =item + -- data._internal.largest_item_h_v = fit_h + -- end + end + end + item._internal.set_map.text(item._private_data.text) + return text_w +end function module:setup_item(data,item,args) --Create the background @@ -130,16 +214,11 @@ function module:setup_item(data,item,args) m:set_right ( data.item_style.margins.RIGHT ) m:set_top ( data.item_style.margins.TOP ) m:set_bottom( data.item_style.margins.BOTTOM ) - local text_w = wibox.widget.textbox() - text_w.draw = function(self,w, cr, width, height) - if item.underlay then - paint_underlay(data,item,cr,width,height) - end - wibox.widget.textbox.draw(self,w, cr, width, height) - end - text_w.fit = function(self,width,height) return width,height end + -- Text + local text_w = module:setup_text(item,data) + -- Background item._private_data._fit = wibox.widget.background.fit m.fit = function(...) if not data.visible or (item.visible == false or item._filter_out == true or item._hidden == true) then @@ -148,24 +227,21 @@ function module:setup_item(data,item,args) return data._internal.layout.item_fit(data,item,...) end + -- F keys if data.fkeys_prefix == true then l:add(fkey(data,item)) m:set_left ( 0 ) end + -- Prefix if args.prefix_widget then l:add(args.prefix_widget) end - local icon = wibox.widget.imagebox() - icon.fit = function(...) - local w,h = wibox.widget.imagebox.fit(...) - return w+3,h - end - if args.icon then - icon:set_image(args.icon) - end + -- Icon + local icon = module:setup_icon(item,data) l:add(icon) + if item._private_data.sub_menu_f or item._private_data.sub_menu_m then local subArrow = wibox.widget.imagebox() --TODO, make global subArrow.fit = function(box, w, h) return subArrow._image:get_width(),item.height end @@ -176,26 +252,19 @@ function module:setup_item(data,item,args) return wibox.widget.background.fit(box,w,h) end end - if item.checkable then - item._internal.get_map.checked = function() - if type(item._private_data.checked) == "function" then - return item._private_data.checked() - else - return item._private_data.checked - end - end - local ck = wibox.widget.imagebox() - ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked()) + + -- Checkbox + local ck = module:setup_checked(item,data) + if ck then lr:add(ck) - item._internal.set_map.checked = function (value) - item._private_data.checked = value - ck:set_image(item.checked and checkbox.checked() or checkbox.unchecked()) - item._internal.has_changed = true - end end + + -- Suffix if args.suffix_widget then lr:add(args.suffix_widget) end + + -- Layout la:set_left(l) la:set_middle(text_w) la:set_right(lr) @@ -203,45 +272,14 @@ function module:setup_item(data,item,args) local fit_w,fit_h = data._internal.layout:fit() data.width = fit_w data.height = fit_h - data.style(data) - item._internal.set_map.text = function (value) - if data.disable_markup then - text_w:set_text(value) - else - text_w:set_markup(value) - end - if data.auto_resize then - local fit_w,fit_h = wibox.widget.textbox.fit(text_w,9999,9999) - local is_largest = item == data._internal.largest_item_w - item._internal.has_changed = true - if not data._internal.largest_item_w_v or data._internal.largest_item_w_v < fit_w then - data._internal.largest_item_w = item - data._internal.largest_item_w_v = fit_w - end - --TODO find new largest is item is smaller - -- if data._internal.largest_item_h_v < fit_h then - -- data._internal.largest_item_h =item - -- data._internal.largest_item_h_v = fit_h - -- end - end + if data.style then + data.style(data) end - item._internal.set_map.f_key = function(value) - item._internal.has_changed = true - item._internal.f_key = value - data:remove_key_hook("F"..value) - data:add_key_hook({}, "F"..value , "press", function() - item.button1() - data.visible = false - end) - end - item._internal.get_map.f_key = function() return item._internal.f_key end - - item._internal.set_map.icon = function (value) - icon:set_image(value) - end - item._internal.set_map.text(item._private_data.text) + -- F keys + module:setup_fkey(item,data) + -- Enable scrollbar if necessary if data._internal.scroll_w and data.rowcount > data.max_items then data._internal.scroll_w.visible = true data._internal.scroll_w["up"]:emit_signal("widget::updated") diff --git a/widgets/fkey.lua b/widgets/fkey.lua index 32350df..cff809f 100644 --- a/widgets/fkey.lua +++ b/widgets/fkey.lua @@ -11,18 +11,18 @@ local module = {} local keys = {} -local pango_l,pango_crx,max_width,m_h = nil,nil,0,0 -local function create_pango() +local pango_l,pango_crx,max_width = nil,nil,0 +local function create_pango(height) local padding = beautiful.menu_height/5 pango_crx = pangocairo.font_map_get_default():create_context() pango_l = pango.Layout.new(pango_crx) local desc = pango.FontDescription() desc:set_family("Verdana") desc:set_weight(pango.Weight.BOLD) - desc:set_size((m_h-padding*2) * pango.SCALE) + desc:set_size((height-padding*2) * pango.SCALE) pango_l:set_font_description(desc) pango_l.text = "F88" - max_width = pango_l:get_pixel_extents().width + m_h + 4 + max_width = pango_l:get_pixel_extents().width + height + 4 end local function new(data,item) @@ -30,19 +30,17 @@ local function new(data,item) local padding = beautiful.menu_height/5 pref.draw = function(self,w, cr, width, height) local key = item._internal.f_key - if m_h == 0 then - m_h = height + if not keys[height] then pref:emit_signal("widget::updated") - create_pango() - keys = {} + create_pango(height) + keys[height] = {} end - if key and key > 12 and keys[0] then - cr:set_source_surface(keys[0]) + if key and key > 12 and keys[height][0] then + cr:set_source_surface(keys[height][0]) cr:paint() - elseif not keys[key] then + elseif not keys[height] or not keys[height][key] then if not pango_l then - m_h = height - create_pango() + create_pango(height) end local img = cairo.ImageSurface(cairo.Format.ARGB32, max_width,beautiful.menu_height) local cr2 = cairo.Context(img) @@ -59,16 +57,16 @@ local function new(data,item) pango_l.text = text cr2:show_layout(pango_l) if key > 12 then - keys[0] = img + keys[height][0] = img else - keys[key] = img + keys[height][key] = img end end - if key and key > 12 and keys[0] then - cr:set_source_surface(keys[0]) + if key and key > 12 and keys[height][0] then + cr:set_source_surface(keys[height][0]) cr:paint() else - cr:set_source_surface(keys[key]) + cr:set_source_surface(keys[height][key]) cr:paint() end end