15 #include "winStatsMonitor.h"
16 #include "winStatsServer.h"
17 #include "winStatsStripChart.h"
18 #include "winStatsPianoRoll.h"
19 #include "winStatsChartMenu.h"
20 #include "winStatsMenuId.h"
21 #include "pStatGraph.h"
22 #include "pStatCollectorDef.h"
25 bool WinStatsMonitor::_window_class_registered =
false;
26 const char *
const WinStatsMonitor::_window_class_name =
"monitor";
53 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
58 ChartMenus::iterator mi;
59 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
65 DestroyWindow(_window);
69 #ifdef DEVELOP_WINSTATS
127 int server_major,
int server_minor) {
129 str <<
"Unable to honor connection attempt from "
131 <<
": unsupported PStats version "
132 << client_major <<
"." << client_minor;
134 if (server_minor == 0) {
135 str <<
" (server understands version " << server_major
136 <<
"." << server_minor <<
" only).";
138 str <<
" (server understands versions " << server_major
139 <<
".0 through " << server_major <<
"." << server_minor <<
").";
142 string message = str.str();
143 MessageBox(NULL, message.c_str(),
"Bad version",
144 MB_OK | MB_ICONINFORMATION | MB_SETFOREGROUND);
161 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
167 ChartMenus::iterator mi;
168 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
188 _chart_menus.push_back(chart_menu);
189 DrawMenuBar(_window);
204 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
206 graph->
new_data(thread_index, frame_number);
224 DestroyWindow(_window);
239 ChartMenus::iterator mi;
240 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
241 (*mi)->check_update();
247 if (frame_rate != 0.0f) {
249 sprintf(buffer,
"%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate);
252 memset(&mii, 0,
sizeof(mii));
253 mii.cbSize =
sizeof(mii);
254 mii.fMask = MIIM_STRING;
255 mii.dwTypeData = buffer;
256 SetMenuItemInfo(_menu_bar, MI_frame_rate_label, FALSE, &mii);
257 DrawMenuBar(_window);
280 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
336 static MenuDef invalid(0, 0,
false);
337 int menu_index = menu_id - MI_new_chart;
338 nassertr(menu_index >= 0 && menu_index < (
int)_menu_by_id.size(), invalid);
339 return _menu_by_id[menu_index];
353 MenuByDef::iterator mi;
354 mi = _menu_by_def.find(menu_def);
355 if (mi != _menu_by_def.end()) {
360 int menu_id = (int)_menu_by_id.size() + MI_new_chart;
361 _menu_by_id.push_back(menu_def);
362 _menu_by_def[menu_def] = menu_id;
377 _time_units = unit_mask;
381 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
388 memset(&mii, 0,
sizeof(mii));
389 mii.cbSize =
sizeof(mii);
390 mii.fMask = MIIM_STATE;
392 mii.fState = ((_time_units & PStatGraph::GBU_ms) != 0) ?
393 MFS_CHECKED : MFS_UNCHECKED;
394 SetMenuItemInfo(_options_menu, MI_time_ms, FALSE, &mii);
396 mii.fState = ((_time_units & PStatGraph::GBU_hz) != 0) ?
397 MFS_CHECKED : MFS_UNCHECKED;
398 SetMenuItemInfo(_options_menu, MI_time_hz, FALSE, &mii);
410 _scroll_speed = scroll_speed;
414 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
421 memset(&mii, 0,
sizeof(mii));
422 mii.cbSize =
sizeof(mii);
423 mii.fMask = MIIM_STATE;
425 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 1.0, 0.1) ?
426 MFS_CHECKED : MFS_UNCHECKED;
427 SetMenuItemInfo(_speed_menu, MI_speed_1, FALSE, &mii);
429 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 2.0, 0.1) ?
430 MFS_CHECKED : MFS_UNCHECKED;
431 SetMenuItemInfo(_speed_menu, MI_speed_2, FALSE, &mii);
433 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 3.0, 0.1) ?
434 MFS_CHECKED : MFS_UNCHECKED;
435 SetMenuItemInfo(_speed_menu, MI_speed_3, FALSE, &mii);
437 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 6.0, 0.1) ?
438 MFS_CHECKED : MFS_UNCHECKED;
439 SetMenuItemInfo(_speed_menu, MI_speed_6, FALSE, &mii);
441 mii.fState = IS_THRESHOLD_EQUAL(_scroll_speed, 12.0, 0.1) ?
442 MFS_CHECKED : MFS_UNCHECKED;
443 SetMenuItemInfo(_speed_menu, MI_speed_12, FALSE, &mii);
458 for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
465 memset(&mii, 0,
sizeof(mii));
466 mii.cbSize =
sizeof(mii);
467 mii.fMask = MIIM_STATE;
469 mii.fState = _pause ? MFS_CHECKED : MFS_UNCHECKED;
470 SetMenuItemInfo(_speed_menu, MI_pause, FALSE, &mii);
479 void WinStatsMonitor::
481 _graphs.insert(graph);
489 void WinStatsMonitor::
491 Graphs::iterator gi = _graphs.find(graph);
492 if (gi != _graphs.end()) {
503 void WinStatsMonitor::
509 HINSTANCE application = GetModuleHandle(NULL);
510 register_window_class(application);
512 _menu_bar = CreateMenu();
514 setup_options_menu();
516 setup_frame_rate_label();
518 ChartMenus::iterator mi;
519 for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
520 (*mi)->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
524 DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
525 WS_CLIPSIBLINGS | WS_VISIBLE;
528 CreateWindow(_window_class_name, _window_title.c_str(), window_style,
529 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
530 NULL, _menu_bar, application, 0);
532 nout <<
"Could not create monitor window!\n";
536 SetWindowLongPtr(_window, 0, (LONG_PTR)
this);
540 ShowWindow(_window, SW_RESTORE);
541 SetForegroundWindow(_window);
549 void WinStatsMonitor::
550 setup_options_menu() {
551 _options_menu = CreatePopupMenu();
554 memset(&mii, 0,
sizeof(mii));
555 mii.cbSize =
sizeof(mii);
557 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
558 mii.fType = MFT_STRING;
559 mii.hSubMenu = _options_menu;
565 mii.dwTypeData =
"Units";
566 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
569 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
570 mii.fType = MFT_STRING | MFT_RADIOCHECK;
571 mii.hbmpChecked = NULL;
572 mii.hbmpUnchecked = NULL;
573 mii.fState = MFS_UNCHECKED;
574 mii.wID = MI_time_ms;
575 mii.dwTypeData =
"ms";
576 InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
578 mii.wID = MI_time_hz;
579 mii.dwTypeData =
"Hz";
580 InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
590 void WinStatsMonitor::
592 _speed_menu = CreatePopupMenu();
595 memset(&mii, 0,
sizeof(mii));
596 mii.cbSize =
sizeof(mii);
598 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
599 mii.fType = MFT_STRING;
600 mii.hSubMenu = _speed_menu;
601 mii.dwTypeData =
"Speed";
602 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
605 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
606 mii.fType = MFT_STRING | MFT_RADIOCHECK;
607 mii.hbmpChecked = NULL;
608 mii.hbmpUnchecked = NULL;
609 mii.fState = MFS_UNCHECKED;
610 mii.wID = MI_speed_1;
611 mii.dwTypeData =
"1";
612 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
614 mii.wID = MI_speed_2;
615 mii.dwTypeData =
"2";
616 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
618 mii.wID = MI_speed_3;
619 mii.dwTypeData =
"3";
620 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
622 mii.wID = MI_speed_6;
623 mii.dwTypeData =
"6";
624 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
626 mii.wID = MI_speed_12;
627 mii.dwTypeData =
"12";
628 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
630 mii.fMask = MIIM_FTYPE;
631 mii.fType = MFT_SEPARATOR;
632 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
634 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
635 mii.fType = MFT_STRING;
637 mii.dwTypeData =
"pause";
638 InsertMenuItem(_speed_menu, GetMenuItemCount(_speed_menu), TRUE, &mii);
653 void WinStatsMonitor::
654 setup_frame_rate_label() {
656 memset(&mii, 0,
sizeof(mii));
657 mii.cbSize =
sizeof(mii);
659 mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID;
660 mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY;
661 mii.wID = MI_frame_rate_label;
663 InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
672 void WinStatsMonitor::
673 register_window_class(HINSTANCE application) {
674 if (_window_class_registered) {
680 ZeroMemory(&wc,
sizeof(WNDCLASS));
682 wc.lpfnWndProc = (WNDPROC)static_window_proc;
683 wc.hInstance = application;
684 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
685 wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
686 wc.lpszMenuName = NULL;
687 wc.lpszClassName = _window_class_name;
692 if (!RegisterClass(&wc)) {
693 nout <<
"Could not register monitor window class!\n";
697 _window_class_registered =
true;
705 LONG WINAPI WinStatsMonitor::
706 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
709 return self->window_proc(hwnd, msg, wparam, lparam);
711 return DefWindowProc(hwnd, msg, wparam, lparam);
720 LONG WinStatsMonitor::
721 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
728 if (HIWORD(wparam) <= 1) {
729 int menu_id = LOWORD(wparam);
730 handle_menu_command(menu_id);
739 return DefWindowProc(hwnd, msg, wparam, lparam);
747 void WinStatsMonitor::
748 handle_menu_command(
int menu_id) {
786 if (menu_id >= MI_new_chart) {
788 if (menu_def._collector_index < 0) {
792 menu_def._show_level);
string get_client_progname() const
Returns the program name of the client we're connected to, if known.
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
virtual string get_monitor_name()
Should be redefined to return a descriptive name for the type of PStatsMonitor this is...
A window that draws a strip chart, given a view.
The class that owns the main loop, waiting for client connections.
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 ...
const MenuDef & lookup_menu(int menu_id) const
Returns the MenuDef properties associated with the indicated menu ID.
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...
void close()
Closes the client connection if it is active.
virtual void new_thread(int thread_index)
Called whenever a new Thread definition is 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 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 user_guide_bars_changed()
Called when the user guide bars have been changed.
void open_strip_chart(int thread_index, int collector_index, bool show_level)
Opens a new strip chart showing the indicated data.
virtual void lost_connection()
Called whenever the connection to the client has been lost.
virtual bool has_idle()
Should be redefined to return true if you want to redefine idle() and expect it to be called...
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 ...
This is an abstract class that presents the interface to any number of different front-ends for the s...
string get_client_hostname() const
Returns the hostname of the client we're connected to, if known.
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...
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
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...
void set_pause(bool pause)
Called when the user selects a pause on or pause off option from the menu.
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 set_time_units(int unit_mask)
Called when the user selects a new time units from the monitor pulldown menu, this should adjust the ...
A collection of FrameData structures for recently-received frames within a particular thread...
This class represents a connection to a PStatsClient and manages the data exchange with the client...
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
const PStatThreadData * get_thread_data(int index) const
Returns the data associated with the indicated thread.
void set_pause(bool pause)
Changes the pause flag for the graph.
A window that draws a piano-roll style chart, which shows the collectors explicitly stopping and star...
virtual void idle()
If has_idle() returns true, this will be called periodically to allow the monitor to update its displ...
virtual void new_data(int thread_index, int frame_number)
Called whenever new data arrives.
int get_menu_id(const MenuDef &menu_def)
Returns the menu ID that is reserved for the indicated MenuDef properties.
void open_piano_roll(int thread_index)
Opens a new piano roll showing the indicated data.
virtual void user_guide_bars_changed()
Called when the user guide bars have been changed.
HWND get_window() const
Returns the window handle to the monitor's window.
double get_frame_rate() const
Computes the average frame rate over the past pstats_average_time seconds, by counting up the number ...
virtual void got_hello()
Called when the "hello" message has been received from the client.