mirror of
https://github.com/MikaylaFischler/cc-mek-scada.git
synced 2024-08-30 18:22:34 +00:00
#184 initial draft of listbox element and associated supervisor front panel test example
This commit is contained in:
parent
4c35233289
commit
ef1ec220a4
@ -45,6 +45,7 @@ local element = {}
|
||||
---|colormap_args
|
||||
---|displaybox_args
|
||||
---|div_args
|
||||
---|listbox_args
|
||||
---|multipane_args
|
||||
---|pipenet_args
|
||||
---|rectangle_args
|
||||
@ -66,7 +67,6 @@ function element.new(args)
|
||||
define_completed = false,
|
||||
p_window = nil, ---@type table
|
||||
position = { x = 1, y = 1 }, ---@type coordinate_2d
|
||||
child_offset = { x = 0, y = 0 }, ---@type coordinate_2d
|
||||
bounds = { x1 = 1, y1 = 1, x2 = 1, y2 = 1 }, ---@class element_bounds
|
||||
next_y = 1,
|
||||
subscriptions = {},
|
||||
@ -112,7 +112,7 @@ function element.new(args)
|
||||
else
|
||||
local w, h = self.p_window.getSize()
|
||||
protected.frame.x = args.x or 1
|
||||
protected.frame.y = args.y or next_y
|
||||
protected.frame.y = args.y or next_y
|
||||
protected.frame.w = args.width or w
|
||||
protected.frame.h = args.height or h
|
||||
end
|
||||
|
190
graphics/elements/listbox.lua
Normal file
190
graphics/elements/listbox.lua
Normal file
@ -0,0 +1,190 @@
|
||||
-- Scroll-able List Box Display Graphics Element
|
||||
|
||||
-- local log = require("scada-common.log")
|
||||
|
||||
local core = require("graphics.core")
|
||||
local element = require("graphics.element")
|
||||
|
||||
local CLICK_TYPE = core.events.CLICK_TYPE
|
||||
|
||||
---@class listbox_args
|
||||
---@field scroll_height integer height of internal scrolling container (must fit all elements vertically tiled)
|
||||
---@field item_pad? integer spacing (lines) between items in the list (default 0)
|
||||
---@field parent graphics_element
|
||||
---@field id? string element id
|
||||
---@field x? integer 1 if omitted
|
||||
---@field y? integer 1 if omitted
|
||||
---@field width? integer parent width if omitted
|
||||
---@field height? integer parent height if omitted
|
||||
---@field gframe? graphics_frame frame instead of x/y/width/height
|
||||
---@field fg_bg? cpair foreground/background colors
|
||||
---@field hidden? boolean true to hide on initial draw
|
||||
|
||||
---@class listbox_item
|
||||
---@field id string|integer element ID
|
||||
---@field e graphics_element element
|
||||
---@field y integer y position
|
||||
---@field h integer element height
|
||||
|
||||
-- new listbox element
|
||||
---@nodiscard
|
||||
---@param args listbox_args
|
||||
---@return graphics_element element, element_id id
|
||||
local function listbox(args)
|
||||
-- create new graphics element base object
|
||||
local e = element.new(args)
|
||||
|
||||
-- create content window for child elements
|
||||
local scroll_frame = window.create(e.window, 1, 1, e.frame.w - 1, args.scroll_height, false)
|
||||
e.content_window = scroll_frame
|
||||
|
||||
-- item list and scroll management
|
||||
local list = {}
|
||||
local item_pad = args.item_pad or 0
|
||||
local scroll_offset = 0
|
||||
local content_height = 0
|
||||
local max_down_scroll = 0
|
||||
|
||||
-- bar control/tracking variables
|
||||
local bar_height = 0 -- full height of bar
|
||||
local bar_bounds = { 0, 0 } -- top and bottom of bar
|
||||
local holding_bar = false -- bar is being held by mouse
|
||||
local bar_grip_pos = 0 -- where the bar was gripped by mouse down
|
||||
local mouse_last_y = 0 -- last reported y coordinate of drag
|
||||
|
||||
-- draw up/down arrows
|
||||
e.window.setCursorPos(e.frame.w, 1)
|
||||
e.window.write("\x1e")
|
||||
e.window.setCursorPos(e.frame.w, e.frame.h)
|
||||
e.window.write("\x1f")
|
||||
|
||||
-- render the scroll bar and re-cacluate height & bounds
|
||||
local function draw_bar()
|
||||
local offset = 2 + math.abs(scroll_offset)
|
||||
|
||||
bar_height = math.max(math.min(e.frame.h - 2 + max_down_scroll, e.frame.h - 2), 1)
|
||||
bar_bounds = { offset, (bar_height + offset) - 1 }
|
||||
|
||||
for i = 2, e.frame.h - 1 do
|
||||
if i >= offset and i < (bar_height + offset) then
|
||||
e.window.setBackgroundColor(e.fg_bg.fgd)
|
||||
else
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
end
|
||||
|
||||
e.window.setCursorPos(e.frame.w, i)
|
||||
e.window.write(" ")
|
||||
end
|
||||
|
||||
e.window.setBackgroundColor(e.fg_bg.bkg)
|
||||
end
|
||||
|
||||
-- update item y positions and move elements
|
||||
local function update_positions()
|
||||
local next_y = 1
|
||||
|
||||
scroll_frame.setVisible(false)
|
||||
scroll_frame.setBackgroundColor(e.fg_bg.bkg)
|
||||
scroll_frame.setTextColor(e.fg_bg.fgd)
|
||||
scroll_frame.clear()
|
||||
|
||||
for i = 1, #list do
|
||||
local item = list[i] ---@type listbox_item
|
||||
item.y = next_y
|
||||
next_y = next_y + item.h + item_pad
|
||||
item.e.reposition(1, item.y)
|
||||
item.e.show()
|
||||
end
|
||||
|
||||
content_height = next_y
|
||||
max_down_scroll = math.min(-1 * (content_height - (e.frame.h + 1 + item_pad)), 0)
|
||||
if scroll_offset < max_down_scroll then scroll_offset = max_down_scroll end
|
||||
|
||||
scroll_frame.reposition(1, 1 + scroll_offset)
|
||||
scroll_frame.setVisible(true)
|
||||
|
||||
draw_bar()
|
||||
|
||||
-- log.info("content_height[" .. content_height .. "] max_down_scroll[" .. max_down_scroll .. "] scroll_offset[" .. scroll_offset .. "] bar_height[" .. bar_height .. "]")
|
||||
end
|
||||
|
||||
-- scroll down the list
|
||||
local function scroll_down()
|
||||
if scroll_offset > max_down_scroll then
|
||||
scroll_offset = scroll_offset - 1
|
||||
update_positions()
|
||||
end
|
||||
end
|
||||
|
||||
-- scroll up the list
|
||||
local function scroll_up()
|
||||
if scroll_offset < 0 then
|
||||
scroll_offset = scroll_offset + 1
|
||||
update_positions()
|
||||
end
|
||||
end
|
||||
|
||||
-- handle a child element having been added to the list
|
||||
---@param id string|integer element identifier
|
||||
---@param child graphics_element child element
|
||||
function e.on_added(id, child)
|
||||
table.insert(list, { id = id, e = child, y = 0, h = child.get_height() })
|
||||
update_positions()
|
||||
end
|
||||
|
||||
-- handle a child element having been removed from the list
|
||||
---@param id string|integer element identifier
|
||||
function e.on_removed(id)
|
||||
for idx, elem in ipairs(list) do
|
||||
if elem.id == id then
|
||||
table.remove(list, idx)
|
||||
update_positions()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- handle mouse interaction
|
||||
---@param event mouse_interaction mouse event
|
||||
function e.handle_mouse(event)
|
||||
if e.enabled then
|
||||
if event.type == CLICK_TYPE.TAP or event.type == CLICK_TYPE.DOWN then
|
||||
if event.current.x == e.frame.w then
|
||||
if event.current.y == 1 or event.current.y < bar_bounds[1] then
|
||||
scroll_up()
|
||||
elseif event.current.y == e.frame.h or event.current.y > bar_bounds[2] then
|
||||
scroll_down()
|
||||
else
|
||||
-- clicked on bar
|
||||
holding_bar = true
|
||||
bar_grip_pos = event.current.y - bar_bounds[1]
|
||||
mouse_last_y = event.current.y
|
||||
end
|
||||
end
|
||||
elseif event.type == CLICK_TYPE.UP then
|
||||
holding_bar = false
|
||||
elseif event.type == CLICK_TYPE.DRAG then
|
||||
if holding_bar then
|
||||
-- if mouse is within vertical frame, including the grip point
|
||||
if event.current.y > (1 + bar_grip_pos) and event.current.y <= ((e.frame.h - bar_height) + bar_grip_pos) then
|
||||
if event.current.y < mouse_last_y then
|
||||
scroll_up()
|
||||
elseif event.current.y > mouse_last_y then
|
||||
scroll_down()
|
||||
end
|
||||
|
||||
mouse_last_y = event.current.y
|
||||
end
|
||||
end
|
||||
elseif event.type == CLICK_TYPE.SCROLL_DOWN then
|
||||
scroll_down()
|
||||
elseif event.type == CLICK_TYPE.SCROLL_UP then
|
||||
scroll_up()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return e.complete()
|
||||
end
|
||||
|
||||
return listbox
|
@ -74,7 +74,7 @@ local function init(panel)
|
||||
|
||||
-- plc page
|
||||
|
||||
local plc_page = Div{parent=page_div,x=1,y=1}
|
||||
local plc_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
||||
local plc_list = Div{parent=plc_page,x=2,y=2,width=49}
|
||||
|
||||
for i = 1, config.NUM_REACTORS do
|
||||
@ -106,12 +106,19 @@ local function init(panel)
|
||||
|
||||
-- rtu page
|
||||
|
||||
local rtu_page = Div{parent=page_div,x=1,y=1}
|
||||
local rtu_list = Div{parent=rtu_page,x=2,y=2,width=49}
|
||||
local rtu_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
||||
local rtu_list = ListBox{parent=rtu_page,x=2,y=2,height=15,width=49,scroll_height=1000,item_pad=1,fg_bg=cpair(colors.black,colors.white)}
|
||||
|
||||
local item_1 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.red),hidden=true}
|
||||
local item_2 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.orange),hidden=true}
|
||||
local item_3 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.yellow),hidden=true}
|
||||
local item_4 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.green),hidden=true}
|
||||
local item_5 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.blue),hidden=true}
|
||||
local item_6 = Div{parent=rtu_list,height=3,fg_bg=cpair(colors.black,colors.purple),hidden=true}
|
||||
|
||||
-- coordinator page
|
||||
|
||||
local crd_page = Div{parent=page_div,x=1,y=1}
|
||||
local crd_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
||||
local crd_box = Div{parent=crd_page,x=2,y=2,width=49,height=4,fg_bg=cpair(colors.black,colors.white)}
|
||||
|
||||
local crd_conn = LED{parent=crd_box,x=2,y=2,label="CONNECTION",colors=cpair(colors.green,colors.green_off)}
|
||||
@ -133,7 +140,7 @@ local function init(panel)
|
||||
|
||||
-- pocket page
|
||||
|
||||
local pkt_page = Div{parent=page_div,x=1,y=1}
|
||||
local pkt_page = Div{parent=page_div,x=1,y=1,hidden=true}
|
||||
local pkt_box = Div{parent=pkt_page,x=2,y=2,width=49}
|
||||
|
||||
local panes = { main_page, plc_page, rtu_page, crd_page, pkt_page }
|
||||
|
Loading…
Reference in New Issue
Block a user