PC-Style MenuBar

Here is an example of a PC-Style MenuBar. I’m not sure how useful this would be, but I just needed something small to work on. Taping the screen at the top displays the menu bar. Tapping the menu bar shows the sub menu items. Tapping a sub menu item starts a simple demo. Tapping the top of the screen again brings the menu bar back to allow you to make another selection. You can make the menu as wide as you want, and you can add as many sub menu items as you want. A sub menu item can call a function or another sub menu, so you can have multiple sub menus below a main menu item. You will get an error if a sub menu item isn’t set up correctly. I left some errors in the sub menu so you can see the error message.


-- PC-Style MenuBar

function setup()
    MenuSetup()
    displayMode(FULLSCREEN)
    supportedOrientations(PORTRAIT)
end

function MenuSetup()
    pointer1=nil
    pointer2=nil
    pointer3=nil
    b1tab={}
    b2tab={}
    b3tab={}
    b3atab={}
    b3btab={}
    b4tab={}
    b5tab={}
    
    y=HEIGHT-30
    -- create table for main menu bar
    -- menuBar(x pos, y pos, width, height, description, table or function pointer)
    table.insert(b1tab,menuBar(100,y,100,30,"Rectangles",b2tab))
    table.insert(b1tab,menuBar(200,y,100,30,"Circles",b3tab))
    table.insert(b1tab,menuBar(300,y,100,30,"Lines",b4tab))
    table.insert(b1tab,menuBar(400,y,100,30,"Squares",b5tab))
    table.insert(b1tab,menuBar(500,y,100,30,"Exit Prog.",exit))  

    y=HEIGHT-60
    -- create tables for sub menu items
    table.insert(b2tab,menuBar(100,y,100,30,"R-Small",rectsmall)) 
    table.insert(b2tab,menuBar(100,y-30,100,30,"R-Medium",rectmedium))
    table.insert(b2tab,menuBar(100,y-60,100,30,"R-Large",rectlarge))
    
    table.insert(b3tab,menuBar(200,y,100,30,"C-Small",circlesmall))
    table.insert(b3tab,menuBar(200,y-30,100,30,"C-Medium",circlemedium))
    table.insert(b3tab,menuBar(200,y-60,100,30,"Next",b3atab))
    
    table.insert(b3atab,menuBar(200,y,100,30,"C-Large",circlelarge))
    table.insert(b3atab,menuBar(200,y-30,100,30,"empty",empty))  -- causes an error
    table.insert(b3atab,menuBar(200,y-60,100,30,"Ellipse",b3btab))
    
    table.insert(b3btab,menuBar(200,y,100,30,"S-Ellipse",ellipsesmall))
    table.insert(b3btab,menuBar(200,y-30,100,30,"Rectangles",rect1))  -- causes an error
    
    table.insert(b4tab,menuBar(300,y,100,30,"L-Thin",linethin))
    table.insert(b4tab,menuBar(300,y-30,100,30,"L-Wide",linewide))
    
    table.insert(b5tab,menuBar(400,y,100,30,"L-Squares",squareslarge))
end

function draw() 
    background(40, 40, 50)
    text("Demo showing PC-Style Menu Bar",WIDTH/2,300)
    text("Tap the top of the screen to show the menu bar",WIDTH/2,200)
    text("Tap the menu bar to show the sub menus",WIDTH/2,175)
    text("Tap a sub menu item for the selected demo",WIDTH/2,150)
    text("Hide the menu bar by tapping away from it",WIDTH/2,125)
    menuBar:menu1()
end

function touched(t)
    if t.state==BEGAN then
        menuBar:check(t)
        menuBar:on(t)
    end
end 

-- demo functions used to show menu bar selection    
function ellipsesmall()
    pushStyle()
    fill(255)
    x=math.random(WIDTH)
    y=math.random(HEIGHT)
    ellipse(x,y,30,60)
    popStyle()
end

function linethin() lines99(6) end

function linewide() lines99(20) end

function lines99(w) 
    pushStyle()
    fill(255)
    x=math.random(WIDTH)
    y=math.random(HEIGHT)
    stroke(255,0,0)
    strokeWidth(w)
    line(x,y,y,x)
    popStyle()
end

function circlesmall() circles99(30)end

function circlemedium() circles99(60) end

function circlelarge() circles99(90) end

function circles99(r)
    pushStyle()
    fill(255)
    x=math.random(WIDTH)
    y=math.random(HEIGHT) 
    ellipse(x,y,r,r)
    popStyle()
end

function rectsmall() rects99(20,40) end

function rectmedium() rects99(40,80) end

function rectlarge() rects99(80,160) end

function rects99(w,h)
    pushStyle()
    fill(255)
    x=math.random(WIDTH)
    y=math.random(HEIGHT)
    stroke(255,0,0)
    strokeWidth(6)
    rect(x,y,w,h)
    popStyle()    
end

function squareslarge()
    pushStyle()
    fill(255)
    x=math.random(WIDTH)
    y=math.random(HEIGHT)
    stroke(255,0,0)
    strokeWidth(6)
    rect(x,y,100,100)
    popStyle()    
end

function exit() close() end
-- end of demo functions used to show menu bar selections


menuBar=class()

local selected

function menuBar:init(x,y,w,h,description,table)
    self.x=x
    self.y=y
    self.w=w
    self.h=h
    self.d=description
    self.pointer=table
    self.error=menuBar:error()
end

function menuBar:on(t)
    if t.y>HEIGHT-30 and table1==nil then
        pointer1=b1tab
    end    
end

function menuBar:check(t)
    local x
    selected=false
    
    if pointer1~= nil then
        for x=1,#pointer1 do
            pointer1[x]:touched(t)
        end
    end  
              
    if pointer2 ~= nil then
        pointer3=nil
        for x=1,#pointer2 do
            pointer2[x]:touched(t)
            if pointer3~= nil then
                return  
            end
        end
    end  
    
    if not selected then
        pointer1=nil
        pointer2=nil
    end
end

function menuBar:menu1()
    local x
    if type(pointer1)== "table" then
        for x=1,#pointer1 do
            pointer1[x]:draw()
        end
    end 
    
    if type(pointer2)== "table" then
        for x=1,#pointer2 do
            pointer2[x]:draw()
        end
    end  
    
    if type(pointer3)== "function" then
        pointer3()
    end    
end

function menuBar:draw()
    pushStyle()
    rectMode(CENTER)
    fill(255)
    rect(self.x,self.y,self.w,self.h)
    fill(255,0,0)
    text(self.d,self.x,self.y)
    popStyle()
end

function menuBar:error()
    fill(255)
    text("pointer to table or function not setup.",WIDTH/2,HEIGHT/2)
end

function menuBar:touched(t)
    if t.state==BEGAN then
        if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 then
            if t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then
                selected=true
                if type(self.pointer)=="table" then
                    pointer2=self.pointer
                elseif type(self.pointer)=="function" then
                    pointer3=self.pointer
                    pointer3()
                    pointer1=nil
                    pointer2=nil
                else
                    pointer3=self.error
                end
            end
        end
    end
end

Thanks @dave1707, this could be useful.

something strange when tring your code:

First run was in landscape mode

Next one was in portrait, as all next trials

I found in the code that you set the portrait mode, why did it stat in landscape then?

Then i replaced portrait by lanscape_any and the game would still always start in portrait…?

Then i copied my modified code, paste it in an new project, run it and is is amways is landscape…?

I assume it is a codea bug, already known or has to be filed somewhere?

Thanks @dave1707 - I think I may have a use for this.

Thank you,this is useful and lovely .

I’m not sure what’s happening. I thought when portrait mode was selected, it would stay in that mode even when the iPad was rotated to landscape. I don’t remember how it worked in previous versions, but I would think that if a specific mode is selected, it would display only in that mode. Did something break in the latest version. @Simeon, could you explain, and if this is how it works, then I suggest that if a specific orientation is specified, then it comes up in that mode and only displays in that mode.

.@dave1707 that sounds like a bug to me. If you could put it on the issue tracker it would be much appreciated.