Skip to content

Instantly share code, notes, and snippets.

@devilstower
Created Aug 24, 2012
Embed
What would you like to do?
OnTopic Beta 1
AgendaItem = class()
-- an item for a meeting agenda
function AgendaItem:init(txt, len, s, e)
    self.startTime = s
    self.endTime = e
    self.duration = len
    self.name = txt
    self.notes = ""
    self.frame = Frame(0,0,0,0)
end
function AgendaItem:draw()
    
end
function AgendaItem:touched(touch)
end
Frame = class()
-- Frame (lite)
-- ver. 1.1
-- 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: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
-- AgendaTimer
-- Use this function to perform your initial setup
displayMode(FULLSCREEN)
rectMode(CORNERS)
font("HelveticaNeue")
function setup()
    --clearProjectData()
    VIEWING = 1
    EDITING = 2
    TITLES = 3
    HELP = 4
    -------------
    meetings = {}
    meeting = nil
    item = nil
    timePassed = 0
    startTime = ElapsedTime
    status = TITLES
    split = false
    blinkTimer = 0
    showSlider = false
    meetingScroll = 0
    itemScroll = 0
    startTime = ElapsedTime
    -------------
    playBtn = Frame(0,0,0,0)
    stopBtn = Frame(0,0,0,0)
    pauseBtn = Frame(0,0,0,0)
    addBtn = Frame(0,0,0,0)
    helpBtn = Frame(0,0,0,0)
    slider = TimeSlider(1)
    timeFrame = Frame(0,0,0,0)
    startFrame = Frame(0,0,0,0)
    -------------
    selectedMeeting = nil
    selectedMeetingPos = 0
    selectedItem = nil
    selectedItemPos = 0
    loadMeetings()
    if #meetings < 1 then
        meeting = Meeting("Example Meeting")
        item = AgendaItem("Greeting", 1, 0, 10)
        meeting:addItem(item)
        item = AgendaItem("Roundtable", 1, 0, 10)
        meeting:addItem(item)
        item = AgendaItem("Break Out", 1, 0, 10)
        meeting:addItem(item)
        item = AgendaItem("Closing", 1, 0, 10)
        meeting:addItem(item)
        meetings[1] = meeting
    end
    -------------
    
    selectedMeeting = meetings[1]
end 
function drawEditor()
    pushMatrix()
    if selectedMeeting and not isKeyboardShowing() 
    and not showSlider then
        showKeyboard()
    elseif showSlider and isKeyboardShowing() then
        hideKeyboard()
    end
    stroke(255, 0, 0, 255) 
    fill(127, 127, 127, 255)
    fontSize(64)
    if selectedItem ~= nil then
        
        --translate(-200,0)
    end
    text("Sessions", WIDTH/4, HEIGHT-35)
    text("Topics", WIDTH/4*3, HEIGHT-35)
    
    fontSize(24)
    textMode(CORNER)
    textAlign(LEFT)
    for i, meeting in ipairs(meetings) do
        meeting.frame = Frame(10, HEIGHT-140-i*50, 
        WIDTH/2 - 20, HEIGHT-140-i*50+50)
        fill(48, 140, 28, 173)
        stroke(40, 40, 50)
        meeting.frame:draw()
        fill(209, 209, 209, 255)
        text(meeting.name, meeting.frame.left+10, 
        meeting.frame.bottom+10)
        
    end
    if selectedMeeting then
        meeting = selectedMeeting
        strokeWidth(5)
        stroke(117, 127, 181, 255)
        line(meeting.frame.right-35,meeting.frame.bottom+15,
        meeting.frame.right-35,meeting.frame.top-15)
        line(meeting.frame.right-35,meeting.frame.bottom+15,
        meeting.frame.right-15,meeting.frame:midY())
        line(meeting.frame.right-35,meeting.frame.top-15,
        meeting.frame.right-15,meeting.frame:midY())
        for i, item in ipairs(meeting.items) do
            item.frame = Frame(WIDTH/2 + 20, HEIGHT-140-i*50, 
            WIDTH - 20, HEIGHT-140-i*50+50)
            fill(48, 140, 28, 169)
            stroke(40, 40, 50)
            item.frame:draw()
            fill(209, 209, 209, 255)
            fontSize(24)
            textAlign(LEFT)
            text(item.name, item.frame.left+10,
             item.frame.bottom+10)
            textAlign(RIGHT)
            fontSize(14)
            if math.floor(item.duration) <  10 then
                text(":0"..item.duration,
                item.frame.right - 48, item.frame.bottom+17)
            else
                text(":"..item.duration,
                item.frame.right - 48, item.frame.bottom+17)
            end
            if i == selectedItemPos then
                noFill()
                stroke(117, 127, 181, 255)
                ellipse(item.frame.right - 40, item.frame:midY(), 42)
           end 
        end
    end
   
    textMode(CENTER)
    textAlign(CENTER)
    stroke(127, 127, 127, 255)
    line(WIDTH/2, 40, WIDTH/2, HEIGHT-150)
    if selectedMeeting then
        stroke(24, 88, 189, 255)
    else
        stroke(122, 127, 134, 87)
    end
    
    addBtn = Frame(25,HEIGHT-125,50,HEIGHT-100)
    helpBtn = Frame(WIDTH-50,HEIGHT-125,WIDTH-25,HEIGHT-100)
    stroke(117, 127, 181, 255)
    strokeWidth(6)
    fill(48, 122, 157, 255)
    --line(addBtn:midX(), addBtn.bottom, addBtn:midX(), addBtn.top)
    --line(addBtn.left, addBtn:midY(), addBtn.right, addBtn:midY())
    fontSize(60)
    text("+", addBtn:midX(), addBtn:midY())
    fontSize(48)
    text("?", helpBtn:midX(), helpBtn:midY())
    if selectedMeeting then
        noFill()
        stroke(31, 64, 116, 255)
        strokeWidth(5)
        if selectedItem == nil then
            selectedMeeting.frame:draw()
        else
            selectedItem.frame:draw()
        end
    end
    textMode(CORNER)
    textAlign(LEFT)
    if showSlider and selectedItem then
        item = selectedItem
        slider:draw(item.value)
    elseif selectedMeeting then 
        if ElapsedTime > blinkTimer + 0.25 then 
            strokeWidth(5)
            stroke(217, 217, 217, 242)
            if selectedItem == nil then
                fontSize(24)
                w,h = textSize(selectedMeeting.name)
                w = w + 14
                line(selectedMeeting.frame.left + w, 
                selectedMeeting.frame.bottom + 10,
                selectedMeeting.frame.left + w, 
                selectedMeeting.frame.top - 10 )
            else
                fontSize(24)
                item = selectedItem
                w,h = textSize(item.name)
                w = w + 14
                line(item.frame.left + w, 
                item.frame.bottom + 10,
                item.frame.left + w, 
                item.frame.top - 10 )
            end
        end
        if ElapsedTime > blinkTimer + 0.5 then
            blinkTimer = ElapsedTime
        end
    end
    textMode(CENTER)
    textAlign(CENTER)
    popMatrix()
end
function draw()
    background(26, 26, 50, 255)
    strokeWidth(5)
    if status == VIEWING then 
        -- meeting underway
        meeting:draw()
    elseif status == TITLES then
        drawTitleScreen()
    elseif status == HELP then
        drawHelpScreen()
    else
        -- in editor
        drawEditor()
    end
    touch()
end
function findMeeting(touch)
    local m, mm
    for m, mm in ipairs(meetings) do
        if mm.frame:touched(CurrentTouch) then
            selectedMeeting = mm
            playBtn = Frame(meeting.frame.right - 65,
            mm.frame.bottom,meeting.frame.right,
            mm.frame.top)
            startFrame = mm.frame
            selectedItem = nil
            selectedItemPos = 0
        end -- end if touched
    end -- for m, meeting
end
function findItem(touch)
    local i, item
    -- see if 
    if selectedMeeting then
        for i, item in ipairs(selectedMeeting.items) do
            if item.frame:touched(CurrentTouch) then
                selectedItemPos = i
                selectedItem = item
                startFrame = item.frame
                timeFrame = item.frame
                timeFrame.left = item.frame.right - 65
            end
        end
    end -- end select item
end
function newMeeting(touch)
    local meeting
    meeting = Meeting("")
    meeting.items[1] = AgendaItem("Welcome", 1, 0, 0)
    table.insert(meetings, meeting)
    selectedMeeting = meeting
    selectedMeetingPos = table.maxn(meetings)
    selectedItem = nil
    selectedItemPos = 0
end
function newItem(touch)
    local item
    item = AgendaItem("", 1, 0, 0)
    table.insert(selectedMeeting.items, item)
    selectedItem = item
    selectedItemPos = table.maxn(selectedMeeting.items)
end
function saveMeetings()
    local n, m, s, c, i
    s = ""
    for n, m in ipairs(meetings) do
        s = s .. m.name 
        if n < #meetings then s=s.. "," end
    end
    saveProjectData("ONTOPIC", s)
    s = "ONTOPIC"
    for n, m in ipairs(meetings) do
        s=""
        for j, i in ipairs(m.items) do
            s = s .. i.name .. ","
            s = s .. math.floor(i.duration)
            if j < #m.items then s = s .. "," end
        end
        saveProjectData(m.name, s)
    end
end
function loadMeetings()
    -- read existing meetings
    local keys, k, s, i, count, m, item
    keys = readProjectData("ONTOPIC")
    if keys ~= nil then
        -- keys are a comma-delimited list
        for k in string.gmatch(keys,"([^,]+)") do
            -- k = name of meeting
            m = Meeting(k)
            -- now read topics for this meeting
            s = readProjectData(k)
            count = 0
            for i in string.gmatch(s,"([^,]+)") do
                if count == 0 then
                    name = i
                    count = 1
                else
                    item = AgendaItem(name, math.floor(i), 0, 0)
                    table.insert(m.items, item)
                    count = 0
                end
            end
            table.insert(meetings, m)
        end
    end
end
function touch()
    if CurrentTouch.state == BEGAN and
    CurrentTouch.state ~= oldState then
        
        -- track where touch began
        startX = CurrentTouch.x
    
        
        if status == VIEWING then
            -- viewing meeting or paused
            
            
            if selectedMeeting:touched(CurrentTouch) then
                status = EDITING
            end
            
        elseif status == TITLES then
            if playBtn:touched(CurrentTouch) then
                status = EDITING
                playBtn = Frame(0,0,0,0)
            end
            
        elseif status == HELP then
            if playBtn:touched(CurrentTouch) then
                status = EDITING
                playBtn = Frame(0,0,0,0)
            end
            
        elseif status == EDITING then
            -- editing meeting
            
            if playBtn:touched(CurrentTouch) then
                saveMeetings()
                meeting.timePassed = 0
                status = VIEWING
            end -- playBtn
            
            if helpBtn:touched(CurrentTouch) then
                saveMeetings()
                status = HELP
            end -- playBtn
            
            if addBtn:touched(CurrentTouch) then
                if selectedItem then
                    newItem(touch)
                else 
                    newMeeting(touch)
                end 
            end -- addBtn
            
            findMeeting(CurrentTouch)
            
            findItem(CurrentTouch)
            
            if timeFrame:touched(CurrentTouch) and selectedItem then
                slider.value = 
                selectedItem.duration
                showSlider = true
            end -- time frame
            
        end -- status == EDITING
    end -- touch == BEGAN
    
    if CurrentTouch.state == MOVING then
        if showSlider then
            slider:touched(CurrentTouch)
            selectedItem.duration = slider.value
        end
    end -- touch == MOVING
    
    if CurrentTouch.state == ENDED and 
    CurrentTouch.state ~= oldState then
        if showSlider then
            showSlider = false
        elseif startFrame:touched(CurrentTouch) and 
        startX < CurrentTouch.x - 75 then
        -- look to see if in start frame
            sound(SOUND_POWERUP, 28072)
            if selectedMeeting.frame:touched(CurrentTouch) then
                table.remove(meetings, selectedMeetingPos)
            elseif selectedItem.frame:touched(CurrentTouch) then
                table.remove(selectedMeeting.items, selectedItemPos)
                selectedItem = nil
                selectedItemPos = 0
            end
        end
    end -- touch == ENDED
    
    oldState = CurrentTouch.state
    
end
            
function keyboard(key)
    if key ~= nil then
        if string.byte(key) == 10 then
            selectedMeeting = nil
            saveMeetings()
            hideKeyboard()
            keyboardShown = false
        elseif string.byte(key) == nil then
            if string.len(selectedMeeting.name) > 0 then
                if selectedItem then
                    selectedItem.name = string.sub(selectedItem.name, 
                    1, string.len(selectedItem.name) - 1)
                else
                    selectedMeeting.name = 
                    string.sub(selectedMeeting.name, 
                    1, string.len(selectedMeeting.name) - 1)
                end
            end
        else
            if selectedItem then
                selectedItem.name = selectedItem.name..key
            else
                selectedMeeting.name = selectedMeeting.name..key
            end
        end
    end
end
 
Meeting = class()
function Meeting:init(txt)
    -- you can accept and set parameters here
    self.name = txt
    self.duration = 0
    self.startTime = ElapsedTime
    self.timePassed = 0
    self.paused = true
    self.items = {}
    self.style = 1
    self.frame = Frame(0,0,0,0)
    self.playBtn = Frame(0,0,0,0)
    self.stopBtn = Frame(0,0,0,0)
    self.pauseBtn = Frame(0,0,0,0)
end
function Meeting:addItem(item)
    self.duration = self.duration  + item.duration
    table.insert(self.items, item)
end
function Meeting:draw()
    local i, pixScale, left, right, bottom, top, totalTime
    pushStyle()
    if isKeyboardShowing() then
        hideKeyboard()
    end
    if self.style == 1 then
        fill(127, 127, 127, 255)
        stroke(255, 255, 255, 255)
        top = HEIGHT / 2 + HEIGHT / 4
        bottom = HEIGHT / 2 - HEIGHT / 4
        rect(10, bottom, WIDTH - 10, top)
        pixScale = (WIDTH-20) / self.duration
        left = 0
        right = 10
        width = 0
        noStroke()
        self.duration = 0
        for i, item in ipairs(self.items) do
            self.duration = self.duration + item.duration
        end
        totalTime = 0
        for i, item in ipairs(self.items) do
            if totalTime + item.duration * 60 < self.timePassed then
                fill(178, 107, 21, 255)
            elseif totalTime > self.timePassed then
                fill(49, 140, 28, 255)
            else
                fill(149, 164, 24, 255)
            end
                
            stroke(220, 218, 232, 255)
            
            left = right
            width = (item.duration * pixScale)
            right = left + width
            rect(left, bottom+5, right, top-5)
            fontSize(16)
            fill(255, 255, 255, 255)
            if right - left < 80 then 
                pushMatrix()
                translate(left + (width/2), HEIGHT/2 + 20)
                rotate(90)
                text(item.name, 0, 0)
                popMatrix()
            else
                text(item.name, left + (width/2), HEIGHT/2 + 20)
                fill(182, 182, 182, 255)
                text("("..timeString(item.duration*60)..")", left + 
                (width/2), HEIGHT/2 )
            end
            totalTime = totalTime + item.duration*60
            if right - left > 50 then
                fontSize(14)
                text(timeString(totalTime, false), 
                right-20, top + 11)
            end
            fontSize(30)
            if self.duration*60 - self.timePassed < 1 then
                self.paused = true
            end
            text(timeString((self.duration*60 - self.timePassed), true), 
            WIDTH/2, HEIGHT-100)
        end
    end
    if self.paused then
        stroke(82, 31, 31, 255)
    else
        stroke(31, 42, 89, 255)
    end
    strokeWidth(5)
    i = 10 + pixScale * self.timePassed / 60
    line(i - 3, top, i - 3, top - 50)
    line(i + 3, top, i + 3, top - 50)
    line(i - 3, bottom, i - 3, bottom + 50)
    line(i + 3, bottom, i + 3, bottom + 50)
    if self.paused then
        stroke(91, 45, 31, 132)
    else
        stroke(31, 41, 84, 125)
    end
    line(i, bottom, i, top)
    fill(220, 220, 220, 255)
    fontSize(14)
    text(timeString(self.timePassed, true),i, bottom-18)
    fontSize(36)
    text(self.name, WIDTH/2, HEIGHT-50)
    -- advance timer
    if not self.paused then
        self.timePassed = self.timePassed + 
        (ElapsedTime - self.startTime)
        self.startTime = ElapsedTime
    end
    
    -- calculate button positions and draw
    stroke(31, 64, 116, 255)
    strokeWidth(5)
    noFill()
    self.playBtn = Frame(100,50,150,100)
    line(100,50,100,100)
    line(100,100,140,75)
    line(140,75,100,50)
    self.pauseBtn = Frame(WIDTH/2-30,50,WIDTH/2+30,100)
    rect(WIDTH/2-30,50,WIDTH/2-5,100)
    rect(WIDTH/2+5,50,WIDTH/2+30,100)
    self.stopBtn = Frame(WIDTH-150,50,WIDTH-100,100)
    rect(self.stopBtn.left,self.stopBtn.bottom,
    self.stopBtn.right,self.stopBtn.top)
    popStyle()
end
function Meeting:touched(touch)
    
    if self.playBtn:touched(touch) and self.paused then
        sound(SOUND_PICKUP, 1329)
        self.paused = false
        self.startTime = ElapsedTime
    elseif self.pauseBtn:touched(touch) and not self.paused then
        self.paused = true
    elseif self.stopBtn:touched(touch) then
        return true
    end
    return false
end
TimeSlider = class()
function TimeSlider:init(v)
    -- you can accept and set parameters here
    self.value = v
end
function TimeSlider:draw()
    local s, t, x, y
    popStyle()
    strokeWidth(0)
    fill(117, 127, 181, 255)
    rect(WIDTH - 100, 50, WIDTH - 10, HEIGHT - 10)
    strokeWidth(5)
    stroke(70, 70, 70, 255)
    ellipse(WIDTH - 55, HEIGHT - 55, 70)
    
    fill(255, 255, 255, 255)
    if self.value < 10 then 
        s = ":0" .. self.value 
    else 
        s = ":" .. self.value 
    end
    fontSize(18)
    textMode(CENTER)
    textAlign(CENTER)
    text(s, WIDTH - 55, HEIGHT - 55)
    line(WIDTH - 90, HEIGHT - 100, WIDTH - 20, HEIGHT - 100)
    stroke(192, 192, 192, 255)
    fontSize(14)
    strokeWidth(2)
    stroke(255, 255, 255, 255)
    for i = 1,60 do
        y = HEIGHT-100-((HEIGHT - 160)/60 * i)
        line(WIDTH - 70, y, WIDTH - 20, y)
    end
    strokeWidth(5)
    for i = 1,6 do
        t = i * 10
        y = HEIGHT-100-((HEIGHT - 160) / 6 * i)
        line(WIDTH - 70, y, WIDTH - 20, y)
        if t < 10 then s = ":0" .. t else s = ":" .. t end
        text(s, WIDTH - 85, y )
    end
    stroke(255, 22, 0, 255)
    y = HEIGHT-100-((HEIGHT - 160)/60 * self.value)
    line(WIDTH - 75, y, WIDTH - 15, y)
   
    pushStyle()
end
function TimeSlider:touched(touch)
    local y 
    y = (HEIGHT - 100 - touch.y) / (HEIGHT - 160) * 60
    if y < 1 then y = 1 elseif y > 60 then y = 60 end
    self.value = math.floor(y)
end
function timeString(time, showSeconds)
    hours = math.floor(time / 3600)
    if hours < 10 then hours = "0"..hours end
    mins = math.floor(time / 60)
    mins = math.fmod(mins, 3600)
    if mins < 10 then mins = "0"..mins end
    if showSeconds then
        secs = math.floor(time)
        secs = math.fmod(secs, 60)
        if secs < 10 then secs = "0"..secs end
        return hours..":"..mins.." " ..secs.."s"
    else
        return hours..":"..mins
    end
end
function drawTitleScreen()
    pushStyle()
    font("Futura-CondensedExtraBold")
    fontSize(96)
    text("OnTopic", WIDTH/2, HEIGHT-100)
    fontSize(30)
    font("Futura-Medium")
    text("Manage your meeting.", WIDTH/2, HEIGHT-200)
    text("Conduct your session.", WIDTH/2, HEIGHT-250)
    text("Keep on schedule.", WIDTH/2, HEIGHT-300)
    text("Stay on topic.", WIDTH/2, HEIGHT-350)
    playBtn = Frame(10, 10, WIDTH-10, HEIGHT-10)
    sprite("Cargo Bot:Made With Codea", WIDTH/2, 70)
    fontSize(24)
    font("Papyrus")
    text("Copyright 2012 by Mark Sumner", WIDTH/2, 300)
    if ElapsedTime > startTime + 8 then
        status = EDITING
        playBtn = Frame(0,0,0,0)
    end
    popStyle()
end
function drawHelpScreen()
    if isKeyboardShowing() then
        hideKeyboard()
    end
    pushStyle()
    font("Futura-CondensedExtraBold")
    fill(82, 82, 82, 255)
    fontSize(96)
    text("OnTopic", WIDTH/2, HEIGHT-100)
    font("Papyrus")
    fontSize(24)
    text("Copyright 2012 by Mark Sumner", WIDTH/2, HEIGHT-220)
    fill(153, 176, 187, 255)
    fontSize(30)
    font("Futura-Medium")
    textMode(CORNER)
    textAlign(LEFT)
    text("Create a new event or topic by selecting an", 100, HEIGHT-400)
    text("existing item and tapping '+'", 100, HEIGHT-450)
    text("Touch the topic timer to change the", 100, HEIGHT-550)
    text("duration of a topic.", 100, HEIGHT-600)
    text("Start the session with a tap on the ", 100, HEIGHT-700)
    text("play button.", 100, HEIGHT-750)
    playBtn = Frame(10, 10, WIDTH-10, HEIGHT-10)
    popStyle()
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment