add scrollbar
This commit is contained in:
@@ -42,6 +42,7 @@ action:register("ac_max",
|
|||||||
"ac_on_selected",
|
"ac_on_selected",
|
||||||
"ac_on_clicked",
|
"ac_on_clicked",
|
||||||
"ac_on_resized",
|
"ac_on_resized",
|
||||||
|
"ac_on_scrolled",
|
||||||
"ac_on_enter",
|
"ac_on_enter",
|
||||||
"ac_on_load",
|
"ac_on_load",
|
||||||
"ac_on_save",
|
"ac_on_save",
|
||||||
|
@@ -40,7 +40,7 @@ function boxdialog:init(name, bounds, title)
|
|||||||
self:text():bounds().ey = self._TEXT_EY
|
self:text():bounds().ey = self._TEXT_EY
|
||||||
self:text():invalidate(true)
|
self:text():invalidate(true)
|
||||||
self:text():option_set("selectable", false)
|
self:text():option_set("selectable", false)
|
||||||
self:text():option_set("progress", false)
|
self:text():option_set("scrollable", false)
|
||||||
|
|
||||||
-- insert box
|
-- insert box
|
||||||
self:panel():insert(self:box())
|
self:panel():insert(self:box())
|
||||||
|
@@ -45,7 +45,7 @@ function inputdialog:init(name, bounds, title)
|
|||||||
self:text():bounds().ey = 1
|
self:text():bounds().ey = 1
|
||||||
self:text():invalidate(true)
|
self:text():invalidate(true)
|
||||||
self:text():option_set("selectable", false)
|
self:text():option_set("selectable", false)
|
||||||
self:text():option_set("progress", false)
|
self:text():option_set("scrollable", false)
|
||||||
|
|
||||||
-- text changed
|
-- text changed
|
||||||
self:text():action_set(action.ac_on_text_changed, function (v)
|
self:text():action_set(action.ac_on_text_changed, function (v)
|
||||||
|
211
src/ltui/scrollbar.lua
Normal file
211
src/ltui/scrollbar.lua
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
---A cross-platform terminal ui library based on Lua
|
||||||
|
--
|
||||||
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
-- you may not use this file except in compliance with the License.
|
||||||
|
-- You may obtain a copy of the License at
|
||||||
|
--
|
||||||
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
--
|
||||||
|
-- Unless required by applicable law or agreed to in writing, software
|
||||||
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
-- See the License for the specific language governing permissions and
|
||||||
|
-- limitations under the License.
|
||||||
|
--
|
||||||
|
-- Copyright (C) 2015-2020, TBOOX Open Source Group.
|
||||||
|
--
|
||||||
|
-- @author ruki
|
||||||
|
-- @file scrollbar.lua
|
||||||
|
--
|
||||||
|
|
||||||
|
-- load modules
|
||||||
|
local log = require("ltui/base/log")
|
||||||
|
local view = require("ltui/view")
|
||||||
|
local event = require("ltui/event")
|
||||||
|
local curses = require("ltui/curses")
|
||||||
|
local action = require("ltui/action")
|
||||||
|
|
||||||
|
-- define module
|
||||||
|
local scrollbar = scrollbar or view()
|
||||||
|
|
||||||
|
-- init scrollbar
|
||||||
|
function scrollbar:init(name, bounds, vertical)
|
||||||
|
|
||||||
|
-- init view
|
||||||
|
view.init(self, name, bounds)
|
||||||
|
|
||||||
|
-- init bar attribute
|
||||||
|
self:charattr_set("black")
|
||||||
|
|
||||||
|
-- init bar vertical
|
||||||
|
self:vertical_set(vertical)
|
||||||
|
|
||||||
|
-- init progress
|
||||||
|
self:progress_set(0)
|
||||||
|
|
||||||
|
-- init character
|
||||||
|
self:char_set(' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get bar attribute
|
||||||
|
function scrollbar:charattr()
|
||||||
|
return self:attr("charattr")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set bar attribute, .e.g charattr_set("yellow onblue bold")
|
||||||
|
function scrollbar:charattr_set(attr)
|
||||||
|
return self:attr_set("charattr", attr)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get the current char attribute value
|
||||||
|
function scrollbar:charattr_val()
|
||||||
|
|
||||||
|
-- get text attribute
|
||||||
|
local charattr = self:charattr()
|
||||||
|
if not charattr then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- no text background? use view's background
|
||||||
|
if self:background() and not charattr:find("on") then
|
||||||
|
charattr = charattr .. " on" .. self:background()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- attempt to get the attribute value from the cache first
|
||||||
|
self._charattr = self._charattr or {}
|
||||||
|
local value = self._charattr[charattr]
|
||||||
|
if value then
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
-- update the cache
|
||||||
|
value = curses.calc_attr(charattr:split("%s+"))
|
||||||
|
self._charattr[charattr] = value
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get bar character
|
||||||
|
function scrollbar:char()
|
||||||
|
return self:attr("char") or ' '
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set bar character
|
||||||
|
function scrollbar:char_set(char)
|
||||||
|
if char ~= self:char() then
|
||||||
|
self:invalidate()
|
||||||
|
end
|
||||||
|
return self:attr_set("char", char)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- is vertical bar?
|
||||||
|
function scrollbar:vertical()
|
||||||
|
return self:attr("vertical") or true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set bar vertical
|
||||||
|
function scrollbar:vertical_set(vertical)
|
||||||
|
return self:attr_set("vertical", vertical)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get bar progress
|
||||||
|
function scrollbar:progress()
|
||||||
|
return self:attr("progress") or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set bar progress, [0, 1]
|
||||||
|
function scrollbar:progress_set(progress)
|
||||||
|
if progress > 1 then
|
||||||
|
progress = 1
|
||||||
|
elseif progress < 0 then
|
||||||
|
progress = 0
|
||||||
|
end
|
||||||
|
if progress ~= self:progress() then
|
||||||
|
self:invalidate()
|
||||||
|
end
|
||||||
|
return self:attr_set("progress", progress)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- get bar step width
|
||||||
|
function scrollbar:stepwidth()
|
||||||
|
return self:attr("stepwidth") or 0.1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- set bar step width, [0, 1]
|
||||||
|
function scrollbar:stepwidth_set(stepwidth)
|
||||||
|
if stepwidth > 1 then
|
||||||
|
stepwidth = 1
|
||||||
|
elseif stepwidth < 0 then
|
||||||
|
stepwidth = 0
|
||||||
|
end
|
||||||
|
if stepwidth ~= self:stepwidth() then
|
||||||
|
self:invalidate()
|
||||||
|
end
|
||||||
|
return self:attr_set("stepwidth", stepwidth)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- draw scrollbar
|
||||||
|
function scrollbar:on_draw(transparent)
|
||||||
|
|
||||||
|
-- draw background
|
||||||
|
view.on_draw(self, transparent)
|
||||||
|
|
||||||
|
-- compute bar range
|
||||||
|
local char = self:char()
|
||||||
|
local charattr = self:charattr_val()
|
||||||
|
local progress = self:progress()
|
||||||
|
local stepwidth = self:stepwidth()
|
||||||
|
local pb = progress
|
||||||
|
local pe = progress + stepwidth
|
||||||
|
if pe > 1 then
|
||||||
|
pb = 1 - stepwidth
|
||||||
|
pe = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
-- draw bar
|
||||||
|
if self:vertical() then
|
||||||
|
local sb = math.floor(self:height() * pb)
|
||||||
|
local se = math.ceil(self:height() * pe)
|
||||||
|
if se > sb and se - sb < self:height() then
|
||||||
|
self:canvas():attr(charattr):move(0, sb):putchar(char, se - sb, true)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local sb = math.floor(self:width() * pb)
|
||||||
|
local se = math.ceil(self:width() * pe)
|
||||||
|
if se > sb and se - sb < self:width() then
|
||||||
|
self:canvas():attr(charattr):move(sb, 0):putchar(char, se - sb)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- scroll bar, e.g. -1 * 0.1, 1 * 0.1
|
||||||
|
function scrollbar:scroll(steps)
|
||||||
|
steps = steps or 1
|
||||||
|
self:progress_set(self:progress() + steps * self:stepwidth())
|
||||||
|
self:action_on(action.ac_on_scrolled, self:progress())
|
||||||
|
end
|
||||||
|
|
||||||
|
-- on event
|
||||||
|
function scrollbar:on_event(e)
|
||||||
|
if e.type == event.ev_keyboard then
|
||||||
|
if self:vertical() then
|
||||||
|
if e.key_name == "Up" then
|
||||||
|
self:scroll(-1)
|
||||||
|
return true
|
||||||
|
elseif e.key_name == "Down" then
|
||||||
|
self:scroll(1)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if e.key_name == "Left" then
|
||||||
|
self:scroll(-1)
|
||||||
|
return true
|
||||||
|
elseif e.key_name == "Right" then
|
||||||
|
self:scroll(1)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- return module
|
||||||
|
return scrollbar
|
@@ -24,6 +24,8 @@ local view = require("ltui/view")
|
|||||||
local label = require("ltui/label")
|
local label = require("ltui/label")
|
||||||
local event = require("ltui/event")
|
local event = require("ltui/event")
|
||||||
local curses = require("ltui/curses")
|
local curses = require("ltui/curses")
|
||||||
|
local action = require("ltui/action")
|
||||||
|
local scrollbar = require("ltui/scrollbar")
|
||||||
|
|
||||||
-- define module
|
-- define module
|
||||||
local textarea = textarea or label()
|
local textarea = textarea or label()
|
||||||
@@ -37,8 +39,8 @@ function textarea:init(name, bounds, text)
|
|||||||
-- mark as selectable
|
-- mark as selectable
|
||||||
self:option_set("selectable", true)
|
self:option_set("selectable", true)
|
||||||
|
|
||||||
-- enable progress
|
-- mark as scrollable
|
||||||
self:option_set("progress", true)
|
self:option_set("scrollable", true)
|
||||||
|
|
||||||
-- init start line
|
-- init start line
|
||||||
self._STARTLINE = 0
|
self._STARTLINE = 0
|
||||||
@@ -60,8 +62,8 @@ function textarea:on_draw(transparent)
|
|||||||
self:canvas():attr(textattr):move(0, 0):putstrs(strs, self._STARTLINE + 1)
|
self:canvas():attr(textattr):move(0, 0):putstrs(strs, self._STARTLINE + 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- draw progress
|
-- draw scrollable
|
||||||
if self:option("progress") then
|
if self:option("scrollable") then
|
||||||
local tb = self._STARTLINE
|
local tb = self._STARTLINE
|
||||||
local fator = self:height() / self._LINECOUNT
|
local fator = self:height() / self._LINECOUNT
|
||||||
local sb = math.min(math.floor(tb * fator), self:height() - 1)
|
local sb = math.min(math.floor(tb * fator), self:height() - 1)
|
||||||
|
@@ -47,8 +47,8 @@ function textedit:init(name, bounds, text)
|
|||||||
self:option_set("mouseable", true)
|
self:option_set("mouseable", true)
|
||||||
self:action_set(action.ac_on_clicked, function () return true end)
|
self:action_set(action.ac_on_clicked, function () return true end)
|
||||||
|
|
||||||
-- disable progress
|
-- disable scrollbar
|
||||||
self:option_set("progress", false)
|
self:option_set("scrollable", false)
|
||||||
|
|
||||||
-- enable multiple line
|
-- enable multiple line
|
||||||
self:option_set("multiline", true)
|
self:option_set("multiline", true)
|
||||||
|
Reference in New Issue
Block a user