|
|
@@ -23,45 +23,29 @@
|
|
|
#include "pStatGraph.h"
|
|
|
#include "pStatCollectorDef.h"
|
|
|
|
|
|
+#include "convert_srgb.h"
|
|
|
+
|
|
|
#include <algorithm>
|
|
|
|
|
|
#include <commctrl.h>
|
|
|
-
|
|
|
-bool WinStatsMonitor::_window_class_registered = false;
|
|
|
-const char * const WinStatsMonitor::_window_class_name = "monitor";
|
|
|
+#include <commdlg.h>
|
|
|
+#include <uxtheme.h>
|
|
|
|
|
|
/**
|
|
|
*
|
|
|
*/
|
|
|
WinStatsMonitor::
|
|
|
WinStatsMonitor(WinStatsServer *server) : PStatMonitor(server) {
|
|
|
- _window = 0;
|
|
|
- _menu_bar = 0;
|
|
|
- _options_menu = 0;
|
|
|
+ _window = server->get_window();
|
|
|
+ _menu_bar = server->get_menu_bar();
|
|
|
+ _status_bar = server->get_status_bar();
|
|
|
|
|
|
// These will be filled in later when the menu is created.
|
|
|
- _time_units = 0;
|
|
|
_scroll_speed = 0.0;
|
|
|
_pause = false;
|
|
|
|
|
|
- // Create the fonts used for rendering the UI.
|
|
|
- NONCLIENTMETRICS metrics = {0};
|
|
|
- metrics.cbSize = sizeof(NONCLIENTMETRICS);
|
|
|
- if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &metrics, 0)) {
|
|
|
- _font = CreateFontIndirect(&metrics.lfMenuFont);
|
|
|
- } else {
|
|
|
- _font = (HFONT)GetStockObject(ANSI_VAR_FONT);
|
|
|
- }
|
|
|
-
|
|
|
- HDC dc = GetDC(nullptr);
|
|
|
- _pixel_scale = 0;
|
|
|
- if (dc) {
|
|
|
- _pixel_scale = GetDeviceCaps(dc, LOGPIXELSX) / (96 / 4);
|
|
|
- }
|
|
|
- if (_pixel_scale <= 0) {
|
|
|
- _pixel_scale = 4;
|
|
|
- }
|
|
|
- ReleaseDC(nullptr, dc);
|
|
|
+ setup_speed_menu();
|
|
|
+ setup_frame_rate_label();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -69,27 +53,28 @@ WinStatsMonitor(WinStatsServer *server) : PStatMonitor(server) {
|
|
|
*/
|
|
|
WinStatsMonitor::
|
|
|
~WinStatsMonitor() {
|
|
|
- Graphs::iterator gi;
|
|
|
- for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
|
|
|
- delete (*gi);
|
|
|
- }
|
|
|
- _graphs.clear();
|
|
|
+ close();
|
|
|
+}
|
|
|
|
|
|
- ChartMenus::iterator mi;
|
|
|
- for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
|
|
|
- delete (*mi);
|
|
|
- }
|
|
|
- _chart_menus.clear();
|
|
|
+/**
|
|
|
+ * Closes the client connection if it is active.
|
|
|
+ */
|
|
|
+void WinStatsMonitor::
|
|
|
+close() {
|
|
|
+ PStatMonitor::close();
|
|
|
+
|
|
|
+ remove_all_graphs();
|
|
|
+
|
|
|
+ RemoveMenu(_menu_bar, 2, MF_BYPOSITION);
|
|
|
+ RemoveMenu(_menu_bar, 2, MF_BYPOSITION);
|
|
|
|
|
|
- if (_window) {
|
|
|
- DestroyWindow(_window);
|
|
|
- _window = 0;
|
|
|
+ for (WinStatsChartMenu *chart_menu : _chart_menus) {
|
|
|
+ RemoveMenu(_menu_bar, 2, MF_BYPOSITION);
|
|
|
+ delete chart_menu;
|
|
|
}
|
|
|
+ _chart_menus.clear();
|
|
|
|
|
|
-#ifdef DEVELOP_WINSTATS
|
|
|
- // For Winstats developers, exit when the first monitor closes.
|
|
|
- exit(0);
|
|
|
-#endif
|
|
|
+ DrawMenuBar(_window);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -118,8 +103,6 @@ initialized() {
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
got_hello() {
|
|
|
- create_window();
|
|
|
- open_strip_chart(0, 0, false);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -160,16 +143,13 @@ got_bad_version(int client_major, int client_minor,
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
new_collector(int collector_index) {
|
|
|
- Graphs::iterator gi;
|
|
|
- for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
|
|
|
- WinStatsGraph *graph = (*gi);
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
graph->new_collector(collector_index);
|
|
|
}
|
|
|
|
|
|
// We might need to update our menus.
|
|
|
- ChartMenus::iterator mi;
|
|
|
- for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
|
|
|
- (*mi)->do_update();
|
|
|
+ for (WinStatsChartMenu *chart_menu : _chart_menus) {
|
|
|
+ chart_menu->do_update();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -186,6 +166,10 @@ new_thread(int thread_index) {
|
|
|
chart_menu->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
|
|
|
_chart_menus.push_back(chart_menu);
|
|
|
DrawMenuBar(_window);
|
|
|
+
|
|
|
+ if (thread_index == 0) {
|
|
|
+ update_status_bar();
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -203,6 +187,11 @@ new_data(int thread_index, int frame_number) {
|
|
|
if (thread_index == 0) {
|
|
|
update_status_bar();
|
|
|
}
|
|
|
+
|
|
|
+ if (!_have_data) {
|
|
|
+ open_default_graphs();
|
|
|
+ _have_data = true;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -213,11 +202,6 @@ new_data(int thread_index, int frame_number) {
|
|
|
void WinStatsMonitor::
|
|
|
lost_connection() {
|
|
|
nout << "Lost connection to " << get_client_hostname() << "\n";
|
|
|
-
|
|
|
- if (_window) {
|
|
|
- DestroyWindow(_window);
|
|
|
- _window = 0;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -227,9 +211,8 @@ lost_connection() {
|
|
|
void WinStatsMonitor::
|
|
|
idle() {
|
|
|
// Check if any of our chart menus need updating.
|
|
|
- ChartMenus::iterator mi;
|
|
|
- for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
|
|
|
- (*mi)->check_update();
|
|
|
+ for (WinStatsChartMenu *chart_menu : _chart_menus) {
|
|
|
+ chart_menu->check_update();
|
|
|
}
|
|
|
|
|
|
// Update the frame rate label from the main thread (thread 0).
|
|
|
@@ -268,9 +251,7 @@ has_idle() {
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
user_guide_bars_changed() {
|
|
|
- Graphs::iterator gi;
|
|
|
- for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
|
|
|
- WinStatsGraph *graph = (*gi);
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
graph->user_guide_bars_changed();
|
|
|
}
|
|
|
}
|
|
|
@@ -288,7 +269,7 @@ get_window() const {
|
|
|
*/
|
|
|
HFONT WinStatsMonitor::
|
|
|
get_font() const {
|
|
|
- return _font;
|
|
|
+ return ((WinStatsServer *)_server)->get_font();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -296,7 +277,7 @@ get_font() const {
|
|
|
*/
|
|
|
int WinStatsMonitor::
|
|
|
get_pixel_scale() const {
|
|
|
- return _pixel_scale;
|
|
|
+ return ((WinStatsServer *)_server)->get_pixel_scale();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -304,64 +285,100 @@ get_pixel_scale() const {
|
|
|
*/
|
|
|
POINT WinStatsMonitor::
|
|
|
get_new_window_pos() {
|
|
|
- int offset = _graphs.size() * 10 * _pixel_scale;
|
|
|
+ WinStatsServer *server = (WinStatsServer *)_server;
|
|
|
+ int offset = _graphs.size() * 10 * server->get_pixel_scale();
|
|
|
+ POINT client_origin = server->get_client_origin();
|
|
|
POINT pt;
|
|
|
- pt.x = offset + _client_origin.x;
|
|
|
- pt.y = offset + _client_origin.y;
|
|
|
+ pt.x = offset + client_origin.x;
|
|
|
+ pt.y = offset + client_origin.y;
|
|
|
return pt;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * Opens a new timeline.
|
|
|
+ */
|
|
|
+PStatGraph *WinStatsMonitor::
|
|
|
+open_timeline() {
|
|
|
+ WinStatsTimeline *graph = new WinStatsTimeline(this);
|
|
|
+ add_graph(graph);
|
|
|
+ return graph;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* Opens a new strip chart showing the indicated data.
|
|
|
*/
|
|
|
-void WinStatsMonitor::
|
|
|
+PStatGraph *WinStatsMonitor::
|
|
|
open_strip_chart(int thread_index, int collector_index, bool show_level) {
|
|
|
WinStatsStripChart *graph =
|
|
|
new WinStatsStripChart(this, thread_index, collector_index, show_level);
|
|
|
add_graph(graph);
|
|
|
+ return graph;
|
|
|
+}
|
|
|
|
|
|
- graph->set_time_units(_time_units);
|
|
|
- graph->set_scroll_speed(_scroll_speed);
|
|
|
- graph->set_pause(_pause);
|
|
|
+/**
|
|
|
+ * Opens a new flame graph showing the indicated data.
|
|
|
+ */
|
|
|
+PStatGraph *WinStatsMonitor::
|
|
|
+open_flame_graph(int thread_index, int collector_index) {
|
|
|
+ WinStatsFlameGraph *graph = new WinStatsFlameGraph(this, thread_index, collector_index);
|
|
|
+ add_graph(graph);
|
|
|
+ return graph;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Opens a new piano roll showing the indicated data.
|
|
|
*/
|
|
|
-void WinStatsMonitor::
|
|
|
+PStatGraph *WinStatsMonitor::
|
|
|
open_piano_roll(int thread_index) {
|
|
|
WinStatsPianoRoll *graph = new WinStatsPianoRoll(this, thread_index);
|
|
|
add_graph(graph);
|
|
|
-
|
|
|
- graph->set_time_units(_time_units);
|
|
|
- graph->set_scroll_speed(_scroll_speed);
|
|
|
- graph->set_pause(_pause);
|
|
|
+ return graph;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Opens a new flame graph showing the indicated data.
|
|
|
+ * Opens a dialog to change the given collector color.
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
-open_flame_graph(int thread_index, int collector_index) {
|
|
|
- WinStatsFlameGraph *graph = new WinStatsFlameGraph(this, thread_index, collector_index);
|
|
|
- add_graph(graph);
|
|
|
-
|
|
|
- graph->set_time_units(_time_units);
|
|
|
- graph->set_scroll_speed(_scroll_speed);
|
|
|
- graph->set_pause(_pause);
|
|
|
+choose_collector_color(int collector_index) {
|
|
|
+ const LRGBColor ¤t = get_collector_color(collector_index);
|
|
|
+ static COLORREF custom_colors[16] = {0};
|
|
|
+
|
|
|
+ CHOOSECOLORA cc = {
|
|
|
+ sizeof(CHOOSECOLORA),
|
|
|
+ _window,
|
|
|
+ 0,
|
|
|
+ RGB(encode_sRGB_uchar(current[0]), encode_sRGB_uchar(current[1]), encode_sRGB_uchar(current[2])),
|
|
|
+ (LPDWORD)custom_colors,
|
|
|
+ CC_FULLOPEN | CC_RGBINIT,
|
|
|
+ 0,
|
|
|
+ nullptr,
|
|
|
+ nullptr,
|
|
|
+ };
|
|
|
+
|
|
|
+ if (ChooseColorA(&cc)) {
|
|
|
+ LRGBColor result(
|
|
|
+ decode_sRGB_float(GetRValue(cc.rgbResult)),
|
|
|
+ decode_sRGB_float(GetGValue(cc.rgbResult)),
|
|
|
+ decode_sRGB_float(GetBValue(cc.rgbResult)));
|
|
|
+
|
|
|
+ set_collector_color(collector_index, result);
|
|
|
+
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
+ graph->reset_collector_color(collector_index);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Opens a new timeline.
|
|
|
+ * Resets the color of the given collector to the default.
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
-open_timeline() {
|
|
|
- WinStatsTimeline *graph = new WinStatsTimeline(this);
|
|
|
- add_graph(graph);
|
|
|
+reset_collector_color(int collector_index) {
|
|
|
+ clear_collector_color(collector_index);
|
|
|
|
|
|
- graph->set_time_units(_time_units);
|
|
|
- graph->set_scroll_speed(_scroll_speed);
|
|
|
- graph->set_pause(_pause);
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
+ graph->reset_collector_color(collector_index);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -404,28 +421,9 @@ get_menu_id(const MenuDef &menu_def) {
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
set_time_units(int unit_mask) {
|
|
|
- _time_units = unit_mask;
|
|
|
-
|
|
|
- // First, change all of the open graphs appropriately.
|
|
|
- Graphs::iterator gi;
|
|
|
- for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
|
|
|
- WinStatsGraph *graph = (*gi);
|
|
|
- graph->set_time_units(_time_units);
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
+ graph->set_time_units(unit_mask);
|
|
|
}
|
|
|
-
|
|
|
- // Now change the checkmark on the pulldown menu.
|
|
|
- MENUITEMINFO mii;
|
|
|
- memset(&mii, 0, sizeof(mii));
|
|
|
- mii.cbSize = sizeof(mii);
|
|
|
- mii.fMask = MIIM_STATE;
|
|
|
-
|
|
|
- mii.fState = ((_time_units & PStatGraph::GBU_ms) != 0) ?
|
|
|
- MFS_CHECKED : MFS_UNCHECKED;
|
|
|
- SetMenuItemInfo(_options_menu, MI_time_ms, FALSE, &mii);
|
|
|
-
|
|
|
- mii.fState = ((_time_units & PStatGraph::GBU_hz) != 0) ?
|
|
|
- MFS_CHECKED : MFS_UNCHECKED;
|
|
|
- SetMenuItemInfo(_options_menu, MI_time_hz, FALSE, &mii);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -437,9 +435,7 @@ set_scroll_speed(double scroll_speed) {
|
|
|
_scroll_speed = scroll_speed;
|
|
|
|
|
|
// First, change all of the open graphs appropriately.
|
|
|
- Graphs::iterator gi;
|
|
|
- for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
|
|
|
- WinStatsGraph *graph = (*gi);
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
graph->set_scroll_speed(_scroll_speed);
|
|
|
}
|
|
|
|
|
|
@@ -478,9 +474,7 @@ set_pause(bool pause) {
|
|
|
_pause = pause;
|
|
|
|
|
|
// First, change all of the open graphs appropriately.
|
|
|
- Graphs::iterator gi;
|
|
|
- for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
|
|
|
- WinStatsGraph *graph = (*gi);
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
graph->set_pause(_pause);
|
|
|
}
|
|
|
|
|
|
@@ -500,6 +494,10 @@ set_pause(bool pause) {
|
|
|
void WinStatsMonitor::
|
|
|
add_graph(WinStatsGraph *graph) {
|
|
|
_graphs.insert(graph);
|
|
|
+
|
|
|
+ graph->set_time_units(((WinStatsServer *)_server)->get_time_units());
|
|
|
+ graph->set_scroll_speed(_scroll_speed);
|
|
|
+ graph->set_pause(_pause);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -515,91 +513,14 @@ remove_graph(WinStatsGraph *graph) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Creates the window for this monitor.
|
|
|
+ * Deletes all open graphs.
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
-create_window() {
|
|
|
- if (_window) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- HINSTANCE application = GetModuleHandle(nullptr);
|
|
|
- register_window_class(application);
|
|
|
-
|
|
|
- _menu_bar = CreateMenu();
|
|
|
-
|
|
|
- setup_options_menu();
|
|
|
- setup_speed_menu();
|
|
|
- setup_frame_rate_label();
|
|
|
-
|
|
|
- ChartMenus::iterator mi;
|
|
|
- for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) {
|
|
|
- (*mi)->add_to_menu_bar(_menu_bar, MI_frame_rate_label);
|
|
|
- }
|
|
|
-
|
|
|
- _window_title = get_client_progname() + " on " + get_client_hostname();
|
|
|
- DWORD window_style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN |
|
|
|
- WS_CLIPSIBLINGS | WS_VISIBLE;
|
|
|
-
|
|
|
- _window =
|
|
|
- CreateWindow(_window_class_name, _window_title.c_str(), window_style,
|
|
|
- CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
- nullptr, _menu_bar, application, 0);
|
|
|
- if (!_window) {
|
|
|
- nout << "Could not create monitor window!\n";
|
|
|
- exit(1);
|
|
|
+remove_all_graphs() {
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
+ delete graph;
|
|
|
}
|
|
|
-
|
|
|
- SetWindowLongPtr(_window, 0, (LONG_PTR)this);
|
|
|
-
|
|
|
- create_status_bar(application);
|
|
|
-
|
|
|
- // For some reason, SW_SHOWNORMAL doesn't always work, but SW_RESTORE seems
|
|
|
- // to.
|
|
|
- ShowWindow(_window, SW_RESTORE);
|
|
|
- SetForegroundWindow(_window);
|
|
|
-
|
|
|
- _client_origin.x = 0;
|
|
|
- _client_origin.y = 0;
|
|
|
- ClientToScreen(_window, &_client_origin);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * Creates the "Options" pulldown menu.
|
|
|
- */
|
|
|
-void WinStatsMonitor::
|
|
|
-setup_options_menu() {
|
|
|
- _options_menu = CreatePopupMenu();
|
|
|
-
|
|
|
- MENUITEMINFO mii;
|
|
|
- memset(&mii, 0, sizeof(mii));
|
|
|
- mii.cbSize = sizeof(mii);
|
|
|
-
|
|
|
- mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
|
|
|
- mii.fType = MFT_STRING;
|
|
|
- mii.hSubMenu = _options_menu;
|
|
|
-
|
|
|
- // One day, when there is more than one option here, we will actually
|
|
|
- // present this to the user as the "Options" menu. For now, the only option
|
|
|
- // we have is time units. mii.dwTypeData = "Options";
|
|
|
- mii.dwTypeData = "Units";
|
|
|
- InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
|
|
|
-
|
|
|
-
|
|
|
- mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_CHECKMARKS | MIIM_STATE;
|
|
|
- mii.fType = MFT_STRING | MFT_RADIOCHECK;
|
|
|
- mii.hbmpChecked = nullptr;
|
|
|
- mii.hbmpUnchecked = nullptr;
|
|
|
- mii.fState = MFS_UNCHECKED;
|
|
|
- mii.wID = MI_time_ms;
|
|
|
- mii.dwTypeData = "ms";
|
|
|
- InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
|
|
|
-
|
|
|
- mii.wID = MI_time_hz;
|
|
|
- mii.dwTypeData = "Hz";
|
|
|
- InsertMenuItem(_options_menu, GetMenuItemCount(_options_menu), TRUE, &mii);
|
|
|
-
|
|
|
- set_time_units(PStatGraph::GBU_ms);
|
|
|
+ _graphs.clear();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -678,26 +599,6 @@ setup_frame_rate_label() {
|
|
|
InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Sets up a status bar at the bottom of the screen showing assorted level
|
|
|
- * values.
|
|
|
- */
|
|
|
-void WinStatsMonitor::
|
|
|
-create_status_bar(HINSTANCE application) {
|
|
|
- _status_bar = CreateWindow(STATUSCLASSNAME, nullptr,
|
|
|
- SBARS_SIZEGRIP | WS_CHILD | WS_VISIBLE,
|
|
|
- 0, 0, 0, 0,
|
|
|
- _window, (HMENU)0, application, nullptr);
|
|
|
-
|
|
|
- update_status_bar();
|
|
|
-
|
|
|
-
|
|
|
- ShowWindow(_status_bar, SW_SHOW);
|
|
|
- UpdateWindow(_status_bar);
|
|
|
-
|
|
|
- InvalidateRect(_status_bar, NULL, TRUE);
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* Updates the status bar.
|
|
|
*/
|
|
|
@@ -758,8 +659,10 @@ update_status_bar() {
|
|
|
HLOCAL hloc = LocalAlloc(LHND, sizeof(int) * (parts.size() + 1));
|
|
|
PINT sizes = (PINT)LocalLock(hloc);
|
|
|
|
|
|
+ int pixel_scale = get_pixel_scale();
|
|
|
+
|
|
|
// Allocate the left-most slot for the framerate indicator.
|
|
|
- double offset = 28.0 * _pixel_scale;
|
|
|
+ double offset = 28.0 * pixel_scale;
|
|
|
sizes[0] = (int)(offset + 0.5);
|
|
|
|
|
|
if (!parts.empty()) {
|
|
|
@@ -769,11 +672,11 @@ update_status_bar() {
|
|
|
double width_per_char = 0;
|
|
|
GetClientRect(_status_bar, &rect);
|
|
|
// Leave room for the grip.
|
|
|
- rect.right -= _pixel_scale * 4;
|
|
|
+ rect.right -= pixel_scale * 4;
|
|
|
width_per_char = (rect.right - rect.left - offset) / (double)total_chars;
|
|
|
|
|
|
// If we get below a minimum width, start chopping parts off.
|
|
|
- while (!parts.empty() && width_per_char < _pixel_scale * 1.5) {
|
|
|
+ while (!parts.empty() && width_per_char < pixel_scale * 1.5) {
|
|
|
total_chars -= parts.back().size();
|
|
|
parts.pop_back();
|
|
|
width_per_char = (rect.right - rect.left - offset) / (double)total_chars;
|
|
|
@@ -846,152 +749,89 @@ show_popup_menu(int collector) {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Registers the window class for the monitor window, if it has not already
|
|
|
- * been registered.
|
|
|
+ * Called when a graph window is iconified or moved in the iconified state.
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
-register_window_class(HINSTANCE application) {
|
|
|
- if (_window_class_registered) {
|
|
|
- return;
|
|
|
- }
|
|
|
+calc_iconic_graph_window_pos(WinStatsGraph *moved_graph, int &x, int &y) {
|
|
|
+ MINIMIZEDMETRICS metrics;
|
|
|
+ metrics.cbSize = sizeof(metrics);
|
|
|
+ SystemParametersInfoA(SPI_GETMINIMIZEDMETRICS, 0, &metrics, 0);
|
|
|
|
|
|
- WNDCLASS wc;
|
|
|
+ int height = GetThemeSysSize(nullptr, SM_CYSIZE) + GetThemeSysSize(nullptr, SM_CXPADDEDBORDER) * 2;
|
|
|
|
|
|
- ZeroMemory(&wc, sizeof(WNDCLASS));
|
|
|
- wc.style = 0;
|
|
|
- wc.lpfnWndProc = (WNDPROC)static_window_proc;
|
|
|
- wc.hInstance = application;
|
|
|
- wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
|
|
- wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
|
|
|
- wc.lpszMenuName = nullptr;
|
|
|
- wc.lpszClassName = _window_class_name;
|
|
|
+ RECT client_rect;
|
|
|
+ GetClientRect(_window, &client_rect);
|
|
|
+ MapWindowPoints(_window, nullptr, (POINT *)&client_rect, 2);
|
|
|
|
|
|
- // Reserve space to associate the this pointer with the window.
|
|
|
- wc.cbWndExtra = sizeof(WinStatsMonitor *);
|
|
|
+ // Remove the status bar from the client rectangle.
|
|
|
+ RECT status_bar_rect;
|
|
|
+ GetWindowRect(_status_bar, &status_bar_rect);
|
|
|
+ client_rect.bottom -= (status_bar_rect.bottom - status_bar_rect.top);
|
|
|
|
|
|
- if (!RegisterClass(&wc)) {
|
|
|
- nout << "Could not register monitor window class!\n";
|
|
|
- exit(1);
|
|
|
- }
|
|
|
+ int iconic_offset = 0;
|
|
|
|
|
|
- _window_class_registered = true;
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
+ RECT child_rect;
|
|
|
+ HWND window = graph->get_window();
|
|
|
+ if (graph == moved_graph) {
|
|
|
+ x = client_rect.left + iconic_offset;
|
|
|
+ y = client_rect.bottom - height;
|
|
|
+ iconic_offset += metrics.iWidth + metrics.iHorzGap;
|
|
|
+ }
|
|
|
+ else if (IsIconic(window) && GetWindowRect(window, &child_rect)) {
|
|
|
+ // Keep it glued to the bottom-left corner of the parent window.
|
|
|
+ child_rect.left = client_rect.left + iconic_offset;
|
|
|
+ child_rect.top = client_rect.bottom - height;
|
|
|
+ iconic_offset += metrics.iWidth + metrics.iHorzGap;
|
|
|
+
|
|
|
+ SetWindowPos(window, 0, child_rect.left, child_rect.top, 0, 0,
|
|
|
+ SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
+ * Called when the server window is moved.
|
|
|
*/
|
|
|
-LONG WINAPI WinStatsMonitor::
|
|
|
-static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
|
- WinStatsMonitor *self = (WinStatsMonitor *)GetWindowLongPtr(hwnd, 0);
|
|
|
- if (self != nullptr && self->_window == hwnd) {
|
|
|
- return self->window_proc(hwnd, msg, wparam, lparam);
|
|
|
- } else {
|
|
|
- return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
+void WinStatsMonitor::
|
|
|
+handle_window_moved(const RECT &client_rect, int delta_x, int delta_y) {
|
|
|
+ if (_graphs.empty()) {
|
|
|
+ return;
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-/**
|
|
|
- *
|
|
|
- */
|
|
|
-LONG WinStatsMonitor::
|
|
|
-window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
|
- switch (msg) {
|
|
|
- case WM_DESTROY:
|
|
|
- close();
|
|
|
- break;
|
|
|
+ MINIMIZEDMETRICS metrics;
|
|
|
+ metrics.cbSize = sizeof(metrics);
|
|
|
+ SystemParametersInfoA(SPI_GETMINIMIZEDMETRICS, 0, &metrics, 0);
|
|
|
|
|
|
- case WM_WINDOWPOSCHANGED:
|
|
|
- if (!_graphs.empty()) {
|
|
|
- RECT status_bar_rect;
|
|
|
- GetWindowRect(_status_bar, &status_bar_rect);
|
|
|
-
|
|
|
- RECT client_rect;
|
|
|
- GetClientRect(_window, &client_rect);
|
|
|
- MapWindowPoints(_window, nullptr, (POINT *)&client_rect, 2);
|
|
|
-
|
|
|
- int delta_x = client_rect.left - _client_origin.x;
|
|
|
- int delta_y = client_rect.top - _client_origin.y;
|
|
|
- _client_origin.x = client_rect.left;
|
|
|
- _client_origin.y = client_rect.top;
|
|
|
-
|
|
|
- int iconic_offset = 0;
|
|
|
-
|
|
|
- for (WinStatsGraph *graph : _graphs) {
|
|
|
- RECT child_rect;
|
|
|
- HWND window = graph->get_window();
|
|
|
- if (GetWindowRect(window, &child_rect)) {
|
|
|
- if (IsIconic(window)) {
|
|
|
- // Keep it glued to the bottom-left corner of the parent window.
|
|
|
- child_rect.left = client_rect.left + iconic_offset;
|
|
|
- child_rect.top = client_rect.bottom - (child_rect.bottom - child_rect.top) - (status_bar_rect.bottom - status_bar_rect.top);
|
|
|
- iconic_offset += (child_rect.right - child_rect.left);
|
|
|
- } else {
|
|
|
- child_rect.left += delta_x;
|
|
|
- child_rect.top += delta_y;
|
|
|
- }
|
|
|
- SetWindowPos(window, 0, child_rect.left, child_rect.top, 0, 0,
|
|
|
- SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW | SWP_NOACTIVATE);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- break;
|
|
|
+ int height = GetThemeSysSize(nullptr, SM_CYSIZE) + GetThemeSysSize(nullptr, SM_CXPADDEDBORDER) * 2;
|
|
|
|
|
|
- case WM_SIZE:
|
|
|
- if (_status_bar) {
|
|
|
- SendMessage(_status_bar, WM_SIZE, 0, 0);
|
|
|
- update_status_bar();
|
|
|
- }
|
|
|
- break;
|
|
|
+ int iconic_offset = 0;
|
|
|
|
|
|
- case WM_NOTIFY:
|
|
|
- if (((LPNMHDR)lparam)->code == NM_DBLCLK) {
|
|
|
- NMMOUSE &mouse = *(NMMOUSE *)lparam;
|
|
|
- if (mouse.dwItemSpec == 0) {
|
|
|
- open_strip_chart(0, 0, false);
|
|
|
- }
|
|
|
- else if (mouse.dwItemSpec >= 1 && mouse.dwItemSpec <= _status_bar_collectors.size()) {
|
|
|
- int collector = _status_bar_collectors[mouse.dwItemSpec - 1];
|
|
|
- open_strip_chart(0, collector, true);
|
|
|
-
|
|
|
- // Also open a strip chart for other threads with data for this
|
|
|
- // collector.
|
|
|
- const PStatClientData *client_data = get_client_data();
|
|
|
- for (int thread_index = 1; thread_index < client_data->get_num_threads(); ++thread_index) {
|
|
|
- PStatView &view = get_level_view(collector, thread_index);
|
|
|
- if (view.get_net_value() > 0.0) {
|
|
|
- open_strip_chart(thread_index, collector, true);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return TRUE;
|
|
|
- }
|
|
|
- else if (((LPNMHDR)lparam)->code == NM_RCLICK) {
|
|
|
- NMMOUSE &mouse = *(NMMOUSE *)lparam;
|
|
|
- if (mouse.dwItemSpec >= 1 &&
|
|
|
- mouse.dwItemSpec <= _status_bar_collectors.size()) {
|
|
|
- int collector = _status_bar_collectors[mouse.dwItemSpec - 1];
|
|
|
- show_popup_menu(collector);
|
|
|
+ for (WinStatsGraph *graph : _graphs) {
|
|
|
+ WINDOWPLACEMENT wp;
|
|
|
+ HWND window = graph->get_window();
|
|
|
+ if (GetWindowPlacement(window, &wp)) {
|
|
|
+ if (wp.showCmd == SW_SHOWMINIMIZED) {
|
|
|
+ // Keep the minimized window title bar glued to the bottom-left
|
|
|
+ // corner of the parent window.
|
|
|
+ wp.flags |= WPF_SETMINPOSITION;
|
|
|
+ wp.ptMinPosition.x = client_rect.left + iconic_offset;
|
|
|
+ wp.ptMinPosition.y = client_rect.bottom - height;
|
|
|
+ iconic_offset += metrics.iWidth + metrics.iHorzGap;
|
|
|
}
|
|
|
- }
|
|
|
- break;
|
|
|
|
|
|
- case WM_COMMAND:
|
|
|
- if (HIWORD(wparam) <= 1) {
|
|
|
- int menu_id = LOWORD(wparam);
|
|
|
- handle_menu_command(menu_id);
|
|
|
- return 0;
|
|
|
+ // Move the "restored" window (even when it's currently min/maximized).
|
|
|
+ wp.rcNormalPosition.left += delta_x;
|
|
|
+ wp.rcNormalPosition.top += delta_y;
|
|
|
+ wp.rcNormalPosition.right += delta_x;
|
|
|
+ wp.rcNormalPosition.bottom += delta_y;
|
|
|
+ SetWindowPlacement(window, &wp);
|
|
|
}
|
|
|
- break;
|
|
|
-
|
|
|
- default:
|
|
|
- break;
|
|
|
}
|
|
|
-
|
|
|
- return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- *
|
|
|
+ * Called when a menu item is clicked.
|
|
|
*/
|
|
|
void WinStatsMonitor::
|
|
|
handle_menu_command(int menu_id) {
|
|
|
@@ -999,14 +839,6 @@ handle_menu_command(int menu_id) {
|
|
|
case MI_none:
|
|
|
break;
|
|
|
|
|
|
- case MI_time_ms:
|
|
|
- set_time_units(PStatGraph::GBU_ms);
|
|
|
- break;
|
|
|
-
|
|
|
- case MI_time_hz:
|
|
|
- set_time_units(PStatGraph::GBU_hz);
|
|
|
- break;
|
|
|
-
|
|
|
case MI_speed_1:
|
|
|
set_scroll_speed(1);
|
|
|
break;
|
|
|
@@ -1031,6 +863,19 @@ handle_menu_command(int menu_id) {
|
|
|
set_pause(!_pause);
|
|
|
break;
|
|
|
|
|
|
+ case MI_graphs_close_all:
|
|
|
+ remove_all_graphs();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case MI_graphs_reopen_default:
|
|
|
+ remove_all_graphs();
|
|
|
+ open_default_graphs();
|
|
|
+ break;
|
|
|
+
|
|
|
+ case MI_graphs_save_default:
|
|
|
+ save_default_graphs();
|
|
|
+ break;
|
|
|
+
|
|
|
default:
|
|
|
if (menu_id >= MI_new_chart) {
|
|
|
const MenuDef &menu_def = lookup_menu(menu_id);
|
|
|
@@ -1055,3 +900,38 @@ handle_menu_command(int menu_id) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Called when a status bar item is double-clicked.
|
|
|
+ */
|
|
|
+void WinStatsMonitor::
|
|
|
+handle_status_bar_click(int item) {
|
|
|
+ if (item == 0) {
|
|
|
+ open_strip_chart(0, 0, false);
|
|
|
+ }
|
|
|
+ else if (item >= 1 && item <= _status_bar_collectors.size()) {
|
|
|
+ int collector = _status_bar_collectors[item - 1];
|
|
|
+ open_strip_chart(0, collector, true);
|
|
|
+
|
|
|
+ // Also open a strip chart for other threads with data for this
|
|
|
+ // collector.
|
|
|
+ const PStatClientData *client_data = get_client_data();
|
|
|
+ for (int thread_index = 1; thread_index < client_data->get_num_threads(); ++thread_index) {
|
|
|
+ PStatView &view = get_level_view(collector, thread_index);
|
|
|
+ if (view.get_net_value() > 0.0) {
|
|
|
+ open_strip_chart(thread_index, collector, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Called when a status bar item is right-clicked.
|
|
|
+ */
|
|
|
+void WinStatsMonitor::
|
|
|
+handle_status_bar_popup(int item) {
|
|
|
+ if (item >= 1 && item <= _status_bar_collectors.size()) {
|
|
|
+ int collector = _status_bar_collectors[item - 1];
|
|
|
+ show_popup_menu(collector);
|
|
|
+ }
|
|
|
+}
|