Page Controller

This is a page controller designed to mimic the behaviour of things like the home screen on your ipad. It is still work in progress but it is usable as it is. There are instructions for use in the HowTo tab. If you have any questions, feedback or suggestions please comment below.


--# Main

function setup()
   
    pgCtrl=PageController(6)
    print("swipe about and press the buttons!")
end

function draw()
    pgCtrl:update()
    background(0)
    spriteMode(CENTER)
    sprite("Cargo Bot:Game Lower BG",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
    pushMatrix()
    translate(pgCtrl:getTranslateAmount())
    fill(0)
    textMode(CENTER)
    fontSize(50)
    for i=1,6 do
        local W=300
        if i==pgCtrl:currentPage() then W=400 end
        sprite("Cargo Bot:Codea Icon",WIDTH*(i-0.5),HEIGHT/2,W)
        text(i,WIDTH*(i-0.5),HEIGHT/2)
    end
    popMatrix()
    spriteMode(CORNER)
    sprite("Cargo Bot:Command Right",WIDTH-50,0,50)
    sprite("Cargo Bot:Command Left",0,0,50)
    text("page "..pgCtrl:currentPage(),WIDTH/2,HEIGHT-50)
    pgCtrl:drawPageCircs(30)
end

function touched(touch)
    local translatedTouch=pgCtrl:touched(touch)
    if touch.state==BEGAN then
        if pointInRect(touch.x,touch.y,0,0,50,50) then 
            pgCtrl:goRight() 
        end
        if pointInRect(touch.x,touch.y,WIDTH-50,0,50,50) then 
            pgCtrl:goLeft() 
        end
        local W,H=400,400
        for i=1,6 do
if pointInRect(translatedTouch.x,translatedTouch.y,WIDTH*(i-0.5)-W/2,HEIGHT/2-H/2,W,H) then
                print("you touched button: "..i)
            end
        end
    end
end

function pointInRect(ptx,pty,x,y,w,h)
    return (x<=ptx and ptx<=x+w and y<=pty and pty<=y+h)
end








--# PageController
PageController = class()

function PageController:init(npgs,page,width)
    self.numPages=npgs
    self.pageW=w or WIDTH
    self.offset=((page or 1)-1)*self.pageW
    self.min=0
    self.max=self.pageW*(self.numPages-1)
    self.alignTw=nil
    self.swipeSpeed=800
    self.tweenDelay=0.3
    self.touchInfo={startPos=0,startTime=0,time=0,dist=0,speed=0}
    self.touchDown=false
end

function PageController:update()
    if self.alignTw==nil and self.touchDown==false then
        self:snap()
    end
    --translate(-self.offset,0)
end

function PageController:getTranslateAmount()
    return -self.offset,0
end

function PageController:drawPageCircs(s)
    local r=s or 20
    local w=(self.numPages*2-1)*r
    noStroke()
    fill(255)
    ellipseMode(CORNER)
    for i=1,self.numPages do
        local x=(self.pageW/2-w/2)+(r*(i-1)*2)
        if i==
math.min(self.numPages,math.max(1,math.floor((self.offset+self.pageW)/self.pageW+0.5))) then 
            fill(255,255) 
        else 
            fill(255,100) 
        end
        ellipse(x,0+r,r,r)
    end
end

function PageController:touched(t)
    if t.state==BEGAN then
        self.touchInfo.startPos=t.x
        self.touchInfo.startTime=ElapsedTime
        if self.alignTw then
            tween.stop(self.alignTw)
            self.alignTw=nil
        end
        self.touchDown=true
    end
if (ElapsedTime-self.touchInfo.startTime)>0.1 then
    local move=-t.deltaX
    local factr=20
    if self.offset<=self.min and move<0 then
        local diff=self.min-self.offset
        if diff~=0 then
            move=move/diff*factr
        end
    elseif self.offset>=self.max and move>0 then
        local diff=self.offset-self.max
        if diff~=0 then
            move=move/diff*factr
        end
    end
    self.offset = self.offset +move
end
    if t.state==ENDED then
        self.touchDown=false
        self.touchInfo.dist=(t.x-self.touchInfo.startPos)
        self.touchInfo.time=ElapsedTime-self.touchInfo.startTime
        self.touchInfo.speed=self.touchInfo.dist/self.touchInfo.time
        if self.touchInfo.speed>self.swipeSpeed and self:currentPage()>1 then
            self:goTo(self:currentPage()-1)
        elseif self.touchInfo.speed<-self.swipeSpeed and self:currentPage()<self.numPages then
            self:goTo(self:currentPage()+1)
        end
    end
    local tch=self:makeTouch(t)
    tch.x = tch.x +self.offset
    tch.prevX = tch.prevX +self.offset
    return tch
end

function PageController:goTo(num)
    if self.alignTw then tween.stop(self.alignTw)end
    self.alignTw=tween(0.3,self,{offset=(num-1)*self.pageW},
                       nil,function(obj) obj.alignTw=nil end,self)
end

function PageController:snap()
    self.alignTw=tween(0.2,self,{offset=(self:currentPage()-1)*self.pageW},
                       nil,function(obj) obj.alignTw=nil end,self)
end

function PageController:currentPage()
    return math.floor(self.offset/self.pageW+0.5)+1
end

function PageController:goLeft()
    local t=self:currentPage()+1
    if t<=self.numPages then
        self:goTo(t)
    end
end

function PageController:goRight()
    local t=self:currentPage()-1
    if t>=1 then
        self:goTo(t)
    end
end

function PageController:makeTouch(touch)
    local t={}
    t.x=touch.x;t.y=touch.y;t.deltaX=touch.deltaX;t.deltaY=touch.deltaY;t.prevX=touch.prevX;
    t.prevY=touch.prevY;t.id=touch.id;t.state=touch.state;t.tapCount=touch.tapCount;
    return t
end


--# HowTo
--[[

PageController
this class manages menus and other page based scrolling interfaces. it is based on the apple 
home screen.

How to use:

-define a PageController and pass it:
    a number of pages, 
    the page it will start on(default 1),
    and the width of each page(default is the screen width: WIDTH)
~~
pgCtrl=PageController(6,2,WIDTH)
~~

-in draw, call the update method
~~
pgCtrl:update()
~~
    before you draw elements that will move when you scroll the pages do:
~~
translate(pgCtrl:getTranslateAmount())
~~
    this will move them to the right position
    objects should be placed relative to the first page so an object on page 'n' should be at:
        x=pgCtrl.pageW*(n-1)+x_position_on_page,y=y_position_on_page

    you can also call the drawPageCircs method to draw the circles which indocate the page you
    are on, you can optionaly pass it the circle radius
~~
pgCtrl:drawPageCircs(10)
~~

-in the touched(touch)function call the touched method for the page controller. this will 
deal with scrolling the pages. it returns a touch that has been translated relative to the current
page.
~~
local translatedTouch=pgCtrl:touched(touch)
~~
    use translatedTouch for objects that scroll with the page controller and normal touch for ones
    that don't

-call the goTo method to go to the specified page
~~
pgCtrl:goTo(3)
~~

-call the goRight and goLeft methods to move one page right or left
~~
pgCtrl:goRight()
pgCtrl:goLeft()
~~

-call the currentPage method to get the current page number
~~
pgCtrl:currentPage()
~~


--]]

The user and all related content has been deleted.

Thanks :slight_smile: feel free to use it if you want