1 /***********************************************************
2 * Copyright (C) 1997, Be Inc. Copyright (C) 1999, Jake Hamby.
4 * This program is freely distributable without licensing fees
5 * and is provided without guarantee or warrantee expressed or
6 * implied. This program is -not- in the public domain.
10 * DESCRIPTION: code for popup menu handling
11 ***********************************************************/
13 /***********************************************************
15 ***********************************************************/
20 #include "glutState.h"
22 /***********************************************************
24 ***********************************************************/
25 static GlutMenu
**menuList
= 0;
26 static int menuListSize
= 0;
28 /***********************************************************
29 * FUNCTION: getUnusedMenuSlot
31 * DESCRIPTION: helper function to get a new menu slot
32 ***********************************************************/
33 GlutMenu
*__glutGetMenuByNum(int menunum
)
35 if (menunum
< 1 || menunum
> menuListSize
) {
38 return menuList
[menunum
- 1];
41 /***********************************************************
42 * FUNCTION: getUnusedMenuSlot
44 * DESCRIPTION: helper function to get a new menu slot
45 ***********************************************************/
47 getUnusedMenuSlot(void)
51 /* Look for allocated, unused slot. */
52 for (i
= 0; i
< menuListSize
; i
++) {
57 /* Allocate a new slot. */
59 menuList
= (GlutMenu
**)
60 realloc(menuList
, menuListSize
* sizeof(GlutMenu
*));
62 __glutFatalError("out of memory.");
63 menuList
[menuListSize
- 1] = NULL
;
64 return menuListSize
- 1;
67 /***********************************************************
68 * FUNCTION: glutCreateMenu (6.1)
70 * DESCRIPTION: create a new menu
71 ***********************************************************/
73 glutCreateMenu(GLUTselectCB selectFunc
)
78 menuid
= getUnusedMenuSlot();
79 menu
= new GlutMenu(menuid
, selectFunc
); // constructor sets up members
80 menuList
[menuid
] = menu
;
81 gState
.currentMenu
= menu
;
85 /***********************************************************
86 * FUNCTION: glutSetMenu (6.2)
89 * DESCRIPTION: set and get the current menu
90 ***********************************************************/
94 if (gState
.currentMenu
) {
95 return gState
.currentMenu
->id
+ 1;
102 glutSetMenu(int menuid
)
106 if (menuid
< 1 || menuid
> menuListSize
) {
107 __glutWarning("glutSetMenu attempted on bogus menu.");
110 menu
= menuList
[menuid
- 1];
112 __glutWarning("glutSetMenu attempted on bogus menu.");
115 gState
.currentMenu
= menu
;
118 /***********************************************************
119 * FUNCTION: glutDestroyMenu (6.3)
121 * DESCRIPTION: destroy the specified menu
122 ***********************************************************/
124 glutDestroyMenu(int menunum
)
126 GlutMenu
*menu
= __glutGetMenuByNum(menunum
);
127 menuList
[menunum
- 1] = 0;
128 if (gState
.currentMenu
== menu
) {
129 gState
.currentMenu
= 0;
134 /***********************************************************
135 * FUNCTION: glutAddMenuEntry (6.4)
137 * DESCRIPTION: add a new menu item
138 ***********************************************************/
140 glutAddMenuEntry(const char *label
, int value
)
142 new GlutMenuItem(gState
.currentMenu
, false, value
, label
);
145 /***********************************************************
146 * FUNCTION: glutAddSubMenu (6.5)
148 * DESCRIPTION: add a new submenu
149 ***********************************************************/
151 glutAddSubMenu(const char *label
, int menu
)
153 new GlutMenuItem(gState
.currentMenu
, true, menu
-1, label
);
156 /***********************************************************
157 * FUNCTION: glutChangeToMenuEntry (6.6)
159 * DESCRIPTION: change menuitem into a menu entry
160 ***********************************************************/
162 glutChangeToMenuEntry(int num
, const char *label
, int value
)
167 i
= gState
.currentMenu
->num
;
168 item
= gState
.currentMenu
->list
;
172 item
->label
= strdup(label
);
173 item
->isTrigger
= false;
180 __glutWarning("Current menu has no %d item.", num
);
183 /***********************************************************
184 * FUNCTION: glutChangeToSubMenu (6.7)
186 * DESCRIPTION: change menuitem into a submenu
187 ***********************************************************/
189 glutChangeToSubMenu(int num
, const char *label
, int menu
)
194 i
= gState
.currentMenu
->num
;
195 item
= gState
.currentMenu
->list
;
199 item
->label
= strdup(label
);
200 item
->isTrigger
= true;
201 item
->value
= menu
-1;
207 __glutWarning("Current menu has no %d item.", num
);
210 /***********************************************************
211 * FUNCTION: glutRemoveMenuItem (6.8)
213 * DESCRIPTION: remove a menu item
214 ***********************************************************/
216 glutRemoveMenuItem(int num
)
218 GlutMenuItem
*item
, **prev
;
221 i
= gState
.currentMenu
->num
;
222 prev
= &gState
.currentMenu
->list
;
223 item
= gState
.currentMenu
->list
;
227 gState
.currentMenu
->num
--;
229 /* Patch up menu's item list. */
240 __glutWarning("Current menu has no %d item.", num
);
243 /***********************************************************
244 * FUNCTION: glutAttachMenu (6.9)
247 * DESCRIPTION: attach and detach menu from view
248 ***********************************************************/
250 glutAttachMenu(int button
)
252 gState
.currentWindow
->menu
[button
] = gState
.currentMenu
->id
+ 1;
256 glutDetachMenu(int button
)
258 gState
.currentWindow
->menu
[button
] = 0;
261 /***********************************************************
264 * FUNCTION: CreateBMenu
266 * DESCRIPTION: construct a BPopupMenu for this menu
267 ***********************************************************/
268 BMenu
*GlutMenu::CreateBMenu(bool toplevel
) {
271 bpopup
= new GlutPopUp(id
+1);
273 bpopup
= new BMenu("");
275 GlutMenuItem
*item
= list
;
277 GlutBMenuItem
*bitem
;
278 if(item
->isTrigger
) {
279 // recursively call CreateBMenu
280 bitem
= new GlutBMenuItem(menuList
[item
->value
]->CreateBMenu(false));
281 bitem
->SetLabel(item
->label
);
282 bitem
->menu
= 0; // real menu items start at 1
285 bitem
= new GlutBMenuItem(item
->label
);
286 bitem
->menu
= id
+ 1;
287 bitem
->value
= item
->value
;
289 bpopup
->AddItem(bitem
, 0);
295 /***********************************************************
298 * FUNCTION: (destructor)
300 * DESCRIPTION: destroy the menu and its items (but not submenus!)
301 ***********************************************************/
302 GlutMenu::~GlutMenu() {
304 GlutMenuItem
*next
= list
->next
;
310 /***********************************************************
311 * CLASS: GlutMenuItem
313 * FUNCTION: (constructor)
315 * DESCRIPTION: construct the new menu item and add to parent
316 ***********************************************************/
317 GlutMenuItem::GlutMenuItem(GlutMenu
*n_menu
, bool n_trig
, int n_value
, const char *n_label
)
322 label
= strdup(n_label
);