Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local drawFuncs = {}
- local maxid = 0
- local defaults = {
- label = {
- bgColor = colors.black;
- textColor = colors.white;
- };
- button = {
- bgColor = colors.blue;
- textColor = colors.white;
- padding = {2, 1};
- };
- slider = {
- orientation = 'horizontal';
- length = 20;
- bgColor = colors.gray;
- fgColor = colors.blue;
- min = 0;
- max = 1;
- };
- }
- local mouse = {
- clicked = false;
- dragged = false;
- focus = nil;
- x = 1;
- y = 1;
- }
- local function copy(source, from)
- for k,v in pairs(from) do
- if type(v) == 'table' then
- copy(source[k], v)
- else
- source[k] = v
- end
- end
- end
- local function genid()
- maxid = maxid + 1
- return maxid
- end
- local function checkArea(mx, my, x, y, w, h)
- return mx >= x and mx < x + w and my >= y and my < y + h
- end
- local function checkClick(...)
- return mouse.clicked and checkArea(mouse.x, mouse.y, ...)
- end
- local function checkDrag(...)
- return mouse.dragged and checkArea(mouse.x, mouse.y, ...)
- end
- local function dimensions(text)
- return #text + (defaults.button.padding[1] or 2) * 2,
- 1 + (defaults.button.padding[2] or 1) * 2
- end
- local function rect(x, y, width, height, color)
- local fill = string.rep(' ', width)
- if color then term.setBackgroundColor(color) end
- for i=1, height do
- term.setCursorPos(x, y + (i - 1))
- term.write(fill)
- end
- end
- local function checkInfo(info)
- if type(info) ~= 'table' then
- error("Bad argument: table expected", 3)
- end
- end
- local function drawButton(info)
- rect(info.x, info.y, info.width, info.height,
- info.bgColor or (defaults.button and defaults.button.bgColor))
- if info.text then
- textColor = info.textColor or defaults.button.textColor
- if textColor then term.setTextColor(textColor) end
- term.setCursorPos(
- info.x + math.ceil(info.width/2) - math.ceil(#info.text/2),
- info.y + math.ceil(info.height/2) - 1)
- term.write(tostring(info.text))
- end
- end
- local function drawSlider(info, width, height)
- rect(info.x, info.y, width, height, info.bgColor)
- -- i hate this math
- -- i really do
- if info.orientation == 'horizontal' then
- width = math.max(math.ceil(width * ((info.value - info.min) / (info.max - info.min))), 1)
- else
- height = math.max(math.ceil(height * ((info.value - info.min) / (info.max - info.min))), 1)
- end
- rect(info.x, info.y, width, height, info.fgColor)
- end
- function setDefaults(t)
- copy(defaults, t)
- end
- function clear(color)
- if color then term.setBackgroundColor(color) end
- term.clear()
- end
- function label(info)
- checkInfo(info)
- register(function()
- bgColor = info.bgColor or defaults.label.bgColor
- textColor = info.textColor or defaults.label.textColor
- if bgColor then term.setBackgroundColor(bgColor) end
- if textColor then term.setTextColor(textColor) end
- term.setCursorPos(info.x, info.y)
- term.write(info.text)
- end)
- end
- function button(info)
- checkInfo(info)
- local tw, th = dimensions(info.text)
- info.width = info.width or tw
- info.height = info.height or th
- info.bgColor = info.bgColor or defaults.button.bgColor
- info.textColor = info.textColor or defaults.button.textColor
- local clicked = checkClick(info.x, info.y, info.width, info.height)
- if clicked then
- mouse.clicked = false -- to make sure overlapping items don't receive clicks
- end
- info.text = tostring(info.text)
- register(drawButton, info)
- return clicked
- end
- function slider(info)
- checkInfo(info)
- setmetatable(info, { __index = defaults.slider })
- info.value = info.value or (info.max - info.min) / 2
- local width, height = info.length, 1
- if info.orientation == 'vertical' then
- width, height = height, width
- end
- local id = genid()
- local clicked = checkClick(info.x, info.y, width, height)
- local changed = false
- if clicked then
- mouse.clicked = false
- mouse.focus = id
- end
- if clicked or mouse.dragged and mouse.focus == id then
- local dist = (info.orientation == 'horizontal' and mouse.x - info.x or mouse.y - info.y)
- local ratio = math.min(dist / (info.length - 1), 1)
- info.value = ratio * (info.max - info.min) + info.min
- changed = true
- end
- register(drawSlider, info, width, height)
- return changed
- end
- function register(func, ...)
- table.insert(drawFuncs, {func, ...})
- end
- function draw()
- for i=1, #drawFuncs do
- local func, params = table.remove(drawFuncs[i], 1), drawFuncs[i]
- func(unpack(params))
- end
- drawFuncs = {}
- end
- function pullEvent()
- mouse.clicked = false
- mouse.dragged = false
- maxid = 0
- local params = {os.pullEvent()}
- local event = table.remove(params, 1)
- if event:match 'mouse' then
- mouse.x = params[2]
- mouse.y = params[3]
- if event == 'mouse_click' then
- mouse.clicked = true
- elseif event == 'mouse_drag' then
- mouse.dragged = true
- end
- end
- return event, unpack(params)
- end
Advertisement
Add Comment
Please, Sign In to add comment