Panda3D
winStatsMonitor.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 winStatsMonitor.cxx
10  * @author drose
11  * @date 2003-12-02
12  */
13 
14 #include "winStatsMonitor.h"
15 #include "winStatsServer.h"
16 #include "winStatsStripChart.h"
17 #include "winStatsPianoRoll.h"
18 #include "winStatsChartMenu.h"
19 #include "winStatsMenuId.h"
20 #include "pStatGraph.h"
21 #include "pStatCollectorDef.h"
22 #include "indent.h"
23 
24 bool WinStatsMonitor::_window_class_registered = false;
25 const char * const WinStatsMonitor::_window_class_name = "monitor";
26 
27 /**
28  *
29  */
30 WinStatsMonitor::
31 WinStatsMonitor(WinStatsServer *server) : PStatMonitor(server) {
32  _window = 0;
33  _menu_bar = 0;
34  _options_menu = 0;
35 
36  // These will be filled in later when the menu is created.
37  _time_units = 0;
38  _scroll_speed = 0.0;
39  _pause = false;
40 }
41 
42 /**
43  *
44  */
45 WinStatsMonitor::
46 ~WinStatsMonitor() {
47  Graphs::iterator gi;
48  for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
49  delete (*gi);
50  }
51  _graphs.clear();
52 
53  ChartMenus::iterator mi;
54  for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
55  delete (*mi);
56  }
57  _chart_menus.clear();
58 
59  if (_window) {
60  DestroyWindow(_window);
61  _window = 0;
62  }
63 
64 #ifdef DEVELOP_WINSTATS
65  // For Winstats developers, exit when the first monitor closes.
66  exit(0);
67 #endif
68 }
69 
70 /**
71  * Should be redefined to return a descriptive name for the type of
72  * PStatsMonitor this is.
73  */
74 std::string WinStatsMonitor::
76  return "WinStats";
77 }
78 
79 /**
80  * Called after the monitor has been fully set up. At this time, it will have
81  * a valid _client_data pointer, and things like is_alive() and close() will
82  * be meaningful. However, we may not yet know who we're connected to
83  * (is_client_known() may return false), and we may not know anything about
84  * the threads or collectors we're about to get data on.
85  */
87 initialized() {
88 }
89 
90 /**
91  * Called when the "hello" message has been received from the client. At this
92  * time, the client's hostname and program name will be known.
93  */
95 got_hello() {
96  create_window();
97  open_strip_chart(0, 0, false);
98 }
99 
100 /**
101  * Like got_hello(), this is called when the "hello" message has been received
102  * from the client. At this time, the client's hostname and program name will
103  * be known. However, the client appears to be an incompatible version and
104  * the connection will be terminated; the monitor should issue a message to
105  * that effect.
106  */
108 got_bad_version(int client_major, int client_minor,
109  int server_major, int server_minor) {
110  std::ostringstream str;
111  str << "Unable to honor connection attempt from "
112  << get_client_progname() << " on " << get_client_hostname()
113  << ": unsupported PStats version "
114  << client_major << "." << client_minor;
115 
116  if (server_minor == 0) {
117  str << " (server understands version " << server_major
118  << "." << server_minor << " only).";
119  } else {
120  str << " (server understands versions " << server_major
121  << ".0 through " << server_major << "." << server_minor << ").";
122  }
123 
124  std::string message = str.str();
125  MessageBox(nullptr, message.c_str(), "Bad version",
126  MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
127 }
128 
129 /**
130  * Called whenever a new Collector definition is received from the client.
131  * Generally, the client will send all of its collectors over shortly after
132  * connecting, but there's no guarantee that they will all be received before
133  * the first frames are received. The monitor should be prepared to accept
134  * new Collector definitions midstream.
135  */
137 new_collector(int collector_index) {
138  Graphs::iterator gi;
139  for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
140  WinStatsGraph *graph = (*gi);
141  graph->new_collector(collector_index);
142  }
143 
144  // We might need to update our menus.
145  ChartMenus::iterator mi;
146  for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
147  (*mi)->do_update();
148  }
149 }
150 
151 /**
152  * Called whenever a new Thread definition is received from the client.
153  * Generally, the client will send all of its threads over shortly after
154  * connecting, but there's no guarantee that they will all be received before
155  * the first frames are received. The monitor should be prepared to accept
156  * new Thread definitions midstream.
157  */
159 new_thread(int thread_index) {
160  WinStatsChartMenu *chart_menu = new WinStatsChartMenu(this, thread_index);
161  chart_menu->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
162  _chart_menus.push_back(chart_menu);
163  DrawMenuBar(_window);
164 }
165 
166 /**
167  * Called as each frame's data is made available. There is no guarantee the
168  * frames will arrive in order, or that all of them will arrive at all. The
169  * monitor should be prepared to accept frames received out-of-order or
170  * missing.
171  */
173 new_data(int thread_index, int frame_number) {
174  Graphs::iterator gi;
175  for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
176  WinStatsGraph *graph = (*gi);
177  graph->new_data(thread_index, frame_number);
178  }
179 }
180 
181 
182 /**
183  * Called whenever the connection to the client has been lost. This is a
184  * permanent state change. The monitor should update its display to represent
185  * this, and may choose to close down automatically.
186  */
188 lost_connection() {
189  nout << "Lost connection to " << get_client_hostname() << "\n";
190 
191  if (_window) {
192  DestroyWindow(_window);
193  _window = 0;
194  }
195 }
196 
197 /**
198  * If has_idle() returns true, this will be called periodically to allow the
199  * monitor to update its display or whatever it needs to do.
200  */
202 idle() {
203  // Check if any of our chart menus need updating.
204  ChartMenus::iterator mi;
205  for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
206  (*mi)->check_update();
207  }
208 
209  // Update the frame rate label from the main thread (thread 0).
210  const PStatThreadData *thread_data = get_client_data()->get_thread_data(0);
211  double frame_rate = thread_data->get_frame_rate();
212  if (frame_rate != 0.0f) {
213  char buffer[128];
214  sprintf(buffer, "%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate);
215 
216  MENUITEMINFO mii;
217  memset(&mii, 0, sizeof(mii));
218  mii.cbSize = sizeof(mii);
219  mii.fMask = MIIM_STRING;
220  mii.dwTypeData = buffer;
221  SetMenuItemInfo(_menu_bar, MI_frame_rate_label, FALSE, &mii);
222  DrawMenuBar(_window);
223  }
224 }
225 
226 /**
227  * Should be redefined to return true if you want to redefine idle() and
228  * expect it to be called.
229  */
231 has_idle() {
232  return true;
233 }
234 
235 /**
236  * Called when the user guide bars have been changed.
237  */
240  Graphs::iterator gi;
241  for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
242  WinStatsGraph *graph = (*gi);
243  graph->user_guide_bars_changed();
244  }
245 }
246 
247 /**
248  * Returns the window handle to the monitor's window.
249  */
251 get_window() const {
252  return _window;
253 }
254 
255 /**
256  * Opens a new strip chart showing the indicated data.
257  */
259 open_strip_chart(int thread_index, int collector_index, bool show_level) {
260  WinStatsStripChart *graph =
261  new WinStatsStripChart(this, thread_index, collector_index, show_level);
262  add_graph(graph);
263 
264  graph->set_time_units(_time_units);
265  graph->set_scroll_speed(_scroll_speed);
266  graph->set_pause(_pause);
267 }
268 
269 /**
270  * Opens a new piano roll showing the indicated data.
271  */
273 open_piano_roll(int thread_index) {
274  WinStatsPianoRoll *graph = new WinStatsPianoRoll(this, thread_index);
275  add_graph(graph);
276 
277  graph->set_time_units(_time_units);
278  graph->set_scroll_speed(_scroll_speed);
279  graph->set_pause(_pause);
280 }
281 
282 /**
283  * Returns the MenuDef properties associated with the indicated menu ID. This
284  * specifies what we expect to do when the given menu has been selected.
285  */
287 lookup_menu(int menu_id) const {
288  static MenuDef invalid(0, 0, false);
289  int menu_index = menu_id - MI_new_chart;
290  nassertr(menu_index >= 0 && menu_index < (int)_menu_by_id.size(), invalid);
291  return _menu_by_id[menu_index];
292 }
293 
294 /**
295  * Returns the menu ID that is reserved for the indicated MenuDef properties.
296  * If this is the first time these particular properties have been requested,
297  * a new menu ID is returned; otherwise, the existing menu ID is returned.
298  */
300 get_menu_id(const MenuDef &menu_def) {
301  MenuByDef::iterator mi;
302  mi = _menu_by_def.find(menu_def);
303  if (mi != _menu_by_def.end()) {
304  return (*mi).second;
305  }
306 
307  // Slot a new id.
308  int menu_id = (int)_menu_by_id.size() + MI_new_chart;
309  _menu_by_id.push_back(menu_def);
310  _menu_by_def[menu_def] = menu_id;
311 
312  return menu_id;
313 }
314 
315 /**
316  * Called when the user selects a new time units from the monitor pulldown
317  * menu, this should adjust the units for all graphs to the indicated mask if
318  * it is a time-based graph.
319  */
321 set_time_units(int unit_mask) {
322  _time_units = unit_mask;
323 
324  // First, change all of the open graphs appropriately.
325  Graphs::iterator gi;
326  for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
327  WinStatsGraph *graph = (*gi);
328  graph->set_time_units(_time_units);
329  }
330 
331  // Now change the checkmark on the pulldown menu.
332  MENUITEMINFO mii;
333  memset(&mii, 0, sizeof(mii));
334  mii.cbSize = sizeof(mii);
335  mii.fMask = MIIM_STATE;
336 
337  mii.fState = ((_time_units & PStatGraph::GBU_ms) != 0) ?
338  MFS_CHECKED : MFS_UNCHECKED;
339  SetMenuItemInfo(_options_menu, MI_time_ms, FALSE, &mii);
340 
341  mii.fState = ((_time_units & PStatGraph::GBU_hz) != 0) ?
342  MFS_CHECKED : MFS_UNCHECKED;
343  SetMenuItemInfo(_options_menu, MI_time_hz, FALSE, &mii);
344 }
345 
346 /**
347  * Called when the user selects a new scroll speed from the monitor pulldown
348  * menu, this should adjust the speeds for all graphs to the indicated value.
349  */
351 set_scroll_speed(double scroll_speed) {
352  _scroll_speed = scroll_speed;
353 
354  // First, change all of the open graphs appropriately.
355  Graphs::iterator gi;
356  for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
357  WinStatsGraph *graph = (*gi);
358  graph->set_scroll_speed(_scroll_speed);
359  }
360 
361  // Now change the checkmark on the pulldown menu.
362  MENUITEMINFO mii;
363  memset(&mii, 0, sizeof(mii));
364  mii.cbSize = sizeof(mii);
365  mii.fMask = MIIM_STATE;
366 
367  mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 1.0, 0.1) ?
368  MFS_CHECKED : MFS_UNCHECKED;
369  SetMenuItemInfo(_speed_menu, MI_speed_1, FALSE, &mii);
370 
371  mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 2.0, 0.1) ?
372  MFS_CHECKED : MFS_UNCHECKED;
373  SetMenuItemInfo(_speed_menu, MI_speed_2, FALSE, &mii);
374 
375  mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 3.0, 0.1) ?
376  MFS_CHECKED : MFS_UNCHECKED;
377  SetMenuItemInfo(_speed_menu, MI_speed_3, FALSE, &mii);
378 
379  mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 6.0, 0.1) ?
380  MFS_CHECKED : MFS_UNCHECKED;
381  SetMenuItemInfo(_speed_menu, MI_speed_6, FALSE, &mii);
382 
383  mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 12.0, 0.1) ?
384  MFS_CHECKED : MFS_UNCHECKED;
385  SetMenuItemInfo(_speed_menu, MI_speed_12, FALSE, &mii);
386 }
387 
388 /**
389  * Called when the user selects a pause on or pause off option from the menu.
390  */
392 set_pause(bool pause) {
393  _pause = pause;
394 
395  // First, change all of the open graphs appropriately.
396  Graphs::iterator gi;
397  for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
398  WinStatsGraph *graph = (*gi);
399  graph->set_pause(_pause);
400  }
401 
402  // Now change the checkmark on the pulldown menu.
403  MENUITEMINFO mii;
404  memset(&mii, 0, sizeof(mii));
405  mii.cbSize = sizeof(mii);
406  mii.fMask = MIIM_STATE;
407 
408  mii.fState = _pause ? MFS_CHECKED : MFS_UNCHECKED;
409  SetMenuItemInfo(_speed_menu, MI_pause, FALSE, &mii);
410 }
411 
412 /**
413  * Adds the newly-created graph to the list of managed graphs.
414  */
415 void WinStatsMonitor::
416 add_graph(WinStatsGraph *graph) {
417  _graphs.insert(graph);
418 }
419 
420 /**
421  * Deletes the indicated graph.
422  */
423 void WinStatsMonitor::
424 remove_graph(WinStatsGraph *graph) {
425  Graphs::iterator gi = _graphs.find(graph);
426  if (gi != _graphs.end()) {
427  _graphs.erase(gi);
428  delete graph;
429  }
430 }
431 
432 /**
433  * Creates the window for this monitor.
434  */
435 void WinStatsMonitor::
436 create_window() {
437  if (_window) {
438  return;
439  }
440 
441  HINSTANCE application = GetModuleHandle(nullptr);
442  register_window_class(application);
443 
444  _menu_bar = CreateMenu();
445 
446  setup_options_menu();
447  setup_speed_menu();
448  setup_frame_rate_label();
449 
450  ChartMenus::iterator mi;
451  for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
452  (*mi)->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
453  }
454 
455  _window_title = get_client_progname() + " on " + get_client_hostname();
456  DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
457  WS_CLIPSIBLINGS | WS_VISIBLE;
458 
459  _window =
460  CreateWindow(_window_class_name, _window_title.c_str(), window_style,
461  CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
462  nullptr, _menu_bar, application, 0);
463  if (!_window) {
464  nout << "Could not create monitor window!\n";
465  exit(1);
466  }
467 
468  SetWindowLongPtr(_window, 0, (LONG_PTR)this);
469 
470  // For some reason, SW_SHOWNORMAL doesn't always work, but SW_RESTORE seems
471  // to.
472  ShowWindow(_window, SW_RESTORE);
473  SetForegroundWindow(_window);
474 }
475 
476 /**
477  * Creates the "Options" pulldown menu.
478  */
479 void WinStatsMonitor::
480 setup_options_menu() {
481  _options_menu = CreatePopupMenu();
482 
483  MENUITEMINFO mii;
484  memset(&mii, 0, sizeof(mii));
485  mii.cbSize = sizeof(mii);
486 
487  mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
488  mii.fType = MFT_STRING;
489  mii.hSubMenu = _options_menu;
490 
491  // One day, when there is more than one option here, we will actually
492  // present this to the user as the "Options" menu. For now, the only option
493  // we have is time units. mii.dwTypeData = "Options";
494  mii.dwTypeData = "Units";
495  InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
496 
497 
498  mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
499  mii.fType = MFT_STRING | MFT_RADIOCHECK;
500  mii.hbmpChecked = nullptr;
501  mii.hbmpUnchecked = nullptr;
502  mii.fState = MFS_UNCHECKED;
503  mii.wID = MI_time_ms;
504  mii.dwTypeData = "ms";
505  InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
506 
507  mii.wID = MI_time_hz;
508  mii.dwTypeData = "Hz";
509  InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
510 
511  set_time_units(PStatGraph::GBU_ms);
512 }
513 
514 /**
515  * Creates the "Speed" pulldown menu.
516  */
517 void WinStatsMonitor::
518 setup_speed_menu() {
519  _speed_menu = CreatePopupMenu();
520 
521  MENUITEMINFO mii;
522  memset(&mii, 0, sizeof(mii));
523  mii.cbSize = sizeof(mii);
524 
525  mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
526  mii.fType = MFT_STRING;
527  mii.hSubMenu = _speed_menu;
528  mii.dwTypeData = "Speed";
529  InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
530 
531 
532  mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
533  mii.fType = MFT_STRING | MFT_RADIOCHECK;
534  mii.hbmpChecked = nullptr;
535  mii.hbmpUnchecked = nullptr;
536  mii.fState = MFS_UNCHECKED;
537  mii.wID = MI_speed_1;
538  mii.dwTypeData = "1";
539  InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
540 
541  mii.wID = MI_speed_2;
542  mii.dwTypeData = "2";
543  InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
544 
545  mii.wID = MI_speed_3;
546  mii.dwTypeData = "3";
547  InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
548 
549  mii.wID = MI_speed_6;
550  mii.dwTypeData = "6";
551  InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
552 
553  mii.wID = MI_speed_12;
554  mii.dwTypeData = "12";
555  InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
556 
557  mii.fMask = MIIM_FTYPE;
558  mii.fType = MFT_SEPARATOR;
559  InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
560 
561  mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
562  mii.fType = MFT_STRING;
563  mii.wID = MI_pause;
564  mii.dwTypeData = "pause";
565  InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
566 
567  set_scroll_speed(3);
568  set_pause(false);
569 }
570 
571 /**
572  * Creates the frame rate label on the right end of the menu bar. This is
573  * used as a text label to display the main thread's frame rate to the user,
574  * although it is implemented as a right-justified toplevel menu item that
575  * doesn't open to anything.
576  */
577 void WinStatsMonitor::
578 setup_frame_rate_label() {
579  MENUITEMINFO mii;
580  memset(&mii, 0, sizeof(mii));
581  mii.cbSize = sizeof(mii);
582 
583  mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
584  mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY;
585  mii.wID = MI_frame_rate_label;
586  mii.dwTypeData = "";
587  InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
588 }
589 
590 /**
591  * Registers the window class for the monitor window, if it has not already
592  * been registered.
593  */
594 void WinStatsMonitor::
595 register_window_class(HINSTANCE application) {
596  if (_window_class_registered) {
597  return;
598  }
599 
600  WNDCLASS wc;
601 
602  ZeroMemory(&wc, sizeof(WNDCLASS));
603  wc.style = 0;
604  wc.lpfnWndProc = (WNDPROC)static_window_proc;
605  wc.hInstance = application;
606  wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
607  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
608  wc.lpszMenuName = nullptr;
609  wc.lpszClassName = _window_class_name;
610 
611  // Reserve space to associate the this pointer with the window.
612  wc.cbWndExtra = sizeof(WinStatsMonitor *);
613 
614  if (!RegisterClass(&wc)) {
615  nout << "Could not register monitor window class!\n";
616  exit(1);
617  }
618 
619  _window_class_registered = true;
620 }
621 
622 /**
623  *
624  */
625 LONG WINAPI WinStatsMonitor::
626 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
627  WinStatsMonitor *self = (WinStatsMonitor *)GetWindowLongPtr(hwnd, 0);
628  if (self != nullptr && self->_window == hwnd) {
629  return self->window_proc(hwnd, msg, wparam, lparam);
630  } else {
631  return DefWindowProc(hwnd, msg, wparam, lparam);
632  }
633 }
634 
635 /**
636  *
637  */
638 LONG WinStatsMonitor::
639 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
640  switch (msg) {
641  case WM_DESTROY:
642  close();
643  break;
644 
645  case WM_COMMAND:
646  if (HIWORD(wparam) <= 1) {
647  int menu_id = LOWORD(wparam);
648  handle_menu_command(menu_id);
649  return 0;
650  }
651  break;
652 
653  default:
654  break;
655  }
656 
657  return DefWindowProc(hwnd, msg, wparam, lparam);
658 }
659 
660 /**
661  *
662  */
663 void WinStatsMonitor::
664 handle_menu_command(int menu_id) {
665  switch (menu_id) {
666  case MI_none:
667  break;
668 
669  case MI_time_ms:
670  set_time_units(PStatGraph::GBU_ms);
671  break;
672 
673  case MI_time_hz:
674  set_time_units(PStatGraph::GBU_hz);
675  break;
676 
677  case MI_speed_1:
678  set_scroll_speed(1);
679  break;
680 
681  case MI_speed_2:
682  set_scroll_speed(2);
683  break;
684 
685  case MI_speed_3:
686  set_scroll_speed(3);
687  break;
688 
689  case MI_speed_6:
690  set_scroll_speed(6);
691  break;
692 
693  case MI_speed_12:
694  set_scroll_speed(12);
695  break;
696 
697  case MI_pause:
698  set_pause(!_pause);
699  break;
700 
701  default:
702  if (menu_id >= MI_new_chart) {
703  const MenuDef &menu_def = lookup_menu(menu_id);
704  if (menu_def._collector_index < 0) {
705  open_piano_roll(menu_def._thread_index);
706  } else {
707  open_strip_chart(menu_def._thread_index, menu_def._collector_index,
708  menu_def._show_level);
709  }
710  }
711  }
712 }
const PStatThreadData * get_thread_data(int index) const
Returns the data associated with the indicated thread.
This is an abstract class that presents the interface to any number of different front-ends for the s...
Definition: pStatMonitor.h:39
std::string get_client_progname() const
Returns the program name of the client we're connected to, if known.
Definition: pStatMonitor.I:69
std::string get_client_hostname() const
Returns the hostname of the client we're connected to, if known.
Definition: pStatMonitor.I:58
void close()
Closes the client connection if it is active.
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
Definition: pStatMonitor.I:26
A collection of FrameData structures for recently-received frames within a particular thread.
double get_frame_rate() const
Computes the average frame rate over the past pstats_average_time seconds, by counting up the number ...
A pulldown menu of charts available for a particular thread.
void add_to_menu_bar(HMENU menu_bar, int before_menu_id)
Adds the menu to the end of the indicated menu bar.
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
Definition: winStatsGraph.h:32
void set_pause(bool pause)
Changes the pause flag for the graph.
virtual void set_scroll_speed(double scroll_speed)
Called when the user selects a new scroll speed from the monitor pulldown menu, this should adjust th...
virtual void set_time_units(int unit_mask)
Called when the user selects a new time units from the monitor pulldown menu, this should adjust the ...
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
void user_guide_bars_changed()
Called when the user guide bars have been changed.
virtual void new_data(int thread_index, int frame_number)
Called whenever new data arrives.
This class represents a connection to a PStatsClient and manages the data exchange with the client.
virtual bool has_idle()
Should be redefined to return true if you want to redefine idle() and expect it to be called.
void open_strip_chart(int thread_index, int collector_index, bool show_level)
Opens a new strip chart showing the indicated data.
int get_menu_id(const MenuDef &menu_def)
Returns the menu ID that is reserved for the indicated MenuDef properties.
void set_pause(bool pause)
Called when the user selects a pause on or pause off option from the menu.
virtual void got_hello()
Called when the "hello" message has been received from the client.
virtual void idle()
If has_idle() returns true, this will be called periodically to allow the monitor to update its displ...
virtual void user_guide_bars_changed()
Called when the user guide bars have been changed.
virtual std::string get_monitor_name()
Should be redefined to return a descriptive name for the type of PStatsMonitor this is.
HWND get_window() const
Returns the window handle to the monitor's window.
virtual void got_bad_version(int client_major, int client_minor, int server_major, int server_minor)
Like got_hello(), this is called when the "hello" message has been received from the client.
virtual void new_data(int thread_index, int frame_number)
Called as each frame's data is made available.
virtual void initialized()
Called after the monitor has been fully set up.
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
virtual void new_thread(int thread_index)
Called whenever a new Thread definition is received from the client.
void set_time_units(int unit_mask)
Called when the user selects a new time units from the monitor pulldown menu, this should adjust the ...
void set_scroll_speed(double scroll_speed)
Called when the user selects a new scroll speed from the monitor pulldown menu, this should adjust th...
void open_piano_roll(int thread_index)
Opens a new piano roll showing the indicated data.
const MenuDef & lookup_menu(int menu_id) const
Returns the MenuDef properties associated with the indicated menu ID.
virtual void lost_connection()
Called whenever the connection to the client has been lost.
A window that draws a piano-roll style chart, which shows the collectors explicitly stopping and star...
virtual void set_time_units(int unit_mask)
Called when the user selects a new time units from the monitor pulldown menu, this should adjust the ...
The class that owns the main loop, waiting for client connections.
A window that draws a strip chart, given a view.
virtual void set_scroll_speed(double scroll_speed)
Called when the user selects a new scroll speed from the monitor pulldown menu, this should adjust th...
virtual void set_time_units(int unit_mask)
Called when the user selects a new time units from the monitor pulldown menu, this should adjust the ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.