diff --git a/pandatool/src/gtk-stats/Sources.pp b/pandatool/src/gtk-stats/Sources.pp index d826df33c3..34aad99125 100644 --- a/pandatool/src/gtk-stats/Sources.pp +++ b/pandatool/src/gtk-stats/Sources.pp @@ -14,6 +14,7 @@ #define SOURCES \ gtkStats.cxx \ + gtkStatsChartMenu.cxx gtkStatsChartMenu.h \ gtkStatsGraph.cxx gtkStatsGraph.h \ gtkStatsLabel.cxx gtkStatsLabel.h \ gtkStatsLabelStack.cxx gtkStatsLabelStack.h \ @@ -22,7 +23,6 @@ gtkStatsServer.cxx gtkStatsServer.h \ gtkStatsStripChart.cxx gtkStatsStripChart.h -// gtkStatsChartMenu.cxx gtkStatsChartMenu.h \ // gtkStatsPianoRoll.cxx gtkStatsPianoRoll.h \ #if $[DEVELOP_GTKSTATS] diff --git a/pandatool/src/gtk-stats/gtkStats.cxx b/pandatool/src/gtk-stats/gtkStats.cxx index c93eecd59d..77370754c9 100644 --- a/pandatool/src/gtk-stats/gtkStats.cxx +++ b/pandatool/src/gtk-stats/gtkStats.cxx @@ -39,8 +39,19 @@ destroy(GtkWidget *widget, gpointer data) { static gboolean timer(gpointer data) { + static int count = 0; server->poll(); + if (++count == 5) { + count = 0; + // Every once in a while, say once a second, we call this + // function, which should force gdk to make all changes visible. + // We do this in case we are getting starved and falling behind, + // so that the user still gets a chance to see *something* happen + // onscreen, even if it's just increasingly old data. + gdk_window_process_all_updates(); + } + return TRUE; } diff --git a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx index eaa4cb7856..f466b98f0c 100755 --- a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx +++ b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx @@ -29,7 +29,8 @@ GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index) : _monitor(monitor), _thread_index(thread_index) { - _menu = CreatePopupMenu(); + _menu = gtk_menu_new(); + gtk_widget_show(_menu); do_update(); } @@ -43,13 +44,13 @@ GtkStatsChartMenu:: } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsChartMenu::get_menu_handle +// Function: GtkStatsChartMenu::get_menu_widget // Access: Public -// Description: Returns the Windows menu handle for this particular +// Description: Returns the gtk widget for this particular // menu. //////////////////////////////////////////////////////////////////// -HMENU GtkStatsChartMenu:: -get_menu_handle() { +GtkWidget *GtkStatsChartMenu:: +get_menu_widget() { return _menu; } @@ -59,7 +60,7 @@ get_menu_handle() { // Description: Adds the menu to the end of the indicated menu bar. //////////////////////////////////////////////////////////////////// void GtkStatsChartMenu:: -add_to_menu_bar(HMENU menu_bar, int before_menu_id) { +add_to_menu_bar(GtkWidget *menu_bar, int before_menu_id) { const PStatClientData *client_data = _monitor->get_client_data(); string thread_name; if (_thread_index == 0) { @@ -69,15 +70,11 @@ add_to_menu_bar(HMENU menu_bar, int before_menu_id) { thread_name = client_data->get_thread_name(_thread_index); } - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); + GtkWidget *menu_item = gtk_menu_item_new_with_label(thread_name.c_str()); + gtk_widget_show(menu_item); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), _menu); - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; - mii.fType = MFT_STRING; - mii.hSubMenu = _menu; - mii.dwTypeData = (char *)thread_name.c_str(); - InsertMenuItem(menu_bar, before_menu_id, FALSE, &mii); + gtk_menu_bar_append(GTK_MENU_BAR(menu_bar), menu_item); } //////////////////////////////////////////////////////////////////// @@ -107,10 +104,7 @@ do_update() { _last_level_index = view.get_level_index(); // First, remove all of the old entries from the menu. - int num_items = GetMenuItemCount(_menu); - for (int i = num_items - 1; i >= 0; i--) { - DeleteMenu(_menu, i, MF_BYPOSITION); - } + gtk_container_foreach(GTK_CONTAINER(_menu), remove_menu_child, _menu); // Now rebuild the menu with the new set of entries. @@ -118,9 +112,6 @@ do_update() { add_view(_menu, view.get_top_level(), false); bool needs_separator = true; - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); // And then the menu item(s) for each of the level values. const PStatClientData *client_data = _monitor->get_client_data(); @@ -133,9 +124,11 @@ do_update() { // We put a separator between the above frame collector and the // first level collector. if (needs_separator) { + /* mii.fMask = MIIM_FTYPE; mii.fType = MFT_SEPARATOR; InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); + */ needs_separator = false; } @@ -145,6 +138,7 @@ do_update() { } } + /* // Also a menu item for a piano roll (following a separator). mii.fMask = MIIM_FTYPE; mii.fType = MFT_SEPARATOR; @@ -158,6 +152,7 @@ do_update() { mii.wID = menu_id; mii.dwTypeData = "Piano Roll"; InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); + */ } //////////////////////////////////////////////////////////////////// @@ -167,37 +162,36 @@ do_update() { // indicated view and its children. //////////////////////////////////////////////////////////////////// void GtkStatsChartMenu:: -add_view(HMENU parent_menu, const PStatViewLevel *view_level, bool show_level) { +add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level, + bool show_level) { int collector = view_level->get_collector(); const PStatClientData *client_data = _monitor->get_client_data(); string collector_name = client_data->get_collector_name(collector); - GtkStatsMonitor::MenuDef menu_def(_thread_index, collector, show_level); - int menu_id = _monitor->get_menu_id(menu_def); + GtkStatsMonitor::MenuDef smd(_thread_index, collector, show_level); + const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd); - MENUITEMINFO mii; - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); + GtkWidget *menu_item = gtk_menu_item_new_with_label(collector_name.c_str()); + gtk_widget_show(menu_item); + gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), menu_item); - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; - mii.fType = MFT_STRING; - mii.wID = menu_id; - mii.dwTypeData = (char *)collector_name.c_str(); - InsertMenuItem(parent_menu, GetMenuItemCount(parent_menu), TRUE, &mii); + g_signal_connect_swapped(G_OBJECT(menu_item), "activate", + G_CALLBACK(handle_menu), (void *)(const void *)menu_def); int num_children = view_level->get_num_children(); if (num_children > 1) { // If the collector has more than one child, add a menu entry to go // directly to each of its children. - HMENU submenu = CreatePopupMenu(); string submenu_name = collector_name + " components"; - mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; - mii.fType = MFT_STRING; - mii.hSubMenu = submenu; - mii.dwTypeData = (char *)submenu_name.c_str(); - InsertMenuItem(parent_menu, GetMenuItemCount(parent_menu), TRUE, &mii); + GtkWidget *submenu_item = gtk_menu_item_new_with_label(submenu_name.c_str()); + gtk_widget_show(submenu_item); + gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), submenu_item); + + GtkWidget *submenu = gtk_menu_new(); + gtk_widget_show(submenu); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenu_item), submenu); // Reverse the order since the menus are listed from the top down; // we want to be visually consistent with the graphs, which list @@ -207,3 +201,37 @@ add_view(HMENU parent_menu, const PStatViewLevel *view_level, bool show_level) { } } } + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::handle_menu +// Access: Private, Static +// Description: Callback when a menu item is selected. +//////////////////////////////////////////////////////////////////// +void GtkStatsChartMenu:: +handle_menu(gpointer data) { + const GtkStatsMonitor::MenuDef *menu_def = (GtkStatsMonitor::MenuDef *)data; + GtkStatsMonitor *monitor = menu_def->_monitor; + + if (monitor == NULL) { + return; + } + + if (menu_def->_collector_index < 0) { + monitor->open_piano_roll(menu_def->_thread_index); + } else { + monitor->open_strip_chart(menu_def->_thread_index, + menu_def->_collector_index, + menu_def->_show_level); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::remove_menu_child +// Access: Private, Static +// Description: Removes a previous menu child from the menu. +//////////////////////////////////////////////////////////////////// +void GtkStatsChartMenu:: +remove_menu_child(GtkWidget *widget, gpointer data) { + GtkWidget *menu = (GtkWidget *)data; + gtk_container_remove(GTK_CONTAINER(menu), widget); +} diff --git a/pandatool/src/gtk-stats/gtkStatsChartMenu.h b/pandatool/src/gtk-stats/gtkStatsChartMenu.h index a31d893f09..9f0f84837a 100755 --- a/pandatool/src/gtk-stats/gtkStatsChartMenu.h +++ b/pandatool/src/gtk-stats/gtkStatsChartMenu.h @@ -21,7 +21,7 @@ #include "pandatoolbase.h" -#include +#include class GtkStatsMonitor; class PStatView; @@ -37,21 +37,24 @@ public: GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index); ~GtkStatsChartMenu(); - HMENU get_menu_handle(); - void add_to_menu_bar(HMENU menu_bar, int before_menu_id); + GtkWidget *get_menu_widget(); + void add_to_menu_bar(GtkWidget *menu_bar, int before_menu_id); void check_update(); void do_update(); private: - void add_view(HMENU parent_menu, const PStatViewLevel *view_level, + void add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level, bool show_level); + static void handle_menu(gpointer data); + static void remove_menu_child(GtkWidget *widget, gpointer data); + GtkStatsMonitor *_monitor; int _thread_index; int _last_level_index; - HMENU _menu; + GtkWidget *_menu; }; #endif diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.I b/pandatool/src/gtk-stats/gtkStatsMonitor.I index 11a8d907b8..f9b233dd17 100755 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.I +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.I @@ -26,7 +26,8 @@ GtkStatsMonitor::MenuDef:: MenuDef(int thread_index, int collector_index, bool show_level) : _thread_index(thread_index), _collector_index(collector_index), - _show_level(show_level) + _show_level(show_level), + _monitor(NULL) { } diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx index 9bcaa84d78..04b2d5586f 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx @@ -20,10 +20,8 @@ #include "gtkStats.h" #include "gtkStatsServer.h" #include "gtkStatsStripChart.h" -/* -#include "gtkStatsPianoRoll.h" #include "gtkStatsChartMenu.h" -*/ +//#include "gtkStatsPianoRoll.h" #include "gtkStatsMenuId.h" #include "pStatGraph.h" #include "pStatCollectorDef.h" @@ -77,13 +75,11 @@ GtkStatsMonitor:: } _graphs.clear(); - /* ChartMenus::iterator mi; for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { delete (*mi); } _chart_menus.clear(); - */ if (_window != NULL) { gtk_widget_destroy(_window); @@ -193,13 +189,11 @@ new_collector(int collector_index) { graph->new_collector(collector_index); } - /* // We might need to update our menus. ChartMenus::iterator mi; for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { (*mi)->do_update(); } - */ } //////////////////////////////////////////////////////////////////// @@ -215,12 +209,10 @@ new_collector(int collector_index) { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: new_thread(int thread_index) { - /* GtkStatsChartMenu *chart_menu = new GtkStatsChartMenu(this, thread_index); - chart_menu->add_to_menu_bar(_menu_bar, MI_frame_rate_label); + GtkWidget *menu_bar = gtk_item_factory_get_widget(_item_factory, ""); + chart_menu->add_to_menu_bar(menu_bar, MI_frame_rate_label); _chart_menus.push_back(chart_menu); - DrawMenuBar(_window); - */ } //////////////////////////////////////////////////////////////////// @@ -269,13 +261,13 @@ lost_connection() { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: idle() { - /* // Check if any of our chart menus need updating. ChartMenus::iterator mi; for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { (*mi)->check_update(); } + /* // Update the frame rate label from the main thread (thread 0). const PStatThreadData *thread_data = get_client_data()->get_thread_data(0); float frame_rate = thread_data->get_frame_rate(); @@ -363,43 +355,21 @@ open_piano_roll(int thread_index) { } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsMonitor::lookup_menu +// Function: GtkStatsMonitor::add_menu // Access: Public -// Description: Returns the MenuDef properties associated with the -// indicated menu ID. This specifies what we expect to -// do when the given menu has been selected. +// Description: Adds a new MenuDef to the monitor, or returns an +// existing one if there is already one just like it. //////////////////////////////////////////////////////////////////// -const GtkStatsMonitor::MenuDef &GtkStatsMonitor:: -lookup_menu(int menu_id) const { - static MenuDef invalid(0, 0, false); - int menu_index = menu_id - MI_new_chart; - nassertr(menu_index >= 0 && menu_index < (int)_menu_by_id.size(), invalid); - return _menu_by_id[menu_index]; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMonitor::get_menu_id -// Access: Public -// Description: Returns the menu ID that is reserved for the -// indicated MenuDef properties. If this is the first -// time these particular properties have been requested, -// a new menu ID is returned; otherwise, the existing -// menu ID is returned. -//////////////////////////////////////////////////////////////////// -int GtkStatsMonitor:: -get_menu_id(const MenuDef &menu_def) { - MenuByDef::iterator mi; - mi = _menu_by_def.find(menu_def); - if (mi != _menu_by_def.end()) { - return (*mi).second; +const GtkStatsMonitor::MenuDef *GtkStatsMonitor:: +add_menu(const MenuDef &menu_def) { + pair result = _menus.insert(menu_def); + Menus::iterator mi = result.first; + const GtkStatsMonitor::MenuDef &new_menu_def = (*mi); + if (result.second) { + // A new MenuDef was inserted. + ((GtkStatsMonitor::MenuDef &)new_menu_def)._monitor = this; } - - // Slot a new id. - int menu_id = (int)_menu_by_id.size() + MI_new_chart; - _menu_by_id.push_back(menu_def); - _menu_by_def[menu_def] = menu_id; - - return menu_id; + return &new_menu_def; } //////////////////////////////////////////////////////////////////// @@ -514,19 +484,17 @@ create_window() { gtk_item_factory_create_items(_item_factory, num_menu_entries, menu_entries, this); gtk_window_add_accel_group(GTK_WINDOW(_window), accel_group); - GtkWidget *menubar = gtk_item_factory_get_widget(_item_factory, ""); + GtkWidget *menu_bar = gtk_item_factory_get_widget(_item_factory, ""); - /* ChartMenus::iterator mi; for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { - (*mi)->add_to_menu_bar(_menu_bar, MI_frame_rate_label); + (*mi)->add_to_menu_bar(menu_bar, MI_frame_rate_label); } - */ // Pack the menu into the window. GtkWidget *main_vbox = gtk_vbox_new(FALSE, 1); gtk_container_add(GTK_CONTAINER(_window), main_vbox); - gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(main_vbox), menu_bar, FALSE, TRUE, 0); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(gtk_item_factory_get_item(_item_factory, "/Speed/3")), TRUE); @@ -633,17 +601,5 @@ handle_menu_command(gpointer callback_data, guint menu_id, GtkWidget *widget) { case MI_pause: self->set_pause(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); break; - - default: - if (menu_id >= MI_new_chart) { - const MenuDef &menu_def = self->lookup_menu(menu_id); - if (menu_def._collector_index < 0) { - self->open_piano_roll(menu_def._thread_index); - } else { - self->open_strip_chart(menu_def._thread_index, - menu_def._collector_index, - menu_def._show_level); - } - } } } diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.h b/pandatool/src/gtk-stats/gtkStatsMonitor.h index 84a1f350a9..397aafd09c 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.h +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.h @@ -48,6 +48,7 @@ public: int _thread_index; int _collector_index; bool _show_level; + GtkStatsMonitor *_monitor; }; GtkStatsMonitor(GtkStatsServer *server); @@ -72,8 +73,7 @@ public: void open_strip_chart(int thread_index, int collector_index, bool show_level); void open_piano_roll(int thread_index); - const MenuDef &lookup_menu(int menu_id) const; - int get_menu_id(const MenuDef &menu_def); + const MenuDef *add_menu(const MenuDef &menu_def); void set_time_units(int unit_mask); void set_scroll_speed(float scroll_speed); @@ -97,10 +97,8 @@ private: typedef pvector ChartMenus; ChartMenus _chart_menus; - typedef pvector MenuById; - typedef pmap MenuByDef; - MenuById _menu_by_id; - MenuByDef _menu_by_def; + typedef pset Menus; + Menus _menus; GtkWidget *_window; GtkItemFactory *_item_factory;