summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/include_lua/print.lua
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lua/include_lua/print.lua')
-rw-r--r--apps/plugins/lua/include_lua/print.lua377
1 files changed, 377 insertions, 0 deletions
diff --git a/apps/plugins/lua/include_lua/print.lua b/apps/plugins/lua/include_lua/print.lua
new file mode 100644
index 0000000000..0e9be373d8
--- /dev/null
+++ b/apps/plugins/lua/include_lua/print.lua
@@ -0,0 +1,377 @@
1--[[ Lua Print functions
2/***************************************************************************
3 * __________ __ ___.
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
8 * \/ \/ \/ \/ \/
9 * $Id$
10 *
11 * Copyright (C) 2017 William Wilgus
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22]]
23
24--[[ Exposed Functions
25
26 _print.clear
27 _print.f
28 _print.opt
29 _print.opt.area
30 _print.opt.autoupdate
31 _print.opt.color
32 _print.opt.column
33 _print.opt.defaults
34 _print.opt.get
35 _print.opt.justify
36 _print.opt.line
37 _print.opt.overflow
38 _print.opt.sel_line
39 _print.opt.set
40
41]]
42
43if not rb.lcd_framebuffer then rb.splash(rb.HZ, "No Support!") return nil end
44
45local _print = {} do
46
47 -- internal constants
48 local _clr = require("color") -- _clr functions required
49
50 local _NIL = nil -- _NIL placeholder
51 local _LCD = rb.lcd_framebuffer()
52 local LCD_W, LCD_H = rb.LCD_WIDTH, rb.LCD_HEIGHT
53 local WHITE = _clr.set(-1, 255, 255, 255)
54 local BLACK = _clr.set(0, 0, 0, 0)
55 local DRMODE_SOLID = 3
56 local col_buf, s_lines = {}, {}
57 local _p_opts = _NIL
58
59-- print internal helper functions
60--------------------------------------------------------------------------------
61 -- clamps value to >= min and <= max
62 local function clamp(val, min, max)
63 -- Warning doesn't check if min < max
64 if val < min then
65 return min
66 elseif val < max then
67 return val
68 end
69 return max
70 end
71
72 -- updates screen in specified rectangle
73 local function update_rect(x, y, w, h)
74 rb.lcd_update_rect(x - 1, y - 1,
75 clamp(x + w, 1, LCD_W) - 1,
76 clamp(y + h, 1, LCD_H) - 1)
77 end
78
79 -- Gets size of text
80 local function text_extent(msg, font)
81 font = font or rb.FONT_UI
82 -- res, w, h
83 return rb.font_getstringsize(msg, font)
84 end
85
86 -- Sets viewport size
87 local function set_viewport(vp)
88 if not vp then rb.set_viewport() return end
89
90 if rb.LCD_DEPTH == 2 then -- invert 2-bit screens
91 --vp.drawmode = bit.bxor(vp.drawmode, 4)
92 vp.fg_pattern = 3 - vp.fg_pattern
93 vp.bg_pattern = 3 - vp.bg_pattern
94 end
95 rb.set_viewport(vp)
96 end
97
98 -- shallow copy of table
99 function table_clone(t)
100 local copy = {}
101 for k, v in pairs(t) do
102 copy[k] = v
103 end
104 return copy
105 end
106
107 -- Updates a single line on the screen
108 local function update_line(enabled, opts, line, h)
109 if enabled ~= true then return end
110 local o = opts or _p_opts
111 update_rect(o.x, o.y + line * h + 1, o.width, h)
112 end
113
114 -- Clears a single line on the screen
115 local function clear_line(opts, line, h)
116 local o = opts or _p_opts
117 _LCD:clear(o.bg_pattern, o.x, o.y + line * h + 1,
118 o.x + o.width, line * h + h + o.y)
119 end
120
121 -- Sets the maximum number of lines on the screen
122 local function max_lines(opts)
123 local h = opts.height
124 local _, _, th = text_extent("W", opts.font)
125 return h / th
126 end
127
128 --saves the items displayed for side to side scroll
129 local function col_buf_insert(msg, line, _p_opts)
130 --if _p_opts.line <= 1 then col_buf = {} end
131 if not col_buf[line] then
132 table.insert(col_buf, line, msg) end
133 end
134
135 --replaces / strips escape characters
136 local function check_escapes(o, msg)
137 local tabsz = 2
138 local tabstr = string.rep(" ", tabsz)
139
140 local function repl(esc)
141 local ret = ""
142 if esc:sub(1,1) == "\t" then ret = string.rep(tabstr, esc:len()) end
143 return ret
144 end
145
146 msg = msg:gsub("(%c+)", repl)
147
148 local res, w, h = text_extent(msg, o.font)
149 return w, h, msg
150 end
151--------------------------------------------------------------------------------
152
153 -- set defaults for print view
154 local function set_defaults()
155 _p_opts = { x = 1,
156 y = 1,
157 width = LCD_W - 1,
158 height = LCD_H - 1,
159 font = rb.FONT_UI,
160 drawmode = DRMODE_SOLID,
161 fg_pattern = WHITE,
162 bg_pattern = BLACK,
163 sel_pattern = WHITE,
164 line = 1,
165 max_line = _NIL,
166 col = 0,
167 ovfl = "auto",
168 justify = "left",
169 autoupdate = true,
170 }
171 _p_opts.max_line = max_lines(_p_opts)
172
173 s_lines, col_buf = {}, {}
174 return _p_opts
175 end
176
177 -- returns table with settings for print
178 -- if bByRef is _NIL or false then a copy is returned
179 local function get_settings(bByRef)
180 _p_opts = _p_opts or set_defaults()
181 if not bByRef then return table_clone(_p_opts) end
182 return _p_opts
183 end
184
185 -- sets the settings for print with your passed table
186 local function set_settings(t_opts)
187 _p_opts = t_opts or set_defaults()
188 if t_opts then
189 _p_opts.max_line = max_lines(_p_opts)
190 col_buf = {}
191 end
192 end
193
194 -- sets colors for print
195 local function set_color(fgclr, bgclr, selclr)
196 local o = get_settings(true)
197
198 if fgclr ~= _NIL then
199 o.fg_pattern, o.sel_pattern = fgclr, fgclr
200 end
201 o.sel_pattern = selclr or o.sel_pattern
202 o.bg_pattern = bgclr or o.bg_pattern
203 end
204
205 -- helper function sets up colors/marker for selected items
206 local function show_selected(iLine, msg)
207 local o = get_settings() -- using a copy of opts so changes revert
208
209 if s_lines[iLine] == true then
210 if not rb.lcd_set_background then
211 o.drawmode = bit.bxor(o.drawmode, 4)
212 else
213 o.fg_pattern = o.bg_pattern
214 o.bg_pattern = o.sel_pattern
215 end
216 -- alternative selection method
217 --msg = "> " .. msg
218 end
219 set_viewport(o)
220 o = _NIL
221 end
222
223 -- sets line explicitly or increments line if line is _NIL
224 local function set_line(iLine)
225 local o = get_settings(true)
226
227 o.line = iLine or o.line + 1
228
229 if(o.line < 1 or o.line > o.max_line) then
230 o.line = 1
231 end
232 end
233
234 -- clears the set print area
235 local function clear()
236 local o = get_settings(true)
237 _LCD:clear(o.bg_pattern, o.x, o.y, o.x + o.width, o.y + o.height)
238 if o.autoupdate == true then rb.lcd_update() end
239 set_line(1)
240 for i=1, #col_buf do col_buf[i] = _NIL end
241 s_lines = {}
242 collectgarbage("collect")
243 end
244
245 -- screen update after each call to print.f
246 local function set_update(bAutoUpdate)
247 local o = get_settings(true)
248 o.autoupdate = bAutoUpdate or false
249 end
250
251 -- sets print area
252 local function set_area(x, y, w, h)
253 local o = get_settings(true)
254 o.x, o.y = clamp(x, 1, LCD_W), clamp(y, 1, LCD_H)
255 o.width, o.height = clamp(w, 1, LCD_W - o.x), clamp(h, 1, LCD_H - o.y)
256 o.max_line = max_lines(_p_opts)
257
258 clear()
259 return o.line, o.max_line
260 end
261
262 -- when string is longer than print width scroll -- "auto", "manual", "none"
263 local function set_overflow(str_mode)
264 -- "auto", "manual", "none"
265 local str_mode = str_mode or "auto"
266 local o = get_settings(true)
267 o.ovfl = str_mode:lower()
268 col_buf = {}
269 end
270
271 -- aligns text to: "left", "center", "right"
272 local function set_justify(str_mode)
273 -- "left", "center", "right"
274 local str_mode = str_mode or "left"
275 local o = get_settings(true)
276 o.justify = str_mode:lower()
277 end
278
279 -- selects line
280 local function select_line(iLine)
281 s_lines[iLine] = true
282 end
283
284 -- Internal print function
285 local function print_internal(t_opts, x, w, h, msg)
286
287 local o = t_opts
288 if o.justify == "center" then
289 x = x + (o.width - w) / 2
290 elseif o.justify == "right" then
291 x = x + (o.width - w)
292 end
293
294 local line = o.line - 1 -- rb is 0-based lua is 1-based
295 if(o.ovfl == "auto" and w >= o.width) then -- -o.x
296 rb.lcd_puts_scroll(0, line, msg)
297 else
298 rb.lcd_putsxy(x, line * h, msg)
299 if o.ovfl == "manual" then --save msg for later side scroll
300 col_buf_insert(msg, o.line, o)
301 end
302 end
303
304 --only update the line we changed
305 update_line(o.autoupdate, o, line, h)
306
307 set_line(_NIL) -- increments line counter
308 end
309
310 -- Helper function that acts mostly like a normal printf() would
311 local function printf(...)
312 local o = get_settings(true)
313 local w, h, msg
314 local line = o.line - 1 -- rb is 0-based lua is 1-based
315 if not (...) or (...) == "\n" then -- handles blank line / single '\n'
316 local res, w, h = text_extent(" ", o.font)
317
318 clear_line(o, line, h)
319 update_line(o.autoupdate, o, line, h)
320
321 if (...) then set_line(_NIL) end
322
323 return o.line, o.max_line, o.width, h
324 end
325
326 msg = string.format(...)
327
328 show_selected(o.line, msg)
329
330 w, h, msg = check_escapes(o, msg)
331
332 print_internal(o, o.col, w, h, msg)
333
334 return o.line, o.max_line, w, h
335 end
336
337 -- x > 0 scrolls right x < 0 scrolls left
338 local function set_column(x)
339 local o = get_settings()
340 if o.ovfl ~= "manual" then return end -- no buffer stored to scroll
341 local res, w, h, str, line
342
343 for key, value in pairs(col_buf) do
344 line = key - 1 -- rb is 0-based lua is 1-based
345 o.line = key
346
347 if value then
348 show_selected(key, value)
349 res, w, h = text_extent(value, o.font)
350 clear_line(o, line, h)
351
352 print_internal(o, x + o.col, w, h, value)
353 update_line(o.autoupdate, o, line, h)
354 end
355 end
356 o = _NIL
357 end
358
359 --expose functions to the outside through _print table
360 _print.opt = {}
361 _print.opt.column = set_column
362 _print.opt.color = set_color
363 _print.opt.area = set_area
364 _print.opt.set = set_settings
365 _print.opt.get = get_settings
366 _print.opt.defaults = set_defaults
367 _print.opt.overflow = set_overflow
368 _print.opt.justify = set_justify
369 _print.opt.sel_line = select_line
370 _print.opt.line = set_line
371 _print.opt.autoupdate = set_update
372 _print.clear = clear
373 _print.f = printf
374
375end --_print functions
376
377return _print