1 // This is core/vgui/impl/glut/vgui_glut_popup_impl.cxx 2 //: 3 // \file 4 // \author fsm 5 6 #include <iostream> 7 #include "vgui_glut_popup_impl.h" 8 #include "vgui_glut_adaptor.h" 9 #ifdef _MSC_VER 10 # include "vcl_msvc_warnings.h" 11 #endif 12 #include "vgui/vgui_macro.h" 13 #include "vgui/vgui_command.h" 14 #include "vgui/vgui_glut.h" 15 vgui_glut_popup_impl()16vgui_glut_popup_impl::vgui_glut_popup_impl() 17 { 18 #ifdef DEBUG 19 std::cerr << "popup_impl ctor\n"; 20 #endif 21 int old_id = glutGetMenu(); 22 menu_id = glutCreateMenu(command_func); 23 #ifdef DEBUG 24 std::cerr << "created menu_id = " << menu_id << '\n'; 25 #endif 26 27 // vgui_macro_warning << "before\n"; 28 if (old_id) 29 glutSetMenu(old_id); 30 // vgui_macro_warning << "after\n"; 31 } 32 33 34 void clear()35vgui_glut_popup_impl::clear() 36 { 37 int old_id = glutGetMenu(); 38 glutSetMenu(menu_id); 39 40 // 41 unsigned n = glutGet(GLenum(GLUT_MENU_NUM_ITEMS)); 42 #ifdef DEBUG 43 std::cerr << "removing " << n << " items in menu\n"; 44 #endif 45 for (int i = n; i >= 1; --i) 46 glutRemoveMenuItem(i); 47 48 // 49 // vgui_macro_warning << "before\n"; 50 if (old_id) 51 glutSetMenu(old_id); 52 // vgui_macro_warning << "after\n"; 53 54 // 55 for (unsigned i = 0; i < subs.size(); ++i) 56 delete static_cast<vgui_glut_popup_impl *>(subs[i]); 57 subs.clear(); 58 } 59 ~vgui_glut_popup_impl()60vgui_glut_popup_impl::~vgui_glut_popup_impl() 61 { 62 #ifdef DEBUG 63 std::cerr << "popup_impl dtor\n"; 64 #endif 65 clear(); 66 glutDestroyMenu(menu_id); 67 menu_id = 0; 68 } 69 70 void build(vgui_menu const & m)71vgui_glut_popup_impl::build(vgui_menu const & m) 72 { 73 // clear(); 74 75 // FIXME - this line here is to make sure the commands in the 76 // given menu stay alive while the popup menu is active : 77 tmp_menu = m; 78 79 #ifdef DEBUG 80 std::cerr << "popup_impl::build : m =\n" << m << '\n'; 81 #endif 82 this->build_internal(m); 83 } 84 85 void build_internal(vgui_menu const & m)86vgui_glut_popup_impl::build_internal(vgui_menu const & m) 87 { 88 int old_id = glutGetMenu(); 89 // vgui_macro_warning << "before\n"; 90 glutSetMenu(menu_id); 91 // vgui_macro_warning << "after\n"; 92 93 for (unsigned i = 0; i < m.size(); ++i) 94 { 95 if (m[i].is_command()) 96 glutAddMenuEntry(m[i].name.c_str(), reinterpret_cast<long>(m[i].cmnd.as_pointer())); 97 98 else if (m[i].is_submenu()) 99 { 100 vgui_glut_popup_impl * sub = new vgui_glut_popup_impl; 101 sub->build_internal(*m[i].menu); 102 glutAddSubMenu(m[i].name.c_str(), sub->menu_id); 103 subs.push_back(sub); 104 } 105 106 else if (m[i].is_toggle_button()) 107 { 108 vgui_command_toggle * c = static_cast<vgui_command_toggle *>(m[i].cmnd.as_pointer()); 109 glutAddMenuEntry((m[i].name + (c->state ? " (on)" : " (off)")).c_str(), 110 reinterpret_cast<long>(m[i].cmnd.as_pointer())); 111 } 112 113 else if (m[i].is_separator()) 114 { 115 // do glut menus have real separators? 116 if (0 < i && i < m.size() - 1) // ignore separators at start and end. 117 glutAddMenuEntry("----------------", 1); 118 } 119 120 else 121 { 122 vgui_macro_warning << "unknown menu item\n" 123 << "menu =\n" 124 << m << std::endl; 125 } 126 } 127 128 // vgui_macro_warning << "before\n"; 129 if (old_id) 130 glutSetMenu(old_id); // restore 131 // vgui_macro_warning << "after\n"; 132 } 133 134 // When a menu item is selected, glut may have upset its internal 135 // state considerably and so it is advisable to wait for the next 136 // idle event before invoking the vgui_command. E.g. if the command 137 // were to start run_one_event()ing, heap corruption often results. 138 // To accomplish that, the action of selecting a menu item just 139 // queues the command for later execution. 140 141 #include "vgui_glut_impl.h" 142 143 void command_func(int value)144vgui_glut_popup_impl::command_func(int value) 145 { 146 if (value == 0) 147 vgui_macro_warning << "null command\n"; 148 else if (value == 1) 149 std::cerr << "[that's a separator]\n"; 150 else 151 { 152 int win = glutGetWindow(); 153 vgui_glut_adaptor * a = vgui_glut_adaptor::get_adaptor(win); 154 vgui_command * c = reinterpret_cast<vgui_command *>(value); 155 vgui_glut_impl_queue_command(a, c); 156 } 157 } 158