Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Object = {}
- Object_mt = { __index = Object }
- function new (class, ...)
- return class:create(unpack(arg))
- end
- function extends (baseClass)
- local new_class = {}
- local class_mt = { __index = new_class }
- baseClass = baseClass or Object
- function new_class:create(...)
- local newinst = {}
- setmetatable(newinst, class_mt)
- self.__parent = parent
- self:__init(newinst, unpack(arg))
- return newinst
- end
- function new_class.super()
- return baseClass
- end
- if baseClass then
- setmetatable(new_class, { __index = baseClass })
- end
- return new_class
- end
- function Object:create(...)
- local new_inst = {}
- setmetatable( new_inst, Control_mt )
- self:__init(new_inst, unpack(arg))
- return new_inst
- end
- function Object:__init(instance, ...)
- if self.super and self.super() then
- self.super():__init(instance)
- end
- if self.init then
- self.init(instance, unpack(arg))
- end
- end
- Control = extends()
- Control.unique = 1
- function Control:init()
- self:setPos(0, 0)
- self:setSize(0, 0)
- self:setVisible(true)
- self:setName("Control_"..Control.unique)
- Control.unique = Control.unique + 1
- end
- function Control:setPos(x, y)
- self.x = x
- self.y = y
- return self
- end
- function Control:getPos()
- return self.x, self.y
- end
- function Control:getAbsPos()
- local x, y = 0, 0
- if self.__parent then
- x, y = self.__parent:getAbsPos()
- end
- x = x + self.x
- y = y + self.y
- return x, y
- end
- function Control:setSize(w, h)
- self.width = w
- self.height = h
- return self
- end
- function Control:getSize()
- return self.width, self.height
- end
- function Control:getMinSize()
- return 1, 1
- end
- function Control:setName(name)
- self.name = name
- return self
- end
- function Control:setFGColor(color)
- self.fgc = color
- return self
- end
- function Control:setBGColor(color)
- self.bgc = color
- return self
- end
- function Control:click(x, y)
- end
- function Control:onClick()
- end
- function Control:setVisible(visible)
- self.visible = visible
- return self
- end
- function Control:isVisible()
- return self.visible
- end
- function Control:draw()
- if not self:isVisible() then return nil end
- local device = self:getDevice()
- if device then
- local l, t = self:getAbsPos()
- local w, h = self:getSize()
- local r, b = l + w - 1, t + h - 1
- local dx, dy = device.getSize()
- print("Drawing control at ("..l..","..t..")")
- if l < 1 then l = 1 end
- if t < 1 then t = 1 end
- if r > dx then r = dx end
- if b > dy then b = dy end
- if self.bgc then
- if device.setBackgroundColor then
- device.setBackgroundColor(self.bgc)
- end
- for row = t, b do
- device.setCursorPos(l, row)
- for col = l, r do
- device.write(" ")
- end
- end
- end
- end
- return device
- end
- function Control:getDevice()
- if self.__parent then
- return self.__parent:getDevice()
- else return nil
- end
- end
- function Control:contains(x, y)
- return x >= self.x and x < self.x + self.width and
- y >= self.y and y < self.y + self.height
- end
- Label = inheritsfrom(Control)
- function Label:init()
- self:setAlign("center"):setVAlign(center):setText("")
- end
- function Label:getMinSize()
- return #(self.text), 1
- end
- function Label:setText(text)
- self.text = text
- return self
- end
- function Label:setAlign(align)
- self.align = align
- return self
- end
- function Label:setVAlign(align)
- self.valign = align
- return self
- end
- function Label:draw()
- local device = Label.super().draw(self)
- if not device then return end
- -- print("drawing label "..self.name)
- local x, y = self:getAbsPos()
- local text = self.text
- local slackx = self.width - #text
- local slacky = self.height - 1
- if self.align == "center" then
- x = x + slackx / 2
- elseif self.align == "right" then
- x = x + slackx
- end
- if self.valign == "center" then
- y = y + slacky / 2
- elseif self.valign == "bottom" then
- y = y + slacky
- end
- -- print("Displaying text '"..text.."' at ("..x..", "..y..")")
- device.setCursorPos(x, y)
- device.setTextColor(self.fgc)
- device.write(text)
- return device
- end
- Button = inheritsfrom(Label)
- function Button:setActive(state)
- self.state = state
- end
- function Button:setActiveColor(color)
- self.hlc = color
- end
- function Button:setInactiveColor(color)
- self.iac = color
- end
- function Button:update()
- self.bgc = self.state and hlc or iac
- self:draw()
- end
- function Button:click()
- self:setActive(true)
- self:update()
- self:onClick()
- self:setActive(false)
- self:update()
- end
- Container = inheritsfrom(Control)
- function Container:clear()
- self.controls = {}
- self.controlsByName = {}
- end
- function Container:init()
- self:clear()
- end
- function Container:add(control)
- self.controls[#(self.controls)+1] = control
- -- print(control.name)
- self.controlsByName[control.name] = control
- control.__parent = self
- control.__idx = #(self.controls)
- end
- function Container:find(name)
- return controlsByName[name]
- end
- function Container:findIndex(control)
- if type(control) == "string" then
- control = self:find(control)
- end
- if control.__parent ~= self then return nil end
- if control.__idx and controls[control.__idx] == control then
- return control.__idx
- end
- for i = 1, #controls do
- if controls[i] == control then
- control.__idx = i
- return i
- end
- end
- return nil
- end
- function Container:moveUp(control)
- idx = self:findIndex(control)
- if not idx or idx >= #controls then return nil end
- controls[idx] = controls[idx+1]
- controls[idx].__idx = idx
- controls[idx+1] = control
- control.__idx = idx+1
- end
- function Container:moveDown(control)
- idx = self:findIndex(control)
- if not idx or idx <= 1 then return nil end
- controls[idx] = controls[idx-1]
- controls[idx]._idx = idx
- controls[idx-1] = control
- control.__idx = idx-1
- end
- function Container:moveTop(control)
- while self:moveUp(control) do end
- end
- function Container:moveBottom(control)
- while self:moveDown(control) do end
- end
- function Container:addButton(name, text, func, param, x, y, w, h)
- b = Button:create()
- b.name = name
- b:setText(text)
- b:setPos(x, y)
- b:setSize(w, h)
- b:setAction(func, param)
- b:setActive(false)
- self:add(b)
- end
- function Container:addLabel(name, text, x, y, w, h)
- l = Label:create()
- l.name = name
- l:setText(text)
- l:setPos(x, y)
- l:setSize(w, h)
- self:add(l)
- end
- function Container:draw()
- local device = Container.super().draw(self)
- if not device then return end
- for k, v in ipairs(self.controls) do
- v:draw()
- end
- return device
- end
- Screen = inheritsfrom(Container)
- function Screen:init()
- self:setPos(1,1)
- end
- function Screen:setDevice(device)
- self.device = device
- if device then self:setSize(device.getSize()) end
- return self
- end
- function Screen:getDevice()
- return self.device
- end
- function Screen:draw()
- if self.device then
- self.device.clear()
- return Screen.super().draw(self)
- end
- end
- Scrollbar = inheritsfrom(Control)
- function Scrollbar:init()
- self.thumb = Control:create()
- self.thumb.__parent = self
- self.pos = 0
- self.max = 0
- end
- function Scrollbar:setBounds(min, max)
- self.pos = 0
- self.min = min
- self.max = max
- return self
- end
- function Scrollbar:setProgress(value)
- if value >= self.min and value <= self.max then
- self.pos = value
- end
- return self
- end
- function Scrollbar:getProgress()
- return self.pos
- end
- function Scrollbar:setPercent(value)
- local range = self.max - self.min
- if range > 0 and value >= 0 and value <= 100 then
- self.pos = self.min + range * value
- end
- return self
- end
- function Scrollbar:setType(value)
- self.type = value
- return self
- end
- function Scrollbar:draw()
- device = Scrollbar.super().draw(self)
- if not device then return end
- if self.width >= 1 and self.height >= 1 then
- print("Drawing scrollbar at ("..self.x..","..self.y..")")
- print("Min "..self.min.." Max "..self.max)
- if self.max > self.min then
- if self.type == "horizontal" then
- self.thumb:setSize(1, self.height)
- self.thumb:setPos((self.pos - self.min) / (self.max - self.min) * (self.width-1), 0)
- else
- self.thumb:setSize(self.width, 1)
- self.thumb:setPos(0, (self.pos - self.min) / (self.max - self.min) * (self.height-1))
- end
- print(self.thumb.name)
- print(self.thumb:isVisible())
- self.thumb:setBGColor(colors.blue)
- local tx, ty = self.thumb:getAbsPos()
- print("Drawing thumb at ("..tx..","..ty..")")
- self.thumb:draw()
- end
- end
- return device
- end
- Grid = inheritsfrom(Container)
- function Grid:init()
- self.hscroll = Scrollbar:create(self)
- :setFGColor(colors.gray)
- :setBGColor(colors.lightGray)
- :setType("horizontal")
- self.vscroll = Scrollbar:create(self)
- :setFGColor(colors.gray)
- :setBGColor(colors.lightGray)
- :setType("vertical")
- self.rows, self.cols = 0, 0
- end
- function Grid:setMargins(ml, mt, mr, mb)
- self.ml, self.mt, self.mr, self.mb = ml, mt, mr, mb
- return self
- end
- function Grid:setHGap(gap)
- self.hgap = gap
- return self
- end
- function Grid:setVGap(gap)
- self.vgap = gap
- return self
- end
- function Grid:setRows(rows)
- self.rows = rows
- return self
- end
- function Grid:setCols(cols)
- self.cols = cols
- return self
- end
- --"horizontal": will lay out by columns
- --"vertical": will lay out by rows
- function Grid:setDirection(dir)
- self.dir = dir
- return self
- end
- function Grid:doLayout()
- local minx, miny = 0, 0
- for k, v in ipairs(self.controls) do
- local w, h = v:getMinSize()
- if w > minx then minx = w end
- if h > miny then miny = h end
- end
- self.vcols = math.floor((self.width - self.ml - self.mr - 1 + self.hgap) / (minx + self.hgap))
- self.vrows = math.floor((self.height - self.mt - self.mb - 1 + self.vgap) / (miny + self.vgap))
- if self.rows < 1 and self.cols >= 1 then
- self.rows = math.ceil(#(self.controls) / self.cols)
- elseif self.cols < 1 and self.rows >=1 then
- self.cols = math.ceil(#(self.controls) / self.rows)
- else
- if self.dir == "vertical" then
- if self.cols < 1 then self.cols = self.vcols end
- self.rows = math.ceil(#(self.controls) / self.cols)
- else
- if self.rows < 1 then self.rows = self.vrows end
- self.cols = math.ceil(#(self.controls) / self.rows)
- end
- end
- if self.rows > self.vrows then
- self.vscroll:setBounds(0, self.rows - self.vrows)
- self.vscroll:setVisible(true)
- else
- self.vscroll:setBounds(0, 0)
- self.vscroll:setVisible(false)
- end
- if self.cols > self.vcols then
- self.hscroll:setBounds(0, self.cols - self.vcols)
- self.hscroll:setVisible(true)
- else
- self.hscroll:setBounds(0, 0)
- self.hscroll:setVisible(false)
- end
- self.vscroll:setPos(self.width - 1 - self.mr, self.mt)
- if self.hscroll:isVisible() then
- self.vscroll:setSize(1, self.height - self.mt - self.mb - 1)
- else self.vscroll:setSize(1, self.height - self.mt - self.mb)
- end
- self.hscroll:setPos(self.ml, self.height - 1 - self.mb)
- if self.vscroll:isVisible() then
- self.hscroll:setSize(self.width - self.ml - self.mr - 1, 1)
- else self.hscroll:setSize(self.width - self.ml - self.mr, 1)
- end
- self.cwidth = math.floor((self.width - self.ml - self.mr - 1 + self.hgap) / self.vcols) - self.hgap
- self.cheight = math.floor((self.height - self.mt - self.mb - 1 + self.vgap) / self.vrows) - self.vgap
- for k, v in ipairs(self.controls) do
- v:setSize(self.cwidth, self.cheight)
- end
- end
- function Grid:draw()
- local voff = self.vscroll:getProgress()
- local hoff = self.hscroll:getProgress()
- if self.dir == "vertical" then
- local y = self.mt
- for row = 0, self.vrows - 1 do
- local x = self.ml
- for col = 0, self.vcols - 1 do
- local index = (row + voff) * self.cols + col + hoff + 1
- local control = self.controls[index]
- if control then
- control:setPos(x, y)
- control:draw()
- end
- x = x + self.cwidth + self.hgap
- end
- y = y + self.cheight + self.vgap
- end
- else
- local x = self.ml
- for col = 0, self.vcols - 1 do
- local y = self.mt
- for row = 0, self.vrows - 1 do
- local index = (col + hoff) * self.rows + row + voff + 1
- local control = self.controls[index]
- if control then
- control:setPos(x, y)
- control:draw()
- end
- y = y + self.cheight + self.vgap
- end
- x = x + self.cwidth + self.hgap
- end
- end
- self.vscroll:draw()
- self.hscroll:draw()
- end
- function screen()
- local currColor
- for name,data in pairs(button) do
- local on = data["active"]
- if on == true then currColor = colors.lime else currColor = colors.red end
- fill(name, currColor, data)
- end
- end
- function Button:toggle()
- self.state = not self.state
- screen()
- end
- function flash(name)
- toggleButton(name)
- screen()
- sleep(0.15)
- toggleButton(name)
- screen()
- end
- function checkxy(x, y)
- for name, data in pairs(button) do
- if y>=data["ymin"] and y <= data["ymax"] then
- if x>=data["xmin"] and x<= data["xmax"] then
- if data["param"] == "" then
- data["func"]()
- else
- data["func"](data["param"])
- end
- return true
- --data["active"] = not data["active"]
- --print(name)
- end
- end
- end
- return false
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement