summaryrefslogtreecommitdiff
path: root/xmake/core/ui/choicebox.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2020-11-29 22:36:04 +0800
committerruki <[email protected]>2020-11-29 22:36:04 +0800
commite4058387bfd67c02aa0e065705655b1e4b0aafbf (patch)
treed2dfd95343e3161a9e4dc55691e37abbca69b430 /xmake/core/ui/choicebox.lua
parentd48118e840fc0be69f3d78a3894e4bf76b8d801b (diff)
support scrollbar
Diffstat (limited to 'xmake/core/ui/choicebox.lua')
-rw-r--r--xmake/core/ui/choicebox.lua173
1 files changed, 132 insertions, 41 deletions
diff --git a/xmake/core/ui/choicebox.lua b/xmake/core/ui/choicebox.lua
index 1dd84159a..da39dc00c 100644
--- a/xmake/core/ui/choicebox.lua
+++ b/xmake/core/ui/choicebox.lua
@@ -38,27 +38,11 @@ function choicebox:init(name, bounds)
-- init panel
panel.init(self, name, bounds)
- -- init values
- self._VALUES = {}
-end
-
--- on event
-function choicebox:on_event(e)
+ -- init items
+ self._ITEMS = {}
- -- select config
- if e.type == event.ev_keyboard then
- if e.key_name == "Down" then
- return self:select_next()
- elseif e.key_name == "Up" then
- return self:select_prev()
- elseif e.key_name == "Enter" or e.key_name == " " then
- self:_do_select()
- return true
- end
- elseif e.type == event.ev_command and e.command == "cm_enter" then
- self:_do_select()
- return true
- end
+ -- init start index
+ self._STARTINDEX = 1
end
-- load values
@@ -67,38 +51,152 @@ function choicebox:load(values, selected)
-- clear the views first
self:clear()
- -- insert values
- self._VALUES = values
+ -- load items
+ local items = {}
for idx, value in ipairs(values) do
- self:_do_insert(value, idx, idx == selected)
+ 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() - 1 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
--- do insert a value item
-function choicebox:_do_insert(value, index, selected)
+-- 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() - 1 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 resize
+function choicebox:on_resize()
+ local items = self:_items()
+ local totalcount = #items
+ local startindex = self._STARTINDEX
+ for idx = 1, totalcount do
+ local item = items[idx]
+ if item then
+ if idx >= startindex and idx < startindex + self:height() then
+ if not self:view(item:name()) then
+ item:bounds():move2(0, idx - startindex)
+ self:insert(item)
+ end
+ else
+ if self:view(item:name()) then
+ self:remove(item)
+ end
+ end
+ end
+ end
+ panel.on_resize(self)
+end
+
+-- on event
+function choicebox:on_event(e)
+ if e.type == event.ev_keyboard then
+ if e.key_name == "Down" then
+ if self:current() == self:last() then
+ self:scroll(self:height())
+ else
+ self:select_next()
+ end
+ self:_notify_scrolled()
+ return true
+ elseif e.key_name == "Up" then
+ if self:current() == self:first() then
+ self:scroll(-self:height())
+ else
+ self:select_prev()
+ end
+ self:_notify_scrolled()
+ return true
+ elseif e.key_name == "Enter" or e.key_name == " " then
+ self:_do_select()
+ return true
+ end
+ elseif e.type == event.ev_command and e.command == "cm_enter" then
+ self:_do_select()
+ return true
+ end
+end
+
+-- 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 +206,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