support scrollbar for choicedialog
This commit is contained in:
@@ -38,8 +38,81 @@ function choicebox:init(name, bounds)
|
||||
-- init panel
|
||||
panel.init(self, name, bounds)
|
||||
|
||||
-- init values
|
||||
self._VALUES = {}
|
||||
-- init items
|
||||
self._ITEMS = {}
|
||||
|
||||
-- init start index
|
||||
self._STARTINDEX = 1
|
||||
end
|
||||
|
||||
-- load values
|
||||
function choicebox:load(values, selected)
|
||||
|
||||
-- clear the views first
|
||||
self:clear()
|
||||
|
||||
-- load items
|
||||
local items = {}
|
||||
for idx, value in ipairs(values) do
|
||||
table.insert(items, self:_load_item(value, idx, idx == selected))
|
||||
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())
|
||||
|
||||
-- invalidate
|
||||
self:invalidate()
|
||||
|
||||
-- on loaded
|
||||
self:action_on(action.ac_on_load)
|
||||
end
|
||||
|
||||
-- is scrollable?
|
||||
function choicebox:scrollable()
|
||||
return #self:_items() > self:height()
|
||||
end
|
||||
|
||||
-- scroll
|
||||
function choicebox: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
|
||||
|
||||
-- on event
|
||||
@@ -48,9 +121,19 @@ function choicebox:on_event(e)
|
||||
-- select config
|
||||
if e.type == event.ev_keyboard 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
|
||||
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
|
||||
self:_do_select()
|
||||
return true
|
||||
@@ -61,44 +144,36 @@ function choicebox:on_event(e)
|
||||
end
|
||||
end
|
||||
|
||||
-- load values
|
||||
function choicebox:load(values, selected)
|
||||
|
||||
-- clear the views first
|
||||
self:clear()
|
||||
|
||||
-- insert values
|
||||
self._VALUES = values
|
||||
for idx, value in ipairs(values) do
|
||||
self:_do_insert(value, idx, idx == selected)
|
||||
end
|
||||
|
||||
-- select the first item
|
||||
self:select(self:first())
|
||||
|
||||
-- invalidate
|
||||
self:invalidate()
|
||||
end
|
||||
|
||||
-- do insert a value item
|
||||
function choicebox:_do_insert(value, index, selected)
|
||||
-- load a item with value
|
||||
function choicebox:_load_item(value, index, selected)
|
||||
|
||||
-- init text
|
||||
local text = (selected and "(X) " or "( ) ") .. tostring(value)
|
||||
|
||||
-- init a value item view
|
||||
local item = button:new("choicebox.value." .. self:count(),
|
||||
rect:new(0, self:count(), self:width(), 1),
|
||||
local item = button:new("choicebox.value." .. index,
|
||||
rect:new(0, index - 1, self:width(), 1),
|
||||
text,
|
||||
function (v, e)
|
||||
self:_do_select()
|
||||
end)
|
||||
|
||||
-- attach this index
|
||||
-- attach index and value
|
||||
item:extra_set("index", index)
|
||||
item:extra_set("value", value)
|
||||
return item
|
||||
end
|
||||
|
||||
-- insert this config item
|
||||
self:insert(item)
|
||||
-- notify scrolled
|
||||
function choicebox:_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 choicebox:_items()
|
||||
return self._ITEMS
|
||||
end
|
||||
|
||||
-- do select the current config
|
||||
@@ -108,24 +183,17 @@ function choicebox:_do_select()
|
||||
for v in self:views() do
|
||||
local text = v:text()
|
||||
if text and text:startswith("(X) ") then
|
||||
local i = v:extra("index")
|
||||
if i then
|
||||
local t = self._VALUES[i]
|
||||
v:text_set("( ) " .. tostring(t))
|
||||
end
|
||||
local t = v:extra("value")
|
||||
v:text_set("( ) " .. tostring(t))
|
||||
end
|
||||
end
|
||||
|
||||
-- get the current item
|
||||
local item = self:current()
|
||||
|
||||
-- get the current index
|
||||
local index = item:extra("index")
|
||||
|
||||
-- get the current value
|
||||
local value = self._VALUES[index]
|
||||
|
||||
-- do action: on selected
|
||||
local index = item:extra("index")
|
||||
local value = item:extra("value")
|
||||
self:action_on(action.ac_on_selected, index, value)
|
||||
|
||||
-- update text
|
||||
|
||||
@@ -25,6 +25,7 @@ local event = require("ltui/event")
|
||||
local action = require("ltui/action")
|
||||
local curses = require("ltui/curses")
|
||||
local window = require("ltui/window")
|
||||
local scrollbar = require("ltui/scrollbar")
|
||||
local choicebox = require("ltui/choicebox")
|
||||
local boxdialog = require("ltui/boxdialog")
|
||||
|
||||
@@ -50,23 +51,57 @@ function choicedialog:init(name, bounds, title)
|
||||
end)
|
||||
self:buttons():select(self:button("select"))
|
||||
|
||||
-- insert scrollbar
|
||||
self:box():panel():insert(self:scrollbar_box())
|
||||
|
||||
-- insert choice box
|
||||
self:box():panel():insert(self:choicebox())
|
||||
|
||||
-- disable to select to box (disable Tab switch and only response to buttons)
|
||||
self:box():option_set("selectable", false)
|
||||
|
||||
-- on resize for panel
|
||||
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:scrollbar_box():bounds_set(rect:new(v:width() - 1, 0, 1, v:height()))
|
||||
end)
|
||||
|
||||
-- show scrollbar?
|
||||
self:choicebox():action_set(action.ac_on_load, function (v)
|
||||
if v:scrollable() then
|
||||
self:scrollbar_box():show(true)
|
||||
else
|
||||
self:scrollbar_box():show(false)
|
||||
end
|
||||
end)
|
||||
|
||||
-- on scroll
|
||||
self:choicebox():action_set(action.ac_on_scrolled, function (v, progress)
|
||||
if self:scrollbar_box():state("visible") then
|
||||
self:scrollbar_box():progress_set(progress)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- get choice box
|
||||
function choicedialog:choicebox()
|
||||
if not self._CHOICEBOX then
|
||||
local bounds = self:box():panel():bounds()
|
||||
self._CHOICEBOX = choicebox:new("choicedialog.choicebox", rect:new(0, 0, bounds:width(), bounds:height()))
|
||||
self._CHOICEBOX = choicebox:new("choicedialog.choicebox", rect:new(0, 0, bounds:width() - 1, bounds:height()))
|
||||
self._CHOICEBOX:state_set("focused", true) -- we can select and highlight selected item
|
||||
end
|
||||
return self._CHOICEBOX
|
||||
end
|
||||
|
||||
-- get box scrollbar
|
||||
function choicedialog:scrollbar_box()
|
||||
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()))
|
||||
self._SCROLLBAR_BOX:show(false)
|
||||
end
|
||||
return self._SCROLLBAR_BOX
|
||||
end
|
||||
|
||||
-- on event
|
||||
function choicedialog:on_event(e)
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ function textarea:scroll(lines)
|
||||
if self._STARTLINE < 0 then
|
||||
self._STARTLINE = 0
|
||||
end
|
||||
local startline_end = self._LINECOUNT - self:height()
|
||||
local startline_end = self._LINECOUNT > self:height() and self._LINECOUNT - self:height() or self._LINECOUNT
|
||||
if self._STARTLINE > startline_end then
|
||||
self._STARTLINE = startline_end
|
||||
end
|
||||
@@ -91,7 +91,7 @@ end
|
||||
-- scroll to end
|
||||
function textarea:scroll_to_end()
|
||||
if self:scrollable() then
|
||||
local startline_end = self._LINECOUNT - self:height()
|
||||
local startline_end = self._LINECOUNT > self:height() and self._LINECOUNT - self:height() or self._LINECOUNT
|
||||
self._STARTLINE = startline_end
|
||||
self:action_on(action.ac_on_scrolled, self._STARTLINE / startline_end)
|
||||
self:invalidate()
|
||||
|
||||
@@ -72,7 +72,7 @@ function textdialog:init(name, bounds, title)
|
||||
|
||||
-- on scroll for text and scrollbar
|
||||
self:text():action_set(action.ac_on_scrolled, function (v, progress)
|
||||
if self:option("scrollable") then
|
||||
if self:scrollbar():state("visible") then
|
||||
self:scrollbar():progress_set(progress)
|
||||
end
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user