1 #include <cassert>
2 #include <iostream>
3 #include <map>
4 #include <string>
5 #include <vector>
6 #include <cmath>
7 #include <SDL_types.h>
8
9 #include "context_menu.h"
10 #include "elconfig.h"
11 #include "elwindows.h"
12 #include "font.h"
13 #include "gamewin.h"
14 #include "gl_init.h"
15 #include "interface.h"
16 #include "sound.h"
17
18 //
19 // Implements a simple context menu system using the standard el windows.
20 // Intended to be a familiar GUI context menu activated via a right mouse click.
21 // At its simplest, the user code just needs to create a new context object
22 // providing a callback function for when an option is selected or using boolean
23 // only options. The Container class provides a creation/destruction/management/access
24 // wrapper.
25 // Author bluap/pjbroad March/April 2008
26 //
27 namespace cm
28 {
29 //
30 // The context menu class. Each manu uses a seperate object stored in
31 // the Container class. One el window is used for all menus. This class
32 // implements the menu display, option hight-lighting, checkbox options and
33 // menu option selection. It also stores size, colour and state information.
34 //
35 class Menu
36 {
37 public:
38 Menu(const char *menu_list, int (*handler)(window_info *, int, int, int, int));
39 int show(int cm_widget_id);
40 int display(window_info *win, int mx, int my, Uint32 flags);
41 int click(window_info *win, int mx, int my, Uint32 flags);
42 int set(const char *menu_list, int (*handler)(window_info *, int, int, int, int));
43 int add(const char *menu_list, int (*handler)(window_info *, int, int, int, int));
set_pre_show_handler(void (* handler)(window_info *,int,int,int,window_info *))44 void set_pre_show_handler(void (*handler)(window_info *, int, int, int, window_info *)) { pre_show_handler = handler; }
45 int set_sizes(int border, int text_border, int line_sep, float zoom);
46 int set_colour(size_t cm_id, enum CM_COLOUR_NAME colour_name, float r, float g, float b);
47 int change_line(size_t line_index, const char *new_entry);
48 int bool_line(size_t line_index, int *control_var, const char *config_name);
49 int grey_line(size_t line_index, bool is_grey);
50 void show_lines(size_t my_id);
set_data(void * data)51 void set_data(void *data) { data_ptr = data; }
get_data(void) const52 void *get_data(void) const { return data_ptr; }
53 float scaled_value(float val) const;
54
55 private:
56 int resize(void);
bool_box_size(void) const57 int bool_box_size(void) const { return 15; }
58 int border, text_border, line_sep;
59 float zoom, bool_tick_width;
60 int opened_mouse_x, opened_mouse_y;
61 int (*handler)(window_info *, int, int, int, int);
62 void (*pre_show_handler)(window_info *, int, int, int, window_info *);
63 void *data_ptr;
64 int width, height;
65 int selection;
66 bool menu_has_bools;
67 class Menu_Line
68 {
69 public:
Menu_Line(const std::string & _text)70 Menu_Line(const std::string& _text) : text(_text), control_var(0), config_name(0), is_grey(false), is_separator(false) {}
71 std::string text;
72 int *control_var;
73 const char *config_name;
74 bool is_grey;
75 bool is_separator;
76 };
77 std::vector<Menu_Line> menu_lines;
78 class myRGB
79 {
80 public:
myRGB(void)81 myRGB(void) : r(0.0), g(0.0), b(0.0) {}
set(float _r,float _g,float _b)82 void set(float _r, float _g, float _b) { r=_r; g=_g; b=_b; }
83 float r, g, b;
84 };
85 myRGB highlight_top;
86 myRGB highlight_bottom;
87 myRGB text_colour;
88 myRGB grey_colour;
89 };
90
91
92 //
93 // A simple container class for the context menus.
94 // Provides creation and destruction of context menus
95 // and any other 'across all menu' functions
96 // There can only be one instance!
97 //
98 class Container
99 {
100 public:
101 ~Container();
102
103 // Return the singleton instance of this container
get_instance()104 static Container& get_instance()
105 {
106 static Container container;
107 return container;
108 }
109
110 size_t create(const char *menu_list, int (*handler)(window_info *, int, int, int, int ));
111 int destroy(size_t cm_id);
112 int pre_show_check(Uint32 flags);
113 void post_show_check(bool force);
114 int show_if_active(int window_id);
115 int show_direct(size_t cm_id, int window_id, int widget_id);
set(size_t cm_id,const char * menu_list,int (* handler)(window_info *,int,int,int,int))116 int set(size_t cm_id, const char *menu_list, int (*handler)(window_info *, int, int, int, int)) { if (!valid(cm_id)) return 0; return menus[cm_id]->set(menu_list, handler); }
add(size_t cm_id,const char * menu_list,int (* handler)(window_info *,int,int,int,int))117 int add(size_t cm_id, const char *menu_list, int (*handler)(window_info *, int, int, int, int)) { if (!valid(cm_id)) return 0; return menus[cm_id]->add(menu_list, handler); }
set_pre_show_handler(size_t cm_id,void (* handler)(window_info *,int,int,int,window_info *))118 int set_pre_show_handler(size_t cm_id, void (*handler)(window_info *, int, int, int, window_info *)) { if (!valid(cm_id)) return 0; menus[cm_id]->set_pre_show_handler(handler); return 1; }
bool_line(size_t cm_id,size_t line_index,int * control_var,const char * config_name)119 int bool_line(size_t cm_id, size_t line_index, int *control_var, const char *config_name) { if (!valid(cm_id)) return 0; return menus[cm_id]->bool_line(line_index, control_var, config_name); }
grey_line(size_t cm_id,size_t line_index,bool is_grey)120 int grey_line(size_t cm_id, size_t line_index, bool is_grey) { if (!valid(cm_id)) return 0; return menus[cm_id]->grey_line(line_index, is_grey); }
set_sizes(size_t cm_id,int border,int text_border,int line_sep,float zoom)121 int set_sizes(size_t cm_id, int border, int text_border, int line_sep, float zoom) { if (!valid(cm_id)) return 0; return menus[cm_id]->set_sizes(border, text_border, line_sep, zoom); }
set_colour(size_t cm_id,enum CM_COLOUR_NAME colour_name,float r,float g,float b)122 int set_colour(size_t cm_id, enum CM_COLOUR_NAME colour_name, float r, float g, float b) { if (!valid(cm_id)) return 0; return menus[cm_id]->set_colour(cm_id, colour_name, r, g, b); }
add_window(size_t cm_id,int window_id)123 int add_window(size_t cm_id, int window_id) { if (!valid(cm_id)) return 0; full_windows.insert(std::pair<int, size_t>(window_id, cm_id)); return 1; }
add_region(size_t cm_id,int window_id,int posx,int posy,int lenx,int leny)124 int add_region(size_t cm_id, int window_id, int posx, int posy, int lenx, int leny) { if (!valid(cm_id)) return 0; window_regions.insert(std::pair<int, Region>(window_id, Region(cm_id, posx, posy, lenx, leny))); return 1; }
add_widget(size_t cm_id,int window_id,int widget_id)125 int add_widget(size_t cm_id, int window_id, int widget_id) { if (!valid(cm_id)) return 0; window_widgets.insert(std::pair<int, Widget>(window_id, Widget(cm_id, widget_id))); return 1; }
remove_window(int window_id)126 int remove_window(int window_id) { if (full_windows.erase(window_id)) return 1; return 0;}
remove_regions(int window_id)127 int remove_regions(int window_id) { if (window_regions.erase(window_id)) return 1; return 0; }
128 int remove_widget(int window_id, int widget_id);
get_active_window_id(void) const129 int get_active_window_id(void) const { return active_window_id; }
get_active_widget_id(void) const130 int get_active_widget_id(void) const { return active_widget_id; }
valid(size_t cm_id) const131 bool valid(size_t cm_id) const { return cm_id<menus.size() && menus[cm_id]; }
132 size_t window_shown(void) const;
133 void showinfo(void);
get_data(size_t cm_id) const134 void *get_data(size_t cm_id) const { if (!valid(cm_id)) return 0; return menus[cm_id]->get_data(); }
set_data(size_t cm_id,void * data)135 void set_data(size_t cm_id, void *data) { if (valid(cm_id)) menus[cm_id]->set_data(data); }
get_current_scale(void) const136 float get_current_scale(void) const { return windows_list.window[cm_window_id].current_scale; }
137
138 private:
139 Container();
140 Container(const Container&) = delete;
141 Container& operator=(const Container&) = delete;
142
143 class Region // Wrapper for window region activation area.
144 {
145 public:
Region(size_t _cm_id,int _pos_x,int _pos_y,int _len_x,int _len_y)146 Region(size_t _cm_id, int _pos_x, int _pos_y, int _len_x, int _len_y)
147 : cm_id(_cm_id), pos_x(_pos_x), pos_y(_pos_y), len_x(_len_x), len_y(_len_y) {}
148 size_t cm_id;
149 int pos_x, pos_y, len_x, len_y;
150 };
151 typedef std::multimap<int, Region> REG_MM;
152 REG_MM window_regions;
153 class Widget // Wrapper for window widget activation area.
154 {
155 public:
Widget(size_t _cm_id,int _widget_id)156 Widget(size_t _cm_id, int _widget_id)
157 : cm_id(_cm_id), widget_id(_widget_id) {}
158 size_t cm_id;
159 int widget_id;
160 };
161 typedef std::multimap<int, Widget > WID_MM;
162 WID_MM window_widgets;
163 int cm_window_id;
164 int active_window_id;
165 int active_widget_id;
166 std::vector<Menu*> menus;
167 std::map<int, size_t> full_windows; // <window_id, cm_id>
168 bool menu_opened;
169 };
170
171 // Generic el windows callback for clicks in a context menu.
click_context_handler(window_info * win,int mx,int my,Uint32 flags)172 extern "C" int click_context_handler(window_info *win, int mx, int my, Uint32 flags)
173 {
174 Menu *thismenu = (Menu *)win->data;
175 int return_value = thismenu->click(win, mx, my, flags);
176 if (return_value)
177 do_click_sound();
178 else
179 do_alert1_sound();
180 return return_value;
181 }
182
183
184 // Generic el windows callback for displaying a context menu.
display_context_handler(window_info * win,int mx,int my,Uint32 flags)185 extern "C" int display_context_handler(window_info *win, int mx, int my, Uint32 flags)
186 {
187 Menu *thismenu = (Menu *)win->data;
188 return thismenu->display(win, mx, my, flags);
189 }
190
191
192 // safely get a window_info pointer from a window_id
window_info_from_id(int window_id)193 window_info * window_info_from_id(int window_id)
194 {
195 if ((window_id > -1) && (window_id < windows_list.num_windows))
196 return &windows_list.window[window_id];
197 else
198 return NULL;
199 }
200
201
202 // constructor - create the context menu window and initialise containers
Container()203 Container::Container()
204 : cm_window_id(-1), active_window_id(-1), active_widget_id(-1), menu_opened(false)
205 {
206 menus.resize(20,0);
207 if ((cm_window_id = create_window("Context Menu", -1, 0, 0, 0, 0, 0,
208 ELW_USE_UISCALE|ELW_SWITCHABLE_OPAQUE|ELW_USE_BACKGROUND|ELW_USE_BORDER|ELW_ALPHA_BORDER)) == -1)
209 return;
210 set_window_handler(cm_window_id, ELW_HANDLER_DISPLAY, (int (*)())&display_context_handler );
211 set_window_handler(cm_window_id, ELW_HANDLER_CLICK, (int (*)())&click_context_handler );
212 }
213
214
215 // destructor - destory all instances of context menus and the context menu window
~Container(void)216 Container::~Container(void)
217 {
218 for (size_t i=0; i<menus.size(); ++i)
219 {
220 if (menus[i])
221 {
222 delete menus[i];
223 menus[i] = 0;
224 }
225 }
226 destroy_window(cm_window_id);
227 }
228
229
230 // create a new context menu object
create(const char * menu_list,int (* handler)(window_info *,int,int,int,int))231 size_t Container::create(const char *menu_list, int (*handler)(window_info *, int, int, int, int ))
232 {
233 Menu *temp = new Menu(menu_list, handler);
234 // find an unused slot ...
235 for (size_t i=0; i<menus.size(); ++i)
236 {
237 if (!menus[i])
238 {
239 menus[i] = temp;
240 return i;
241 }
242 }
243 // ... or create some more space
244 size_t oldsize = menus.size();
245 menus.resize(oldsize*2,0);
246 menus[oldsize] = temp;
247 return oldsize;
248 }
249
250
251 // destroy the specified context menu object, removing all the activation points too
destroy(size_t cm_id)252 int Container::destroy(size_t cm_id)
253 {
254 if (!valid(cm_id))
255 return 0;
256
257 bool found_entry = false;
258
259 // remove all full windows linked to this context menu
260 do
261 {
262 found_entry = false;
263 for (std::map<int, size_t>::iterator itp = full_windows.begin(); itp != full_windows.end(); ++itp)
264 {
265 if (itp->second == cm_id)
266 {
267 full_windows.erase(itp);
268 found_entry = true;
269 break;
270 }
271 }
272 } while (found_entry);
273
274
275 // remove all regions linked to this context menu
276 do
277 {
278 found_entry = false;
279 for (REG_MM::iterator itp = window_regions.begin(); itp != window_regions.end(); ++itp)
280 {
281 if (itp->second.cm_id == cm_id)
282 {
283 window_regions.erase(itp);
284 found_entry = true;
285 break;
286 }
287 }
288 } while (found_entry);
289
290
291 // remove all widgets linked to this context menu
292 do
293 {
294 found_entry = false;
295 for (WID_MM::iterator itp = window_widgets.begin(); itp != window_widgets.end(); ++itp)
296 {
297 if (itp->second.cm_id == cm_id)
298 {
299 window_widgets.erase(itp);
300 found_entry = true;
301 break;
302 }
303 }
304 } while (found_entry);
305
306 delete menus[cm_id];
307 menus[cm_id] = 0;
308 return 1;
309
310 } // end Container::destroy()
311
312
313 // do the pre show checks and return the activation state, e.g. if mouse right-clicked
pre_show_check(Uint32 flags)314 int Container::pre_show_check(Uint32 flags)
315 {
316 int cm_to_activate = flags & ELW_RIGHT_MOUSE;
317 if (cm_to_activate && ((flags & KMOD_SHIFT) || (flags & KMOD_ALT) || (flags & KMOD_CTRL)))
318 cm_to_activate = 0; // exclude right clicks with modifier keys pressed
319 menu_opened = false;
320 return cm_to_activate;
321 }
322
323
324 // hide the window if its's open and reset the active window/widget values
post_show_check(bool force)325 void Container::post_show_check(bool force)
326 {
327 // don't close a just (show_direct()) opened context menu
328 if (!force && menu_opened)
329 select_window(cm_window_id);
330 else
331 {
332 hide_window(cm_window_id);
333 active_window_id = active_widget_id = -1;
334 }
335 menu_opened = false;
336 }
337
338
339 // check if the specified window has any activation points then open the relevant context menu
show_if_active(int window_id)340 int Container::show_if_active(int window_id)
341 {
342 // check if we're right clicking the title of a window that has a context menu
343 if (window_id >= 0 && window_id < windows_list.num_windows)
344 {
345 window_info *win = &windows_list.window[window_id];
346 int y = mouse_y - win->cur_y;
347 if (y < 0 && valid(win->cm_id) && mouse_in_window(window_id, mouse_x, mouse_y))
348 return show_direct(win->cm_id, window_id, -1);
349 }
350
351 // check we're in the specified window
352 if (mouse_in_window(window_id, mouse_x, mouse_y) < 1)
353 return 0;
354
355 // check if this window has any widget activation settings and open if mouse in that widget
356 {
357 std::pair< WID_MM::iterator, WID_MM::iterator> itp = window_widgets.equal_range(window_id);
358 for (WID_MM::iterator it = itp.first; it != itp.second; ++it)
359 {
360 window_info *win = window_info_from_id(window_id);
361 widget_list *wid = widget_find(window_id, it->second.widget_id);
362 assert(wid!=NULL && win!=NULL);
363 if ((mouse_x > win->cur_x + wid->pos_x) && (mouse_x <= win->cur_x + wid->pos_x + wid->len_x) &&
364 (mouse_y > win->cur_y + wid->pos_y) && (mouse_y <= win->cur_y + wid->pos_y + wid->len_y))
365 return show_direct(it->second.cm_id, window_id, it->second.widget_id);
366 }
367 }
368
369 // check if this window has any active regions and open if mouse in that region
370 {
371 std::pair< REG_MM::iterator, REG_MM::iterator> itp = window_regions.equal_range(window_id);
372 for (REG_MM::iterator it = itp.first; it != itp.second; ++it)
373 {
374 window_info *win = window_info_from_id(window_id);
375 assert(win!=NULL);
376 Region *cr = &it->second;
377 if ((mouse_x > win->cur_x + cr->pos_x) && (mouse_x < win->cur_x + cr->pos_x + cr->len_x) &&
378 (mouse_y > win->cur_y + cr->pos_y) && (mouse_y < win->cur_y + cr->pos_y + cr->len_y))
379 return show_direct(cr->cm_id, window_id, -1);
380 }
381 }
382
383 // check if this window has a full-window context menu - do this last to allow others within window
384 std::map<int,size_t>::iterator fwit = full_windows.find(window_id);
385 if (fwit != full_windows.end())
386 return show_direct(fwit->second, window_id, -1);
387
388 return 0;
389
390 } // end Container::show_if_active()
391
392
393 // directly open the specified conetext menu, use specified window/widget id as if activated
show_direct(size_t cm_id,int window_id,int widget_id)394 int Container::show_direct(size_t cm_id, int window_id, int widget_id)
395 {
396 if (!valid(cm_id))
397 return 0;
398 menu_opened = true;
399 active_window_id = window_id;
400 active_widget_id = widget_id;
401 return menus[cm_id]->show(cm_window_id);
402 }
403
404
405 // remove any activation for the specifed window/widget
remove_widget(int window_id,int widget_id)406 int Container::remove_widget(int window_id, int widget_id)
407 {
408 std::pair< WID_MM::iterator, WID_MM::iterator> itp = window_widgets.equal_range(window_id);
409 for (WID_MM::iterator it = itp.first; it != itp.second; ++it)
410 {
411 if (it->second.widget_id == widget_id)
412 {
413 window_widgets.erase(it);
414 return 1;
415 }
416 }
417 return 0;
418 }
419
420
421 // return the id the currently open context menu or CM_INIT_VALUE is none open
window_shown(void) const422 size_t Container::window_shown(void) const
423 {
424 window_info * win = window_info_from_id(cm_window_id);
425 if (!get_show_window(cm_window_id) || win == NULL)
426 return CM_INIT_VALUE;
427
428 Menu *current_menu = (Menu *)win->data;
429 for (size_t i=0; i<menus.size(); i++)
430 if (current_menu == menus[i])
431 return i;
432 return CM_INIT_VALUE;
433 }
434
435
436 // for debug - display info on status of container object
showinfo(void)437 void Container::showinfo(void)
438 {
439 std::cout << "\nContext menu information:" << std::endl;
440
441 std::cout << "\nMenus:-" << std::endl;
442 for (size_t i=0; i<menus.size(); ++i)
443 if (menus[i])
444 menus[i]->show_lines(i);
445
446 std::cout << "\nFull Windows:-" << std::endl;
447 for (std::map<int, size_t>::iterator itp = full_windows.begin(); itp != full_windows.end(); ++itp)
448 {
449 window_info *win = window_info_from_id(itp->first);
450 std::cout << " window_id=" << itp->first << " name=[" << ((win!=NULL)?win->window_name:"")
451 << "] menu_id=" << itp->second << std::endl;
452 }
453
454 std::cout << "\nWindow Regions:-" << std::endl;
455 for (REG_MM::iterator itp = window_regions.begin(); itp != window_regions.end(); ++itp)
456 {
457 window_info *win = window_info_from_id(itp->first);
458 std::cout << " window_id=" << itp->first << " name=[" << ((win!=NULL)?win->window_name:"")
459 << "] region=(" << itp->second.pos_x << ", " << itp->second.pos_y << ", " << itp->second.len_x
460 << ", " << itp->second.len_y << ")" << " menu_id=" << itp->second.cm_id << std::endl;
461 }
462
463 std::cout << "\nWindow Widgets:-" << std::endl;
464 for (WID_MM::iterator itp = window_widgets.begin(); itp != window_widgets.end(); ++itp)
465 {
466 window_info *win = window_info_from_id(itp->first);
467 std::cout << " window_id=" << itp->first << " name=[" << ((win!=NULL)?win->window_name:"")
468 << "] widget=" << itp->second.widget_id << " menu_id=" << itp->second.cm_id << std::endl;
469 }
470
471 } // end showinfo()
472
473
474
475
476
477 // Constructor - set default values for new menu
Menu(const char * menu_list,int (* handler)(window_info *,int,int,int,int))478 Menu::Menu(const char *menu_list, int (*handler)(window_info *, int, int, int, int))
479 : border(5), text_border(5), line_sep(3), zoom(0.8), data_ptr(0), selection(-1), menu_has_bools(false)
480 {
481 set(menu_list, handler);
482 pre_show_handler = 0;
483 highlight_top.set(gui_invert_color[0], gui_invert_color[1], gui_invert_color[2]);
484 highlight_bottom.set(gui_color[0], gui_color[1], gui_color[2]);
485 text_colour.set(1.0f, 1.0f, 1.0f);
486 grey_colour.set(0.7f, 0.7f, 0.7f);
487 }
488
489
490 // Set or replace the menu items
set(const char * menu_list,int (* handler)(window_info *,int,int,int,int))491 int Menu::set(const char *menu_list, int (*handler)(window_info *, int, int, int, int))
492 {
493 this->handler = handler;
494 menu_lines.clear();
495 return add(menu_list, handler);
496 }
497
498
499 // Add new the menu items and optionally replace the handler
add(const char * menu_list,int (* handler)(window_info *,int,int,int,int))500 int Menu::add(const char *menu_list, int (*handler)(window_info *, int, int, int, int))
501 {
502 if (handler)
503 this->handler = handler;
504 if (menu_list == NULL)
505 menu_list = "";
506 std::string menu_string(menu_list);
507 for (size_t pos = 0; pos != std::string::npos;)
508 {
509 size_t endpos = menu_string.find('\n', pos);
510 std::string new_entry = menu_string.substr(pos, endpos-pos);
511 if (!new_entry.empty())
512 {
513 Menu_Line newline(new_entry);
514 if (new_entry == std::string("--"))
515 newline.is_separator = true;
516 menu_lines.push_back(newline);
517 }
518 if (endpos == std::string::npos)
519 break;
520 pos = endpos+1;
521 }
522 return resize();
523 }
524
525
526 // Change a single menu item if it exists
change_line(size_t line_index,const char * new_entry)527 int Menu::change_line(size_t line_index, const char *new_entry)
528 {
529 if (line_index >= menu_lines.size())
530 return 0;
531 menu_lines[line_index].text = std::string(new_entry);
532 menu_lines[line_index].control_var = 0;
533 menu_lines[line_index].config_name = 0;
534 menu_lines[line_index].is_grey = menu_lines[line_index].is_separator = false;
535 if (new_entry == std::string("--"))
536 menu_lines[line_index].is_separator = true;
537 return 1;
538 }
539
540
541 // Make a line in the menu an off/on option, control_var determines state
bool_line(size_t line_index,int * control_var,const char * config_name)542 int Menu::bool_line(size_t line_index, int *control_var, const char *config_name)
543 {
544 if (line_index >= menu_lines.size())
545 return 0;
546 menu_lines[line_index].control_var = control_var;
547 menu_lines[line_index].config_name = config_name;
548 if (!menu_has_bools)
549 {
550 menu_has_bools = true;
551 resize();
552 }
553 return 1;
554 }
555
556
557 // grey/ungrey a menu line
grey_line(size_t line_index,bool is_grey)558 int Menu::grey_line(size_t line_index, bool is_grey)
559 {
560 if (line_index >= menu_lines.size())
561 return 0;
562 menu_lines[line_index].is_grey = is_grey;
563 return 1;
564 }
565
566
567 // Calculate the height/width of the context menu and resize the window
resize(void)568 int Menu::resize(void)
569 {
570 const float scale = scaled_value(1.0);
571 float fwidth = 0, fheight = 0;
572 for (size_t i=0; i<menu_lines.size(); i++)
573 {
574 const unsigned char* thetext = reinterpret_cast<const unsigned char*>(menu_lines[i].text.c_str());
575 int str_width = get_string_width_zoom(thetext, UI_FONT, scale);
576 if (str_width > fwidth)
577 fwidth = str_width;
578 if (menu_lines[i].is_separator)
579 fheight += get_line_height(UI_FONT, 0.5 * scale);
580 else
581 fheight += get_line_height(UI_FONT, scale) + line_sep;
582 }
583 bool_tick_width = (menu_has_bools)? scaled_value(bool_box_size()+text_border) : 0;
584 fwidth += bool_tick_width + (border + text_border) * 2;
585 fheight += border * 2;
586 height = static_cast<int>(fheight+0.5);
587 width = static_cast<int>(fwidth+0.5);
588 return 1;
589 }
590
591
592 // show the selected context menu
show(int cm_window_id)593 int Menu::show(int cm_window_id)
594 {
595 // if the window is already displayed, hide it then return
596 if (get_show_window(cm_window_id))
597 {
598 hide_window(cm_window_id);
599 return 1;
600 }
601
602 // save the mouse position for the callback
603 int wx = opened_mouse_x = mouse_x;
604 int wy = opened_mouse_y = mouse_y;
605
606 // resize in case scaling changed
607 resize();
608
609 // move the window, one corner anchored to the mouse click position, so its on screen
610 if (wx+width > window_width)
611 wx -= width;
612 if (wy+height > window_height)
613 wy -= height;
614 move_window(cm_window_id, -1, 0, wx, wy);
615
616 // make sure the window is updated with this instances size and data
617 windows_list.window[cm_window_id].data = this;
618 resize_window(cm_window_id, width, height);
619
620 // parent_win will be NULL if we don't have one
621 const Container& container = Container::get_instance();
622 window_info *parent_win = window_info_from_id(container.get_active_window_id());
623
624 // copy any parent window opacity to the context menu
625 if (parent_win != NULL && (parent_win->flags & ELW_SWITCHABLE_OPAQUE))
626 windows_list.window[cm_window_id].opaque = parent_win->opaque;
627 else
628 // otherwise use the default setting
629 windows_list.window[cm_window_id].opaque = opaque_window_backgrounds;
630
631 /* call any registered pre_show handler */
632 if (pre_show_handler)
633 {
634 // if we have a parent window, the mouse position is the original position that opened the menu
635 if (parent_win != NULL)
636 {
637 int parent_win_x = opened_mouse_x - parent_win->cur_x;
638 int parent_win_y = opened_mouse_y - parent_win->cur_y;
639 (*pre_show_handler)(parent_win, container.get_active_widget_id(),
640 parent_win_x, parent_win_y, window_info_from_id(cm_window_id));
641 }
642 else
643 (*pre_show_handler)(NULL, 0, 0, 0, window_info_from_id(cm_window_id));
644 }
645
646 show_window(cm_window_id);
647 select_window(cm_window_id);
648
649 return 1;
650 }
651
652
653 // display the menu options with highlight if mouse is over one
display(window_info * win,int mx,int my,Uint32 flags)654 int Menu::display(window_info *win, int mx, int my, Uint32 flags)
655 {
656 CHECK_GL_ERRORS();
657 float currenty = border + line_sep;
658 float scale = scaled_value(1.0);
659 int line_height = get_line_height(win->font_category, scale);
660 int box_size = std::round(scaled_value(bool_box_size()));
661 float line_step = line_sep + max2i(box_size, line_height);
662
663 selection = -1;
664 for (size_t i=0; i<menu_lines.size(); ++i)
665 {
666 // if the mouse is over a valid line, draw the highlight and select line
667 if (!menu_lines[i].is_grey && !menu_lines[i].is_separator &&
668 (mouse_y > win->cur_y + currenty - line_sep) &&
669 (mouse_y < win->cur_y + currenty + line_step - line_sep) &&
670 (mouse_x > win->cur_x + border) &&
671 (mouse_x < win->cur_x + width - border))
672 {
673 glDisable(GL_TEXTURE_2D);
674 glBegin(GL_QUADS);
675 glColor3f(highlight_top.r, highlight_top.g, highlight_top.b);
676 glVertex3i(border, int(currenty + 0.5) - line_sep, 0);
677 glColor3f(highlight_bottom.r, highlight_bottom.g, highlight_bottom.b);
678 glVertex3i(border, int(currenty + line_step + 0.5) - line_sep, 0);
679 glVertex3i(border+width-2*border, int(currenty + line_step + 0.5) - line_sep, 0);
680 glColor3f(highlight_top.r, highlight_top.g, highlight_top.b);
681 glVertex3i(border+width-2*border, int(currenty + 0.5) - line_sep, 0);
682 glEnd();
683 glEnable(GL_TEXTURE_2D);
684 selection = i;
685 }
686
687 // draw a separator ...
688 if (menu_lines[i].is_separator)
689 {
690 int posx = border + text_border;
691 int posy = currenty + get_line_height(win->font_category, 0.25*scale) - line_sep;
692 glColor3f(grey_colour.r, grey_colour.g, grey_colour.b);
693 glDisable(GL_TEXTURE_2D);
694 glBegin(GL_LINES);
695 glVertex2i(posx, posy);
696 glVertex2i(win->len_x - posx, posy);
697 glEnd();
698 glEnable(GL_TEXTURE_2D);
699 currenty += get_line_height(win->font_category, 0.5*scale);
700 }
701
702 // ... or the menu line
703 else
704 {
705 if (menu_lines[i].is_grey)
706 glColor3f(grey_colour.r, grey_colour.g, grey_colour.b);
707 else
708 glColor3f(text_colour.r, text_colour.g, text_colour.b);
709
710 // draw the tickbox if bool option */
711 if (menu_has_bools && menu_lines[i].control_var)
712 {
713 int box_x = border+text_border;
714 int box_y = std::round(currenty + (box_size < line_height ? 0.5 * (line_height - box_size) : 0)) - line_sep / 2;
715 glDisable(GL_TEXTURE_2D);
716 glBegin( *menu_lines[i].control_var ? GL_QUADS: GL_LINE_LOOP);
717 glVertex3i(box_x, box_y, 0);
718 glVertex3i(box_x + box_size, box_y, 0);
719 glVertex3i(box_x + box_size, box_y + box_size, 0);
720 glVertex3i(box_x, box_y + box_size, 0);
721 glEnd();
722 glEnable(GL_TEXTURE_2D);
723 }
724
725 // draw the text
726 int text_y = std::round(currenty + (box_size < line_height ? 0 : 0.5*(box_size - line_height)));
727 draw_string_zoomed(int(border+text_border+bool_tick_width+0.5), text_y - line_sep / 2,
728 (const unsigned char *)menu_lines[i].text.c_str(), 1, scaled_value(1.0));
729 currenty += line_step;
730 }
731
732 } // end foir each line
733
734 CHECK_GL_ERRORS();
735 return 1;
736
737 } // end Menu::display()
738
739
740 // if an option is selected, toggle if a bool option and call any callback function
click(window_info * win,int mx,int my,Uint32 flags)741 int Menu::click(window_info *win, int mx, int my, Uint32 flags)
742 {
743 if (selection < 0)
744 return 0;
745
746 // if a bool line, toggle the control variable
747 if (menu_lines[selection].control_var)
748 {
749 // if we have a config control name, use the vars change function, otherwise just toggle
750 if (menu_lines[selection].config_name)
751 toggle_OPT_BOOL_by_name(menu_lines[selection].config_name);
752 else
753 *menu_lines[selection].control_var = !*menu_lines[selection].control_var;
754 if (!handler)
755 return 1;
756 }
757
758 if (!handler)
759 return 0;
760
761 // if we have a parent window, the mouse position is the original position that opened the menu
762 const Container& container = Container::get_instance();
763 window_info *parent_win = window_info_from_id(container.get_active_window_id());
764 if (parent_win != NULL)
765 {
766 int parent_win_x = opened_mouse_x - parent_win->cur_x;
767 int parent_win_y = opened_mouse_y - parent_win->cur_y;
768 return (*handler)(parent_win, container.get_active_widget_id(),
769 parent_win_x, parent_win_y, selection);
770 }
771 else
772 return (*handler)(NULL, 0, 0, 0, selection);
773 }
774
775
776 // set basic size properties
set_sizes(int border,int text_border,int line_sep,float zoom)777 int Menu::set_sizes(int border, int text_border, int line_sep, float zoom)
778 {
779 this->border = border;
780 this->text_border = text_border;
781 this->line_sep = line_sep;
782 this->zoom = zoom;
783 return resize();
784 }
785
786 // set the named property colour
set_colour(size_t cm_id,enum CM_COLOUR_NAME colour_name,float r,float g,float b)787 int Menu::set_colour(size_t cm_id, enum CM_COLOUR_NAME colour_name, float r, float g, float b)
788 {
789 switch (colour_name)
790 {
791 case CM_HIGHLIGHT_TOP: highlight_top.set(r,g,b); break;
792 case CM_HIGHLIGHT_BOTTOM: highlight_bottom.set(r,g,b); break;
793 case CM_TEXT: text_colour.set(r,g,b); break;
794 case CM_GREY: grey_colour.set(r,g,b); break;
795 default:
796 return 0;
797 }
798 return 1;
799 }
800
801
802 // show information about menu lines
show_lines(size_t my_id)803 void Menu::show_lines(size_t my_id)
804 {
805 std::cout << " menu_id=" << my_id << " has_bools=" << menu_has_bools << std::endl;
806 for (size_t i=0; i<menu_lines.size(); ++i)
807 {
808 if (menu_lines[i].control_var)
809 {
810 std::cout << " [" << menu_lines[i].text << "] value=" << *menu_lines[i].control_var;
811 if (menu_lines[i].config_name)
812 std::cout << " config name=[" << *menu_lines[i].config_name << "]";
813 }
814 else
815 std::cout << " [" << menu_lines[i].text << "]";
816 std::cout << " " << ((menu_lines[i].is_grey) ?"greyed":"ungreyed")
817 << " " << ((menu_lines[i].is_separator) ?"separator":"normal") << std::endl;
818 }
819 }
820
821 // calculate a scaled value
scaled_value(float val) const822 float Menu::scaled_value(float val) const
823 {
824 return val * Container::get_instance().get_current_scale() * zoom;
825 }
826
827
828 } // end cm namespace
829
830
831
832 // C wrapper functions
cm_create(const char * menu_list,int (* handler)(window_info *,int,int,int,int))833 extern "C" size_t cm_create(const char *menu_list, int (*handler)(window_info *, int, int, int, int )) { return cm::Container::get_instance().create(menu_list, handler); }
cm_destroy(size_t cm_id)834 extern "C" int cm_destroy(size_t cm_id) { return cm::Container::get_instance().destroy(cm_id); }
cm_pre_show_check(Uint32 flags)835 extern "C" int cm_pre_show_check(Uint32 flags) { return cm::Container::get_instance().pre_show_check(flags); }
cm_post_show_check(int force)836 extern "C" void cm_post_show_check(int force) { cm::Container::get_instance().post_show_check(force); }
cm_show_if_active(int window_id)837 extern "C" int cm_show_if_active(int window_id) { return cm::Container::get_instance().show_if_active(window_id); }
cm_show_direct(size_t cm_id,int window_id,int widget_id)838 extern "C" int cm_show_direct(size_t cm_id, int window_id, int widget_id) { return cm::Container::get_instance().show_direct(cm_id, window_id, widget_id); }
cm_bool_line(size_t cm_id,size_t line_index,int * control_var,const char * config_name)839 extern "C" int cm_bool_line(size_t cm_id, size_t line_index, int *control_var, const char *config_name) { return cm::Container::get_instance().bool_line(cm_id, line_index, control_var, config_name); }
cm_grey_line(size_t cm_id,size_t line_index,int is_grey)840 extern "C" int cm_grey_line(size_t cm_id, size_t line_index, int is_grey) { return cm::Container::get_instance().grey_line(cm_id, line_index, is_grey); }
cm_set(size_t cm_id,const char * menu_list,int (* handler)(window_info *,int,int,int,int))841 extern "C" int cm_set(size_t cm_id, const char *menu_list, int (*handler)(window_info *, int, int, int, int)) { return cm::Container::get_instance().set(cm_id, menu_list, handler); }
cm_add(size_t cm_id,const char * menu_list,int (* handler)(window_info *,int,int,int,int))842 extern "C" int cm_add(size_t cm_id, const char *menu_list, int (*handler)(window_info *, int, int, int, int)) { return cm::Container::get_instance().add(cm_id, menu_list, handler); }
cm_set_pre_show_handler(size_t cm_id,void (* handler)(window_info *,int,int,int,window_info *))843 extern "C" int cm_set_pre_show_handler(size_t cm_id, void (*handler)(window_info *, int, int, int, window_info *)) { return cm::Container::get_instance().set_pre_show_handler(cm_id, handler); }
cm_set_sizes(size_t cm_id,int border,int text_border,int line_sep,float zoom)844 extern "C" int cm_set_sizes(size_t cm_id, int border, int text_border, int line_sep, float zoom) { return cm::Container::get_instance().set_sizes(cm_id, border, text_border, line_sep, zoom); }
cm_set_colour(size_t cm_id,enum CM_COLOUR_NAME colour_name,float r,float g,float b)845 extern "C" int cm_set_colour(size_t cm_id, enum CM_COLOUR_NAME colour_name, float r, float g, float b) { return cm::Container::get_instance().set_colour(cm_id, colour_name, r, g, b); }
cm_add_window(size_t cm_id,int window_id)846 extern "C" int cm_add_window(size_t cm_id, int window_id) { return cm::Container::get_instance().add_window(cm_id, window_id); }
cm_add_region(size_t cm_id,int window_id,int posx,int posy,int lenx,int leny)847 extern "C" int cm_add_region(size_t cm_id, int window_id, int posx, int posy, int lenx, int leny) { return cm::Container::get_instance().add_region(cm_id, window_id, posx, posy, lenx, leny); }
cm_add_widget(size_t cm_id,int window_id,int widget_id)848 extern "C" int cm_add_widget(size_t cm_id, int window_id, int widget_id) { return cm::Container::get_instance().add_widget(cm_id, window_id, widget_id); }
cm_remove_window(int window_id)849 extern "C" int cm_remove_window(int window_id) { return cm::Container::get_instance().remove_window(window_id); }
cm_remove_regions(int window_id)850 extern "C" int cm_remove_regions(int window_id) { return cm::Container::get_instance().remove_regions(window_id); }
cm_remove_widget(int window_id,int widget_id)851 extern "C" int cm_remove_widget(int window_id, int widget_id) { return cm::Container::get_instance().remove_widget(window_id, widget_id); }
cm_showinfo(void)852 extern "C" void cm_showinfo(void) { cm::Container::get_instance().showinfo(); }
cm_valid(size_t cm_id)853 extern "C" int cm_valid(size_t cm_id) { if (cm::Container::get_instance().valid(cm_id)) return 1; else return 0; }
cm_window_shown(void)854 extern "C" size_t cm_window_shown(void) { return cm::Container::get_instance().window_shown(); }
cm_get_data(size_t cm_id)855 extern "C" void *cm_get_data(size_t cm_id) { return cm::Container::get_instance().get_data(cm_id); }
cm_set_data(size_t cm_id,void * data)856 extern "C" void cm_set_data(size_t cm_id, void *data) { cm::Container::get_instance().set_data(cm_id, data); }
857
858
859
860
861
862
863 //
864 // Provides a window to exercise context menu functions.
865 //
866 #ifdef CONTEXT_MENUS_TEST
867
868 static int cm_test_win = -1;
869 static size_t cm_test_win_menu = -1;
870 static size_t cm_test_reg_menu = -1;
871 static size_t cm_test_wid_menu = -1;
872 static size_t cm_test_dir_menu = -1;
873 static int cm_test_wid = -1;
874 static int cm_bool_var = 0;
875 static int cm_coord[2][4] = {{200, 100, 40, 40}, {250, 150, 40, 40}};
876 static int cm_grey_var = 0;
877
cm_test_window_display_handler(window_info * win)878 static int cm_test_window_display_handler(window_info *win)
879 {
880 static int last_bool_var = cm_bool_var;
881 int i;
882 CHECK_GL_ERRORS();
883 // draw the region boxes so we know where they are
884 for (i=0; i<2; i++)
885 {
886 glDisable(GL_TEXTURE_2D);
887 glColor3fv(gui_color);
888 glBegin(GL_LINE_LOOP);
889 glVertex3i(cm_coord[i][0], cm_coord[i][1], 0);
890 glVertex3i(cm_coord[i][0]+cm_coord[i][2], cm_coord[i][1], 0);
891 glVertex3i(cm_coord[i][0]+cm_coord[i][2], cm_coord[i][1]+cm_coord[i][3], 0);
892 glVertex3i(cm_coord[i][0], cm_coord[i][1]+cm_coord[i][3], 0);
893 glEnd();
894 glEnable(GL_TEXTURE_2D);
895 }
896 if (cm_bool_var != last_bool_var)
897 {
898 last_bool_var = cm_bool_var;
899 printf("Bool var changed, now=%d\n", cm_bool_var);
900 }
901 CHECK_GL_ERRORS();
902 return 1;
903 }
904
cm_test_menu_pre_show_handler(window_info * win,int widget_id,int mx,int my,window_info * cm_win)905 static void cm_test_menu_pre_show_handler(window_info *win, int widget_id, int mx, int my, window_info *cm_win)
906 {
907 printf("CM pre show: Set bool menu cm_grey_line()=%d window_id=%d widget_id=%d mx=%d my=%d winid=%d\n",
908 cm_grey_line(cm_test_win_menu, 3, cm_grey_var), win->window_id, widget_id, mx, my, cm_win->window_id);
909 }
910
cm_test_menu_handler(window_info * win,int widget_id,int mx,int my,int option)911 static int cm_test_menu_handler(window_info *win, int widget_id, int mx, int my, int option)
912 {
913 printf("CM selected: window_id=%d widget_id=%d mx=%d my=%d option=%d\n", win->window_id, widget_id, mx, my, option );
914 return 1;
915 }
916
cm_info_but_handler(widget_list * widget,int mx,int my,Uint32 flags)917 static int cm_info_but_handler(widget_list *widget, int mx, int my, Uint32 flags)
918 {
919 cm_showinfo();
920 return 1;
921 }
922
cm_dir_click_handler(widget_list * widget,int mx,int my,Uint32 flags)923 static int cm_dir_click_handler(widget_list *widget, int mx, int my, Uint32 flags)
924 {
925 if (flags & ELW_RIGHT_MOUSE)
926 printf("Direct clicked cm_show_direct()=%d\n", cm_show_direct(cm_test_dir_menu, cm_test_win, -1));
927 return 1;
928 }
929
cm_add_win_handler(widget_list * widget,int mx,int my,Uint32 flags)930 static int cm_add_win_handler(widget_list *widget, int mx, int my, Uint32 flags)
931 {
932 printf("Adding window cm_add_window()=%d\n", cm_add_window(cm_test_win_menu, widget->window_id));
933 return 1;
934 }
935
cm_del_win_handler(widget_list * widget,int mx,int my,Uint32 flags)936 extern "C" int cm_del_win_handler(widget_list *widget, int mx, int my, Uint32 flags)
937 {
938 printf("Removing window cm_remove_window()=%d\n", cm_remove_window(widget->window_id));
939 return 1;
940 }
941
cm_add_reg_handler(widget_list * widget,int mx,int my,Uint32 flags)942 static int cm_add_reg_handler(widget_list *widget, int mx, int my, Uint32 flags)
943 {
944 int i;
945 for (i=0; i<2; i++)
946 printf("Adding region %d cm_add_region()=%d\n", i,
947 cm_add_region(cm_test_reg_menu, widget->window_id, cm_coord[i][0], cm_coord[i][1], cm_coord[i][2], cm_coord[i][3] ));
948 return 1;
949 }
950
cm_del_reg_handler(widget_list * widget,int mx,int my,Uint32 flags)951 extern "C" int cm_del_reg_handler(widget_list *widget, int mx, int my, Uint32 flags)
952 {
953 printf("Removing regions status=%d\n", cm_remove_regions(widget->window_id));
954 return 1;
955 }
956
cm_add_wid_handler(widget_list * widget,int mx,int my,Uint32 flags)957 static int cm_add_wid_handler(widget_list *widget, int mx, int my, Uint32 flags)
958 {
959 printf("Adding widget cm_add_widget()=%d\n", cm_add_widget(cm_test_wid_menu, widget->window_id, cm_test_wid));
960 return 1;
961 }
962
cm_del_wid_handler(widget_list * widget,int mx,int my,Uint32 flags)963 extern "C" int cm_del_wid_handler(widget_list *widget, int mx, int my, Uint32 flags)
964 {
965 printf("Removing widget cm_remove_widget()=%d\n", cm_remove_widget(widget->window_id, cm_test_wid));
966 return 1;
967 }
968
cm_test_window(char * text,int len)969 extern "C" int cm_test_window(char *text, int len)
970 {
971 int cm_add_win = -1;
972 int cm_add_reg = -1;
973 int cm_add_wid = -1;
974 int cm_del_win = -1;
975 int cm_del_reg = -1;
976 int cm_del_wid = -1;
977 int cm_info_but = -1;
978 int cm_dir_but = -1;
979
980 if (cm_test_win == -1)
981 {
982 cm_test_win = create_window("Test Context Menu", -1, -1, 0, 0, 400, 400, ELW_WIN_DEFAULT);
983 set_window_handler(cm_test_win, ELW_HANDLER_DISPLAY, (int (*)())&cm_test_window_display_handler );
984
985 cm_add_win = button_add_extended(cm_test_win, 100, NULL, 10, 10, 0, 0, 0, 1.0f, "Add window");
986 cm_add_reg = button_add_extended(cm_test_win, 101, NULL, 10, 50, 0, 0, 0, 1.0f, "Add region");
987 cm_add_wid = button_add_extended(cm_test_win, 102, NULL, 10, 90, 0, 0, 0, 1.0f, "Add widget");
988 cm_del_win = button_add_extended(cm_test_win, 103, NULL, 10, 130, 0, 0, 0, 1.0f, "Del window");
989 cm_del_reg = button_add_extended(cm_test_win, 104, NULL, 10, 170, 0, 0, 0, 1.0f, "Del regions");
990 cm_del_wid = button_add_extended(cm_test_win, 105, NULL, 10, 210, 0, 0, 0, 1.0f, "Del widget");
991 cm_info_but = button_add_extended(cm_test_win, 106, NULL, 200, 10, 0, 0, 0, 1.0f, "Show Info");
992 cm_test_wid = button_add_extended(cm_test_win, 107, NULL, 200, 50, 0, 0, 0, 1.0f, "Test Menu");
993 cm_dir_but = button_add_extended(cm_test_win, 108, NULL, 200, 200, 0, 0, 0, 1.0f, "Direct Menu");
994
995 widget_set_OnClick(cm_test_win, cm_add_win, (int (*)())&cm_add_win_handler);
996 widget_set_OnClick(cm_test_win, cm_del_win, (int (*)())&cm_del_win_handler);
997 widget_set_OnClick(cm_test_win, cm_add_reg, (int (*)())&cm_add_reg_handler);
998 widget_set_OnClick(cm_test_win, cm_del_reg, (int (*)())&cm_del_reg_handler);
999 widget_set_OnClick(cm_test_win, cm_add_wid, (int (*)())&cm_add_wid_handler);
1000 widget_set_OnClick(cm_test_win, cm_del_wid, (int (*)())&cm_del_wid_handler);
1001 widget_set_OnClick(cm_test_win, cm_info_but, (int (*)())&cm_info_but_handler);
1002 widget_set_OnClick(cm_test_win, cm_dir_but, (int (*)())&cm_dir_click_handler);
1003
1004 cm_test_win_menu = cm_create("", NULL);
1005 cm_test_reg_menu = cm_create("Region 1\nRegion 2\n", cm_test_menu_handler);
1006 cm_test_wid_menu = cm_create("Widget 1\n--\nWidget 3\nWidget 4\nWidget 5\nWidget 6\n", cm_test_menu_handler);
1007 cm_test_dir_menu = cm_create("Direct 1\nDirect 2\n", cm_test_menu_handler);
1008 printf("Created menus window=%lu region=%lu widget=%lu direct=%lu\n",
1009 cm_test_win_menu, cm_test_reg_menu, cm_test_wid_menu, cm_test_dir_menu);
1010
1011 printf("Replacing window menu cm_set()=%d\n", cm_set(cm_test_win_menu, "Window 1\nWindow 2\n--\nGrey me...\nGrey above\n", cm_test_menu_handler));
1012 printf("Set win menu cm_bool_line()=%d\n", cm_bool_line(cm_test_win_menu, 0, &cm_bool_var, NULL));
1013 printf("Set win menu cm_bool_line()=%d\n", cm_bool_line(cm_test_win_menu, 1, &cm_bool_var, NULL));
1014 printf("Set win menu cm_grey_line()=%d\n", cm_grey_line(cm_test_win_menu, 3, cm_grey_var));
1015 printf("Set win menu cm_bool_line()=%d\n", cm_bool_line(cm_test_win_menu, 4, &cm_grey_var, NULL));
1016 printf("Set widget menu cm_grey_line()=%d\n", cm_grey_line(cm_test_wid_menu, 3, 1));
1017 printf("Calling cm_set_pre_show_handler()=%d\n", cm_set_pre_show_handler(cm_test_win_menu, cm_test_menu_pre_show_handler) );
1018 printf("Changing widget menu sizes cm_set_sizes()=%d\n", cm_set_sizes(cm_test_wid_menu, 10, 10, 10, 2));
1019 printf("Changing widget menu text colour cm_set_colour()=%d\n", cm_set_colour(cm_test_wid_menu, CM_TEXT, 0, 0, 1));
1020 printf("Changing widget menu grey colour cm_set_colour()=%d\n", cm_set_colour(cm_test_wid_menu, CM_GREY, 0, 0, 0.5));
1021 printf("Changing widget menu pale highlight colour cm_set_colour()=%d\n", cm_set_colour(cm_test_wid_menu, CM_HIGHLIGHT_TOP, 1, 0, 0));
1022 printf("Changing widget menu bright highlight colour cm_set_colour()=%d\n", cm_set_colour(cm_test_wid_menu, CM_HIGHLIGHT_BOTTOM, 0, 1, 0));
1023 }
1024 else
1025 {
1026 printf("\n\nDestroy cm_test_win_menu cm_destroy()=%d\n", cm_destroy(cm_test_win_menu));
1027 printf("Destroy cm_test_reg_menu cm_destroy()=%d\n", cm_destroy(cm_test_reg_menu));
1028 printf("Destroy cm_test_wid_menu cm_destroy()=%d\n", cm_destroy(cm_test_wid_menu));
1029 printf("Destroy cm_test_dir_menu cm_destroy()=%d\n", cm_destroy(cm_test_dir_menu));
1030 destroy_window(cm_test_win);
1031 cm_test_win = -1;
1032 cm_showinfo();
1033 }
1034
1035 return 1;
1036 }
1037
1038 #endif
1039