00001 // This is core/vgui/impl/glut/vgui_glut_popup_impl.cxx 00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE 00003 #pragma implementation 00004 #endif 00005 //: 00006 // \file 00007 // \author fsm 00008 00009 #include "vgui_glut_popup_impl.h" 00010 #include "vgui_glut_adaptor.h" 00011 #include <vcl_iostream.h> 00012 #include <vgui/vgui_macro.h> 00013 #include <vgui/vgui_command.h> 00014 #include <vgui/vgui_glut.h> 00015 00016 vgui_glut_popup_impl::vgui_glut_popup_impl() 00017 { 00018 #ifdef DEBUG 00019 vcl_cerr << "popup_impl ctor\n"; 00020 #endif 00021 int old_id = glutGetMenu(); 00022 menu_id = glutCreateMenu(command_func); 00023 #ifdef DEBUG 00024 vcl_cerr << "created menu_id = " << menu_id << '\n'; 00025 #endif 00026 00027 //vgui_macro_warning << "before\n"; 00028 if (old_id) 00029 glutSetMenu(old_id); 00030 //vgui_macro_warning << "after\n"; 00031 } 00032 00033 00034 void vgui_glut_popup_impl::clear() 00035 { 00036 int old_id = glutGetMenu(); 00037 glutSetMenu(menu_id); 00038 00039 // 00040 unsigned n = glutGet(GLenum(GLUT_MENU_NUM_ITEMS)); 00041 #ifdef DEBUG 00042 vcl_cerr << "removing " << n << " items in menu\n"; 00043 #endif 00044 for (int i=n; i>=1; --i) 00045 glutRemoveMenuItem(i); 00046 00047 // 00048 //vgui_macro_warning << "before\n"; 00049 if (old_id) 00050 glutSetMenu(old_id); 00051 //vgui_macro_warning << "after\n"; 00052 00053 // 00054 for (unsigned i=0; i<subs.size(); ++i) 00055 delete static_cast<vgui_glut_popup_impl*>( subs[i] ); 00056 subs.clear(); 00057 } 00058 00059 vgui_glut_popup_impl::~vgui_glut_popup_impl() 00060 { 00061 #ifdef DEBUG 00062 vcl_cerr << "popup_impl dtor\n"; 00063 #endif 00064 clear(); 00065 glutDestroyMenu( menu_id ); 00066 menu_id = 0; 00067 } 00068 00069 void vgui_glut_popup_impl::build(vgui_menu const &m) 00070 { 00071 //clear(); 00072 00073 // FIXME - this line here is to make sure the commands in the 00074 // given menu stay alive while the popup menu is active : 00075 tmp_menu = m; 00076 00077 #ifdef DEBUG 00078 vcl_cerr << "popup_impl::build : m =\n" << m << '\n'; 00079 #endif 00080 this->build_internal(m); 00081 } 00082 00083 void vgui_glut_popup_impl::build_internal(vgui_menu const &m) 00084 { 00085 int old_id = glutGetMenu(); 00086 //vgui_macro_warning << "before\n"; 00087 glutSetMenu(menu_id); 00088 //vgui_macro_warning << "after\n"; 00089 00090 for (unsigned i=0; i<m.size(); ++i) { 00091 if (m[i].is_command()) 00092 glutAddMenuEntry( m[i].name.c_str(), 00093 reinterpret_cast<long>(m[i].cmnd.as_pointer())); 00094 00095 else if (m[i].is_submenu()) { 00096 vgui_glut_popup_impl *sub = new vgui_glut_popup_impl; 00097 sub->build_internal( * m[i].menu ); 00098 glutAddSubMenu (m[i].name.c_str(), sub->menu_id); 00099 subs.push_back(sub); 00100 } 00101 00102 else if (m[i].is_toggle_button()) { 00103 vgui_command_toggle *c = static_cast<vgui_command_toggle*>( m[i].cmnd.as_pointer() ); 00104 glutAddMenuEntry( (m[i].name + (c->state ? " (on)" : " (off)")).c_str(), 00105 reinterpret_cast<long>(m[i].cmnd.as_pointer())); 00106 } 00107 00108 else if (m[i].is_separator()) { 00109 // do glut menus have real separators? 00110 if (0<i && i<m.size()-1) // ignore separators at start and end. 00111 glutAddMenuEntry( "----------------", 1); 00112 } 00113 00114 else { 00115 vgui_macro_warning << "unknown menu item\n" 00116 << "menu =\n" << m << vcl_endl; 00117 } 00118 } 00119 00120 //vgui_macro_warning << "before\n"; 00121 if (old_id) 00122 glutSetMenu(old_id); // restore 00123 //vgui_macro_warning << "after\n"; 00124 } 00125 00126 // When a menu item is selected, glut may have upset its internal 00127 // state considerably and so it is advisable to wait for the next 00128 // idle event before invoking the vgui_command. E.g. if the command 00129 // were to start run_one_event()ing, heap corruption often results. 00130 // To accomplish that, the action of selecting a menu item just 00131 // queues the command for later execution. 00132 00133 #include "vgui_glut_impl.h" 00134 00135 void vgui_glut_popup_impl::command_func(int value) 00136 { 00137 if (value == 0) 00138 vgui_macro_warning << "null command\n"; 00139 else if (value == 1) 00140 vcl_cerr << "[that's a separator]\n"; 00141 else { 00142 int win = glutGetWindow(); 00143 vgui_glut_adaptor *a = vgui_glut_adaptor::get_adaptor(win); 00144 vgui_command *c = reinterpret_cast<vgui_command *>(value); 00145 vgui_glut_impl_queue_command(a, c); 00146 } 00147 }