00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "winStatsGraph.h"
00016 #include "winStatsMonitor.h"
00017 #include "winStatsLabelStack.h"
00018
00019 bool WinStatsGraph::_graph_window_class_registered = false;
00020 const char * const WinStatsGraph::_graph_window_class_name = "graph";
00021
00022 DWORD WinStatsGraph::graph_window_style =
00023 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_VISIBLE;
00024
00025
00026
00027
00028
00029
00030 WinStatsGraph::
00031 WinStatsGraph(WinStatsMonitor *monitor) :
00032 _monitor(monitor)
00033 {
00034 _window = 0;
00035 _graph_window = 0;
00036 _sizewe_cursor = LoadCursor(NULL, IDC_SIZEWE);
00037 _hand_cursor = LoadCursor(NULL, IDC_HAND);
00038 _bitmap = 0;
00039 _bitmap_dc = 0;
00040
00041 _graph_left = 0;
00042 _graph_top = 0;
00043 _bitmap_xsize = 0;
00044 _bitmap_ysize = 0;
00045
00046 _dark_color = RGB(51, 51, 51);
00047 _light_color = RGB(154, 154, 154);
00048 _user_guide_bar_color = RGB(130, 150, 255);
00049 _dark_pen = CreatePen(PS_SOLID, 1, _dark_color);
00050 _light_pen = CreatePen(PS_SOLID, 1, _light_color);
00051 _user_guide_bar_pen = CreatePen(PS_DASH, 1, _user_guide_bar_color);
00052
00053 _drag_mode = DM_none;
00054 _potential_drag_mode = DM_none;
00055 _drag_scale_start = 0.0f;
00056
00057 _pause = false;
00058 }
00059
00060
00061
00062
00063
00064
00065 WinStatsGraph::
00066 ~WinStatsGraph() {
00067 _monitor = (WinStatsMonitor *)NULL;
00068 release_bitmap();
00069
00070 DeleteObject(_dark_pen);
00071 DeleteObject(_light_pen);
00072 DeleteObject(_user_guide_bar_pen);
00073
00074 Brushes::iterator bi;
00075 for (bi = _brushes.begin(); bi != _brushes.end(); ++bi) {
00076 HBRUSH brush = (*bi).second;
00077 DeleteObject(brush);
00078 }
00079
00080 if (_graph_window) {
00081 DestroyWindow(_graph_window);
00082 _graph_window = 0;
00083 }
00084
00085 if (_window) {
00086 DestroyWindow(_window);
00087 _window = 0;
00088 }
00089 }
00090
00091
00092
00093
00094
00095
00096
00097 void WinStatsGraph::
00098 new_collector(int new_collector) {
00099 }
00100
00101
00102
00103
00104
00105
00106 void WinStatsGraph::
00107 new_data(int thread_index, int frame_number) {
00108 }
00109
00110
00111
00112
00113
00114
00115 void WinStatsGraph::
00116 force_redraw() {
00117 }
00118
00119
00120
00121
00122
00123
00124
00125 void WinStatsGraph::
00126 changed_graph_size(int graph_xsize, int graph_ysize) {
00127 }
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 void WinStatsGraph::
00138 set_time_units(int unit_mask) {
00139 }
00140
00141
00142
00143
00144
00145
00146
00147
00148 void WinStatsGraph::
00149 set_scroll_speed(double scroll_speed) {
00150 }
00151
00152
00153
00154
00155
00156
00157
00158
00159 void WinStatsGraph::
00160 set_pause(bool pause) {
00161 _pause = pause;
00162 }
00163
00164
00165
00166
00167
00168
00169 void WinStatsGraph::
00170 user_guide_bars_changed() {
00171 InvalidateRect(_window, NULL, TRUE);
00172 InvalidateRect(_graph_window, NULL, TRUE);
00173 }
00174
00175
00176
00177
00178
00179
00180 void WinStatsGraph::
00181 clicked_label(int collector_index) {
00182 }
00183
00184
00185
00186
00187
00188
00189
00190 void WinStatsGraph::
00191 close() {
00192 WinStatsMonitor *monitor = _monitor;
00193 _monitor = (WinStatsMonitor *)NULL;
00194 if (monitor != (WinStatsMonitor *)NULL) {
00195 monitor->remove_graph(this);
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204
00205 void WinStatsGraph::
00206 setup_label_stack() {
00207 _label_stack.setup(_window);
00208 move_label_stack();
00209 }
00210
00211
00212
00213
00214
00215
00216
00217 void WinStatsGraph::
00218 move_label_stack() {
00219 if (_label_stack.is_setup()) {
00220 RECT rect;
00221 GetClientRect(_window, &rect);
00222
00223 rect.left += 8;
00224 rect.right = _left_margin - 8;
00225 rect.bottom -= _bottom_margin;
00226
00227 _label_stack.set_pos(rect.left, rect.top,
00228 rect.right - rect.left, rect.bottom - rect.top);
00229 }
00230 }
00231
00232
00233
00234
00235
00236
00237
00238 HBRUSH WinStatsGraph::
00239 get_collector_brush(int collector_index) {
00240 Brushes::iterator bi;
00241 bi = _brushes.find(collector_index);
00242 if (bi != _brushes.end()) {
00243 return (*bi).second;
00244 }
00245
00246
00247 LRGBColor rgb = _monitor->get_collector_color(collector_index);
00248 int r = (int)(rgb[0] * 255.0f);
00249 int g = (int)(rgb[1] * 255.0f);
00250 int b = (int)(rgb[2] * 255.0f);
00251 HBRUSH brush = CreateSolidBrush(RGB(r, g, b));
00252
00253 _brushes[collector_index] = brush;
00254 return brush;
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264 LONG WinStatsGraph::
00265 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00266 switch (msg) {
00267 case WM_DESTROY:
00268 close();
00269 break;
00270
00271 case WM_SIZE:
00272 move_label_stack();
00273 InvalidateRect(hwnd, NULL, TRUE);
00274 break;
00275
00276 case WM_SIZING:
00277 set_drag_mode(DM_sizing);
00278 break;
00279
00280 case WM_EXITSIZEMOVE:
00281 set_drag_mode(DM_none);
00282 break;
00283
00284 case WM_SETCURSOR:
00285 {
00286
00287
00288 POINT point;
00289 GetCursorPos(&point);
00290 WINDOWINFO winfo;
00291 GetWindowInfo(hwnd, &winfo);
00292 const RECT &rect = winfo.rcClient;
00293 int x = point.x - rect.left;
00294 int y = point.y - rect.top;
00295 int width = rect.right - rect.left;
00296 int height = rect.bottom - rect.top;
00297
00298 _potential_drag_mode = consider_drag_start(x, y, width, height);
00299
00300 switch (_potential_drag_mode) {
00301 case DM_left_margin:
00302 case DM_right_margin:
00303 SetCursor(_sizewe_cursor);
00304 return TRUE;
00305
00306 case DM_guide_bar:
00307 SetCursor(_hand_cursor);
00308 return TRUE;
00309
00310 default:
00311 case DM_none:
00312 break;
00313 }
00314 }
00315 break;
00316
00317 case WM_LBUTTONDOWN:
00318 if (_potential_drag_mode != DM_none) {
00319 set_drag_mode(_potential_drag_mode);
00320 _drag_start_x = (PN_int16)LOWORD(lparam);
00321 _drag_start_y = (PN_int16)HIWORD(lparam);
00322 SetCapture(_window);
00323 }
00324 return 0;
00325
00326 case WM_MOUSEMOVE:
00327 if (_drag_mode == DM_left_margin) {
00328 PN_int16 x = LOWORD(lparam);
00329 _left_margin += (x - _drag_start_x);
00330 _drag_start_x = x;
00331 InvalidateRect(hwnd, NULL, TRUE);
00332 move_label_stack();
00333 return 0;
00334
00335 } else if (_drag_mode == DM_right_margin) {
00336 PN_int16 x = LOWORD(lparam);
00337 _right_margin += (_drag_start_x - x);
00338 _drag_start_x = x;
00339 InvalidateRect(hwnd, NULL, TRUE);
00340 return 0;
00341 }
00342 break;
00343
00344 case WM_LBUTTONUP:
00345 set_drag_mode(DM_none);
00346 ReleaseCapture();
00347 break;
00348
00349 case WM_PAINT:
00350 {
00351 PAINTSTRUCT ps;
00352 HDC hdc = BeginPaint(hwnd, &ps);
00353
00354
00355 RECT rect;
00356 GetClientRect(hwnd, &rect);
00357
00358 rect.left += _left_margin;
00359 rect.top += _top_margin;
00360 rect.right -= _right_margin;
00361 rect.bottom -= _bottom_margin;
00362
00363 if (rect.right > rect.left && rect.bottom > rect.top) {
00364 DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
00365
00366 int graph_xsize = rect.right - rect.left;
00367 int graph_ysize = rect.bottom - rect.top;
00368 if (_bitmap_dc == 0 ||
00369 graph_xsize != _bitmap_xsize ||
00370 graph_ysize != _bitmap_ysize) {
00371
00372 changed_graph_size(graph_xsize, graph_ysize);
00373 move_graph_window(rect.left, rect.top, graph_xsize, graph_ysize);
00374 force_redraw();
00375 }
00376 }
00377
00378 additional_window_paint(hdc);
00379
00380 EndPaint(hwnd, &ps);
00381 return 0;
00382 }
00383
00384 default:
00385 break;
00386 }
00387
00388 return DefWindowProc(hwnd, msg, wparam, lparam);
00389 }
00390
00391
00392
00393
00394
00395
00396 LONG WinStatsGraph::
00397 graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00398 switch (msg) {
00399 case WM_DISPLAYCHANGE:
00400 setup_bitmap(_bitmap_xsize, _bitmap_ysize);
00401 force_redraw();
00402 break;
00403
00404 case WM_LBUTTONDOWN:
00405
00406
00407 if (_potential_drag_mode != DM_none) {
00408 PN_int16 x = LOWORD(lparam) + _graph_left;
00409 PN_int16 y = HIWORD(lparam) + _graph_top;
00410 return window_proc(_window, msg, wparam, MAKELPARAM(x, y));
00411 }
00412 break;
00413
00414 case WM_LBUTTONUP:
00415 set_drag_mode(DM_none);
00416 ReleaseCapture();
00417 break;
00418
00419 case WM_PAINT:
00420 {
00421
00422 PAINTSTRUCT ps;
00423 HDC hdc = BeginPaint(hwnd, &ps);
00424
00425 BitBlt(hdc, 0, 0,
00426 _bitmap_xsize, _bitmap_ysize,
00427 _bitmap_dc, 0, 0,
00428 SRCCOPY);
00429
00430 additional_graph_window_paint(hdc);
00431
00432 EndPaint(hwnd, &ps);
00433 return 0;
00434 }
00435
00436 default:
00437 break;
00438 }
00439
00440 return DefWindowProc(hwnd, msg, wparam, lparam);
00441 }
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 void WinStatsGraph::
00452 additional_window_paint(HDC hdc) {
00453 }
00454
00455
00456
00457
00458
00459
00460
00461
00462 void WinStatsGraph::
00463 additional_graph_window_paint(HDC hdc) {
00464 }
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 WinStatsGraph::DragMode WinStatsGraph::
00475 consider_drag_start(int mouse_x, int mouse_y, int width, int height) {
00476 if (mouse_x >= _left_margin - 2 && mouse_x <= _left_margin + 2) {
00477 return DM_left_margin;
00478 } else if (mouse_x >= width - _right_margin - 2 && mouse_x <= width - _right_margin + 2) {
00479 return DM_right_margin;
00480 }
00481
00482 return DM_none;
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492 void WinStatsGraph::
00493 set_drag_mode(WinStatsGraph::DragMode drag_mode) {
00494 _drag_mode = drag_mode;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503 void WinStatsGraph::
00504 move_graph_window(int graph_left, int graph_top, int graph_xsize, int graph_ysize) {
00505 if (_graph_window == 0) {
00506 create_graph_window();
00507 }
00508
00509 _graph_left = graph_left;
00510 _graph_top = graph_top;
00511
00512 SetWindowPos(_graph_window, 0,
00513 _graph_left, _graph_top,
00514 graph_xsize, graph_ysize,
00515 SWP_NOZORDER | SWP_SHOWWINDOW);
00516
00517 if (graph_xsize != _bitmap_xsize || graph_ysize != _bitmap_ysize) {
00518 setup_bitmap(graph_xsize, graph_ysize);
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527 void WinStatsGraph::
00528 setup_bitmap(int xsize, int ysize) {
00529 release_bitmap();
00530 _bitmap_xsize = max(xsize, 0);
00531 _bitmap_ysize = max(ysize, 0);
00532
00533 HDC hdc = GetDC(_graph_window);
00534 _bitmap_dc = CreateCompatibleDC(hdc);
00535 _bitmap = CreateCompatibleBitmap(hdc, _bitmap_xsize, _bitmap_ysize);
00536 SelectObject(_bitmap_dc, _bitmap);
00537
00538 RECT rect = { 0, 0, _bitmap_xsize, _bitmap_ysize };
00539 FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
00540
00541 ReleaseDC(_window, hdc);
00542 }
00543
00544
00545
00546
00547
00548
00549
00550 void WinStatsGraph::
00551 release_bitmap() {
00552 if (_bitmap) {
00553 DeleteObject(_bitmap);
00554 _bitmap = 0;
00555 }
00556 if (_bitmap_dc) {
00557 DeleteDC(_bitmap_dc);
00558 _bitmap_dc = 0;
00559 }
00560 }
00561
00562
00563
00564
00565
00566
00567 void WinStatsGraph::
00568 create_graph_window() {
00569 if (_graph_window) {
00570 return;
00571 }
00572
00573 HINSTANCE application = GetModuleHandle(NULL);
00574 register_graph_window_class(application);
00575
00576 string window_title = "graph";
00577 DWORD window_style = WS_CHILD | WS_CLIPSIBLINGS;
00578
00579 _graph_window =
00580 CreateWindow(_graph_window_class_name, window_title.c_str(), window_style,
00581 0, 0, 0, 0,
00582 _window, NULL, application, 0);
00583 if (!_graph_window) {
00584 nout << "Could not create graph window!\n";
00585 exit(1);
00586 }
00587
00588 SetWindowLongPtr(_graph_window, 0, (LONG_PTR)this);
00589 }
00590
00591
00592
00593
00594
00595
00596
00597 void WinStatsGraph::
00598 register_graph_window_class(HINSTANCE application) {
00599 if (_graph_window_class_registered) {
00600 return;
00601 }
00602
00603 WNDCLASS wc;
00604
00605 ZeroMemory(&wc, sizeof(WNDCLASS));
00606 wc.style = CS_DBLCLKS;
00607 wc.lpfnWndProc = (WNDPROC)static_graph_window_proc;
00608 wc.hInstance = application;
00609 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00610 wc.hbrBackground = NULL;
00611 wc.lpszMenuName = NULL;
00612 wc.lpszClassName = _graph_window_class_name;
00613
00614
00615 wc.cbWndExtra = sizeof(WinStatsGraph *);
00616
00617 if (!RegisterClass(&wc)) {
00618 nout << "Could not register graph window class!\n";
00619 exit(1);
00620 }
00621
00622 _graph_window_class_registered = true;
00623 }
00624
00625
00626
00627
00628
00629
00630 LONG WINAPI WinStatsGraph::
00631 static_graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00632 WinStatsGraph *self = (WinStatsGraph *)GetWindowLongPtr(hwnd, 0);
00633 if (self != (WinStatsGraph *)NULL && self->_graph_window == hwnd) {
00634 return self->graph_window_proc(hwnd, msg, wparam, lparam);
00635 } else {
00636 return DefWindowProc(hwnd, msg, wparam, lparam);
00637 }
00638 }