Skip to content

Instantly share code, notes, and snippets.

@devilstower
Created January 26, 2014 04:23

Revisions

  1. devilstower created this gist Jan 26, 2014.
    784 changes: 784 additions & 0 deletions Cider 7.1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,784 @@

    --# Main
    -- Cider 7
    -- an interactive interface builder for Codea
    -- version 7.1
    -- 2 Jan 2014
    -- Mark Sumner
    -- [email protected]

    displayMode(FULLSCREEN_NO_BUTTONS)
    supportedOrientations(PORTRAIT_ANY)

    function setup()
    elements = {}
    dragElement = nil
    selectedElement = 0
    elementCount = 0

    tray = Tray()
    writer = CodeWriter()
    dialog =nil

    font("HelveticaNeue-Light")
    end

    function drawBackground()
    pushStyle()
    fontSize(222)
    fill(146, 140, 140, 35)
    text("Cider", WIDTH / 2, HEIGHT / 2 + 300)
    text("7", WIDTH / 2, HEIGHT / 2 + 100)
    fontSize(72)
    text("Interface Designer", WIDTH / 2, HEIGHT / 2 - 150)
    text("for Codea", WIDTH / 2, HEIGHT / 2 - 220)
    fontSize(32)
    text("Version 7.1", WIDTH / 2, 120)
    text("by Mark Sumner", WIDTH / 2, 70)
    popStyle()
    end

    function draw()
    local i, x
    background(255, 255, 255, 255)
    if tray.swtTitle.selected then drawBackground() end

    -- draw grid
    stroke(146, 138, 138, 44)
    strokeWidth(2)
    if tray.swtGrid.selected then
    for x=0, WIDTH, 20 do
    line(x, 0, x, HEIGHT)
    end
    for x=0, HEIGHT, 20 do
    line(0, x, WIDTH, x)
    end
    end

    -- draw elements

    for i, e in ipairs(elements) do
    e:draw()
    end

    tray:draw()

    if dialog ~= nil then
    if dialog.visible then dialog:draw() end
    end

    if dragElement then
    dragElement:draw()
    end

    end

    function touched(touch)
    local found
    tray:touched(touch)
    if dialog then
    if dialog.visible then dialog:touched(touch) end
    end

    if touch.state == BEGAN then
    found = 0
    for i, e in ipairs(elements) do
    if e:touched(touch) then
    found = i
    end
    end
    if selectedElement > 0 then
    elements[selectedElement].handles = false
    end
    selectedElement = found
    if selectedElement > 0 then
    elements[selectedElement].handles = true
    elements[selectedElement]:setHandles()
    end
    end

    if touch.state == MOVING then
    if dragElement then
    dragElement.element:setPosition(touch)
    end
    if selectedElement > 0 then
    elements[selectedElement]:touched(touch)
    end
    end

    if touch.state == ENDED then
    if dragElement then
    table.insert(elements, dragElement)
    dragElement = nil
    end
    end

    end

    function keyboard(key)
    if dialog.visible then
    if CCActiveTextBox then
    CCActiveTextBox:acceptKey(key)
    end
    end
    end

    --# PropertiesDialog
    PropertiesDialog = class(Dialog)

    function PropertiesDialog:init(tablePos, control)
    Dialog.init(self, "Properties", 100, 280,
    WIDTH - 200, HEIGHT - 290)
    ds = ""
    self.hasDrop = false
    self.tablePos = tablePos
    s = "&Name;"
    s = s.."Font;"
    s = s.."Background;"
    s = s.."Foreground;"
    s = s.."Text Color;"
    s = s.."Highlight Color;"
    s = s.."Highlighted Text Color;"
    s = s.."&Text"
    if control.type == TEXTFIELDTYPE then
    s = s..";Style;&Title"
    ds = "Standard;Titled;Search"
    self.hasDrop = true
    end
    if control.type == BUTTONTYPE then
    s = s..";Style"
    ds = "Standard;Warning;Info;Details;Add;Round;Action"
    self.hasDrop = true
    end
    self.list = SelectList(s, self.x + 10, self.y + 80,
    self.w - 20, self.h - 150)
    self.control = control
    self.list.item[1].text = self.control.name
    self.list.item[8].text = self.control.element.text
    if self.hasDrop then
    self.drop = DropList(ds, self.x + 335,
    self.list.item[9].y + 4, 220, 30)
    end

    self.sldSize = Slider("Font Size", self.x + 30,
    self.list.item[#self.list.item].y - 60, self.w - 60,
    40, 1, 8, 48,
    control.element.fontSize)

    --self.list.item[1].type = 1
    self.patches = {}

    self.patches[1] = Frame(self:right() - 120, self.list.item[3].y + 4,
    70, 30)
    self.patches[2] = Frame(self:right() - 120, self.list.item[4].y + 4,
    70, 30)
    self.patches[3] = Frame(self:right() - 120, self.list.item[5].y + 4,
    70, 30)
    self.patches[4] = Frame(self:right() - 120, self.list.item[6].y + 4,
    70, 30)
    self.patches[5] = Frame(self:right() - 120, self.list.item[7].y + 4,
    70, 30)

    if control.type == TEXTFIELDTYPE then
    self.list.item[10].text = control.element.title
    self.drop.selectedItem = control.element.type + 1
    end
    if control.type == BUTTONTYPE then
    self.drop.selectedItem = control.element.type + 1
    end

    self.colorSelector = ColorSelector(0, 0,
    self.control.element.background)

    self.sheet = ActionSheet("ArialMT;Copperplate-Light;"..
    "Futura-Medium;GillSans-Light;HelveticaNeue;HelveticaNeue-Light;"..
    "HelveticaNeue-UltraLight;Optima-Regular;SourceSansPro-Bold",
    450, 450, 250, 480)

    self.btnDelete = Button("Delete", self.x + 10, self.y + 10,
    180, 50, ButtonTypeWarning)
    self.btnOK = Button("OK", self:right() - 190, self.y + 10,
    180, 50, 0)
    self.btnCopy = Button("Copy", self:midX() - 90, self.y + 10,
    180, 50, 0)
    self.btnOK.textColor = color(228, 226, 226, 255)
    self.btnOK.background = color(78, 136, 78, 255)
    self.btnCopy.background = color(205, 200, 200, 255)
    self.sheet.visible = false
    self.visible = false
    end

    function PropertiesDialog:draw()
    pushStyle()
    Dialog.draw(self)
    self.list:draw()

    self.btnDelete:draw()
    self.btnOK:draw()
    self.btnCopy:draw()

    fill(96, 96, 96, 255)
    font(self.control.element.font)
    text(self.control.element.font,
    self:right() - 120, self.list.item[2]:midY())

    -- color patches
    stroke(178, 178, 178, 255)
    strokeWidth(1)
    fill(self.control.element.background)
    self.patches[1]:draw()
    fill(self.control.element.foreground)
    self.patches[2]:draw()
    fill(self.control.element.textColor)
    self.patches[3]:draw()
    fill(self.control.element.highlightColor)
    self.patches[4]:draw()
    fill(self.control.element.highlightedTextColor)
    self.patches[5]:draw()

    self.sldSize:draw()
    font("HelveticaNeue-Light")
    fontSize(self.sldSize.val)
    fill(0, 0, 0, 255)
    p = self.sldSize:getPointerPosition()
    text(self.sldSize.val, p.x, p.y - 30)

    if self.hasDrop then self.drop:draw() end

    if self.colorSelector.visible then self.colorSelector:draw() end
    if self.sheet.visible then self.sheet:draw() end
    popStyle()
    end

    function PropertiesDialog:setColorSelector(x, y, c)
    self.colorSelector = ColorSelector(x, y, c)
    self.colorSelector.visible = true
    end

    function PropertiesDialog:getColorSelector()
    self.colorSelector.closedOK = false
    return self.colorSelector.color
    end

    function PropertiesDialog:touched(touch)
    if not self.visible then
    return false
    else
    if self.colorSelector.visible then
    self.colorSelector:touched(touch)
    elseif self.sheet.visible then
    self.sheet:touched(touch)
    if self.sheet.selectionMade then
    self.control.element.font =
    self.sheet.itemText[self.sheet.selectedItem]
    self.sheet.visible = false
    self.sheet.selectionMade = false
    end
    elseif self.hasDrop and self.drop:touched(touch) then
    if self.control.type == BUTTONTYPE then
    self.control.element:setType(self.drop.selectedItem - 1)
    self.control.element.type = self.drop.selectedItem - 1
    end
    elseif self.sldSize:touched(touch) then
    elseif self.list:touched(touch) and touch.state == BEGAN then
    if self.list.selectedItem == 2 then
    self.sheet.visible = true
    end
    if self.list.selectedItem == 3 then
    self:setColorSelector(350, 600,
    self.control.element.background)
    end
    if self.list.selectedItem == 4 then
    self:setColorSelector(350, 570,
    self.control.element.foreground)
    end
    if self.list.selectedItem == 5 then
    self:setColorSelector(350, 540,
    self.control.element.textColor)
    end
    if self.list.selectedItem == 6 then
    self:setColorSelector(350, 510,
    self.control.element.highlightColor)
    end
    if self.list.selectedItem == 7 then
    self:setColorSelector(350, 540,
    self.control.element.highlightedTextColor)
    end
    end
    if self.colorSelector.visible == false and
    self.colorSelector.closedOK then
    if self.list.selectedItem == 3 then
    self.control.element.background =
    self:getColorSelector()
    end
    if self.list.selectedItem == 4 then
    self.control.element.foreground =
    self:getColorSelector()
    end
    if self.list.selectedItem == 5 then
    self.control.element.textColor =
    self:getColorSelector()
    end
    if self.list.selectedItem == 6 then
    self.control.element.highlightColor =
    self:getColorSelector()
    end
    if self.list.selectedItem == 7 then
    self.control.element.highlightedTextColor =
    self:getColorSelector()
    end
    end
    end

    if self.btnOK:touched(touch) then
    self.visible = false
    self.control.element.fontSize = self.sldSize.val
    self.control.name = self.list.item[1].text
    self.control.element.text = self.list.item[8].text
    if isKeyboardShowing() then hideKeyboard() end
    if self.control.type == TEXTFIELDTYPE then
    self.control.element.title = self.list.item[10].text
    self.control.element.type = self.drop.selectedItem - 1
    end
    if self.control.type == DROPLISTTYPE or
    self.control.type == SEGMENTEDCONTROLTYPE then
    self.control.element:splitText()
    end
    end
    if self.btnDelete:touched(touch) then
    table.remove(elements, self.tablePos)
    selectedElement = 0
    self.visible = false
    end
    if self.btnCopy:touched(touch) then
    newElement = table.deepcopy(elements[self.tablePos])
    newElement.name = newElement.name .. #elements + 1
    newElement.element.x = newElement.element.x + 30
    newElement.element.y = newElement.element.y - 30
    print(newElement.name)
    table.insert(elements, newElement)

    selectedElement = 0
    self.visible = false
    end
    end


    function table.deepcopy(object)
    local lookup_table = {}
    local function _copy(object)
    if type(object) ~= "table" then
    return object
    elseif lookup_table[object] then
    return lookup_table[object]
    end
    local new_table = {}
    lookup_table[object] = new_table
    for index, value in pairs(object) do
    new_table[_copy(index)] = _copy(value)
    end
    return setmetatable(new_table, getmetatable(object))
    end
    return _copy(object)
    end

    --# Tray
    Tray = class(Control)

    function Tray:init()
    Control.init(self, "", WIDTH, 0, 250, HEIGHT)
    self.background = color(255, 255, 255, 255)
    self.visible = true

    self.handle = Frame(self.x-20, self:midY() - 40, 20, 80)

    self.speed = 0
    self.elements = {}
    for i = 1, 10 do
    self.elements[i] = UIElement(i, elementNames[i], 10,
    HEIGHT - i * 70, 200, 40)
    end
    self.selectedElement = 0

    self.swtGrid = Switch("Show Grid", 10, 90, 200, 35)
    self.swtTitle = Switch("Show About", 10, 140, 200, 35)
    self.swtTitle.selected = true
    self.btnCode = Button("Save Code", 10, 30, 200, 35, 1)
    self.btnCode.background = color(62, 170, 65, 255)
    end

    function Tray:move()
    self.x = self.x + self.speed
    end

    function Tray:copyElement(e)
    local u = {}
    for k, v in pairs(e) do u[k] = v end
    return setmetatable(u, getmetatable(t))
    end

    function Tray:draw()
    -- update position
    self:offset(self.speed, 0)
    self.handle:offset(self.speed, 0)
    if self.speed < 0 and self.x <= WIDTH - self.w then
    self.speed = 0
    elseif self.speed > 0 and self.x >= WIDTH then
    self.speed = 0
    end

    -- draw handle
    pushMatrix()
    pushStyle()
    fill(153, 165, 169, 255)
    stroke(146, 158, 163, 255)
    self.handle:roundRect(4)
    fill(255, 255, 255, 255)
    translate(self.handle:midX(), self.handle:midY())
    rotate(90)
    text("Controls", 0, 0)
    popMatrix()
    popStyle()

    pushMatrix()
    pushStyle()
    -- draw outer box
    stroke(self.foreground)
    fill(self.background)
    Frame.draw(self)

    -- draw contents
    translate(self.x, self.y)

    for i, e in ipairs(self.elements) do
    e:draw()
    stroke(211, 211, 211, 255)
    strokeWidth(1)
    noSmooth()
    line(e.element:left(), e.element:bottom() - 8,
    e.element:right(), e.element:bottom() - 8)
    smooth()
    end
    self.swtGrid:draw()
    self.swtTitle:draw()
    self.btnCode:draw()
    translate(-self.x, -self.y)

    popStyle()
    popMatrix()
    end

    function Tray:touched(touch)
    if self.handle:touched(touch) and touch.state == BEGAN then
    if self.x >= WIDTH then
    self.speed = - 50
    elseif self.x <= WIDTH - self.w then
    self.speed = 50
    end
    end
    tt = Ttouch(touch)
    tt.x = tt.x - self.x
    self.swtGrid:touched(tt)
    self.swtTitle:touched(tt)
    for i, e in ipairs(self.elements) do
    if e:touched(tt) and touch.state == BEGAN then
    elementCount = elementCount + 1
    dragElement =
    UIElement(i,elementNames[i],
    touch.x, touch.y, 200, 40)
    self.speed = 50
    end
    end
    if self.btnCode:touched(tt) then
    writer:write()
    end
    end


    --# UIElement
    UIElement = class()

    CONTROLTYPE = 1
    LABELTYPE = 2
    BUTTONTYPE = 3
    TEXTFIELDTYPE = 4
    SWITCHTYPE = 5
    SLIDERTYPE = 6
    DROPLISTTYPE = 7
    SEGMENTEDCONTROLTYPE = 8
    SPOTSWITCHTYPE = 9
    ICONBUTTONTYPE = 10
    SELECTLISTTYPE = 11

    elementNames = {"Control", "Label", "Button", "TextField", "Switch",
    "Slider", "DropList", "Segment;Control", "SpotSwitch", "IconButton",
    "SelectSwitch"}

    handleNames = {"X", "Y", "W", "H", "i"}

    function UIElement:init(eType, text, x, y, w, h, tab)
    self.type = eType
    self.element = nil
    self.tab = tab
    self.source = 1
    self.handles = false
    self.hRect = {}
    self.handleInfo = nil
    self.handleTouched = 0
    self.expandedFrame = nil

    if self.type == CONTROLTYPE then
    self.element = Control(text, x, y, w, h)
    self.element.background = color(247, 247, 247, 255)
    self.name = "ctl"
    elseif self.type == LABELTYPE then
    self.element = Label(text, x, y, w, h)
    self.name = "lbl"
    elseif self.type == BUTTONTYPE then
    self.element = Button(text, x, y, w, h, 0)
    self.element.foreground = color(255, 255, 255, 0)
    self.name = "btn"
    elseif self.type == TEXTFIELDTYPE then
    self.element = TextField("Title", x, y, w, h, text, 0)
    self.name = "txt"
    elseif self.type == SWITCHTYPE then
    self.element = Switch(text, x, y, w, h)
    self.name = "swt"
    elseif self.type == SLIDERTYPE then
    self.element = Slider(text, x, y, w, h, 0, 0, 100, 50)
    self.name = "sld"
    elseif self.type == DROPLISTTYPE then
    self.element = DropList(text, x, y, w, h)
    self.name = "dpl"
    elseif self.type == SEGMENTEDCONTROLTYPE then
    self.element = SegmentedControl(text, x, y, w, h, 0)
    self.name = "sct"
    elseif self.type == SPOTSWITCHTYPE then
    self.element = SpotSwitch(text, x, y, w, h)
    self.name = "chb"
    elseif self.type == ICONBUTTONTYPE then
    self.element = IconButton(text, x + 50, y - 20, w - 100, h + 30,
    "Cargo Bot:Crate Goal Red", "Top Text", "Bottom Text")
    self.name = "ibn"
    elseif self.type == SELECTLISTTYPE then
    self.element = SelectList(text, x, y, w, h, true)
    self.name = "sls"
    end
    self.name = self.name .. elementCount
    end

    function UIElement:setHandles()
    self.hRect[1] = Frame(self.element.x - 15, self.element:midY() - 15,
    30, 30)
    self.hRect[2] = Frame(self.element:midX() - 15, self.element.y - 15,
    30, 30)
    self.hRect[3] = Frame(self.element:right() - 15,
    self.element:midY() - 15, 30, 30)
    self.hRect[4] = Frame(self.element:midX() - 15,
    self.element:top() - 15, 30, 30)
    self.hRect[5] = Frame(self.element:midX() - 20,
    self.element:top() + 20, 40, 40)
    self.expandedFrame = Frame(self.element.x - 20, self.element.y - 20,
    self.element.w + 40, self.element.h + 50)
    end

    function UIElement:draw()
    self.element:draw()
    if self.handles then
    strokeWidth(2)
    noFill()
    for i = 1, 4 do
    if self.handleTouched == i then
    stroke(37, 219, 46, 106)
    else
    stroke(20, 47, 233, 118)
    end
    self.hRect[i]:roundRect(2)
    fill(57, 80, 208, 255)
    text(handleNames[i], self.hRect[i]:midX(),
    self.hRect[i]:midY())
    noFill()
    end
    stroke(19, 46, 233, 175)
    ellipse(self.hRect[5]:midX(), self.hRect[5]:midY(), 35)
    fill(48, 65, 193, 255)
    text("i", self.hRect[5]:midX(), self.hRect[5]:midY())
    end
    end

    function UIElement:decodeColor(c)
    return "color("..c.r..", "..c.g..", "..c.b..", "..c.a..")"
    end

    function UIElement:printInit()
    local s
    s = " "..self.name.." = "..self.element:initString("test").."\n"
    if self.element.fontSize ~= 18 then
    s = s.." "..self.name..".fontSize = "..self.element.fontSize
    .."\n"
    end
    if self.element.font ~= "HelveticaNeue-Light" then
    s = s.." "..self.name..".font = '"..self.element.font.."'\n"
    end
    if self.element.textColor ~= color(0, 0, 0, 255) then
    s = s.." "..self.name..
    ".textColor = "..
    self:decodeColor(self.element.textColor).."\n"
    end
    if self.element.background ~= color(0, 0, 0, 0) then
    s = s.." "..self.name..
    ".background = "..
    self:decodeColor(self.element.background).."\n"
    end
    if self.element.foreground ~= color(14, 14, 14, 255) then
    s = s.." "..self.name..
    ".foreground = "..
    self:decodeColor(self.element.foreground).."\n"
    end
    if self.element.highlightColor ~= color(0, 50, 255, 255) then
    s = s.." "..self.name..
    ".highlightColor = "..
    self:decodeColor(self.element.highlightColor).."\n"
    end
    if self.element.highlightedTextColor ~=
    color(255, 255, 255, 255) then
    s = s.." "..self.name..
    ".highlightedTextColor = "..
    self:decodeColor(self.element.highlightedTextColor).."\n"
    end
    return s
    end

    function UIElement:printDraw()
    return " "..self.name..":draw()\n"
    end

    function UIElement:printTouched()
    return " "..self.name..":touched(touch)\n"
    end

    function UIElement:touched(touch)
    if self.handles then
    if touch.state == BEGAN then
    self.handleTouched = 0
    for i = 1, 5 do
    if self.hRect[i]:touched(touch) then
    self.handleTouched = i
    end
    end
    if self.handleTouched == 5 then
    dialog = PropertiesDialog(selectedElement, self)
    dialog.visible = true
    end
    if self.handleTouched == 0 and
    self.expandedFrame:touched(touch) then
    self.handleTouched = 6
    end
    end

    if touch.state == MOVING then
    x = touch.x
    if tray.swtGrid.selected then
    x = math.floor(x/20) * 20
    end
    y = touch.y
    if tray.swtGrid.selected then
    y = math.floor(y/20) * 20
    end
    if self.handleTouched == 1 then
    self.element.x = x
    self:setHandles()
    end
    if self.handleTouched == 2 then
    self.element.y = y
    self:setHandles()
    end
    if self.handleTouched == 3 then
    if x > self.element.x + 30 then
    self.element.w = x - self.element.x
    end
    self:setHandles()
    end
    if self.handleTouched == 4 then
    if y > self.element.y + 30 then
    self.element.h = y - self.element.y
    end
    self:setHandles()
    end
    if self.handleTouched == 6 then
    self.element.x = x - self.element:width() / 2
    self.element.y = y
    self:setHandles()
    end
    end
    end
    if self.handles then
    if self.handleTouched > 0 then
    return true
    else
    return false
    end
    else
    return self.element:ptIn(touch)
    end
    end




    --# CodeWriter
    CodeWriter = class()

    function CodeWriter:init()

    end

    function CodeWriter:write()
    local s

    s = ""

    s = s.."-- Generated by Cider7\n"
    s = s.."--\n"
    s = s.."-- Add CiderControls7 as a dependency\n"
    s = s.."--\n"
    s = s.." \n"
    s = s.." \n"
    s = s.."function setup()\n"
    s = s.." displayMode(FULLSCREEN)\n"

    for i, e in ipairs(elements) do
    s = s..e:printInit().."\n"
    end


    s = s.."end\n"
    s = s.."\n"
    s = s.."function draw()\n"
    s = s.." background(255, 255, 255, 255)\n"

    for i, e in ipairs(elements) do
    s = s..e:printDraw()
    end


    s = s.."end\n"
    s = s.."\n"
    s = s.."function touched(touch)\n"

    for i, e in ipairs(elements) do
    s = s..e:printTouched()
    end

    s = s.."end\n"
    s = s.."\n"

    s = s.."function keyboard(key)\n"
    s = s.." if CCActiveTextBox then\n"
    s = s.." CCActiveTextBox:acceptKey(key)\n"
    s = s.." end\n"
    s = s.."end\n"
    s = s.." \n"
    saveProjectTab("Output", s)
    end