Here is a set of functions to create and manipulate drop down menus in a generic way. I tried to make the function names as similar to built in functions.
Available functions:
-- All arguments after height are optional. They default to "", 1, "bottom", "down".
createMenu(menuName, x, y, width, height, menuText, numButtons, buttonPosition, buttonDirection)
-- This function sets the stylesheet for the menu buttons. To set all buttons at once, omit the buttonNumber variable. To set the stylesheet for the main button, and a different stylesheet for the other buttons, omit the buttonNumber variable, then pass the stylesheet info for the main button, followed by the stylesheet info for the rest of the buttons.
setMenuStyleSheet(menuName, buttonNumber, buttonCSS)
-- This function sets the click callback for the menu buttons
setMenuClickCallback(menuName, buttonNumber, ...)
-- This function is used to set the text for the various menu buttons. It accepts color names, or rgb values for color. To set the main button text, omit the buttonNumber. Default color is "white".
setMenuText(menuName, text, buttonNumber, r, g, b)
-- This function changes the number of buttons in the menu
setMenuNumberButtons(menuName, numButtons)
-- This function changes the size of the buttons (if this function isn't called, the menu buttons will be the same size as the main button that opens and closes the menu)
setMenuButtonSize(menuName, width, height)
-- These functions change where the menu buttons appear relative to the main button, and in which direction they extend
setMenuPosition(menuName, position)
setMenuDirection(menuName, direction)
-- These functions open and close the menu (show or hide the menu items). If toggle is true for openMenu then it will open if it is closed and close if it is open (this is used to make clicking the main button work as expected)
openMenu(menuName, toggle)
closeMenu(menuName)
-- These functions act exactly like similar functions for windows
resizeMenu(menuName, width, height)
moveMenu(menuName, x, y)
hideMenu(menuName)
showMenu(menuName)
menusTable = menusTable or {}
function createMenu(menuName, x, y, width, height, menuText, numButtons, buttonPosition, buttonDirection)
menuText = menuText or ""
numButtons = numButtons or 1
buttonPosition = buttonPosition or "bottom"
buttonDirection = buttonDirecton or "down"
assert(table.contains({"bottom","top","left","right"},buttonPosition), "createMenu: buttonPosition must be bottom, top, left, or right")
assert(table.contains({"up","down","left","right"},buttonDirection), "createMenu: buttonDirection must be up, down, left, or right")
local tbl = {open = false, width = width, height = height, x = x, y = y, text = menuText, numButtons = numButtons, buttonPos = buttonPosition, buttonDir = buttonDirection}
-- save new values in table
menusTable[menuName] = tbl
createLabel(menuName,0,0,0,0,1)
setBackgroundColor(menuName,0,0,0,255)
setLabelClickCallback(menuName, "openMenu", menuName, "true")
for k = 1,numButtons do
createLabel(menuName.."_menubutton_"..k,0,0,0,0,1)
setBackgroundColor(menuName.."_menubutton_"..k,0,0,0,255)
setMenuText(menuName, "Button " .. k, k, "white")
setLabelClickCallback(menuName.."_menubutton_"..k, "closeMenu", menuName)
hideWindow(menuName.."_menubutton_"..k)
end
-- resize and move menu to desired position
resizeMenu(menuName, tbl.width, tbl.height)
moveMenu(menuName, tbl.x, tbl.y)
-- write text on main menu button
setMenuText(menuName, menuText, "white")
showMenu(menuName)
end
function setMenuPosition(menuName, position)
assert(menusTable[menuName], "setMenuPosition: no such menu exists.")
assert(table.contains({"bottom","top","left","right"},position), "setMenuPosition: Position must be bottom, top, left, or right")
menusTable[menuName].buttonPos = position
end
function setMenuDirection(menuName, direction)
assert(menusTable[menuName], "setMenuDirection: no such menu exists.")
assert(table.contains({"up","down","left","right"},direction), "setMenuDirection: Direction must be up, down, left, or right")
menusTable[menuName].buttonDir = direction
end
function setMenuNumberButtons(menuName, numButtons)
assert(menusTable[menuName], "setMenuNumberButtons: no such menu exists.")
local curButtons = menusTable[menuName].numButtons
menusTable[menuName].numButtons = numButtons
if curButtons < numButtons then
for k = curButtons + 1,numButtons do
createLabel(menuName.."_menubutton_"..k,0,0,0,0,1)
setBackgroundColor(menuName.."_menubutton_"..k,0,0,0,255)
setMenuText(menuName, "Button " .. k, k, "white")
setLabelClickCallback(menuName.."_menubutton_"..k, "closeMenu", menuName)
hideWindow(menuName.."_menubutton_"..k)
end
elseif curButtons > numButtons then
for k = numButtons + 1, curButtons do
hideWindow(menuName.."_menubutton_"..k)
end
end
end
function setMenuStyleSheet(menuName, buttonNumber, buttonCSS)
assert(menusTable[menuName], "setMenuStyleSheet: no such menu exists.")
if tonumber(buttonNumber) then
assert(buttonNumber <= menusTable[menuName].numButtons, "setMenuStyleSheet: buttonNumber higher than number of buttons in menu.")
setLabelStyleSheet(menuName.."_menubutton_"..buttonNumber, buttonCSS)
else
buttonCSS = buttonCSS or buttonNumber
setLabelStyleSheet(menuName, buttonNumber)
for k = 1, menusTable[menuName].numButtons do
setLabelStyleSheet(menuName.."_menubutton_"..k, buttonCSS)
end
end
end
function setMenuClickCallback(menuName, buttonNumber, ...)
assert(menusTable[menuName], "setMenuClickCallback: no such menu exists.")
assert(tonumber(buttonNumber) and buttonNumber <= menusTable[menuName].numButtons, "setMenuClickCallback: buttonNumber higher than number of buttons in menu.")
setLabelClickCallback(menuName.."_menubutton_"..buttonNumber, ...)
end
function setMenuText(menuName, text, buttonNumber, r, g, b)
assert(menusTable[menuName], "setMenuText: no such menu exists.")
if r ~= nil then
if g == nil then
r,g,b = getRGB(r)
elseif b == nil then
r,g,b = buttonNumber,r,g
buttonNumber = nil
end
elseif buttonNumber and not tonumber(buttonNumber) then
r,g,b = getRGB(buttonNumber)
buttonNumber = nil
else
r,g,b = 255,255,255
end
local echoString = [[<font color ="#]] .. RGB2Hex(r,g,b) .. [[">]] .. text .. [[</font>]]
local labelName = menuName
if buttonNumber then
assert(menusTable[menuName].numButtons >= buttonNumber, "setMenuText: buttonNumber higher than number of buttons in menu.")
labelName = labelName .. "_menubutton_" .. buttonNumber
menusTable[menuName].buttonText = menusTable[menuName].buttonText or {}
menusTable[menuName].buttonText[buttonNumber] = echoString
else
menusTable[menuName].text = echoString
end
echo(labelName, echoString)
end
function setMenuButtonSize(menuName, width, height)
assert(menusTable[menuName], "setMenuButtonSize: no such menu exists.")
assert(width and height, "setMenuButtonSize: need to have both width and height.")
menusTable[menuName].bsize = {width = width, height = height}
for k = 1, menusTable[menuName].numButtons do
resizeWindow(menuName.."_menubutton_"..k, width, height)
end
if menusTable[menuName].open then
openMenu()
end
end
function resizeMenu(menuName, width, height)
assert(menusTable[menuName], "resizeMenu: no such menu exists.")
assert(width and height, "resizeMenu: need to have both width and height.")
resizeWindow(menuName, width, height)
if not menusTable[menuName].bsize then
for k = 1,menusTable[menuName].numButtons do
resizeWindow(menuName.."_menubutton_"..k, width, height)
end
end
if menusTable[menuName].open then
openMenu()
end
menusTable[menuName].width, menusTable[menuName].height = width, height
end
function moveMenu(menuName, x, y)
assert(menusTable[menuName], "moveMenu: no such menu exists.")
assert(x and y, "moveMenu: need to have both X and Y positions.")
moveWindow(menuName, x, y)
if menusTable[menuName].open then
openMenu()
end
menusTable[menuName].x, menusTable[menuName].y = x, y
end
function openMenu(menuName, toggle)
assert(menusTable[menuName], "openMenu: no such menu exists.")
if toggle and menusTable[menuName].open then
closeMenu(menuName)
else
menusTable[menuName].open = true
local width, height = menusTable[menuName].width, menusTable[menuName].height
local bwidth, bheight = width, height
local x,y = menusTable[menuName].x, menusTable[menuName].y
local pos, dir = menusTable[menuName].buttonPos, menusTable[menuName].buttonDir
if menusTable[menuName].bsize then
bwidth = menusTable[menuName].bsize.width
bheight = menusTable[menuName].bsize.height
end
if pos == "left" then
x = x - bwidth
elseif pos == "right" then
x = x + width
elseif pos == "top" then
y = y - bheight
elseif pos == "bottom" then
y = y + height
end
for k = 1, menusTable[menuName].numButtons do
moveWindow(menuName.."_menubutton_"..k,x,y)
resizeWindow(menuName.."_menubutton_"..k,bwidth,bheight)
showWindow(menuName.."_menubutton_"..k)
if dir == "left" then
x = x - bwidth
elseif dir == "right" then
x = x + bwidth
elseif dir == "up" then
y = y - bheight
elseif dir == "down" then
y = y + bheight
end
end
end
end
function closeMenu(menuName)
assert(menusTable[menuName], "closeMenu: no such menu exists.")
menusTable[menuName].open = false
for k = 1, menusTable[menuName].numButtons do
hideWindow(menuName.."_menubutton_"..k)
end
end
function hideMenu(menuName)
assert(menusTable[menuName], "hideMenu: no such menu exists.")
hideWindow(menuName)
for k = 1, menusTable[menuName].numButtons do
hideWindow(menuName.."_menubutton_"..k)
end
end
function showMenu(menuName)
assert(menusTable[menuName], "showMenu: no such menu exists.")
showWindow(menuName)
if menusTable[menuName].open then
for k = 1, menusTable[menuName].numButtons do
showWindow(menuName.."_menubutton_"..k)
end
end
end