-
Notifications
You must be signed in to change notification settings - Fork 7
/
scrollBox.lua
98 lines (97 loc) · 4.54 KB
/
scrollBox.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
local PrimeUI = require "util" -- DO NOT COPY THIS LINE
local expect = require "cc.expect".expect -- DO NOT COPY THIS LINE
-- Start copying below this line. --
--- Creates a scrollable window, which allows drawing large content in a small area.
---@param win window The parent window of the scroll box
---@param x number The X position of the box
---@param y number The Y position of the box
---@param width number The width of the box
---@param height number The height of the outer box
---@param innerHeight number The height of the inner scroll area
---@param allowArrowKeys boolean|nil Whether to allow arrow keys to scroll the box (defaults to true)
---@param showScrollIndicators boolean|nil Whether to show arrow indicators on the right side when scrolling is available, which reduces the inner width by 1 (defaults to false)
---@param fgColor number|nil The color of scroll indicators (defaults to white)
---@param bgColor color|nil The color of the background (defaults to black)
---@return window inner The inner window to draw inside
---@return fun(pos:number) scroll A function to manually set the scroll position of the window
function PrimeUI.scrollBox(win, x, y, width, height, innerHeight, allowArrowKeys, showScrollIndicators, fgColor, bgColor)
expect(1, win, "table")
expect(2, x, "number")
expect(3, y, "number")
expect(4, width, "number")
expect(5, height, "number")
expect(6, innerHeight, "number")
expect(7, allowArrowKeys, "boolean", "nil")
expect(8, showScrollIndicators, "boolean", "nil")
fgColor = expect(9, fgColor, "number", "nil") or colors.white
bgColor = expect(10, bgColor, "number", "nil") or colors.black
if allowArrowKeys == nil then allowArrowKeys = true end
-- Create the outer container box.
local outer = window.create(win == term and term.current() or win, x, y, width, height)
outer.setBackgroundColor(bgColor)
outer.clear()
-- Create the inner scrolling box.
local inner = window.create(outer, 1, 1, width - (showScrollIndicators and 1 or 0), innerHeight)
inner.setBackgroundColor(bgColor)
inner.clear()
-- Draw scroll indicators if desired.
if showScrollIndicators then
outer.setBackgroundColor(bgColor)
outer.setTextColor(fgColor)
outer.setCursorPos(width, height)
outer.write(innerHeight > height and "\31" or " ")
end
-- Get the absolute position of the window.
x, y = PrimeUI.getWindowPos(win, x, y)
-- Add the scroll handler.
local scrollPos = 1
PrimeUI.addTask(function()
while true do
-- Wait for next event.
local ev = table.pack(os.pullEvent())
-- Update inner height in case it changed.
innerHeight = select(2, inner.getSize())
-- Check for scroll events and set direction.
local dir
if ev[1] == "key" and allowArrowKeys then
if ev[2] == keys.up then dir = -1
elseif ev[2] == keys.down then dir = 1 end
elseif ev[1] == "mouse_scroll" and ev[3] >= x and ev[3] < x + width and ev[4] >= y and ev[4] < y + height then
dir = ev[2]
end
-- If there's a scroll event, move the window vertically.
if dir and (scrollPos + dir >= 1 and scrollPos + dir <= innerHeight - height) then
scrollPos = scrollPos + dir
inner.reposition(1, 2 - scrollPos)
end
-- Redraw scroll indicators if desired.
if showScrollIndicators then
outer.setBackgroundColor(bgColor)
outer.setTextColor(fgColor)
outer.setCursorPos(width, 1)
outer.write(scrollPos > 1 and "\30" or " ")
outer.setCursorPos(width, height)
outer.write(scrollPos < innerHeight - height and "\31" or " ")
end
end
end)
-- Make a function to allow external scrolling.
local function scroll(pos)
expect(1, pos, "number")
pos = math.floor(pos)
expect.range(pos, 1, innerHeight - height)
-- Scroll the window.
scrollPos = pos
inner.reposition(1, 2 - scrollPos)
-- Redraw scroll indicators if desired.
if showScrollIndicators then
outer.setBackgroundColor(bgColor)
outer.setTextColor(fgColor)
outer.setCursorPos(width, 1)
outer.write(scrollPos > 1 and "\30" or " ")
outer.setCursorPos(width, height)
outer.write(scrollPos < innerHeight - height and "\31" or " ")
end
end
return inner, scroll
end