Alerts library in codea

This is a basic WIP library for displaying iOS style alerts in codea. The code is below (very messy)with two examples of use.

Alert = class()

function Alert:init(t,d)
    self.shown=false
    self.drawstuff=d
    self.touchcode=t
    self.padding=5
    self.width=300
    self.buttons={}
end

function Alert:draw()
    if self.shown then
        pushStyle()
        if self.drawstuff then
            if self.img==nil then
                self.img=image(WIDTH,HEIGHT)
                setContext(self.img)
                self.drawstuff()
            end
        spriteMode(CORNER)
        sprite(self.img,0,0)
        end
        fill(0,100)
        rectMode(CORNER)
        rect(-1,-1,WIDTH+2,HEIGHT+2)
        stroke(0)
        strokeWidth(2)
        
        textAlign(CENTER)
        font("HelveticaNeue-Bold")
        fontSize(30)
        
        local lastH,points=self:drawtext(self.info.title,color(0))
        
        font("HelveticaNeue")
        fontSize(20)
        
        lastH,points=self:drawtext(self.info.body,color(0),lastH)
        
        for i=1,#self.options do
            lastH,points=self:drawtext(self.options[i].display,color(0,0,255),lastH)
            if not self.buttons[i] then
                self.buttons[i]=RectButton(points,self.options[i].call)
            end
        end
        
        for i=1,#self.buttons do
            self.buttons[i]:draw()
        end
        
        popStyle()
        
    else
        if self.drawstuff then self.drawstuff() end
    end
end

function Alert:touched(touch)
    if self.shown then
        local i=1
        while i<=#self.buttons do
            self.buttons[i]:touched(touch)
            if self.buttons[i].pressed==true then
                self:hide()
                return
            end
            i = i + 1
        end
    else
        self.touchcode(touch)
    end
end

function Alert:show(i,o)
    self.shown=true
    self.info=i
    --{title="",body=""}
    self.options=o
    --{{title,function}...}
end

function Alert:hide()
    for i=#self.buttons,1,-1 do
        table.remove(self.buttons,i)
    end
    self.img=nil
    self.info =nil
    self.options=nil
    self.shown=false
end

function Alert:drawtext(t,tcol,height)
    local y=height or WIDTH/2
    local w,h=textSize(t)
    if w>self.width-self.padding*2 then
        textWrapWidth(self.width-self.padding*2)
    end
    w,h=textSize(t)
    fill(255)
    rectMode(CENTER)
    rect(WIDTH/2,y-h/2+self.padding,self.width,h+self.padding+2)
    fill(tcol)
    text(t,WIDTH/2,y-h/2+self.padding)
           
    textWrapWidth(0)
    return y-h-self.padding,{x=WIDTH/2,y=y-h/2+self.padding,w=self.width,h=h+self.padding}
end


RectButton = class()

function RectButton:init(i,a)
    self.x = i.x
    self.y = i.y 
    self.width = i.w
    self.height = i.h
    self.action=a
    self.pressed=false
    self.col=color(0,100)
    self.hit=false
end

function RectButton:draw()
    pushStyle()
    rectMode(CENTER)
    noStroke()
    if self.hit then fill(self.col) else noFill() end
    rect(self.x,self.y,self.width,self.height)
    popStyle()
end

function RectButton:touched(touch)
    if self.x-self.width/2 < touch.x and touch.x < self.x+self.width/2 and 
       self.y-self.height/2 < touch.y and touch.y < self.y+self.height/2 then
        self.hit=true
        if touch.state == ENDED then
            self.action()
            self.pressed=true
            self.hit=false
        end
        --return true
    else
        self.hit =false
    end
    if touch.state==ENDED then
        self.hit=false
    end
end

Tap to show an alert
Example 1: this will pause all drawing

function setup()
    a=Alert(touchcode,drawstuff) 
--the two function that handle normal drawing and touch reaction
    x=0
end

function draw()
    a:draw()
end

function touched(touch)
    a:touched(touch)
end

function drawstuff()
    background(29, 255, 0, 255)
    x = x + 4
    if x>WIDTH then x=0 end
    fill(255, 0, 0, 255)
    ellipse(x,100,50,50)
end

function touchcode(touch)
    if touch.state==ENDED then --trigger an alert
        a:show({title="alert title",body="alert description"},
        {{display="close",call=close},-- the two buttons to press
        {display="print hello",call=function()print("hello") end}}) 
    end
end

Example2: this will not pause normal drawing

function setup()
    a=Alert(touchcode)
--only pass the function that handles touches as we will do the drawing ourselves
    x=0
end

function draw()
    background(29, 255, 0, 255)
    x = x + 4
    if x>WIDTH then x=0 end
    fill(255, 0, 0, 255)
    ellipse(x,100,50,50)
    a:draw()
end

function touched(touch)
    a:touched(touch)
end

function touchcode(touch)
    if touch.state==ENDED then
        a:show({title="alert title",body="alert description"},
        {{display="close",call=close},
        {display="print hello",call=function()print("hello") end}}) 
    end
end

@Coder, or

-- alert

function setup()
    print("Hello world")
    alert("This is a alert", "Alert") -- alert
end

We got alerts in 2.0 didn’t we?

@Luatee - I think it was 1.5.5. Anyways, if you’re making an application for the App Store, make sure to check out my Objective C library for advanced ones.

We got alerts in 1.5.5. I did suggest more advanced alerts though, with multiple buttons and callbacks, as you have here.

You could theoretically automatically pause drawing by overriding the draw function to only be called when an alert is not shown.

@Coder, I like the idea of having multiple buttons and callbacks, I dislike that these don’t look like native alerts. Still nice work!

@Zoyt, your addon is great, but unfortunately it requires exporting. I wish we could enable addons directly in Codea, that’d be really cool.

I’m still working on the way that these are drawn and trying to make them look more like native alerts. I just wanted to solve the problem of not having advanced alerts in codea as I don’t have xcode.