base: Fix scroll, filter and embedded menus

This commit is contained in:
Emmanuel Lepage Vallee 2016-06-24 00:44:43 -04:00
parent ffd1e8003a
commit 7506a8f49d
1 changed files with 56 additions and 68 deletions

114
base.lua
View File

@ -72,49 +72,50 @@ theme.register_color(module.item_flags.HIGHLIGHT , "highlight" , "highlight" , t
local function filter(data) local function filter(data)
if not data.filter == false then local max_items = data.max_items or 9999999
local fs,visible_counter = data.filter_string:lower(),0
data._internal.visible_item_count = 0 local fs = data.filter_string ~= "" and data.filter_string:lower() or nil
for k,v in pairs(data.items) do
local tmp = v._filter_out local start_at, visible_counter = data._start_at or -1, 0
v._filter_out = (v.text:lower():find(fs) == nil)-- or (fs ~= "")
if tmp ~= v._filter_out then -- There is 2 factors to consider to display the item:
v.widget.visible = not v._filter_out --
-- * Is the item within range
-- * Is the item matching the filter
--
for k,v in ipairs(data.items) do
v.widget.visible = (not fs or v.text and v.text:lower():find(fs) ~= nil)
and k >= start_at and visible_counter < max_items
if v.widget.visible then
visible_counter = visible_counter + 1
v.f_key = visible_counter
end end
if (not v._filter_out) and (not v.widget.visible == false) then
visible_counter = visible_counter + v.height -- Don't waste CPU
data._internal.visible_item_count = data._internal.visible_item_count +1 if visible_counter >= max_items then break end
v.f_key = data._internal.visible_item_count
end end
end
data._total_item_height = visible_counter data._internal.visible_item_count = visible_counter
-- Make sure to select an item -- Make sure to select an item
if data._current_item and data._current_item._filter_out then if data._current_item and not data._current_item.widget.visible then
local n = data.next_item local n = data.next_item
if n then if n then
n.selected = true n.selected = true
end end
end end
end
end end
-- Get the number of visible rows -- Get the number of visible rows
local function get_visible_row_count(data) local function get_visible_row_count(data)
local visblerow = data.filter_string == "" and data.rowcount or data._internal.visible_item_count if not data._internal.visible_item_count then
if data.max_items and data.max_items < data.rowcount then filter(data)
visblerow = data.max_items
if data.filter_string ~= "" then
local cur,vis = (data._start_at or 1),0
while (data._internal.items[cur] and data._internal.items[cur]) and cur < data.max_items + (data._start_at or 1) do
vis = vis + (data._internal.items[cur]._filter_out and 0 or 1)
cur = cur +1
end end
visblerow = vis
end return data._internal.visible_item_count
end
return visblerow
end end
------------------------------------KEYBOARD HANDLING----------------------------------- ------------------------------------KEYBOARD HANDLING-----------------------------------
@ -163,10 +164,8 @@ local function activateKeyboard(data)
capi.keygrabber.stop() capi.keygrabber.stop()
elseif (key == 'BackSpace') and data.filter_string ~= "" and data.filter == true then elseif (key == 'BackSpace') and data.filter_string ~= "" and data.filter == true then
data.filter_string = data.filter_string:sub(1,-2) data.filter_string = data.filter_string:sub(1,-2)
filter(data)
elseif data.filter == true and key:len() == 1 then elseif data.filter == true and key:len() == 1 then
data.filter_string = data.filter_string .. key:lower() data.filter_string = data.filter_string .. key:lower()
filter(data)
else else
data.visible = false data.visible = false
capi.keygrabber.stop() capi.keygrabber.stop()
@ -211,6 +210,13 @@ local function add_item(data,args)
item.index = data.rowcount item.index = data.rowcount
data:emit_signal("item::added",item) data:emit_signal("item::added",item)
-- Keep the filter up-to-date
if data.max_items and data.rowcount - (data._start_at or 0) > data.max_items then
--FIXME and data._internal.visible_item_count < data.max_items then
filter(data)
end
return item return item
end end
@ -278,11 +284,6 @@ local function get_widget_fit_sum(data)
return w,h return w,h
end end
local function get_widget_fit_width_sum(data)
-- TODO query this from the layout itself
return get_widget_fit_sum(data)
end
local function get_widget_fit_height_sum(data) local function get_widget_fit_height_sum(data)
-- TODO query this from the layout itself -- TODO query this from the layout itself
local w,h = get_widget_fit_sum(data) local w,h = get_widget_fit_sum(data)
@ -401,8 +402,7 @@ local function new(args)
data.get_items = function(_) return internal.items end data.get_items = function(_) return internal.items end
data.get_rowcount = function(_) return #internal.items end data.get_rowcount = function(_) return #internal.items end
data.get_visible_row_count = get_visible_row_count data.get_visible_row_count = get_visible_row_count
data.get_widget_fit_height_sum = get_widget_fit_height_sum data.get_widget_fit_height_sum = get_widget_fit_height_sum --TODO remove
data.get_widget_fit_width_sum = get_widget_fit_width_sum
-- Setters -- Setters
data.set_auto_resize = function(_,val) private_data[""] = val end data.set_auto_resize = function(_,val) private_data[""] = val end
@ -467,14 +467,14 @@ local function new(args)
data.get_previous_item = function(_) data.get_previous_item = function(_)
local candidate,idx = internal.items[(data.current_index or 0)-1],(data.current_index or 0)-1 local candidate,idx = internal.items[(data.current_index or 0)-1],(data.current_index or 0)-1
while candidate and (candidate.widget.visible == false or candidate._filter_out) and idx > 0 do while candidate and (candidate.widget.visible == false) and idx > 0 do
candidate,idx = internal.items[idx - 1],idx-1 candidate,idx = internal.items[idx - 1],idx-1
end end
return (candidate or internal.items[data.rowcount]) return (candidate or internal.items[data.rowcount])
end end
data.get_next_item = function(_) data.get_next_item = function(_)
local candidate,idx = internal.items[(data.current_index or 0)+1],(data.current_index or 0)+1 local candidate,idx = internal.items[(data.current_index or 0)+1],(data.current_index or 0)+1
while candidate and (candidate.widget.visible == false or candidate._filter_out) and idx <= data.rowcount do while candidate and (candidate.widget.visible == false) and idx <= data.rowcount do
candidate,idx = internal.items[idx + 1],idx+1 candidate,idx = internal.items[idx + 1],idx+1
end end
return (candidate or internal.items[1]) return (candidate or internal.items[1])
@ -491,6 +491,10 @@ local function new(args)
end) end)
end end
-- Make sure the filter doesn't get outdated
data:connect_signal("max_items::changed" , filter)
data:connect_signal("filter_string::changed", filter)
function data:add_key_hook(mod, key, event, func) function data:add_key_hook(mod, key, event, func)
if key and event and func then if key and event and func then
internal.filter_hooks = internal.filter_hooks or {} internal.filter_hooks = internal.filter_hooks or {}
@ -512,19 +516,19 @@ local function new(args)
data:emit_signal("clear::menu") data:emit_signal("clear::menu")
end end
function data:swap(item1,item2) function data:swap(item1,item2) --TODO can item.index be used?
if not item1 or not item2 then return end if not item1 or not item2 then return end
if not item1 or not item2 and item1 ~= item2 then return end if not item1 or not item2 and item1 ~= item2 then return end
local idx1,idx2 local idx1,idx2
for k,v in ipairs(internal.items) do --rows for k,v in ipairs(internal.items) do --rows
for k2,v2 in ipairs(v) do --columns if item2 == v then
if item2 == v2 then
idx2 = k idx2 = k
end end
if item1 == v2 then
if item1 == v then
idx1 = k idx1 = k
end end
end
if idx1 and idx2 then if idx1 and idx2 then
break break
end end
@ -594,17 +598,9 @@ local function new(args)
current_item:set_selected(false,true) current_item:set_selected(false,true)
end end
data._start_at = (data._start_at or 1) - 1 data._start_at = (data._start_at or 1) - 1
internal.items[data._start_at].widget:set_visible(false)
data:emit_signal("_hidden::changed",internal.items[data._start_at])
internal.items[data._start_at+data.max_items].widget:set_visible(true)
data:emit_signal("_hidden::changed",internal.items[data._start_at+data.max_items])
filter(data) filter(data)
--HACK upstream bug
internal.items[data._start_at].widget:emit_signal("widget::layout_changed")
internal.items[data._start_at+data.max_items].widget:emit_signal("widget::layout_changed")
data._internal.layout:emit_signal("widget::redraw_needed")
data._internal.layout:emit_signal("widget::layout_changed")
end end
end end
@ -615,17 +611,9 @@ local function new(args)
current_item:set_selected(false,true) current_item:set_selected(false,true)
end end
data._start_at = (data._start_at or 1) + 1 data._start_at = (data._start_at or 1) + 1
internal.items[data._start_at-1].widget:set_visible(true)
data:emit_signal("_hidden::changed",internal.items[data._start_at-1])
internal.items[data._start_at-1+data.max_items].widget:set_visible(false)
data:emit_signal("_hidden::changed",internal.items[data._start_at-1+data.max_items])
filter(data) filter(data)
--HACK upstream bug
internal.items[data._start_at-1].widget:emit_signal("widget::layout_changed")
internal.items[data._start_at-1+data.max_items].widget:emit_signal("widget::layout_changed")
data._internal.layout:emit_signal("widget::redraw_needed")
data._internal.layout:emit_signal("widget::layout_changed")
end end
end end