Panda3D
gtkStatsChartMenu.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file gtkStatsChartMenu.cxx
10  * @author drose
11  * @date 2006-01-16
12  */
13 
14 #include "gtkStatsChartMenu.h"
15 #include "gtkStatsMonitor.h"
16 
17 /**
18  *
19  */
20 GtkStatsChartMenu::
21 GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index) :
22  _monitor(monitor),
23  _thread_index(thread_index)
24 {
25  _menu = gtk_menu_new();
26  gtk_widget_show(_menu);
27  do_update();
28 }
29 
30 /**
31  *
32  */
33 GtkStatsChartMenu::
34 ~GtkStatsChartMenu() {
35 }
36 
37 /**
38  * Returns the gtk widget for this particular menu.
39  */
40 GtkWidget *GtkStatsChartMenu::
42  return _menu;
43 }
44 
45 /**
46  * Adds the menu to the end of the indicated menu bar.
47  */
49 add_to_menu_bar(GtkWidget *menu_bar, int position) {
50  const PStatClientData *client_data = _monitor->get_client_data();
51  std::string thread_name;
52  if (_thread_index == 0) {
53  // A special case for the main thread.
54  thread_name = "Graphs";
55  } else {
56  thread_name = client_data->get_thread_name(_thread_index);
57  }
58 
59  GtkWidget *menu_item = gtk_menu_item_new_with_label(thread_name.c_str());
60  gtk_widget_show(menu_item);
61  gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), _menu);
62 
63  gtk_menu_shell_insert(GTK_MENU_SHELL(menu_bar), menu_item, position);
64 }
65 
66 /**
67  * Checks to see if the menu needs to be updated (e.g. because of new data
68  * from the client), and updates it if necessary.
69  */
72  PStatView &view = _monitor->get_view(_thread_index);
73  if (view.get_level_index() != _last_level_index) {
74  do_update();
75  }
76 }
77 
78 /**
79  * Unconditionally updates the menu with the latest data from the client.
80  */
83  PStatView &view = _monitor->get_view(_thread_index);
84  _last_level_index = view.get_level_index();
85 
86  // First, remove all of the old entries from the menu.
87  gtk_container_foreach(GTK_CONTAINER(_menu), remove_menu_child, _menu);
88 
89  // Now rebuild the menu with the new set of entries.
90 
91  // The menu item(s) for the thread's frame time goes first.
92  add_view(_menu, view.get_top_level(), false);
93 
94  bool needs_separator = true;
95 
96  // And then the menu item(s) for each of the level values.
97  const PStatClientData *client_data = _monitor->get_client_data();
98  int num_toplevel_collectors = client_data->get_num_toplevel_collectors();
99  for (int tc = 0; tc < num_toplevel_collectors; tc++) {
100  int collector = client_data->get_toplevel_collector(tc);
101  if (client_data->has_collector(collector) &&
102  client_data->get_collector_has_level(collector, _thread_index)) {
103 
104  // We put a separator between the above frame collector and the first
105  // level collector.
106  if (needs_separator) {
107  GtkWidget *sep = gtk_separator_menu_item_new();
108  gtk_widget_show(sep);
109  gtk_menu_shell_append(GTK_MENU_SHELL(_menu), sep);
110 
111  needs_separator = false;
112  }
113 
114  PStatView &level_view = _monitor->get_level_view(collector, _thread_index);
115  add_view(_menu, level_view.get_top_level(), true);
116  }
117  }
118 
119  // Also a menu item for a piano roll (following a separator).
120  GtkWidget *sep = gtk_separator_menu_item_new();
121  gtk_widget_show(sep);
122  gtk_menu_shell_append(GTK_MENU_SHELL(_menu), sep);
123 
124  GtkStatsMonitor::MenuDef smd(_thread_index, -1, false);
125  const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd);
126 
127  GtkWidget *menu_item = gtk_menu_item_new_with_label("Piano Roll");
128  gtk_widget_show(menu_item);
129  gtk_menu_shell_append(GTK_MENU_SHELL(_menu), menu_item);
130 
131  g_signal_connect_swapped(G_OBJECT(menu_item), "activate",
132  G_CALLBACK(handle_menu), (void *)(const void *)menu_def);
133 }
134 
135 /**
136  * Adds a new entry or entries to the menu for the indicated view and its
137  * children.
138  */
139 void GtkStatsChartMenu::
140 add_view(GtkWidget *parent_menu, const PStatViewLevel *view_level,
141  bool show_level) {
142  int collector = view_level->get_collector();
143 
144  const PStatClientData *client_data = _monitor->get_client_data();
145  std::string collector_name = client_data->get_collector_name(collector);
146 
147  GtkStatsMonitor::MenuDef smd(_thread_index, collector, show_level);
148  const GtkStatsMonitor::MenuDef *menu_def = _monitor->add_menu(smd);
149 
150  GtkWidget *menu_item = gtk_menu_item_new_with_label(collector_name.c_str());
151  gtk_widget_show(menu_item);
152  gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), menu_item);
153 
154  g_signal_connect_swapped(G_OBJECT(menu_item), "activate",
155  G_CALLBACK(handle_menu), (void *)(const void *)menu_def);
156 
157  int num_children = view_level->get_num_children();
158  if (num_children > 1) {
159  // If the collector has more than one child, add a menu entry to go
160  // directly to each of its children.
161  std::string submenu_name = collector_name + " components";
162 
163  GtkWidget *submenu_item = gtk_menu_item_new_with_label(submenu_name.c_str());
164  gtk_widget_show(submenu_item);
165  gtk_menu_shell_append(GTK_MENU_SHELL(parent_menu), submenu_item);
166 
167  GtkWidget *submenu = gtk_menu_new();
168  gtk_widget_show(submenu);
169  gtk_menu_item_set_submenu(GTK_MENU_ITEM(submenu_item), submenu);
170 
171  // Reverse the order since the menus are listed from the top down; we want
172  // to be visually consistent with the graphs, which list these labels from
173  // the bottom up.
174  for (int c = num_children - 1; c >= 0; c--) {
175  add_view(submenu, view_level->get_child(c), show_level);
176  }
177  }
178 }
179 
180 /**
181  * Callback when a menu item is selected.
182  */
183 void GtkStatsChartMenu::
184 handle_menu(gpointer data) {
185  const GtkStatsMonitor::MenuDef *menu_def = (GtkStatsMonitor::MenuDef *)data;
186  GtkStatsMonitor *monitor = menu_def->_monitor;
187 
188  if (monitor == nullptr) {
189  return;
190  }
191 
192  if (menu_def->_collector_index < 0) {
193  monitor->open_piano_roll(menu_def->_thread_index);
194  } else {
195  monitor->open_strip_chart(menu_def->_thread_index,
196  menu_def->_collector_index,
197  menu_def->_show_level);
198  }
199 }
200 
201 /**
202  * Removes a previous menu child from the menu.
203  */
204 void GtkStatsChartMenu::
205 remove_menu_child(GtkWidget *widget, gpointer data) {
206  GtkWidget *menu = (GtkWidget *)data;
207  gtk_container_remove(GTK_CONTAINER(menu), widget);
208 }
const PStatViewLevel * get_top_level()
Returns a pointer to the level that corresponds to the Collector we've constrained to.
Definition: pStatView.cxx:239
void check_update()
Checks to see if the menu needs to be updated (e.g.
int get_toplevel_collector(int index) const
Returns the collector index of the nth toplevel collector.
void open_piano_roll(int thread_index)
Opens a new piano roll showing the indicated data.
PStatView & get_level_view(int collector_index, int thread_index)
Returns a view on the level value (as opposed to elapsed time) for the given collector over the given...
const PStatViewLevel * get_child(int n) const
Returns the nth child of this Level/Collector.
void do_update()
Unconditionally updates the menu with the latest data from the client.
The data associated with a particular client, but not with any one particular frame or thread: the li...
std::string get_collector_name(int index) const
Returns the name of the indicated collector.
This is a single level value, or band of color, within a View.
GtkWidget * get_menu_widget()
Returns the gtk widget for this particular menu.
bool has_collector(int index) const
Returns true if the indicated collector has been defined by the client already, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A View boils down the frame data to a linear list of times spent in a number of different Collectors,...
Definition: pStatView.h:31
PStatView & get_view(int thread_index)
Returns a view on the given thread index.
void add_to_menu_bar(GtkWidget *menu_bar, int position)
Adds the menu to the end of the indicated menu bar.
const MenuDef * add_menu(const MenuDef &menu_def)
Adds a new MenuDef to the monitor, or returns an existing one if there is already one just like it.
This class represents a connection to a PStatsClient and manages the data exchange with the client.
void open_strip_chart(int thread_index, int collector_index, bool show_level)
Opens a new strip chart showing the indicated data.
int get_collector() const
Returns the Collector index associated with this level.
int get_level_index() const
Returns an index number that can be used to determine when the set of known levels has changed.
Definition: pStatView.I:68
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
Definition: pStatMonitor.I:26
int get_num_children() const
Returns the number of children of this Level/Collector.
int get_num_toplevel_collectors() const
Returns the total number of collectors that are toplevel collectors.
std::string get_thread_name(int index) const
Returns the name of the indicated thread.
bool get_collector_has_level(int index, int thread_index) const
Returns whether the given collector has level data (and consequently, whether it should appear on the...