24bool WinStatsMonitor::_window_class_registered =
false;
25const char *
const WinStatsMonitor::_window_class_name =
"monitor";
48 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
53 ChartMenus::iterator mi;
54 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
60 DestroyWindow(_window);
64#ifdef DEVELOP_WINSTATS
109 int server_major,
int server_minor) {
110 std::ostringstream str;
111 str <<
"Unable to honor connection attempt from "
113 <<
": unsupported PStats version "
114 << client_major <<
"." << client_minor;
116 if (server_minor == 0) {
117 str <<
" (server understands version " << server_major
118 <<
"." << server_minor <<
" only).";
120 str <<
" (server understands versions " << server_major
121 <<
".0 through " << server_major <<
"." << server_minor <<
").";
124 std::string message = str.str();
125 MessageBox(
nullptr, message.c_str(),
"Bad version",
126 MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
139 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
145 ChartMenus::iterator mi;
146 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
162 _chart_menus.push_back(chart_menu);
163 DrawMenuBar(_window);
173new_data(
int thread_index,
int frame_number) {
175 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
177 graph->
new_data(thread_index, frame_number);
192 DestroyWindow(_window);
204 ChartMenus::iterator mi;
205 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
206 (*mi)->check_update();
212 if (frame_rate != 0.0f) {
214 sprintf(buffer,
"%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate);
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);
241 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
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];
301 MenuByDef::iterator mi;
302 mi = _menu_by_def.find(menu_def);
303 if (mi != _menu_by_def.end()) {
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;
322 _time_units = unit_mask;
326 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
333 memset(&mii, 0,
sizeof(mii));
334 mii.cbSize =
sizeof(mii);
335 mii.fMask = MIIM_STATE;
337 mii.fState = ((_time_units & PStatGraph::GBU_ms) != 0) ?
338 MFS_CHECKED : MFS_UNCHECKED;
339 SetMenuItemInfo(_options_menu, MI_time_ms, FALSE, &mii);
341 mii.fState = ((_time_units & PStatGraph::GBU_hz) != 0) ?
342 MFS_CHECKED : MFS_UNCHECKED;
343 SetMenuItemInfo(_options_menu, MI_time_hz, FALSE, &mii);
352 _scroll_speed = scroll_speed;
356 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
363 memset(&mii, 0,
sizeof(mii));
364 mii.cbSize =
sizeof(mii);
365 mii.fMask = MIIM_STATE;
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);
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);
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);
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);
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);
397 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
404 memset(&mii, 0,
sizeof(mii));
405 mii.cbSize =
sizeof(mii);
406 mii.fMask = MIIM_STATE;
408 mii.fState = _pause ? MFS_CHECKED : MFS_UNCHECKED;
409 SetMenuItemInfo(_speed_menu, MI_pause, FALSE, &mii);
415void WinStatsMonitor::
417 _graphs.insert(graph);
423void WinStatsMonitor::
425 Graphs::iterator gi = _graphs.find(graph);
426 if (gi != _graphs.end()) {
435void WinStatsMonitor::
441 HINSTANCE application = GetModuleHandle(
nullptr);
442 register_window_class(application);
444 _menu_bar = CreateMenu();
446 setup_options_menu();
448 setup_frame_rate_label();
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);
456 DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
457 WS_CLIPSIBLINGS | WS_VISIBLE;
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);
464 nout <<
"Could not create monitor window!\n";
468 SetWindowLongPtr(_window, 0, (LONG_PTR)
this);
472 ShowWindow(_window, SW_RESTORE);
473 SetForegroundWindow(_window);
479void WinStatsMonitor::
480setup_options_menu() {
481 _options_menu = CreatePopupMenu();
484 memset(&mii, 0,
sizeof(mii));
485 mii.cbSize =
sizeof(mii);
487 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
488 mii.fType = MFT_STRING;
489 mii.hSubMenu = _options_menu;
494 mii.dwTypeData =
"Units";
495 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
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);
507 mii.wID = MI_time_hz;
508 mii.dwTypeData =
"Hz";
509 InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
517void WinStatsMonitor::
519 _speed_menu = CreatePopupMenu();
522 memset(&mii, 0,
sizeof(mii));
523 mii.cbSize =
sizeof(mii);
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);
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);
541 mii.wID = MI_speed_2;
542 mii.dwTypeData =
"2";
543 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
545 mii.wID = MI_speed_3;
546 mii.dwTypeData =
"3";
547 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
549 mii.wID = MI_speed_6;
550 mii.dwTypeData =
"6";
551 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
553 mii.wID = MI_speed_12;
554 mii.dwTypeData =
"12";
555 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
557 mii.fMask = MIIM_FTYPE;
558 mii.fType = MFT_SEPARATOR;
559 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
561 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
562 mii.fType = MFT_STRING;
564 mii.dwTypeData =
"pause";
565 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
577void WinStatsMonitor::
578setup_frame_rate_label() {
580 memset(&mii, 0,
sizeof(mii));
581 mii.cbSize =
sizeof(mii);
583 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
584 mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY;
585 mii.wID = MI_frame_rate_label;
587 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
594void WinStatsMonitor::
595register_window_class(HINSTANCE application) {
596 if (_window_class_registered) {
602 ZeroMemory(&wc,
sizeof(WNDCLASS));
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;
614 if (!RegisterClass(&wc)) {
615 nout <<
"Could not register monitor window class!\n";
619 _window_class_registered =
true;
625LONG WINAPI WinStatsMonitor::
626static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
628 if (self !=
nullptr && self->_window == hwnd) {
629 return self->window_proc(hwnd, msg, wparam, lparam);
631 return DefWindowProc(hwnd, msg, wparam, lparam);
638LONG WinStatsMonitor::
639window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
646 if (HIWORD(wparam) <= 1) {
647 int menu_id = LOWORD(wparam);
648 handle_menu_command(menu_id);
657 return DefWindowProc(hwnd, msg, wparam, lparam);
663void WinStatsMonitor::
664handle_menu_command(
int menu_id) {
702 if (menu_id >= MI_new_chart) {
704 if (menu_def._collector_index < 0) {
708 menu_def._show_level);
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...
std::string get_client_progname() const
Returns the program name of the client we're connected to, if known.
std::string get_client_hostname() const
Returns the hostname of the client we're connected to, if known.
void close()
Closes the client connection if it is active.
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
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 ...
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
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.