Codea Flat Look Mockup written in Codea

Hello,
I wanted to see what Codea would look like if it matched the website, and here,s what I came up with:
Thanks!
P.S. The code’s certainly not clean, but it’s a mockup.

Main:

-- Codea Mockup
displayMode(FULLSCREEN_NO_BUTTONS)
supportedOrientations(LANDSCAPE_ANY)

-- Use this function to perform your initial setup
function setup()
    local downloaded = 0
    --saveLocalData("imgDownloaded",false)
    if not readLocalData("imgDownloaded") then
        requests = {
            "AirCode",
            "Assets",
            "Background",
            "Functions",
            "Settings",
            "ShaderLab",
            "Sidebar",
            "Talk"
        }
        local indicateSaved = function()
                if downloaded == #requests then
                    saveLocalData("imgDownloaded",true)
                    ready = true
                end
            end
        for i,v in ipairs(requests) do
            http.request("http://flurry.name/zoyt/flatCodeaImages/"..v..".png",
                function(d,status)
                    if status == 200 then
                        saveImage("Documents:"..v,d)
                        downloaded = downloaded + 1
                        indicateSaved()
                    end
                end,
                function()
                    error("Fail on "..v)
                end)
        end
    end
    
    tUsedId = nil
    colors = {
        color(49,189,181)
    }
    
    scene = Start()
    
    font("SourceSansPro-Regular")
end

-- This function gets called once every frame
function draw()
    if math.random() < .001 then
        alert("@Zoyt commented on your thread","Codea Talk Notification")
    end
    scene:draw()
end

function touched(t)
    scene:touched(t)
end

Start:

Start = class()

function Start:init()
    self.overlayColor = color(0, 0, 0, 0)
    self.transX = 0
    self.mode = 0
    self.bgImg = readImage("Documents:Background")
    self.bgGrad = gradient(
    color(255, 255, 255, 183),
    color(255, 255, 255, 0))
    self.projects = {
        {
            name = "Examples",
            projects = {
                "Sounds-NEW",
                "UI-NEW",
                "3D Models-NEW",
                "GPS-NEW",
                "Sockets",
                "Shapes"
            }
        },
        {
            name = "General",
            projects = {
                "+",
                "Project 1",
                "Project 2"
            }
        },
        {
            name = "Zoyt's Projects",
            projects = {
                "+",
                "StackIt",
                "Draw 'n Bounce",
                "2D Water"
            }
        },
        {
            name = "New Folder",
            projects = {
                "+"
            }
        },
    }
    self.apps = {
        {
            img = readImage("Documents:Functions"),
            name = "Reference"
        },
        {
            img = readImage("Documents:ShaderLab"),
            name = "Shader Lab"
        },
        {
            img = readImage("Documents:Assets"),
            name = "Assets"
        },
        {
            img = readImage("Documents:AirCode"),
            name = "Air Code"
        },
        {
            img = readImage("Documents:Talk",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT),
            name = "Talk"
        }
    }
end

function Start:draw()
    
    background(255, 255, 255, 255)
    pushMatrix()
    translate(self.transX,0)
    if self.bgImage then
        sprite(self.bgImg,WIDTH/2,HEIGHT/2,self.bgImg.width/2,self.bgImg.height/2)
    elseif math.random() < .001 then
        self.bgImg = readImage("Documents:Background")
    end
    fill(255, 255, 255, 255)
    sprite(self.bgGrad,WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    
    local folderY = HEIGHT-130
    for i,v in pairs(self.projects) do
        pushMatrix()
        pushStyle()
        translate(0,folderY)
        strokeWidth(30)
        stroke(colors[1])
        lineCapMode(SQUARE)
        line(0,0,WIDTH,0)
        clip(self.transX,folderY-15,WIDTH,30)
        fill(255, 255, 255, 255)
        fontSize(30)
        textMode(CORNER)
        text(v.name,20,-20)
        clip()
        
        local projX = 20
        noStroke()
        translate(0,-25)
        for i,v in ipairs(v.projects) do
            pushMatrix()
            translate(projX,0)
            fill(colors[1])
            rect(0,-150,150,150)
            clip(projX+self.transX,folderY-175,150,150)
            fill(255, 255, 255, 255)
            fontSize(150)
            textMode(CORNER)
            text(v,40,-170)
            if string.sub(v,-4) == "-NEW" then
                pushMatrix()
                pushStyle()
                translate(17,-15)
                rotate(45)
                fill(255, 0, 0, 255)
                rect(-50,-10,100,20)
                fill(255, 255, 255, 255)
                fontSize(18)
                textMode(CENTER)
                text("New",0,0)
                popMatrix()
                popStyle()
            end
            clip()
            fontSize(17)
            textMode(CENTER)
            if v == "+" then
                v = "Add Project"
            elseif string.sub(v,-4) == "-NEW" then
                v = string.sub(v,0,string.len(v)-4)
            end
            text(v,75,-140)
            projX = projX + 175
            popMatrix()
        end
        folderY = folderY - 200
        popMatrix()
        popStyle()
    end
    
    pushStyle()
    fill(colors[1])
    rect(0,0,10,HEIGHT)
    rect(WIDTH-10,0,10,HEIGHT)
    rect(0,HEIGHT-80,WIDTH,80)
    popStyle()
    
    -- Codea logo
    pushStyle()
    clip(self.transX,HEIGHT-80,WIDTH,80)
    fill(255, 255, 255, 255)
    fontSize(100)
    text("Codea",WIDTH/2,HEIGHT-45)
    clip()
    popStyle()
    
    sprite("Documents:Sidebar",30,HEIGHT-30,30,30)
    sprite("Documents:Settings",WIDTH-30,HEIGHT-30,30,30)
    
    pushStyle()
    fill(self.overlayColor)
    rect(0,0,WIDTH,HEIGHT)
    popStyle()
    
    -- Draw sidebar
    pushMatrix()
    pushStyle()
    fill(colors[1])
    rect(-125,0,125,HEIGHT)
    local appPos = HEIGHT-50
    fill(255, 255, 255, 255)
    for i,v in ipairs(self.apps) do
        sprite(v.img,-62.5,appPos,75,75)
        textWrapWidth(0)
        text(v.name,-62.5,appPos-50)
        appPos = appPos - 125
    end
    popMatrix()
    popStyle()
    
    -- Draw settings
    pushMatrix()
    pushStyle()
    translate(WIDTH,0)
    fill(colors[1])
    rect(0,0,300,HEIGHT)
    fill(255, 255, 255, 255)
    text("Same settings screen",150,HEIGHT/2)
    popMatrix()
    popStyle()
    
    popMatrix()
end

function Start:touched(t)
    if self.mode == 0 then
        if t.x < 75 and t.y > HEIGHT-75 and t.state == 0 and tUsedId ~= t.id then
            tUsedId = t.id
            self.mode = -1
            tween(.2,self,{transX = 125})
            tween(.2,self.overlayColor,{a = 85})
        elseif t.x > WIDTH-75 and t.y > HEIGHT-75 and t.state == 0 and tUsedId ~= t.id then
            tUsedId = t.id
            self.mode = 1
            tween(.2,self,{transX = -300})
            tween(.2,self.overlayColor,{a = 85})
        end
        
        if t.state == 0 and tUsedId ~= t.id then
            local folderY = HEIGHT-130
            for i,v in pairs(self.projects) do
                local projX = 20
                for i,p in ipairs(v.projects) do
                    if isInside(vec2(t.x,t.y),projX+self.transX,folderY-175,150,150) then
                        tUsedId = t.id
                        if p == "+" then
                            table.insert(v.projects,"Hello World")
                        else
                            scene = Code()
                            --alert("","Coding screen coming soon")
                        end
                    end
                    projX = projX + 175
                end
                folderY = folderY - 200
            end
        end
            
    elseif self.mode == -1 then
        if t.x > self.transX and t.state == 0 and tUsedId ~= t.id then
            tUsedId = t.id
            self.mode = 0
            tween(.2,self,{transX = 0})
            tween(.2,self.overlayColor,{a = 0})
        end
    elseif self.mode == 1 then
        if t.x < WIDTH+self.transX and t.state == 0 and tUsedId ~= t.id then
            tUsedId = t.id
            self.mode = 0
            tween(.2,self,{transX = 0})
            tween(.2,self.overlayColor,{a = 0})
        end
    end
end

Code:

Code = class()

function Code:init()
    self.transX = 0
    self.search = false
    self.navBar = {
        left = {
            "Close",
            "Search",
            "Docs"
        },
        right = {
            "Run"
        }
    }
    self.tabs = {
        "Main",
        "Class",
        "Library",
        "Extra tab",
        "Extra tab"
    }
end

function Code:draw()
    background(255, 255, 255, 255)
    pushMatrix()
    translate(self.transX,0)
    
    pushStyle()
    fontSize(50)
    fill(colors[1])
    text("Code here",WIDTH/2,HEIGHT/2)
    popStyle()
    
    pushStyle()
    fill(colors[1])
    rect(0,0,WIDTH,40)
    fill(255, 255, 255, 255)
    iconX = 5
    strokeWidth(2)
    stroke(255, 255, 255, 255)
    fontSize(17)
    for i,v in ipairs(self.navBar.left) do
        iconX = iconX + textSize(v)/2+10
        text(v,iconX,20)
        iconX = iconX + textSize(v)/2+10
        line(iconX,5,iconX,35)
    end
    iconX = WIDTH-5
    for i,v in ipairs(self.navBar.right) do
        iconX = iconX - textSize(v)/2-10
        text(v,iconX,20)
        iconX = iconX - textSize(v)/2-10
        line(iconX,5,iconX,35)
    end
    popStyle()
    
    pushStyle()
    local tabX = 0
    local tabCol = color()
    tabCol.r = colors[1].r
    tabCol.g = colors[1].g
    tabCol.b = colors[1].b
    tabCol.a = colors[1].a
    fontSize(17)
    for i,v in ipairs(self.tabs) do
        local tabSize = textSize(v) + 20
        fill(tabCol)
        rect(tabX,HEIGHT-50,tabSize,50)
        fill(255, 255, 255, 255)
        text(v,tabX+tabSize/2,HEIGHT-25)
        tabX = tabX + tabSize - 1
        tabCol.r = tabCol.r - 20
        tabCol.g = tabCol.g - 20
        tabCol.b = tabCol.b - 20
    end
    zLevel(-1)
    fill(tabCol)
    rect(0,HEIGHT-50,WIDTH,50)
    if self.search then
        pushStyle()
        rect(0,HEIGHT-90,WIDTH,41)
        fill(255, 255, 255, 255)
        textMode(CORNER)
        text("Search:",10,HEIGHT-83)
        rect(75,HEIGHT-85,200,30)
        text("Replace:",285,HEIGHT-83)
        rect(355,HEIGHT-85,200,30)
        tabCol.r = tabCol.r - 20
        tabCol.g = tabCol.g - 20
        tabCol.b = tabCol.b - 20
        fill(tabCol)
        rect(565,HEIGHT-85,75,30)
        fill(255, 255, 255, 255)
        text("Replace",575,HEIGHT-83)
        fill(tabCol)
        rect(650,HEIGHT-85,100,30)
        fill(255, 255, 255, 255)
        text("Replace All",660,HEIGHT-83)
        fill(tabCol)
        rect(WIDTH-62,HEIGHT-85,52,30)
        fill(255, 255, 255, 255)
        text("Next",WIDTH-52,HEIGHT-83)
        fill(tabCol)
        rect(WIDTH-150,HEIGHT-85,80,30)
        fill(255, 255, 255, 255)
        text("Previous",WIDTH-140,HEIGHT-83)
        popStyle()
    end
    
    tabCol.r = tabCol.r - 20
    tabCol.g = tabCol.g - 20
    tabCol.b = tabCol.b - 20
    fill(tabCol)
    rect(WIDTH-50,HEIGHT-50,50,50)
    fill(255, 255, 255, 255)
    fontSize(40)
    text("+",WIDTH-25,HEIGHT-25)
    popStyle()
end

function Code:touched(t)
    local iconX = 5
    for i,v in ipairs(self.navBar.left) do
        local nextIconX = iconX + textSize(v)+20
        if isInside(vec2(t.x,t.y),iconX,0,nextIconX,40) and t.state == 0 and tUsedId ~= t.id then
            tUsedId = t.id
            if i == 1 then
                scene = Start()
            elseif i == 2 then
                if self.search then
                    self.search = false
                else
                    self.search = true
                end
            end
        end
        iconX = nextIconX
    end
end

Functions:

function gradient(startCol, endCol)
    local img = image(64,64)
    
    local function blendColor( c1, c2, a )
        return color( c1.r * a + c2.r * (1 - a),
                      c1.g * a + c2.g * (1 - a),
                      c1.b * a + c2.b * (1 - a),
                      c1.a * a + c2.a * (1 - a) )
    end

    local a = 1
    local c = nil
    
    for y = 1,img.rawHeight do
        a = y / img.rawHeight
        for x = 1,img.rawWidth do
            c = blendColor(startCol, endCol, a)
            img:rawSet( x, y, c )
        end
    end
    
    return img
end

function isInside(p,x,y,width,height)
    if p.x > x and p.x < x+width and p.y > y and p.y < y+height then
        return true
    else
        return false
    end
end

Sprite error in Start : 176
Also it’s a pain to paste in so many tabs. Will it not fit in a single post?

Never mind I forgot about the need to restart codea after images are downloaded.

@Zoyt Very impressive! I really like it. I also love all the example project that include features we are hopeful for :slight_smile:

@Zoyt, haha very nice! Quit spamming my threads, lol :stuck_out_tongue: (that alert kept running in an infinite loop for me after some time, hehe)

@Briarfox - Thanks.
@Slashin8r - Haha. Thanks.

@Zoyt - Thanks. You give me a really good idea ^^

@HyroVitallyProtago - Your welcome. Looking forward to seeing that idea.

Very nice, I especially like the random pop up notification :

@Zoyt very cool concept. I enjoy seeing your take on the UI.

@JakAttak, @Simeon - Thanks.