Code archives/File Utilities/Load a menu from a file

This code has been declared by its author to be Public Domain code.

Download source code

Load a menu from a file by JoshK2006
This is a useful routine to load your application's menu from a file. You can even load a new menu, and the old one will be destroyed. Menu gadgets are stored in a global MenuItem[] array, according to their tag. If you need to check or disable a menu item, just check to see if the menu item exists, then perform the action:
Select WaitEvent()
	Case EVENT_MENUEVENT
		Select EventData()
			Case MENU_ACTION
				If MenuItem[MENU_ACTION] CheckMenu MenuItem[MENU_ACTION]


Here is a sample menu file:
[File]
menu "New", NewFile
<>
menu "Open...", OpenFile, O, 2
menu "Merge...", MergeFile
<>
menu "Save", SaveFile, S, 2
menu "Save As...", SaveFileAs
menu "Save Selected...", SaveSelected
<>
menu "Import....", ImportFile
menu "Export...", ExportFile
menu "Export Selected...", ExportSelected
<>
menu "Run Map...", NewFile, F5
<>
menu "Exit", Exit

[Edit]
menu "Undo", Undo, Z, 2
menu "Redo", Redo, Z, 6
<>
menu "Cut", CutSelection, X, 2
menu "Copy", CopySelection, C, 2
menu "Paste", PasteSelection, V, 2
<>
menu "Select All", SelectAll
menu "Select None", SelectNone, Space
menu "Intert Selection", SelectInvert
<>
menu "Select Object", SelectObject, Z
menu "Select Subobject", SelectSubobject, X
menu "Select Vertex", SelectVertex, C
<>
menu "Properties...", ShowProperties, Enter, 4

[View]
menu "Material Browser", ShowMaterialBrowser
menu "Model Browser", ShowModelBrowser
<>
menu "Toolbar", ShowToolbar
menu "Sidepanel", ShowSidepanel
menu "Scrollbars",ShowScrollbars
<>
menu "Console", ShowConsole
menu "Map Statistics", ShowStats
<>
menu "Full-Screen", FullScreenMode, F12
<>
menu "Increase Grid Size", GridMore, [
menu "Decrease Grid Size", GridLess, ]
<>
menu "Zoom In", ZoomMore, +
menu "Zoom Out", ZoomLess, -
<>
menu "Render View"
{
menu "Perspective"
menu "Front - XY"
menu "Top - XZ"
menu "Side - ZY"
}
menu "Culling"
{
menu "Occlusion"
menu "Frustum"
<>
menu "Freeze Culling"
}
<>
menu "World Render Mode"
{
menu "Wireframe"
menu "Solid"
menu "Textured"
menu "Lighting"
menu "Textured+Lighting"
}
menu "Model Render Mode"
{
menu "Wireframe"
menu "Solid"
menu "Textured"
menu "Lighting"
menu "Textured+Lighting"
}
<>
menu "Render To File", RenderFile, F11

[Help]
menu "Help Contents...", Help, F1
<>
menu "About...", About
Const MaxMenuItems=99

Global menuitem:TGadget[MaxMenuItems]

Const MENU_ABOUT=1
Const MENU_EXIT=2
Const MENU_CONSOLE=3
Const MENU_CONSOLE_COPY=23
Const MENU_CONSOLE_SELECTALL=24
Const MENU_CONSOLE_STARTLOG=27
Const MENU_CONSOLE_STOPLOG=28
Const MENU_CONSOLE_SAVE=19
Const MENU_CONSOLE_CLOSE=20
Const MENU_FULLSCREEN=21

Function LoadMenu:Int(file$,window:TGadget)

	root:TGadget=WindowMenu(window)
	If Not root Return

	f:TStream=ReadFile(file)
	If Not f Return
	
	For menu:TGadget=EachIn root.kids
		FreeMenu menu
	Next

	If Not root Return
	For n=0 To MaxMenuItems-1
		MenuItem[n]=Null
	Next
	
	While Not f.eof()
		s$=f.readline()
		s=Trim(s)
		If Left(s,1)="[" And Right(s,1)="]"
			title$=Mid(s,2,Len(s)-2)
			item:TGadget=Null
			menu:TGadget=CreateMenu(title,0,root)
			parent:TGadget=menu
		Else
			p=Instr(s," ")
			If p
				command$=Left(s,p-1)
			Else
				command=s
			EndIf
			command=Trim(command)
			command=Lower(command)
			If p
				params$=Right(s,Len(s)-p)
			Else
				params=""
			EndIf
			Select command
				Case "<>"
					If parent CreateMenu("",0,parent)
				Case "{"
					If item:TGadget<>Null parent=item
				Case "}"
					parent=menu
				Case "menu"
					If parent
						text$=Trim((piece(params,1,",")))
						If Not Instr(text,Chr(34)) text=""
						text=Replace(text,Chr(34),"")
						tagname$=piece(params,2,",")
						tag=GetMenuAction(tagname)
						hotkeyname$=Trim((piece(params,3,",")))
						hotkey=KeyCode(hotkeyname)
						modifier=Int(piece(params,4,","))
						item:TGadget=CreateMenu(text,tag,parent,hotkey,modifier)
						menuitem[tag]=item
						extrahotkey=0
						Select tag
							Case KEY_0 extrahotkey=KEY_NUM0
							Case KEY_1 extrahotkey=KEY_NUM1
							Case KEY_2 extrahotkey=KEY_NUM2
							Case KEY_3 extrahotkey=KEY_NUM3
							Case KEY_4 extrahotkey=KEY_NUM4
							Case KEY_5 extrahotkey=KEY_NUM5
							Case KEY_7 extrahotkey=KEY_NUM7
							Case KEY_8 extrahotkey=KEY_NUM8
							Case KEY_9 extrahotkey=KEY_NUM9
							
							Case KEY_SLASH extrahotkey=KEY_NUMDIVIDE
							
							Case KEY_PERIOD extrahotkey=KEY_NUMDECIMAL
							Case KEY_EQUALS extrahotkey=KEY_NUMADD
							Case KEY_MINUS extrahotkey=KEY_NUMSUBTRACT					
						EndSelect
						If extrahotkey SetHotKeyEvent(extrahotkey ,modifier,CreateEvent(EVENT_MENUACTION,Null,tag))
					EndIf
			EndSelect
		EndIf
	Wend
	
	f.close()
	UpdateWindowMenu window
	Return True
EndFunction

Function GetMenuAction:Int(actionname$)
	actionname=Upper(actionname)
	actionname=Trim(actionname)
	Select actionname
		Case "ABOUT" Return MENU_ABOUT
		Case "FULLSCREENMODE" Return MENU_FULLSCREEN
		Case "EXIT" Return MENU_EXIT
	EndSelect
EndFunction

Function KeyCode:Int(keyname$)
	keyname=Upper(keyname)
	keyname=Trim(keyname)
	Select keyname
	
		Case "A" Return KEY_A
		Case "B" Return KEY_B
		Case "C" Return KEY_C
		Case "D" Return KEY_D
		Case "E" Return KEY_E
		Case "F" Return KEY_F
		Case "G" Return KEY_G
		Case "H" Return KEY_H
		Case "I" Return KEY_I
		Case "J" Return KEY_J
		Case "K" Return KEY_K
		Case "L" Return KEY_L
		Case "M" Return KEY_M
		Case "N" Return KEY_N
		Case "O" Return KEY_O
		Case "P" Return KEY_P
		Case "Q" Return KEY_Q
		Case "R" Return KEY_R
		Case "S" Return KEY_S
		Case "T" Return KEY_T
		Case "U" Return KEY_U
		Case "V" Return KEY_V
		Case "W" Return KEY_W
		Case "X" Return KEY_X
		Case "Y" Return KEY_Y
		Case "Z" Return KEY_Z
		
		Case "0" Return KEY_0
		Case "1" Return KEY_1
		Case "2" Return KEY_2
		Case "3" Return KEY_3
		Case "4" Return KEY_4
		Case "5" Return KEY_5
		Case "6" Return KEY_6
		Case "7" Return KEY_7
		Case "8" Return KEY_8
		Case "9" Return KEY_9

		Case "F1" Return KEY_F1
		Case "F2" Return KEY_F2
		Case "F3" Return KEY_F3
		Case "F4" Return KEY_F4
		Case "F5" Return KEY_F5
		Case "F6" Return KEY_F6
		Case "F7" Return KEY_F7
		Case "F8" Return KEY_F8
		Case "F9" Return KEY_F9
		Case "F10" Return KEY_F10
		Case "F11" Return KEY_F11
		Case "F12" Return KEY_F12

		Case "SPACE" Return KEY_SPACE
		Case "ESCAPE" Return KEY_ESCAPE
		Case "BACKSPACE" Return KEY_BACKSPACE
		Case "CLEAR" Return KEY_CLEAR
		Case "RETURN" Return KEY_RETURN
		Case "ENTER" Return KEY_ENTER
		Case "PAUSE" Return KEY_PAUSE

		Case "CAPSLOCK" Return KEY_CAPSLOCK
		Case "PAGEUP" Return KEY_PAGEUP
		Case "PAGEDOWN" Return KEY_PAGEDOWN
		Case "END" Return KEY_END
		Case "HOME" Return KEY_HOME
		Case "LEFT" Return KEY_LEFT
		Case "RIGHT" Return KEY_RIGHT
		Case "UP" Return KEY_UP
		Case "DOWN" Return KEY_DOWN
		Case "SELECT" Return KEY_SELECT
		Case "PRINT" Return KEY_PRINT
		Case "EXECUTE" Return KEY_EXECUTE
		Case "SCREEN" Return KEY_SCREEN
		Case "INSERT" Return KEY_INSERT
		Case "DELETE" Return KEY_DELETE
		Case "HELP" Return KEY_HELP
		Case "NUMLOCK" Return KEY_NUMLOCK
		Case "SCROLL" Return KEY_SCROLL
		Case "-","_" Return KEY_MINUS
		Case "="."+" Return KEY_EQUALS
		Case "[","{" Return KEY_OPENBRACKET
		Case "]","}" Return KEY_CLOSEBRACKET
		Case "\","|" Return KEY_BACKSLASH
		Case ";",":" Return KEY_SEMICOLON
		Case "'",Chr(34) Return KEY_QUOTES
		Case ",","<" Return KEY_COMMA
		Case ".".">" Return KEY_PERIOD
		Case "/","?" Return KEY_SLASH

	EndSelect
EndFunction

Function Piece$(s$,entry,char$=" ")
	Local n
	Local p
	Local a$
	While Instr(s,char+char)
		s=Replace(s,char+char,char)
	Wend
	For n=1 To entry-1
		p=Instr(s,char)
		s=Right(s,Len(s)-p)
		If Not p
			If entry=n Exit Else Return
		EndIf
	Next
	p=Instr(s,char)
	If p<1
		a$=s
	Else
		a=Left(s,p-1)
	EndIf
	Return a
End Function

Comments

JoshK2009
Here's an updated version, using the way I code now:


Instead of having menu ids you just get the menu extra parameter, which is set to the action name. You can then make menus in different languages and only have to specify a correct action name at the end. If no action name is specified, the action name will be assumed to be the menu name:
		If EventID()=EVENT_MENUACTION
			Local menu:TGadget
			menu=TGadget(EventSource())
			Select String(menu.extra)
				Case "OpenFile"
					RequestFile("")
			EndSelect
		EndIf


And here is what my new menu file format looks like:
[File]
menu "New"
<>
menu "Open...", O, 2, OpenFile


So it is like this:
menu menuname [, hotkey, modifier, actionname ]


If you need to retrieve a menu other than the current event source, just use GetMenu() to retrieve it by action name.

This will also load a menu icon automatically if a png file exists that matches the action name.


Code Archives Forum