From b6ba3ad383d68a3da777e361af4dfebee8b57249 Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Fri, 21 Feb 2014 22:22:13 -0500 Subject: [PATCH] Replace old state handling implementation by something 'better' While **much** more complex and slower for regular menus, it has advantages: * Better performance scaling when state count grow * Prevent most accidental unsupported state colors * Prevent a big if elseif elseif... switch copy pasted in all item_styles * Make it easier to register new states As for the 'bloated' created by this commit, it will be moved when I will fix issue #12 --- base.lua | 92 +++++++++++++++++++++++++++++++------ item_layout/horizontal.lua | 4 +- item_style/arrow_alt.lua | 6 ++- item_style/arrow_prefix.lua | 8 ++-- item_style/arrow_single.lua | 11 +++-- item_style/basic.lua | 6 ++- item_style/classic.lua | 4 +- item_style/rounded.lua | 8 +++- 8 files changed, 109 insertions(+), 30 deletions(-) diff --git a/base.lua b/base.lua index add8086..07207b7 100644 --- a/base.lua +++ b/base.lua @@ -27,13 +27,13 @@ local module = { LEAVE = 1001, }, item_flags = { - NONE = 0 , - SELECTED = 1 , -- Single item selected [[FOCUS]] - HOVERED = 2 , -- Mouse hover - PRESSED = 3 , -- Mouse pressed - URGENT = 4 , -- Need attention - USED = 5 , -- Common flag - DISABLED = 6 , -- Cannot be interacted with + NONE = 999999 , + DISABLED = 1 , -- Cannot be interacted with + URGENT = 2 , -- Need attention + SELECTED = 3 , -- Single item selected [[FOCUS]] + PRESSED = 4 , -- Mouse pressed + HOVERED = 5 , -- Mouse hover + USED = 6 , -- Common flag CHECKED = 7 , -- When checkbox isn't enough ALTERNATE = 8 , HIGHLIGHT = 9 , @@ -50,9 +50,70 @@ local module = { USR8 = 108, USR9 = 109, USR10 = 110, - } + }, + colors_by_id = {} } + +-- Do some magic to cache the highest state +local function return_data(tab, key) + return tab._real_table[key] +end +local function change_data(tab, key,value) + if not value and key == rawget(tab,"_current_key") then + -- Loop the array to find a new current_key + local win = math.huge + for k,v in pairs(tab._real_table) do + if k < win and k ~= key then + win = k + end + end + rawset(tab,"_current_key",win ~= math.huge and win or nil) + elseif value and (rawget(tab,"_current_key") or math.huge) > key then + rawset(tab,"_current_key",key) + end + tab._real_table[key] = value +end +local function init_state() + local mt = {__newindex = change_data,__index=return_data} + return setmetatable({_real_table={}},mt) +end + +-- Util to help match colors to states +local theme_colors = {} +local function register_color(state_id,name,beautiful_name,allow_fallback) + theme_colors[name] = {id=state_id,beautiful_name=beautiful_name,fallback=allow_fallback} + module.colors_by_id[state_id] = name +end +local function setup_colors(data,args) + local priv = data._internal.private_data + for k,v in pairs(theme_colors) do + priv["fg_"..k] = args["fg_"..k] or beautiful["menu_fg_"..v.beautiful_name] or beautiful["fg_"..v.beautiful_name] or (v.fallback and "#ff0000") + priv["bg_"..k] = args["bg_"..k] or beautiful["menu_bg_"..v.beautiful_name] or beautiful["bg_"..v.beautiful_name] or (v.fallback and "#00ff00") + end +end +register_color(module.item_flags.DISABLED , "disabled" , "disabled" , true ) +register_color(module.item_flags.URGENT , "urgent" , "urgent" , true ) +register_color(module.item_flags.SELECTED , "focus" , "focus" , true ) +register_color(module.item_flags.PRESSED , "pressed" , "pressed" , true ) +register_color(module.item_flags.HOVERED , "hover" , "hover" , true ) +register_color(module.item_flags.USED , "used" , "used" , true ) +register_color(module.item_flags.CHECKED , "checked" , "checked" , true ) +register_color(module.item_flags.ALTERNATE , "alternate" , "alternate" , true ) +register_color(module.item_flags.HIGHLIGHT , "highlight" , "highlight" , true ) +-- register_color(item_flags.HEADER , "" +-- register_color(item_flags.USR1 , "" +-- register_color(item_flags.USR2 , "" +-- register_color(item_flags.USR3 , "" +-- register_color(item_flags.USR4 , "" +-- register_color(item_flags.USR5 , "" +-- register_color(item_flags.USR6 , "" +-- register_color(item_flags.USR7 , "" +-- register_color(item_flags.USR8 , "" +-- register_color(item_flags.USR9 , "" +-- register_color(item_flags.USR10 , "" + + local function filter(data) if not data.filter == false then local fs,visible_counter = data.filter_string:lower(),0 @@ -172,7 +233,7 @@ local function add_item(data,args) item_layout = args.item_layout or nil , selected = false , overlay = args.overlay or data.overlay or nil , - state = {} , + state = init_state() , }, force_private = { visible = true, @@ -301,14 +362,14 @@ local function new(args) -- Default settings bg = args.bg or beautiful.menu_bg_normal or beautiful.bg_normal or "#000000", fg = args.fg or beautiful.menu_fg_normal or beautiful.fg_normal or "#ffffff", - bg_focus = args.bg_focus or beautiful.menu_bg_focus or beautiful.bg_focus or "#ffffff", - fg_focus = args.fg_focus or beautiful.menu_fg_focus or beautiful.fg_focus or "#000000", - bg_alternate = args.bg_alternate or beautiful.menu_bg_alternate or beautiful.bg_alternate or beautiful.bg_normal, - bg_highlight = args.bg_highlight or beautiful.menu_bg_highlight or beautiful.bg_highlight or beautiful.bg_normal, +-- bg_focus = args.bg_focus or beautiful.menu_bg_focus or beautiful.bg_focus or "#ffffff", +-- fg_focus = args.fg_focus or beautiful.menu_fg_focus or beautiful.fg_focus or "#000000", +-- bg_alternate = args.bg_alternate or beautiful.menu_bg_alternate or beautiful.bg_alternate or beautiful.bg_normal, +-- bg_highlight = args.bg_highlight or beautiful.menu_bg_highlight or beautiful.bg_highlight or beautiful.bg_normal, bg_header = args.bg_header or beautiful.menu_bg_header or beautiful.fg_normal, bg_prefix = args.bg_prefix or nil, - bg_hover = args.bg_hover or nil, - fg_hover = args.fg_hover or nil, +-- bg_hover = args.bg_hover or nil, +-- fg_hover = args.fg_hover or nil, border_color = args.border_color or beautiful.menu_border_color or beautiful.border_color or "#333333", border_width = args.border_width or beautiful.menu_border_width or beautiful.border_width or 3, separator_color = args.separator_color or beautiful.menu_separator_color or args.border_color or beautiful.menu_border_color or beautiful.border_color or "#333333", @@ -372,6 +433,7 @@ local function new(args) }) internal.get_map,internal.set_map,internal.private_data = get_map,set_map,private_data data.add_item,data.add_widget,data.add_embeded_menu,data._internal,data.add_key_binding = add_item,add_widget,add_embeded_menu,internal,add_key_binding + setup_colors(data,args) set_map.parent_geometry = function(value) private_data.parent_geometry = value if data._internal.get_direction then diff --git a/item_layout/horizontal.lua b/item_layout/horizontal.lua index 7bf7920..39bd1ab 100644 --- a/item_layout/horizontal.lua +++ b/item_layout/horizontal.lua @@ -86,8 +86,8 @@ end function module:setup_hover(item,data) item._internal.set_map.hover = function(value) local item_style = item.item_style or data.item_style - item.state[2] = value and true or nil - item_style(data,item,{value and 2--[[HOVER]] or nil,item.selected and 1 or nil}) + item.state[5] = value and true or nil + item_style(data,item,{}) end end diff --git a/item_style/arrow_alt.lua b/item_style/arrow_alt.lua index c965de1..187b848 100644 --- a/item_style/arrow_alt.lua +++ b/item_style/arrow_alt.lua @@ -115,14 +115,18 @@ local function draw(data,item,args) item.widget.next_color = hcode[next_idx] local state = item.state or {} + local current_state = state._current_key or nil + local state_name = base.colors_by_id[current_state] local prev_item = get_prev(data,item) - if state[base.item_flags.SELECTED] or (item._tmp_menu) then + if current_state == base.item_flags.SELECTED or (item._tmp_menu) then if prev_item and prev_item.widget.next_color ~= (args.color or data.bg_focus) then prev_item.widget.next_color = args.color or data.bg_focus prev_item.widget:emit_signal("widget::updated") end item.widget:set_bg(args.color or data.bg_focus) + elseif state_name then --TODO untested, most likely broken + item.widget:set_bg(args.color or item["bg_"..state_name] or data["bg_"..state_name]) else if prev_item and prev_item.widget.next_color ~= hcode[color_idx] then prev_item.widget.next_color = hcode[color_idx] diff --git a/item_style/arrow_prefix.lua b/item_style/arrow_prefix.lua index 26dddcc..f3af0dd 100644 --- a/item_style/arrow_prefix.lua +++ b/item_style/arrow_prefix.lua @@ -81,11 +81,13 @@ local function draw(data,item,args) end local state = item.state or {} + local current_state = state._current_key or nil + local state_name = base.colors_by_id[current_state] - if state[base.item_flags.SELECTED] or (item._tmp_menu) then + if current_state == base.item_flags.SELECTED or (item._tmp_menu) then item.widget:set_bg(args.color or data.bg_focus) - elseif state[base.item_flags.HOVERED] then - item.widget:set_bg(args.color or data.bg_hover) + elseif state_name then + item.widget:set_bg(args.color or item["bg_"..state_name] or data["bg_"..state_name]) else item.widget:set_bg(args.color or nil) end diff --git a/item_style/arrow_single.lua b/item_style/arrow_single.lua index ff88f81..6bb5181 100644 --- a/item_style/arrow_single.lua +++ b/item_style/arrow_single.lua @@ -42,11 +42,12 @@ local function draw(data,item,args) item.widget.draw = suffix_draw local state = item.state or {} - - if state[base.item_flags.SELECTED] or (item._tmp_menu) then - item.widget:set_bg(args.color or data.bg_focus) - elseif state[base.item_flags.HOVERED] then - item.widget:set_bg(args.color or data.bg_hover) + local current_state = state._current_key or nil + local state_name = base.colors_by_id[current_state] + if current_state == base.item_flags.SELECTED or (item._tmp_menu) then + item.widget:set_bg(args.color or item.bg_focus or data.bg_focus) + elseif state_name then + item.widget:set_bg(args.color or item["bg_"..state_name] or data["bg_"..state_name]) else item.widget:set_bg(args.color or nil) end diff --git a/item_style/basic.lua b/item_style/basic.lua index 685fb09..1c9d859 100644 --- a/item_style/basic.lua +++ b/item_style/basic.lua @@ -30,9 +30,13 @@ local function draw(data,item,args) end local state = item.state or {} + local current_state = state._current_key or nil + local state_name = base.colors_by_id[current_state] - if state[base.item_flags.SELECTED] or (item._tmp_menu) then + if current_state == base.item_flags.SELECTED or (item._tmp_menu) then item.widget:set_bg(args.color or data.bg_focus) + elseif state_name then + item.widget:set_bg(args.color or item["bg_"..state_name] or data["bg_"..state_name]) else item.widget:set_bg(args.color or nil) end diff --git a/item_style/classic.lua b/item_style/classic.lua index b33ad71..7e90800 100644 --- a/item_style/classic.lua +++ b/item_style/classic.lua @@ -60,8 +60,10 @@ local function draw(data,item,args) end local state = item.state or {} +-- local current_state = state._current_key or nil --TODO +-- local state_name = base.colors_by_id[current_state] - if state[base.item_flags.SELECTED] or (item._tmp_menu) then + if current_state == base.item_flags.SELECTED or (item._tmp_menu) then item.widget:set_bg(focussed[ih]) elseif col then item.widget:set_bg(alt[col][ih]) diff --git a/item_style/rounded.lua b/item_style/rounded.lua index baa1287..4d6fb69 100644 --- a/item_style/rounded.lua +++ b/item_style/rounded.lua @@ -60,11 +60,15 @@ local function draw(data,item,args) end local state = item.state or {} + local current_state = state._current_key or nil + local state_name = base.colors_by_id[current_state] - if state[base.item_flags.SELECTED] or (item._tmp_menu) then + if current_state == base.item_flags.SELECTED or (item._tmp_menu) then item.widget:set_bg(focussed[ih]) + elseif state_name then --TODO incomplete + item.widget:set_bg(args.color or item["bg_"..state_name] or data["bg_"..state_name]) else - item.widget:set_bg(default[ih]) + item.widget:set_bg(default[ih]) end end