1 /***********************************************************
2 * Copyright (C) 1997, Be Inc. All rights reserved.
6 * DESCRIPTION: code for popup menu handling
7 ***********************************************************/
9 /***********************************************************
11 ***********************************************************/
16 #include "glutState.h"
18 /***********************************************************
20 ***********************************************************/
21 static GlutMenu
**menuList
= 0;
22 static int menuListSize
= 0;
24 /***********************************************************
25 * FUNCTION: getUnusedMenuSlot
27 * DESCRIPTION: helper function to get a new menu slot
28 ***********************************************************/
29 GlutMenu
*__glutGetMenuByNum(int menunum
)
31 if (menunum
< 1 || menunum
> menuListSize
) {
34 return menuList
[menunum
- 1];
37 /***********************************************************
38 * FUNCTION: getUnusedMenuSlot
40 * DESCRIPTION: helper function to get a new menu slot
41 ***********************************************************/
43 getUnusedMenuSlot(void)
47 /* Look for allocated, unused slot. */
48 for (i
= 0; i
< menuListSize
; i
++) {
53 /* Allocate a new slot. */
55 menuList
= (GlutMenu
**)
56 realloc(menuList
, menuListSize
* sizeof(GlutMenu
*));
58 __glutFatalError("out of memory.");
59 menuList
[menuListSize
- 1] = NULL
;
60 return menuListSize
- 1;
63 /***********************************************************
64 * FUNCTION: glutCreateMenu (6.1)
66 * DESCRIPTION: create a new menu
67 ***********************************************************/
69 glutCreateMenu(GLUTselectCB selectFunc
)
74 menuid
= getUnusedMenuSlot();
75 menu
= new GlutMenu(menuid
, selectFunc
); // constructor sets up members
76 menuList
[menuid
] = menu
;
77 gState
.currentMenu
= menu
;
81 /***********************************************************
82 * FUNCTION: glutSetMenu (6.2)
85 * DESCRIPTION: set and get the current menu
86 ***********************************************************/
90 if (gState
.currentMenu
) {
91 return gState
.currentMenu
->id
+ 1;
98 glutSetMenu(int menuid
)
102 if (menuid
< 1 || menuid
> menuListSize
) {
103 __glutWarning("glutSetMenu attempted on bogus menu.");
106 menu
= menuList
[menuid
- 1];
108 __glutWarning("glutSetMenu attempted on bogus menu.");
111 gState
.currentMenu
= menu
;
114 /***********************************************************
115 * FUNCTION: glutDestroyMenu (6.3)
117 * DESCRIPTION: destroy the specified menu
118 ***********************************************************/
120 glutDestroyMenu(int menunum
)
122 GlutMenu
*menu
= __glutGetMenuByNum(menunum
);
123 menuList
[menunum
- 1] = 0;
124 if (gState
.currentMenu
== menu
) {
125 gState
.currentMenu
= 0;
130 /***********************************************************
131 * FUNCTION: glutAddMenuEntry (6.4)
133 * DESCRIPTION: add a new menu item
134 ***********************************************************/
136 glutAddMenuEntry(const char *label
, int value
)
138 new GlutMenuItem(gState
.currentMenu
, false, value
, label
);
141 /***********************************************************
142 * FUNCTION: glutAddSubMenu (6.5)
144 * DESCRIPTION: add a new submenu
145 ***********************************************************/
147 glutAddSubMenu(const char *label
, int menu
)
149 new GlutMenuItem(gState
.currentMenu
, true, menu
-1, label
);
152 /***********************************************************
153 * FUNCTION: glutChangeToMenuEntry (6.6)
155 * DESCRIPTION: change menuitem into a menu entry
156 ***********************************************************/
158 glutChangeToMenuEntry(int num
, const char *label
, int value
)
163 i
= gState
.currentMenu
->num
;
164 item
= gState
.currentMenu
->list
;
168 item
->label
= strdup(label
);
169 item
->isTrigger
= false;
176 __glutWarning("Current menu has no %d item.", num
);
179 /***********************************************************
180 * FUNCTION: glutChangeToSubMenu (6.7)
182 * DESCRIPTION: change menuitem into a submenu
183 ***********************************************************/
185 glutChangeToSubMenu(int num
, const char *label
, int menu
)
190 i
= gState
.currentMenu
->num
;
191 item
= gState
.currentMenu
->list
;
195 item
->label
= strdup(label
);
196 item
->isTrigger
= true;
197 item
->value
= menu
-1;
203 __glutWarning("Current menu has no %d item.", num
);
206 /***********************************************************
207 * FUNCTION: glutRemoveMenuItem (6.8)
209 * DESCRIPTION: remove a menu item
210 ***********************************************************/
212 glutRemoveMenuItem(int num
)
214 GlutMenuItem
*item
, **prev
;
217 i
= gState
.currentMenu
->num
;
218 prev
= &gState
.currentMenu
->list
;
219 item
= gState
.currentMenu
->list
;
223 gState
.currentMenu
->num
--;
225 /* Patch up menu's item list. */
236 __glutWarning("Current menu has no %d item.", num
);
239 /***********************************************************
240 * FUNCTION: glutAttachMenu (6.9)
243 * DESCRIPTION: attach and detach menu from view
244 ***********************************************************/
246 glutAttachMenu(int button
)
248 gState
.currentWindow
->menu
[button
] = gState
.currentMenu
->id
+ 1;
252 glutDetachMenu(int button
)
254 gState
.currentWindow
->menu
[button
] = 0;
257 /***********************************************************
260 * FUNCTION: CreateBMenu
262 * DESCRIPTION: construct a BPopupMenu for this menu
263 ***********************************************************/
264 BMenu
*GlutMenu::CreateBMenu(bool toplevel
) {
267 bpopup
= new GlutPopUp(id
+1);
269 bpopup
= new BMenu("");
271 GlutMenuItem
*item
= list
;
273 GlutBMenuItem
*bitem
;
274 if(item
->isTrigger
) {
275 // recursively call CreateBMenu
276 bitem
= new GlutBMenuItem(menuList
[item
->value
]->CreateBMenu(false));
277 bitem
->SetLabel(item
->label
);
278 bitem
->menu
= 0; // real menu items start at 1
281 bitem
= new GlutBMenuItem(item
->label
);
282 bitem
->menu
= id
+ 1;
283 bitem
->value
= item
->value
;
285 bpopup
->AddItem(bitem
, 0);
291 /***********************************************************
294 * FUNCTION: (destructor)
296 * DESCRIPTION: destroy the menu and its items (but not submenus!)
297 ***********************************************************/
298 GlutMenu::~GlutMenu() {
300 GlutMenuItem
*next
= list
->next
;
306 /***********************************************************
307 * CLASS: GlutMenuItem
309 * FUNCTION: (constructor)
311 * DESCRIPTION: construct the new menu item and add to parent
312 ***********************************************************/
313 GlutMenuItem::GlutMenuItem(GlutMenu
*n_menu
, bool n_trig
, int n_value
, const char *n_label
)
318 label
= strdup(n_label
);