Skip to content

Instantly share code, notes, and snippets.

@devilstower
Created October 1, 2012 02:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devilstower/3809050 to your computer and use it in GitHub Desktop.
Save devilstower/3809050 to your computer and use it in GitHub Desktop.
Cider interface builder for Codea
--# Main
-- Cider
-- an interactive interface builder for Codea
-- version 1.00
-- 30 September 2012
-- Mark Sumner
-- devilstower@gmail.com
displayMode(FULLSCREEN)
minSize = 30
function setup()
trayOpen = false
showCode = false
trayTab = Frame(WIDTH - 25, HEIGHT / 2 - 30,
WIDTH + 25, HEIGHT / 2 + 30)
trayWidth = 0
trayMaxWidth = 150
trayFrame = Frame(WIDTH - trayWidth, 0, trayMaxWidth, HEIGHT)
elements = {}
trayElement = {}
traySpeed = 20
trayElement[1] = UIElement(1, "Label", 10, HEIGHT - 60,
130, HEIGHT - 30)
trayElement[2] = UIElement(2, "Button", 10, HEIGHT - 110,
140, HEIGHT - 80)
trayElement[3] = UIElement(3, "Text Box", 10, HEIGHT - 160,
140, HEIGHT - 130)
trayElement[4] = UIElement(4, "Switch;off", 10, HEIGHT - 210,
110, HEIGHT - 180)
trayElement[5] = UIElement(5, "", 10, HEIGHT - 270,
150, HEIGHT - 240)
trayElement[6] = UIElement(6, "Drop List", 10, HEIGHT - 310,
140, HEIGHT - 280)
trayElement[7] = UIElement(7, "Multi;Choice;Button", 10,
HEIGHT - 370, 150, HEIGHT - 330)
btnCode = TextButton("Show Code", 10, 50, 140, 80)
btnCode.background = color(147, 147, 147, 255)
eSelected = 0
eType = 0
dragElement = nil
leftTopSize = Frame(0, 0, 0, 0)
rightTopSize = Frame(0, 0, 0, 0)
leftBottomSize = Frame(0, 0, 0, 0)
rightBottomSize = Frame(0, 0, 0, 0)
infoRect = Frame(-90, 0, -90, 0)
startRect = Frame(0, 0, 0, 0)
stretch = 0
dialog = CiderDialog("Properties", 200, HEIGHT - 500,
WIDTH - 200, HEIGHT - 30)
showProperties = false
showHandles = false
l = dialog.frame.left + 100
r = dialog.frame.right - 30
b = dialog.frame.bottom + 40
t = dialog.frame.top - 75
txtName = TextBox("", l, t, r, t + 30)
txtText = TextBox("", l, t - 40, r, t - 10)
txtName.selected = false
txtText.selected = false
drpFont = DropList("ArialMT;Arial-BoldMT;Copperplate;"..
"Courier;TimesNewRomanPSMT", l, t - 80, r, t - 50)
drpFont.selected = 1
sldFontSize = Slider("", l, t - 140, r, t - 90,
8 , 48, 14)
dragElement = nil
stretch = 0
end
function drawTray()
pushMatrix()
pushStyle()
translate(WIDTH - trayWidth, 0)
for i, e in ipairs(trayElement) do
e:draw()
end
btnCode:draw()
popStyle()
popMatrix()
end
function drawProperties()
pushStyle()
dialog:draw()
strokeWidth(2)
stroke(30, 30, 30, 255)
line(dialog.frame.left, txtName.frame.bottom - 4,
dialog.frame.right, txtName.frame.bottom - 4)
line(dialog.frame.left, txtText.frame.bottom - 4,
dialog.frame.right, txtText.frame.bottom - 4)
line(dialog.frame.left, drpFont.frame.top - 32,
dialog.frame.right, drpFont.frame.top - 32)
textMode(CORNER)
textAlign(LEFT)
fill(0, 0, 0, 255)
text("Name", dialog.frame.left + 10, txtName.frame.bottom + 4)
txtName:draw()
text("Text", dialog.frame.left + 10, txtText.frame.bottom + 4)
txtText:draw()
text("Font", dialog.frame.left + 10, drpFont.frame.top - 24)
text("Font Size", dialog.frame.left + 10,
sldFontSize.frame.top - 24)
sldFontSize:draw()
drpFont:draw()
popStyle()
end
function draw()
-- This sets a dark background color
background(194, 194, 194, 255)
-- Do your drawing here
for i, e in ipairs(elements) do
e:draw()
end
if trayOpen then
if trayWidth < trayMaxWidth then
trayWidth = trayWidth + traySpeed
trayTab:offset(-traySpeed , 0)
end
else
if trayWidth > 0 then
trayWidth = trayWidth - traySpeed
trayTab:offset(traySpeed , 0)
end
end
strokeWidth(2)
fill(216, 216, 216, 255)
ellipse(WIDTH - trayWidth, HEIGHT / 2, 40)
rect(WIDTH - trayWidth, 0, trayWidth, HEIGHT)
noStroke()
rect(WIDTH - trayWidth -5, HEIGHT / 2 - 18, 10, 36)
trayFrame.left = WIDTH - trayWidth
trayFrame.right = trayFrame.left + trayMaxWidth
strokeWidth(5)
stroke(127, 127, 127, 255)
line(WIDTH - trayWidth - 10, HEIGHT / 2,
WIDTH - trayWidth - 0, HEIGHT / 2 - 5)
line(WIDTH - trayWidth - 10, HEIGHT / 2,
WIDTH - trayWidth - 0, HEIGHT / 2 + 5)
if trayWidth > 0 then
drawTray()
end
if dragElement then
dragElement:draw()
end
if showHandles then
stroke(78, 175, 203, 197)
fill(0, 0, 0, 0)
line(leftTopSize.left, leftTopSize.top,
leftTopSize.left + 15, leftTopSize.top)
line(leftTopSize.left, leftTopSize.top,
leftTopSize.left, leftTopSize.top - 15)
line(leftBottomSize.left, leftBottomSize.bottom,
leftBottomSize.left + 15, leftBottomSize.bottom)
line(leftBottomSize.left, leftBottomSize.bottom,
leftBottomSize.left, leftBottomSize.bottom + 15)
line(rightBottomSize.right - 15, rightBottomSize.bottom,
rightBottomSize.right, rightBottomSize.bottom)
line(rightBottomSize.right, rightBottomSize.bottom,
rightBottomSize.right, rightBottomSize.bottom + 15)
line(rightTopSize.right - 15, rightTopSize.top,
rightTopSize.right, rightTopSize.top)
line(rightTopSize.right, rightTopSize.top,
rightTopSize.right, rightTopSize.top - 15)
strokeWidth(1)
stroke(255, 255, 255, 255)
fill(93, 103, 230, 255)
ellipse(infoRect:midX(), infoRect:midY(), 25)
fill(255, 255, 255, 255)
text("i", infoRect:midX(), infoRect:midY())
end
if showProperties then
drawProperties()
end
end
function resetHandles(x, y)
l = dragElement.frame.left - minSize
b = dragElement.frame.bottom - minSize
r = dragElement.frame.right
t = dragElement.frame.top
x = dragElement.frame:midX()
leftTopSize.left = l
leftTopSize.right = l + minSize
leftTopSize.bottom = t
leftTopSize.top = t + minSize
rightTopSize.left = r
rightTopSize.right = r + minSize
rightTopSize.bottom = t
rightTopSize.top = t + minSize
rightBottomSize.left = r
rightBottomSize.right = r + minSize
rightBottomSize.bottom = b
rightBottomSize.top = b + minSize
leftBottomSize.left = l
leftBottomSize.right = l + minSize
leftBottomSize.bottom = b
leftBottomSize.top = b + minSize
infoRect.left = x - minSize / 2
infoRect.right = x + minSize / 2
infoRect.bottom = t + minSize
infoRect.top = t + minSize * 2
end
function printElements()
showCode = true
displayMode(STANDARD)
print("-- ===================")
print("-- Copy this code into the init function")
print("-- ===================")
for i, e in ipairs(elements) do
e:printInit()
end
print(" ")
print("-- ===================")
print("-- Copy this code into the draw function")
print("-- ===================")
for i, e in ipairs(elements) do
e:printDraw()
end
print(" ")
print("-- ===================")
print("-- Copy this code into the touched function")
print("-- ===================")
for i, e in ipairs(elements) do
e:printTouched()
end
end
function closeDialog()
local i, k
showProperties = false
if string.len(txtName.text) > 0 then
dragElement.name = txtName.text
end
dragElement.text = txtText.text
i = 0
for k in string.gmatch(dragElement.text,"([^;]+)") do
i = i + 1
dragElement.itemText[i] = k
end
dragElement.font = drpFont.itemText[drpFont.selected]
dragElement.fontSize = sldFontSize.val
if isKeyboardShowing() then hideKeyboard() end
sound(SOUND_HIT, 28774)
end
function touchedProperties(touch)
if touch.state == BEGAN and oldState ~= BEGAN then
if dialog:touched(touch) then
txtName.selected = false
txtText.selected = false
if txtName:touched(touch) then
txtName.selected = true
if not isKeyboardShowing() then showKeyboard() end
end
if txtText:touched(touch) then
txtText.selected = true
if not isKeyboardShowing() then showKeyboard() end
end
if drpFont:touched(touch) then
end
if sldFontSize:touched(touch) then
end
else
closeDialog()
end
end
if touch.state == MOVING or touch.state == ENDED then
if dialog:touched(touch) then
drpFont:touched(touch)
sldFontSize:touched(touch)
else
--closeDialog()
end
end
oldState = touch.state
end
function touchedHandles(touch)
if touch.state == BEGAN and oldState ~= BEGAN then
stretch = 0
if leftTopSize:touched(touch) then stretch = 1
elseif rightTopSize:touched(touch) then stretch = 2
elseif leftBottomSize:touched(touch) then stretch = 3
elseif rightBottomSize:touched(touch) then stretch = 4
elseif infoRect:touched(touch) then
stretch = 5
showProperties = true
txtName.text = dragElement.name
txtText.text = dragElement.text
sldFontSize.val = dragElement.fontSize
end
if stretch == 0 then
showHandles = false
end
elseif touch.state == MOVING then
x = touch.x
y = touch.y
if stretch == 1 then
-- top left
if x > rightTopSize.left - minSize then
x = rightTopSize.left - minSize
end
if y < leftBottomSize.top + minSize then
y = leftBottomSize.top + minSize
end
dragElement.frame.left = x
dragElement.frame.top = y
elseif stretch == 2 then
-- top right
if x < leftTopSize.right + minSize then
x = leftTopSize.right + minSize
end
if y < leftBottomSize.top + minSize then
y = leftBottomSize.top + minSize
end
dragElement.frame.right = x
dragElement.frame.top = y
elseif stretch == 3 then
-- bottom left
if x > rightTopSize.left - minSize then
x = rightTopSize.left - minSize
end
if y > leftTopSize.bottom - minSize then
y = leftTopSize.bottom - minSize
end
dragElement.frame.left = x
dragElement.frame.bottom = y
elseif stretch == 4 then
-- bottom right
if x < leftTopSize.right + minSize then
x = leftTopSize.right + minSize
end
if y > leftTopSize.bottom - minSize then
y = leftTopSize.bottom - minSize
end
dragElement.frame.right = x
dragElement.frame.bottom = y
end
resetHandles()
elseif touch.state == ENDED and oldState == MOVING then
resetHandles()
end
end
function placeDragElement()
if dragElement then
element = UIElement(dragElement.type, dragElement.text,
dragElement.frame.left, dragElement.frame.bottom,
dragElement.frame.right, dragElement.frame.top)
element.font = dragElement.font
element.fontSize = dragElement.fontSize
element.itemText = dragElement.itemText
table.insert(elements, element)
dragElement = nil
showHandles = false
end
end
function liftDragElement(e, l)
dragElement = UIElement(e.type, e.text,
e.frame.left + l, e.frame.bottom,
e.frame.right + l, e.frame.top)
dragElement.font = e.font
dragElement.fontSize = e.fontSize
dragElement.itemText = e.itemText
end
function touched(touch)
if showProperties then
touchedProperties(touch)
oldState = touch.state
return false
elseif showHandles and dragElement then
touchedHandles(touch)
if showProperties then return false end
end
if touch.state == BEGAN and oldState ~= BEGAN then
if showCode then
showCode = false
displayMode(FULLSCREEN)
return false
end
if dragElement and not showHandles then
if dragElement:touched(touch) then
showHandles = true
end
end
if trayTab:touched(touch) then
placeDragElement()
trayOpen = not trayOpen
elseif trayOpen and trayFrame:touched(touch) then
placeDragElement()
tt = Ttouch(touch)
tt:translate(trayFrame.left, 0)
if btnCode:touched(tt) then
printElements()
end
for i, e in ipairs(trayElement) do
if e:touched(tt) then
if dragElement then placeDragElement() end
liftDragElement(e, trayFrame.left)
trayOpen = false
end
end
else
-- pick up element
for i, e in ipairs(elements) do
if e:touched(touch) then
if dragElement then placeDragElement() end
liftDragElement(e, 0)
table.remove(elements, i)
end
end
end
end
if touch.state == MOVING and dragElement
and showHandles == false then
w = dragElement.frame:width()
h = dragElement.frame:height()
dragElement.frame.left = touch.deltaX + dragElement.frame.left
dragElement.frame.right = dragElement.frame.left + w
dragElement.frame.bottom = dragElement.frame.bottom +
touch.deltaY
dragElement.frame.top = dragElement.frame.bottom + h
elseif touch.state == ENDED and dragElement
and oldState == MOVING then
placeDragElement()
elseif touch.state == ENDED and dragElement
and oldState == BEGAN then
if dragElement:touched(touch) then
resetHandles()
showHandles = true
else
showHandles = false
end
end
oldState = touch.state
end
function keyboard(key)
if showProperties then
if txtName.selected then
i = string.len(txtName.text)
if key == BACKSPACE and i > 0 then
txtName.text = string.sub(txtName.text, 1, i - 1)
else
txtName.text = txtName.text..key
end
end
if txtText.selected then
i = string.len(txtText.text)
if key == BACKSPACE and i > 0 then
txtText.text = string.sub(txtText.text, 1, i - 1)
else
txtText.text = txtText.text..key
end
end
end
end
--# UIElement
UIElement = class()
function UIElement:init(type, text, left, bottom, right, top)
self.type = type
self.text = text
self.frame = Frame(left, bottom, right, top)
self.font = "ArialMT"
self.fontSize = 14
self.itemText = {}
if type == 1 then
self.background = color(0, 0, 0, 0)
self.foreground = color(252, 252, 252, 255)
self.fontSize = 24
self.name = "lbl"..math.random(999)
elseif type == 2 then
self.background = color(127, 127, 127, 255)
self.foreground = color(0, 0, 0, 255)
self.name = "btn"..math.random(999)
elseif type == 3 then
self.background = color(255, 255, 255, 194)
self.foreground = color(29, 29, 29, 255)
self.name = "txt"..math.random(999)
elseif type == 4 then
self.background = color(64, 64, 64, 255)
self.foreground = color(241, 241, 241, 255)
self.name = "swt"..math.random(999)
elseif type == 5 then
self.background = color(238, 238, 238, 255)
self.foreground = color(31, 31, 31, 255)
self.name = "sld"..math.random(999)
elseif type == 6 then
self.background = color(238, 238, 238, 255)
self.foreground = color(31, 31, 31, 255)
self.name = "drp"..math.random(999)
elseif type == 7 then
self.background = color(238, 238, 238, 255)
self.foreground = color(31, 31, 31, 255)
self.name = "mlb"..math.random(999)
end
self.highlight = color(94, 175, 208, 255)
i = 0
for k in string.gmatch(self.text,"([^;]+)") do
i = i + 1
self.itemText[i] = k
end
self.min = 0
self.max = 100
self.val = 100
end
function UIElement:draw()
pushStyle()
pushMatrix()
--print(self.font, self.text)
font(self.font)
textMode(CENTER)
fontSize(self.fontSize)
strokeWidth(2)
if self.type == 1 then
-- label
fill(self.foreground)
text(self.itemText[1], self.frame:midX(), self.frame:midY())
elseif self.type == 2 then
-- text button
stroke(self.background)
fill(self.background)
self.frame:roundRect(10)
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.itemText[1], self.frame:midX(), self.frame:midY())
elseif self.type == 3 then
strokeWidth(1)
stroke(self.foreground)
fill(self.background)
w, h = textSize(self.text)
w = w / 2 + 4
self.frame:draw()
fill(self.foreground)
text(self.itemText[1], self.frame.left + w, self.frame:midY())
elseif self.type == 4 then
strokeWidth(1)
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())
--self.frame:draw()
fill(self.foreground)
text(self.itemText[1], self.frame:midX(), self.frame:midY())
elseif self.type == 5 then
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")
textAlign(RIGHT)
text(self.min, self.frame.left, self.frame:midY())
textAlign(LEFT)
text(self.max, self.frame.right - h / 2, 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
elseif self.type == 6 then
self.frame:draw()
fill(self.foreground)
text(self.itemText[1], self.frame:midX(),
self.frame:midY())
elseif self.type == 7 then
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
popMatrix()
popStyle()
end
function UIElement:printInit()
if self.type == 1 then
print(self.name.." = Label('"..self.text.."', " ..
self.frame.left..", "..self.frame.bottom..", "..
self.frame.right..", "..self.frame.top..")")
elseif self.type == 2 then
print(self.name.." = TextButton('"..self.text.."', " ..
self.frame.left..", "..self.frame.bottom..", "..
self.frame.right..", "..self.frame.top..")")
elseif self.type == 3 then
print(self.name.." = TextBox('"..self.text.."', " ..
self.frame.left..", "..self.frame.bottom..", "..
self.frame.right..", "..self.frame.top..")")
elseif self.type == 4 then
print(self.name.." = Switch('"..self.text.."', " ..
self.frame.left..", "..self.frame.bottom..", "..
self.frame.right..", "..self.frame.top..")")
elseif self.type == 5 then
print(self.name.." = Slider('"..self.text.."', " ..
self.frame.left..", "..self.frame.bottom..", "..
self.frame.right..", "..self.frame.top..", 0, 100, 50)")
elseif self.type == 6 then
print(self.name.." = DropList('"..self.text.."', " ..
self.frame.left..", "..self.frame.bottom..", "..
self.frame.right..", "..self.frame.top..")")
elseif self.type == 7 then
print(self.name.." = MultiButton('"..self.text.."', " ..
self.frame.left..", "..self.frame.bottom..", "..
self.frame.right..", "..self.frame.top..")")
end
if self.font ~= "ArialMT" then
print(self.name..".font = '"..self.font.."'")
end
if self.fontSize ~= 14 then
print(self.name..".fontSize = "..self.fontSize)
end
end
function UIElement:printDraw()
print(self.name..":draw()")
end
function UIElement:printTouched()
print(self.name..":touched(touch)")
end
function UIElement:touched(touch)
return self.frame:touched(touch)
end
--# CiderDialog
CiderDialog = class()
function CiderDialog:init(t, left, bottom, right, top)
self.text = t
self.frame = Frame(left, bottom, right, top)
self.inner = Frame(left + 4, bottom + 4, right - 4, top - 40)
end
function CiderDialog:draw()
fill(0, 0, 0, 255)
stroke(0, 0, 0, 255)
strokeWidth(2)
self.frame:roundRect(8)
stroke(230, 230, 230, 255)
fill(255, 255, 255, 255)
text(self.text, self.frame:midX(), self.frame.top - 20)
fill(255, 255, 255, 255)
stroke(255, 255, 255, 255)
self.inner:roundRect(10)
end
function CiderDialog:touched(touch)
return self.inner:touched(touch)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment