support scrollbar for menuconf

This commit is contained in:
ruki
2020-11-29 21:23:37 +08:00
parent 41a054c176
commit 75b1d2e4c7
5 changed files with 192 additions and 49 deletions

View File

@@ -72,11 +72,11 @@ function choicebox:load(values, selected)
-- select the first item -- select the first item
self:select(self:first()) self:select(self:first())
-- invalidate
self:invalidate()
-- on loaded -- on loaded
self:action_on(action.ac_on_load) self:action_on(action.ac_on_load)
-- invalidate
self:invalidate()
end end
-- is scrollable? -- is scrollable?

View File

@@ -64,10 +64,15 @@ function choicedialog:init(name, bounds, title)
self:box():panel():action_add(action.ac_on_resized, function (v) self:box():panel():action_add(action.ac_on_resized, function (v)
self:choicebox():bounds_set(rect:new(0, 0, v:width() - 1, v:height())) self:choicebox():bounds_set(rect:new(0, 0, v:width() - 1, v:height()))
self:scrollbar_box():bounds_set(rect:new(v:width() - 1, 0, 1, v:height())) self:scrollbar_box():bounds_set(rect:new(v:width() - 1, 0, 1, v:height()))
if self:choicebox():scrollable() then
self:scrollbar_box():show(true)
else
self:scrollbar_box():show(false)
end
end) end)
-- show scrollbar? -- show scrollbar?
self:choicebox():action_set(action.ac_on_load, function (v) self:choicebox():action_add(action.ac_on_load, function (v)
if v:scrollable() then if v:scrollable() then
self:scrollbar_box():show(true) self:scrollbar_box():show(true)
else else
@@ -76,7 +81,7 @@ function choicedialog:init(name, bounds, title)
end) end)
-- on scroll -- on scroll
self:choicebox():action_set(action.ac_on_scrolled, function (v, progress) self:choicebox():action_add(action.ac_on_scrolled, function (v, progress)
if self:scrollbar_box():state("visible") then if self:scrollbar_box():state("visible") then
self:scrollbar_box():progress_set(progress) self:scrollbar_box():progress_set(progress)
end end
@@ -96,7 +101,8 @@ end
-- get box scrollbar -- get box scrollbar
function choicedialog:scrollbar_box() function choicedialog:scrollbar_box()
if not self._SCROLLBAR_BOX then if not self._SCROLLBAR_BOX then
self._SCROLLBAR_BOX = scrollbar:new("choicedialog.scrollbar", rect:new(self:box():panel():width() - 1, 0, 1, self:box():panel():height())) local bounds = self:box():panel():bounds()
self._SCROLLBAR_BOX = scrollbar:new("choicedialog.scrollbar", rect:new(bounds:width() - 1, 0, 1, bounds:height()))
self._SCROLLBAR_BOX:show(false) self._SCROLLBAR_BOX:show(false)
end end
return self._SCROLLBAR_BOX return self._SCROLLBAR_BOX

View File

@@ -26,6 +26,7 @@ local event = require("ltui/event")
local action = require("ltui/action") local action = require("ltui/action")
local curses = require("ltui/curses") local curses = require("ltui/curses")
local window = require("ltui/window") local window = require("ltui/window")
local scrollbar = require("ltui/scrollbar")
local menuconf = require("ltui/menuconf") local menuconf = require("ltui/menuconf")
local boxdialog = require("ltui/boxdialog") local boxdialog = require("ltui/boxdialog")
local textdialog = require("ltui/textdialog") local textdialog = require("ltui/textdialog")
@@ -54,6 +55,9 @@ Pressing <Y> includes, <N> excludes. Enter <Esc> or <Back> to go back, <?> for H
self:button_add("save", "< Save >", function (v, e) self:action_on(action.ac_on_save) end) self:button_add("save", "< Save >", function (v, e) self:action_on(action.ac_on_save) end)
self:buttons():select(self:button("select")) self:buttons():select(self:button("select"))
-- insert scrollbar
self:box():panel():insert(self:scrollbar_menuconf())
-- insert menu config -- insert menu config
self:box():panel():insert(self:menuconf()) self:box():panel():insert(self:menuconf())
self:box():panel():action_add(action.ac_on_resized, function (v) self:box():panel():action_add(action.ac_on_resized, function (v)
@@ -64,6 +68,17 @@ Pressing <Y> includes, <N> excludes. Enter <Esc> or <Back> to go back, <?> for H
-- disable to select to box (disable Tab switch and only response to buttons) -- disable to select to box (disable Tab switch and only response to buttons)
self:box():option_set("selectable", false) self:box():option_set("selectable", false)
-- on resize for panel
self:box():panel():action_add(action.ac_on_resized, function (v)
self:menuconf():bounds_set(rect:new(0, 0, v:width() - 1, v:height()))
self:scrollbar_menuconf():bounds_set(rect:new(v:width() - 1, 0, 1, v:height()))
if self:menuconf():scrollable() then
self:scrollbar_menuconf():show(true)
else
self:scrollbar_menuconf():show(false)
end
end)
-- on selected -- on selected
self:menuconf():action_set(action.ac_on_selected, function (v, config) self:menuconf():action_set(action.ac_on_selected, function (v, config)
@@ -94,6 +109,22 @@ Pressing <Y> includes, <N> excludes. Enter <Esc> or <Back> to go back, <?> for H
return true return true
end end
end) end)
-- show scrollbar?
self:menuconf():action_add(action.ac_on_load, function (v)
if v:scrollable() then
self:scrollbar_menuconf():show(true)
else
self:scrollbar_menuconf():show(false)
end
end)
-- on scroll
self:menuconf():action_add(action.ac_on_scrolled, function (v, progress)
if self:scrollbar_menuconf():state("visible") then
self:scrollbar_menuconf():progress_set(progress)
end
end)
end end
-- load configs -- load configs
@@ -111,12 +142,22 @@ end
function mconfdialog:menuconf() function mconfdialog:menuconf()
if not self._MENUCONF then if not self._MENUCONF then
local bounds = self:box():panel():bounds() local bounds = self:box():panel():bounds()
self._MENUCONF = menuconf:new("mconfdialog.menuconf", rect:new(0, 0, bounds:width(), bounds:height())) self._MENUCONF = menuconf:new("mconfdialog.menuconf", rect:new(0, 0, bounds:width() - 1, bounds:height()))
self._MENUCONF:state_set("focused", true) -- we can select and highlight selected item self._MENUCONF:state_set("focused", true) -- we can select and highlight selected item
end end
return self._MENUCONF return self._MENUCONF
end end
-- get menu scrollbar
function mconfdialog:scrollbar_menuconf()
if not self._SCROLLBAR_MENUCONF then
local bounds = self:box():panel():bounds()
self._SCROLLBAR_MENUCONF = scrollbar:new("mconfdialog.scrollbar", rect:new(bounds:width() - 1, 0, 1, bounds:height()))
self._SCROLLBAR_MENUCONF:show(false)
end
return self._SCROLLBAR_MENUCONF
end
-- get help dialog -- get help dialog
function mconfdialog:helpdialog() function mconfdialog:helpdialog()
if not self._HELPDIALOG then if not self._HELPDIALOG then

View File

@@ -40,18 +40,132 @@ function menuconf:init(name, bounds)
-- init configs -- init configs
self._CONFIGS = {} self._CONFIGS = {}
-- init items
self._ITEMS = {}
-- init start index
self._STARTINDEX = 1
-- on resize for panel
self:action_add(action.ac_on_resized, function (v)
local items = self:_items()
local totalcount = #items
local startindex = self._STARTINDEX
self:clear()
for idx = startindex, startindex + self:height() do
local item = items[idx]
if item then
item:bounds():move2(0, idx - startindex)
self:insert(item)
else
break
end
end
self:select(self:first())
self:invalidate()
end)
end
-- load configs
function menuconf:load(configs)
-- clear the views first
self:clear()
-- detach the previous config and view
local configs_prev = self._CONFIGS._PREV
if configs_prev then
for _, config in ipairs(configs_prev) do
config._view = nil
end
end
-- save configs
self._CONFIGS = configs
-- load items
local items = {}
for idx, config in ipairs(configs) do
table.insert(items, self:_load_item(config, idx))
end
self._ITEMS = items
-- insert top-n items
local startindex = self._STARTINDEX
for idx = startindex, startindex + self:height() do
local item = items[idx]
if item then
self:insert(item)
else
break
end
end
-- select the first item
self:select(self:first())
-- on loaded
self:action_on(action.ac_on_load)
-- invalidate
self:invalidate()
end
-- is scrollable?
function menuconf:scrollable()
return #self:_items() > self:height()
end
-- scroll
function menuconf:scroll(count)
if self:scrollable() then
local items = self:_items()
local totalcount = #items
local startindex = self._STARTINDEX + count
if startindex > totalcount then
return
elseif startindex < 1 then
startindex = 1
end
self._STARTINDEX = startindex
self:clear()
for idx = startindex, startindex + self:height() do
local item = items[idx]
if item then
item:bounds():move2(0, idx - startindex)
self:insert(item)
else
break
end
end
if count > 0 then
self:select(self:first())
else
self:select(self:last())
end
self:invalidate()
end
end end
-- on event -- on event
function menuconf:on_event(e) function menuconf:on_event(e)
-- select config
local back = false local back = false
if e.type == event.ev_keyboard then if e.type == event.ev_keyboard then
if e.key_name == "Down" then if e.key_name == "Down" then
return self:select_next() if self:current() == self:last() then
self:scroll(self:height())
end
self:select_next()
self:_notify_scrolled()
return true
elseif e.key_name == "Up" then elseif e.key_name == "Up" then
return self:select_prev() if self:current() == self:first() then
self:scroll(-self:height())
end
self:select_prev()
self:_notify_scrolled()
return true
elseif e.key_name == "Enter" or e.key_name == " " then elseif e.key_name == "Enter" or e.key_name == " " then
self:_do_select() self:_do_select()
return true return true
@@ -85,54 +199,36 @@ function menuconf:on_event(e)
end end
end end
-- load configs -- load a config item
function menuconf:load(configs) function menuconf:_load_item(config, index)
-- clear the views first
self:clear()
-- detach the previous config and view
local configs_prev = self._CONFIGS._PREV
if configs_prev then
for _, config in ipairs(configs_prev) do
config._view = nil
end
end
-- insert configs
self._CONFIGS = configs
for _, config in ipairs(configs) do
if self:count() < self:height() then
self:_do_insert(config)
end
end
-- select the first item
self:select(self:first())
-- invalidate
self:invalidate()
end
-- do insert a config item
function menuconf:_do_insert(config)
-- init a config item view -- init a config item view
local item = button:new("menuconf.config." .. self:count(), local item = button:new("menuconf.config." .. index,
rect:new(0, self:count(), self:width(), 1), rect:new(0, index - 1, self:width(), 1),
tostring(config), tostring(config),
function (v, e) function (v, e)
self:_do_select() self:_do_select()
end) end)
-- attach this config -- attach this index and config
item:extra_set("index", index)
item:extra_set("config", config) item:extra_set("config", config)
-- attach this view -- attach this view
config._view = item config._view = item
return item
end
-- insert this config item -- notify scrolled
self:insert(item) function menuconf:_notify_scrolled()
local totalcount = #self:_items()
local startindex = self:current():extra("index")
self:action_on(action.ac_on_scrolled, startindex / totalcount)
end
-- get all items
function menuconf:_items()
return self._ITEMS
end end
-- do select the current config -- do select the current config

View File

@@ -60,7 +60,7 @@ function textdialog:init(name, bounds, title)
end) end)
-- show scrollbar? -- show scrollbar?
self:text():action_set(action.ac_on_text_changed, function (v) self:text():action_add(action.ac_on_text_changed, function (v)
if self:option("scrollable") then if self:option("scrollable") then
if v:scrollable() then if v:scrollable() then
self:scrollbar():show(true) self:scrollbar():show(true)
@@ -71,7 +71,7 @@ function textdialog:init(name, bounds, title)
end) end)
-- on scroll for text and scrollbar -- on scroll for text and scrollbar
self:text():action_set(action.ac_on_scrolled, function (v, progress) self:text():action_add(action.ac_on_scrolled, function (v, progress)
if self:scrollbar():state("visible") then if self:scrollbar():state("visible") then
self:scrollbar():progress_set(progress) self:scrollbar():progress_set(progress)
end end