Panda3D
|
00001 // Filename: gtkStatsChartMenu.cxx 00002 // Created by: drose (16Jan06) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "gtkStatsChartMenu.h" 00016 #include "gtkStatsMonitor.h" 00017 00018 //////////////////////////////////////////////////////////////////// 00019 // Function: GtkStatsChartMenu::Constructor 00020 // Access: Public 00021 // Description: 00022 //////////////////////////////////////////////////////////////////// 00023 GtkStatsChartMenu:: 00024 GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index) : 00025 _monitor(monitor), 00026 _thread_index(thread_index) 00027 { 00028 _menu = gtk_menu_new(); 00029 gtk_widget_show(_menu); 00030 do_update(); 00031 } 00032 00033 //////////////////////////////////////////////////////////////////// 00034 // Function: GtkStatsChartMenu::Destructor 00035 // Access: Public 00036 // Description: 00037 //////////////////////////////////////////////////////////////////// 00038 GtkStatsChartMenu:: 00039 ~GtkStatsChartMenu() { 00040 } 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function: GtkStatsChartMenu::get_menu_widget 00044 // Access: Public 00045 // Description: Returns the gtk widget for this particular 00046 // menu. 00047 //////////////////////////////////////////////////////////////////// 00048 GtkWidget *GtkStatsChartMenu:: 00049 get_menu_widget() { 00050 return _menu; 00051 } 00052 00053 //////////////////////////////////////////////////////////////////// 00054 // Function: GtkStatsChartMenu::add_to_menu_bar 00055 // Access: Public 00056 // Description: Adds the menu to the end of the indicated menu bar. 00057 //////////////////////////////////////////////////////////////////// 00058 void GtkStatsChartMenu:: 00059 add_to_menu_bar(GtkWidget *menu_bar, int position) { 00060 const PStatClientData *client_data = _monitor->get_client_data(); 00061 string thread_name; 00062 if (_thread_index == 0) { 00063 // A special case for the main thread. 00064 thread_name = "Graphs"; 00065 } else { 00066 thread_name = client_data->get_thread_name(_thread_index); 00067 } 00068 00069 GtkWidget *menu_item = gtk_menu_item_new_with_label(thread_name.c_str()); 00070 gtk_widget_show(menu_item); 00071 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), _menu); 00072 00073 gtk_menu_shell_insert(GTK_MENU_SHELL(menu_bar), menu_item, position); 00074 } 00075 00076 //////////////////////////////////////////////////////////////////// 00077 // Function: GtkStatsChartMenu::check_update 00078 // Access: Public 00079 // Description: Checks to see if the menu needs to be updated 00080 // (e.g. because of new data from the client), and 00081 // updates it if necessary. 00082 //////////////////////////////////////////////////////////////////// 00083 void GtkStatsChartMenu:: 00084 check_update() { 00085 PStatView &view = _monitor->get_view(_thread_index); 00086 if (view.get_level_index() != _last_level_index) { 00087 do_update(); 00088 } 00089 } 00090 00091 //////////////////////////////////////////////////////////////////// 00092 // Function: GtkStatsChartMenu::do_update 00093 // Access: Public 00094 // Description: Unconditionally updates the menu with the latest data 00095 // from the client. 00096 //////////////////////////////////////////////////////////////////// 00097 void GtkStatsChartMenu:: 00098 do_update() { 00099 PStatView &view = _monitor->get_view(_thread_index); 00100 _last_level_index = view.get_level_index(); 00101 00102 // First, remove all of the old entries from the menu. 00103 gtk_container_foreach(GTK_CONTAINER(_menu), remove_menu_child, _menu); 00104 00105 // Now rebuild the menu with the new set of entries. 00106 00107 // The menu item(s) for the thread's frame time goes first. 00108 add_view(_menu, view.get_top_level(), false); 00109 00110 bool needs_separator = true; 00111 00112 // And then the menu item(s) for each of the level values. 00113 const PStatClientData *client_data = _monitor->get_client_data(); 00114 int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); 00115 for (int tc = 0; tc < num_toplevel_collectors; tc++) { 00116 int collector = client_data->get_toplevel_collector(tc); 00117 if (client_data->has_collector(collector) && 00118 client_data->get_collector_has_level(collector, _thread_index)) { 00119 00120 // We put a separator between the above frame collector and the 00121 // first level collector. 00122 if (needs_separator) { 00123 GtkWidget *sep = gtk_separator_menu_item_new(); 00124 gtk_widget_show(sep); 00125 gtk_menu_shell_append(GTK_MENU_SHELL(_menu), sep); 00126 00127 needs_separator = false; 00128 } 00129 00130 PStatView &level_view = _monitor->get_level_view(collector, _thread_index); 00131 add_view(_menu, level_view.get_top_level(), true); 00132 } 00133 } 00134 00135 // Also a menu item for a piano roll (following a separator). 00136 GtkWidget *sep = gtk_separator_menu_item_new(); 00137 gtk_widget_show(sep); 00138 gtk_menu_shell_append(GTK_MENU_SHELL(_menu), sep); 00139 00140 GtkStatsMonitor::MenuDef smd(_thread_index, -1, false); 00141 const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd); 00142 00143 GtkWidget *menu_item = gtk_menu_item_new_with_label("Piano Roll"); 00144 gtk_widget_show(menu_item); 00145 gtk_menu_shell_append(GTK_MENU_SHELL(_menu), menu_item); 00146 00147 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", 00148 G_CALLBACK(handle_menu), (void *)(const void *)menu_def); 00149 } 00150 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: GtkStatsChartMenu::add_view 00153 // Access: Private 00154 // Description: Adds a new entry or entries to the menu for the 00155 // indicated view and its children. 00156 //////////////////////////////////////////////////////////////////// 00157 void GtkStatsChartMenu:: 00158 add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level, 00159 bool show_level) { 00160 int collector = view_level->get_collector(); 00161 00162 const PStatClientData *client_data = _monitor->get_client_data(); 00163 string collector_name = client_data->get_collector_name(collector); 00164 00165 GtkStatsMonitor::MenuDef smd(_thread_index, collector, show_level); 00166 const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd); 00167 00168 GtkWidget *menu_item = gtk_menu_item_new_with_label(collector_name.c_str()); 00169 gtk_widget_show(menu_item); 00170 gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), menu_item); 00171 00172 g_signal_connect_swapped(G_OBJECT(menu_item), "activate", 00173 G_CALLBACK(handle_menu), (void *)(const void *)menu_def); 00174 00175 int num_children = view_level->get_num_children(); 00176 if (num_children > 1) { 00177 // If the collector has more than one child, add a menu entry to go 00178 // directly to each of its children. 00179 string submenu_name = collector_name + " components"; 00180 00181 GtkWidget *submenu_item = gtk_menu_item_new_with_label(submenu_name.c_str()); 00182 gtk_widget_show(submenu_item); 00183 gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), submenu_item); 00184 00185 GtkWidget *submenu = gtk_menu_new(); 00186 gtk_widget_show(submenu); 00187 gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenu_item), submenu); 00188 00189 // Reverse the order since the menus are listed from the top down; 00190 // we want to be visually consistent with the graphs, which list 00191 // these labels from the bottom up. 00192 for (int c = num_children - 1; c >= 0; c--) { 00193 add_view(submenu, view_level->get_child(c), show_level); 00194 } 00195 } 00196 } 00197 00198 //////////////////////////////////////////////////////////////////// 00199 // Function: GtkStatsChartMenu::handle_menu 00200 // Access: Private, Static 00201 // Description: Callback when a menu item is selected. 00202 //////////////////////////////////////////////////////////////////// 00203 void GtkStatsChartMenu:: 00204 handle_menu(gpointer data) { 00205 const GtkStatsMonitor::MenuDef *menu_def = (GtkStatsMonitor::MenuDef *)data; 00206 GtkStatsMonitor *monitor = menu_def->_monitor; 00207 00208 if (monitor == NULL) { 00209 return; 00210 } 00211 00212 if (menu_def->_collector_index < 0) { 00213 monitor->open_piano_roll(menu_def->_thread_index); 00214 } else { 00215 monitor->open_strip_chart(menu_def->_thread_index, 00216 menu_def->_collector_index, 00217 menu_def->_show_level); 00218 } 00219 } 00220 00221 //////////////////////////////////////////////////////////////////// 00222 // Function: GtkStatsChartMenu::remove_menu_child 00223 // Access: Private, Static 00224 // Description: Removes a previous menu child from the menu. 00225 //////////////////////////////////////////////////////////////////// 00226 void GtkStatsChartMenu:: 00227 remove_menu_child(GtkWidget *widget, gpointer data) { 00228 GtkWidget *menu = (GtkWidget *)data; 00229 gtk_container_remove(GTK_CONTAINER(menu), widget); 00230 }