Skip to content

Instantly share code, notes, and snippets.

@devilstower
Created October 1, 2012 02:04
Show Gist options
  • Save devilstower/3809066 to your computer and use it in GitHub Desktop.
Save devilstower/3809066 to your computer and use it in GitHub Desktop.
Cider library for Codea
--# DropList
DropList = class()
function DropList:init(s, left, bottom, right, top)
local i, k
self.frame = Frame(left, bottom, right, top)
self.text = s
self.itemText = {}
self.value = 1
self.background = color(255, 255, 255, 255)
self.foreground = color(31, 31, 31, 255)
i = 0
for k in string.gmatch(s,"([^;]+)") do
i = i + 1
self.itemText[i] = k
end
self.open = false
self.selected = 1
end
function DropList:draw()
local i, t, h
textMode(CENTER)
stroke(self.foreground)
fill(self.background)
self.frame:draw()
fill(self.foreground)
if self.open then
for i, t in ipairs(self.itemText) do
text(t, self.frame:midX(), self.frame.top - i * 30 + 15)
end
strokeWidth(2)
stroke(243, 9, 9, 255)
line(self.frame.left + 4,
self.frame.top - self.selected * 30,
self.frame.right - 4, self.frame.top - self.selected * 30)
line(self.frame.left + 4,
self.frame.top - self.selected * 30 + 30,
self.frame.right - 4, self.frame.top - self.selected * 30 + 30)
else
text(self.itemText[self.selected], self.frame:midX(),
self.frame:midY())
end
end
function DropList:touched(touch)
local h, tRect
h = #self.itemText * 30
if self.frame:touched(touch) then
if not self.open then
if touch.state == BEGAN then
self.open = true
self.frame.bottom = self.frame.top - h
end
else
self.selected =
math.floor((self.frame.top - touch.y) / 30)
if self.selected < 1 then self.selected = 1
elseif self.selected > #self.itemText then
self.selected = #self.itemText
end
end
end
if touch.state == ENDED then
self.open = false
self.frame.bottom = self.frame.top - 30
end
end
--# Frame
Frame = class()
-- Frame
-- ver. 1.5
-- a simple rectangle for holding controls.
-- ====================
function Frame:init(left, bottom, right, top)
self.left = left
self.right = right
self.bottom = bottom
self.top = top
end
function Frame:inset(dx, dy)
self.left = self.left + dx
self.right = self.right - dx
self.bottom = self.bottom + dy
self.top = self.top - dy
end
function Frame:offset(dx, dy)
self.left = self.left + dx
self.right = self.right + dx
self.bottom = self.bottom + dy
self.top = self.top + dy
end
function Frame:draw()
pushStyle()
rectMode(CORNERS)
rect(self.left, self.bottom, self.right, self.top)
popStyle()
end
function Frame:roundRect(r)
pushStyle()
insetPos = vec2(self.left + r,self.bottom + r)
insetSize = vec2(self:width() - 2 * r,self:height() - 2 * r)
rectMode(CORNER)
rect(insetPos.x, insetPos.y, insetSize.x, insetSize.y)
if r > 0 then
smooth()
lineCapMode(ROUND)
strokeWidth(r * 2)
line(insetPos.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y)
line(insetPos.x, insetPos.y,
insetPos.x, insetPos.y + insetSize.y)
line(insetPos.x, insetPos.y + insetSize.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y)
line(insetPos.x + insetSize.x, insetPos.y,
insetPos.x + insetSize.x, insetPos.y + insetSize.y)
end
popStyle()
end
function Frame:gloss(baseclr)
local i, t, r, g, b, y
pushStyle()
if baseclr == nil then baseclr = color(194, 194, 194, 255) end
fill(baseclr)
rectMode(CORNERS)
rect(self.left, self.bottom, self.right, self.top)
r = baseclr.r
g = baseclr.g
b = baseclr.b
for i = 1 , self:height() / 2 do
r = r - 1
g = g - 1
b = b - 1
stroke(r, g, b, 255)
y = (self.bottom + self.top) / 2
line(self.left, y + i, self.right, y + i)
line(self.left, y - i, self.right, y - i)
end
popStyle()
end
function Frame:shade(base, step)
pushStyle()
strokeWidth(1)
for y = self.bottom, self.top do
i = self.top - y
stroke(base - i * step, base - i * step, base - i * step, 255)
line(self.left, y, self.right, y)
end
popStyle()
end
function Frame:touched(touch)
if touch.x >= self.left and touch.x <= self.right then
if touch.y >= self.bottom and touch.y <= self.top then
return true
end
end
return false
end
function Frame:ptIn(x, y)
if x >= self.left and x <= self.right then
if y >= self.bottom and y <= self.top then
return true
end
end
return false
end
function Frame:overlaps(f)
if self.left > f.right or self.right < f.left or
self.bottom > f.top or self.top < f.bottom then
return false
else
return true
end
end
function Frame:width()
return self.right - self.left
end
function Frame:height()
return self.top - self.bottom
end
function Frame:midX()
return (self.left + self.right) / 2
end
function Frame:midY()
return (self.bottom + self.top) / 2
end
--# IconButton
IconButton = class()
-- IconButton
-- ver. 1.0
-- a simple control that centers an image in a frame
-- ====================
function IconButton:init(x1, y1, x2, y2, img)
self.frame = Frame(x1, y1, x2, y2)
self.img = img
end
function IconButton:draw()
fill(52, 52, 52, 255)
self.frame:draw()
sprite(self.img, self.frame:midX(), self.frame:midY())
end
function IconButton:touched(touch)
return self.frame:touched(touch)
end
--# Label
Label = class()
-- Label
-- ver. 1.5
-- a control for basic text label
-- ====================
function Label:init(s, left, bottom, right, top)
self.text = s
self.frame = Frame(left, bottom, right, top)
self.font = "ArialMT"
self.fontSize = 14
self.background = color(222, 222, 222, 255)
self.foreground = color(20, 20, 20, 255)
end
function Label:draw()
local x, w, h
pushStyle()
pushMatrix()
font(self.font)
textMode(CENTER)
fontSize(self.fontSize)
fill(self.foreground)
text(self.text, self.frame:midX(), self.frame:midY())
popMatrix()
popStyle()
end
function Label:touched(touch)
return self.frame:touched(touch)
end
--# Main
-- Cider Library
-- Use this fuile to test and demostrate controls in the library
function setup()
print("Hello World!")
btnTest = TextButton("Button", 100, HEIGHT - 100, 250, HEIGHT - 70)
txtTest = TextBox("Text Box", 100, HEIGHT - 160, 250, HEIGHT - 130)
sldTest = Slider("sTest", 100, 100, 300, 150, 14, 48, 14)
swtTest = Switch("On;Off", 100, 200, 200, 230, 14, 48, 14)
mlbTest = MultiButton("Left;Center;Right", 100, 400, 450, 440)
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(181, 181, 181, 255)
-- This sets the line thickness
strokeWidth(5)
-- Do your drawing here
btnTest:draw()
txtTest:draw()
sldTest:draw()
swtTest:draw()
mlbTest:draw()
--touched(CurrentTouch)
end
function touched(touch)
sldTest:touched(touch)
swtTest:touched(touch)
mlbTest:touched(touch)
end
--# MultiButton
MultiButton = class()
function MultiButton:init(s, left, bottom, right, top)
local i, k
self.text = s
self.frame = Frame(left, bottom, right, top)
self.font = "ArialMT"
self.fontSize = 14
self.background = color(255, 255, 255, 255)
self.foreground = color(20, 20, 20, 255)
self.highlight = color(22, 127, 185, 32)
self.selected = 1
self.itemText = {}
i = 0
for k in string.gmatch(s,"([^;]+)") do
i = i + 1
self.itemText[i] = k
end
end
function MultiButton:draw()
local w
w = (self.frame:width()) / #self.itemText
h = self.frame:height()
strokeWidth(2)
fill(self.background)
stroke(self.foreground)
self.frame:roundRect(6)
noStroke()
stroke(self.background)
self.frame:inset(2, 2)
self.frame:roundRect(6)
self.frame:inset(-2, -2)
stroke(self.foreground)
textMode(CENTER)
font(self.font)
fontSize(self.fontSize)
for i, b in ipairs(self.itemText) do
fill(self.foreground)
strokeWidth(2)
if i < #self.itemText then
line(self.frame.left + i * w, self.frame.top,
self.frame.left + i * w, self.frame.bottom)
end
text(b, (self.frame.left + i * w) - (w / 2),
self.frame:midY())
noStroke()
fill(0, 0, 0, 22)
if i ~= self.selected then
rect(self.frame.left + i * w - w, self.frame:midY() - h/4,
w, self.frame:height() * 0.4 )
rect(self.frame.left + i * w - w, self.frame.bottom,
w, self.frame:height() * 0.4 )
else
fill(self.highlight)
rect(self.frame.left + i * w - w, self.frame:midY() - h/4,
w, self.frame:height() * 0.6)
rect(self.frame.left + i * w - w, self.frame:midY(),
w, self.frame:height() * 0.4 )
rect(self.frame.left + i * w - w, self.frame:midY() + h/4,
w, self.frame:height() * 0.3 )
end
end
end
function MultiButton:touched(touch)
if self.frame:touched(touch) then
if touch.state == BEGAN and oldState ~= BEGAN then
w = (self.frame:width()) / #self.itemText
i = math.floor((touch.x - self.frame.left) / w) + 1
self.selected = i
end
return true
end
end
--# PopMenu
PopMenu = class()
-- PopMenu
-- ver. 1.0
-- a control that provides a simple menu
-- ====================
function PopMenu:init(x, y)
self.x = x
self.y = y
self.items={}
self.frames = {}
end
function PopMenu:draw()
local h, w, x, i
pushStyle()
h = 10
w = 100
for i, item in ipairs(self.items) do
h = h + 60
if string.len(item) * 20 > w then
w = string.len(item) * 20
end
end
w = w + 20
fill(0, 0, 0, 255)
rect(self.x, self.y, w, h)
textAlign(CENTER)
for i, item in ipairs(self.items) do
self.frames[i] = Frame(self.x + 10, self.y + i * 60 - 50,
self.x + w - 10, self.y + i * 60 )
self.frames[i]:gloss(color(255, 255, 255, 255))
x = self.x + w / 2
text(item, x, self.y + i * 60 - 24)
end
popStyle()
end
function PopMenu:touched(touch)
local i
for i, frame in ipairs(self.frames) do
if frame:touched(touch) then
fill(255, 14, 0, 255)
frame:draw()
return i
end
end
return nil
end
--# Slider
Slider = class()
-- Slider
-- ver. 1.0
-- a control that replicates the iparameter slider
-- ====================
function Slider:init(s, left, bottom, right, top, min, max, val)
self.frame = Frame(left, bottom, right, top)
self.min = min
self.max = max
self.text = s
self.val = val
self.background = color(238, 238, 238, 255)
self.foreground = color(31, 31, 31, 255)
self.highlight = color(53, 176, 215, 255)
self.font = "ArialMT"
self.fontSize = 12
end
function Slider:draw()
local x, y, scale
pushStyle()
textMode(CORNER)
textAlign(LEFT)
font(self.font)
fontSize(self.fontSize)
stroke(self.foreground)
fill(self.background)
h, w = textSize(self.max)
scale = ((self.frame.right - self.frame.left) - h * 2) /
(self.max - self.min)
x = self.frame.left + h + ((self.val - self.min) * scale)
y = (self.frame:midY() + self.frame.top) / 2 + 4
strokeWidth(3)
line(self.frame.left + h, y, self.frame.right - h, y)
stroke(self.background)
line(self.frame.left + h, y + 2, self.frame.right - h, y + 2)
stroke(self.background)
line(self.frame.left + h, y, self.frame.right - h, y)
strokeWidth(1)
stroke(self.foreground)
fill(self.highlight)
ellipse(x, y, 20)
fill(self.foreground)
h, w = textSize("Slider")
text(self.min, self.frame.left, self.frame:midY())
textAlign(RIGHT)
text(self.max, self.frame.right, self.frame:midY())
textMode(CENTER)
textAlign(CENTER)
text(self.text, self.frame:midX(), self.frame:midY() + h)
if self.val > self.min and self.val < self.max then
text(self.val, x, self.frame.top - h)
end
popStyle()
end
function Slider:touched(touch)
local x, scale
if touch.state == BEGAN or touch.state == MOVING then
if self.frame:touched(touch) then
x = touch.x - self.frame.left - 10
scale = ((self.frame.right - self.frame.left) - 20) /
(self.max - self.min)
self.val = math.floor(x / scale) + self.min
if self.val < self.min then
self.val = self.min
elseif self.val > self.max then
self.val = self.max
end
return true
end
end
end
--# Switch
Switch = class()
function Switch:init(s, left, bottom, right, top)
local i, k
self.text = s
self.frame = Frame(left, bottom, right, top)
self.blink = ElapsedTime
self.blinkstate = true
self.font = "ArialMT"
self.fontSize = 14
self.background = color(255, 255, 255, 255)
self.foreground = color(20, 20, 20, 255)
self.highlight = color(23, 127, 185, 255)
self.selected = true
self.itemText = {}
i = 0
for k in string.gmatch(s,"([^;]+)") do
i = i + 1
self.itemText[i] = k
end
end
function Switch:draw()
strokeWidth(1)
if self.selected then
stroke(self.highlight)
fill(self.highlight)
h = self.frame:height()
self.frame:roundRect(h/2)
fill(255, 255, 255, 53)
rect(self.frame.left + h/2, self.frame.top - 10,
self.frame:width() - h, 8)
strokeWidth(1)
stroke(76, 76, 76, 255)
fill(227, 227, 227, 255)
ellipse(self.frame.right - h/2,
self.frame:midY(), self.frame:height())
fill(self.foreground)
if #self.itemText > 0 then
text(self.itemText[1], self.frame:midX(), self.frame:midY())
end
else
fill(self.background)
stroke(self.background)
h = self.frame:height()
self.frame:roundRect(h/2)
fill(0, 0, 0, 18)
rect(self.frame.left + h, self.frame.bottom + 2,
self.frame:width() - h*1.5, 8)
strokeWidth(1)
stroke(self.foreground)
fill(self.background)
ellipse(self.frame.left + h/2,
self.frame:midY(), self.frame:height())
fill(self.foreground)
if #self.itemText > 1 then
text(self.itemText[2], self.frame:midX(), self.frame:midY())
end
end
end
function Switch:touched(touch)
if self.frame:touched(touch) then
if touch.state == BEGAN and oldState ~= BEGAN then
self.selected = not self.selected
end
return true
end
end
--# TextBox
TextBox = class()
-- TextBox
-- ver. 2.0
-- a control for basic string editing
-- ====================
function TextBox:init(s, left, bottom, right, top)
self.text = s
self.frame = Frame(left, bottom, right, top)
self.blink = ElapsedTime
self.blinkstate = true
self.font = "ArialMT"
self.fontSize = 14
self.background = color(255, 255, 255, 255)
self.foreground = color(20, 20, 20, 255)
self.selected = true
end
function TextBox:draw()
local x, w, h
pushStyle()
pushMatrix()
font(self.font)
textMode(CORNER)
textAlign(LEFT)
fontSize(self.fontSize)
noStroke()
fill(self.background)
w, h = textSize(self.text)
self.frame:draw()
fill(self.foreground)
text(self.text, self.frame.left + 4, self.frame.bottom + 4)
if self.selected then
if self.blink < ElapsedTime - 0.3 then
self.blink = ElapsedTime
self.blinkstate = not self.blinkstate
end
if self.blinkstate then
strokeWidth(2)
stroke(45, 45, 45, 255)
x = self.frame.left + w + 6
line(x, self.frame.bottom + 2, x, self.frame.top - 2)
end
end
popMatrix()
popStyle()
end
function TextBox:touched(touch)
return self.frame:touched(touch)
end
function TextBox:acceptKey(k)
if self.selected then
if k ~= nil then
if string.byte(k) == nil then
if string.len(self.text) > 0 then
self.text = string.sub(self.text,
1, string.len(self.text) - 1)
end
end
self.text = self.text..k
end
end
end
--# TextButton
TextButton = class()
-- TextButton
-- ver. 1.0
-- a control for displaying a simple button
-- ====================
function TextButton:init(s, left, bottom, right, top)
local w, h
self.frame = Frame(left, bottom, right, top)
self.font = "ArialMT"
self.fontSize = 14
self.text = s
self.foreground = color(62, 62, 62, 255)
self.background = color(200, 200, 200, 255)
end
function TextButton:draw()
pushStyle()
stroke(self.foreground)
fill(self.foreground)
self.frame:roundRect(10)
self.frame:offset(-2, 2)
stroke(self.background)
fill(self.background)
self.frame:roundRect(10)
self.frame:offset(2, -2)
fill(255, 255, 255, 44)
rect(self.frame.left + 12, self.frame.top - 12,
self.frame:width()- 24, 8)
fill(0, 0, 0, 36)
rect(self.frame.left + 12, self.frame.bottom + 4,
self.frame:width()- 24, 4)
fill(self.foreground)
text(self.text, self.frame:midX(), self.frame:midY() + 2)
popStyle()
end
function TextButton:touched(touch)
return self.frame:touched(touch)
end
--# Ttouch
Ttouch = class()
-- Translatable Touch
-- ver. 1.0
-- maps fields of a touch but is easily modified.
-- ====================.
function Ttouch:init(touch)
self.x = touch.x
self.y = touch.y
self.state = touch.state
self.prevX = touch.prevX
self.prevY = touch.prevY
self.deltaX = touch.deltaX
self.deltaY = touch.deltaY
self.id = touch.id
self.tapCount = touch.tapCount
self.timer = 0
end
function Ttouch:translate(x, y)
self.x = self.x - x
self.y = self.y - y
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment