00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "winStatsPianoRoll.h"
00016 #include "winStatsMonitor.h"
00017 #include "numeric_types.h"
00018
00019 static const int default_piano_roll_width = 400;
00020 static const int default_piano_roll_height = 200;
00021
00022 bool WinStatsPianoRoll::_window_class_registered = false;
00023 const char * const WinStatsPianoRoll::_window_class_name = "piano";
00024
00025
00026
00027
00028
00029
00030 WinStatsPianoRoll::
00031 WinStatsPianoRoll(WinStatsMonitor *monitor, int thread_index) :
00032 PStatPianoRoll(monitor, thread_index,
00033 default_piano_roll_width,
00034 default_piano_roll_height),
00035 WinStatsGraph(monitor)
00036 {
00037 _left_margin = 128;
00038 _right_margin = 8;
00039 _top_margin = 16;
00040 _bottom_margin = 8;
00041
00042
00043 set_guide_bar_units(get_guide_bar_units() | GBU_show_units);
00044
00045 create_window();
00046 clear_region();
00047 }
00048
00049
00050
00051
00052
00053
00054 WinStatsPianoRoll::
00055 ~WinStatsPianoRoll() {
00056 }
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 void WinStatsPianoRoll::
00068 new_data(int thread_index, int frame_number) {
00069 if (!_pause) {
00070 update();
00071 }
00072 }
00073
00074
00075
00076
00077
00078
00079 void WinStatsPianoRoll::
00080 force_redraw() {
00081 PStatPianoRoll::force_redraw();
00082 }
00083
00084
00085
00086
00087
00088
00089
00090 void WinStatsPianoRoll::
00091 changed_graph_size(int graph_xsize, int graph_ysize) {
00092 PStatPianoRoll::changed_size(graph_xsize, graph_ysize);
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 void WinStatsPianoRoll::
00104 set_time_units(int unit_mask) {
00105 int old_unit_mask = get_guide_bar_units();
00106 if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) {
00107 unit_mask = unit_mask & (GBU_hz | GBU_ms);
00108 unit_mask |= (old_unit_mask & GBU_show_units);
00109 set_guide_bar_units(unit_mask);
00110
00111 RECT rect;
00112 GetClientRect(_window, &rect);
00113 rect.left = _right_margin;
00114 InvalidateRect(_window, &rect, TRUE);
00115 }
00116 }
00117
00118
00119
00120
00121
00122
00123 void WinStatsPianoRoll::
00124 clicked_label(int collector_index) {
00125 if (collector_index >= 0) {
00126 WinStatsGraph::_monitor->open_strip_chart(_thread_index, collector_index, false);
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135
00136 void WinStatsPianoRoll::
00137 set_horizontal_scale(double time_width) {
00138 PStatPianoRoll::set_horizontal_scale(time_width);
00139
00140 RECT rect;
00141 GetClientRect(_window, &rect);
00142 rect.bottom = _top_margin;
00143 InvalidateRect(_window, &rect, TRUE);
00144 }
00145
00146
00147
00148
00149
00150
00151 void WinStatsPianoRoll::
00152 clear_region() {
00153 RECT rect = { 0, 0, get_xsize(), get_ysize() };
00154 FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
00155 }
00156
00157
00158
00159
00160
00161
00162
00163 void WinStatsPianoRoll::
00164 begin_draw() {
00165 clear_region();
00166
00167
00168 int num_guide_bars = get_num_guide_bars();
00169 for (int i = 0; i < num_guide_bars; i++) {
00170 draw_guide_bar(_bitmap_dc, get_guide_bar(i));
00171 }
00172 }
00173
00174
00175
00176
00177
00178
00179 void WinStatsPianoRoll::
00180 draw_bar(int row, int from_x, int to_x) {
00181 if (row >= 0 && row < _label_stack.get_num_labels()) {
00182 int y = _label_stack.get_label_y(row) - _graph_top;
00183 int height = _label_stack.get_label_height(row);
00184
00185 RECT rect = {
00186 from_x, y - height + 2,
00187 to_x, y - 2,
00188 };
00189 int collector_index = get_label_collector(row);
00190 HBRUSH brush = get_collector_brush(collector_index);
00191 FillRect(_bitmap_dc, &rect, brush);
00192 }
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 void WinStatsPianoRoll::
00202 end_draw() {
00203 InvalidateRect(_graph_window, NULL, FALSE);
00204 }
00205
00206
00207
00208
00209
00210
00211 void WinStatsPianoRoll::
00212 idle() {
00213 if (_labels_changed) {
00214 update_labels();
00215 }
00216 }
00217
00218
00219
00220
00221
00222
00223 LONG WinStatsPianoRoll::
00224 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00225 switch (msg) {
00226 case WM_LBUTTONDOWN:
00227 if (_potential_drag_mode == DM_new_guide_bar) {
00228 set_drag_mode(DM_new_guide_bar);
00229 SetCapture(_graph_window);
00230 return 0;
00231 }
00232 break;
00233
00234 default:
00235 break;
00236 }
00237
00238 return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam);
00239 }
00240
00241
00242
00243
00244
00245
00246 LONG WinStatsPianoRoll::
00247 graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00248 switch (msg) {
00249 case WM_LBUTTONDOWN:
00250 if (_potential_drag_mode == DM_none) {
00251 set_drag_mode(DM_scale);
00252 PN_int16 x = LOWORD(lparam);
00253 _drag_scale_start = pixel_to_height(x);
00254 SetCapture(_graph_window);
00255 return 0;
00256
00257 } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) {
00258 set_drag_mode(DM_guide_bar);
00259 PN_int16 x = LOWORD(lparam);
00260 _drag_start_x = x;
00261 SetCapture(_graph_window);
00262 return 0;
00263 }
00264 break;
00265
00266 case WM_MOUSEMOVE:
00267 if (_drag_mode == DM_none && _potential_drag_mode == DM_none) {
00268
00269 PN_int16 x = LOWORD(lparam);
00270 PN_int16 y = HIWORD(lparam);
00271 _label_stack.highlight_label(get_collector_under_pixel(x, y));
00272
00273
00274
00275 TRACKMOUSEEVENT tme = {
00276 sizeof(TRACKMOUSEEVENT),
00277 TME_LEAVE,
00278 _graph_window,
00279 0
00280 };
00281 TrackMouseEvent(&tme);
00282
00283 } else {
00284
00285 _label_stack.highlight_label(-1);
00286 }
00287
00288 if (_drag_mode == DM_scale) {
00289 PN_int16 x = LOWORD(lparam);
00290 double ratio = (double)x / (double)get_xsize();
00291 if (ratio > 0.0f) {
00292 set_horizontal_scale(_drag_scale_start / ratio);
00293 }
00294 return 0;
00295
00296 } else if (_drag_mode == DM_new_guide_bar) {
00297
00298
00299 PN_int16 x = LOWORD(lparam);
00300 if (x >= 0 && x < get_xsize()) {
00301 set_drag_mode(DM_guide_bar);
00302 _drag_guide_bar = add_user_guide_bar(pixel_to_height(x));
00303 return 0;
00304 }
00305
00306 } else if (_drag_mode == DM_guide_bar) {
00307 PN_int16 x = LOWORD(lparam);
00308 move_user_guide_bar(_drag_guide_bar, pixel_to_height(x));
00309 return 0;
00310 }
00311 break;
00312
00313 case WM_MOUSELEAVE:
00314
00315 _label_stack.highlight_label(-1);
00316 break;
00317
00318 case WM_LBUTTONUP:
00319 if (_drag_mode == DM_scale) {
00320 set_drag_mode(DM_none);
00321 ReleaseCapture();
00322 return 0;
00323
00324 } else if (_drag_mode == DM_guide_bar) {
00325 PN_int16 x = LOWORD(lparam);
00326 if (x < 0 || x >= get_xsize()) {
00327 remove_user_guide_bar(_drag_guide_bar);
00328 } else {
00329 move_user_guide_bar(_drag_guide_bar, pixel_to_height(x));
00330 }
00331 set_drag_mode(DM_none);
00332 ReleaseCapture();
00333 return 0;
00334 }
00335 break;
00336
00337 case WM_LBUTTONDBLCLK:
00338 {
00339
00340
00341 PN_int16 x = LOWORD(lparam);
00342 PN_int16 y = HIWORD(lparam);
00343 clicked_label(get_collector_under_pixel(x, y));
00344 return 0;
00345 }
00346 break;
00347
00348 default:
00349 break;
00350 }
00351
00352 return WinStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam);
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 void WinStatsPianoRoll::
00364 additional_window_paint(HDC hdc) {
00365
00366 HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT);
00367 SelectObject(hdc, hfnt);
00368 SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
00369 SetBkMode(hdc, TRANSPARENT);
00370
00371 int y = _top_margin;
00372
00373 int i;
00374 int num_guide_bars = get_num_guide_bars();
00375 for (i = 0; i < num_guide_bars; i++) {
00376 draw_guide_label(hdc, y, get_guide_bar(i));
00377 }
00378
00379 int num_user_guide_bars = get_num_user_guide_bars();
00380 for (i = 0; i < num_user_guide_bars; i++) {
00381 draw_guide_label(hdc, y, get_user_guide_bar(i));
00382 }
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393 void WinStatsPianoRoll::
00394 additional_graph_window_paint(HDC hdc) {
00395 int num_user_guide_bars = get_num_user_guide_bars();
00396 for (int i = 0; i < num_user_guide_bars; i++) {
00397 draw_guide_bar(hdc, get_user_guide_bar(i));
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 WinStatsGraph::DragMode WinStatsPianoRoll::
00410 consider_drag_start(int mouse_x, int mouse_y, int width, int height) {
00411 if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) {
00412 if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) {
00413
00414 int x = mouse_x - _graph_left;
00415 double from_height = pixel_to_height(x - 2);
00416 double to_height = pixel_to_height(x + 2);
00417 _drag_guide_bar = find_user_guide_bar(from_height, to_height);
00418 if (_drag_guide_bar >= 0) {
00419 return DM_guide_bar;
00420 }
00421
00422 } else if (mouse_x < _left_margin - 2 ||
00423 mouse_x > width - _right_margin + 2) {
00424
00425
00426 return DM_new_guide_bar;
00427 }
00428 }
00429
00430 return WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height);
00431 }
00432
00433
00434
00435
00436
00437
00438
00439 int WinStatsPianoRoll::
00440 get_collector_under_pixel(int xpoint, int ypoint) {
00441 if (_label_stack.get_num_labels() == 0) {
00442 return -1;
00443 }
00444
00445
00446 int height = _label_stack.get_label_height(0);
00447 int row = (get_ysize() - ypoint) / height;
00448 if (row >= 0 && row < _label_stack.get_num_labels()) {
00449 return _label_stack.get_label_collector_index(row);
00450 } else {
00451 return -1;
00452 }
00453 }
00454
00455
00456
00457
00458
00459
00460 void WinStatsPianoRoll::
00461 update_labels() {
00462 _label_stack.clear_labels();
00463 for (int i = 0; i < get_num_labels(); i++) {
00464 int label_index =
00465 _label_stack.add_label(WinStatsGraph::_monitor, this,
00466 _thread_index,
00467 get_label_collector(i), true);
00468 }
00469 _labels_changed = false;
00470 }
00471
00472
00473
00474
00475
00476
00477
00478 void WinStatsPianoRoll::
00479 draw_guide_bar(HDC hdc, const PStatGraph::GuideBar &bar) {
00480 int x = height_to_pixel(bar._height);
00481
00482 if (x > 0 && x < get_xsize() - 1) {
00483
00484 switch (bar._style) {
00485 case GBS_target:
00486 SelectObject(hdc, _light_pen);
00487 break;
00488
00489 case GBS_user:
00490 SelectObject(hdc, _user_guide_bar_pen);
00491 break;
00492
00493 case GBS_normal:
00494 SelectObject(hdc, _dark_pen);
00495 break;
00496 }
00497 MoveToEx(hdc, x, 0, NULL);
00498 LineTo(hdc, x, get_ysize());
00499 }
00500 }
00501
00502
00503
00504
00505
00506
00507
00508 void WinStatsPianoRoll::
00509 draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar) {
00510 switch (bar._style) {
00511 case GBS_target:
00512 SetTextColor(hdc, _light_color);
00513 break;
00514
00515 case GBS_user:
00516 SetTextColor(hdc, _user_guide_bar_color);
00517 break;
00518
00519 case GBS_normal:
00520 SetTextColor(hdc, _dark_color);
00521 break;
00522 }
00523
00524 int x = height_to_pixel(bar._height);
00525 const string &label = bar._label;
00526 SIZE size;
00527 GetTextExtentPoint32(hdc, label.data(), label.length(), &size);
00528
00529 if (bar._style != GBS_user) {
00530 double from_height = pixel_to_height(x - size.cx);
00531 double to_height = pixel_to_height(x + size.cx);
00532 if (find_user_guide_bar(from_height, to_height) >= 0) {
00533
00534 return;
00535 }
00536 }
00537
00538 int this_x = _graph_left + x - size.cx / 2;
00539 if (x >= 0 && x < get_xsize()) {
00540 TextOut(hdc, this_x, y,
00541 label.data(), label.length());
00542 }
00543 }
00544
00545
00546
00547
00548
00549
00550 void WinStatsPianoRoll::
00551 create_window() {
00552 if (_window) {
00553 return;
00554 }
00555
00556 HINSTANCE application = GetModuleHandle(NULL);
00557 register_window_class(application);
00558
00559 const PStatClientData *client_data =
00560 WinStatsGraph::_monitor->get_client_data();
00561 string thread_name = client_data->get_thread_name(_thread_index);
00562 string window_title = thread_name + " thread piano roll";
00563
00564
00565 RECT win_rect = {
00566 0, 0,
00567 _left_margin + get_xsize() + _right_margin,
00568 _top_margin + get_ysize() + _bottom_margin
00569 };
00570
00571
00572 AdjustWindowRect(&win_rect, graph_window_style, FALSE);
00573
00574 _window =
00575 CreateWindow(_window_class_name, window_title.c_str(), graph_window_style,
00576 CW_USEDEFAULT, CW_USEDEFAULT,
00577 win_rect.right - win_rect.left,
00578 win_rect.bottom - win_rect.top,
00579 WinStatsGraph::_monitor->get_window(), NULL, application, 0);
00580 if (!_window) {
00581 nout << "Could not create PianoRoll window!\n";
00582 exit(1);
00583 }
00584
00585 SetWindowLongPtr(_window, 0, (LONG_PTR)this);
00586 setup_label_stack();
00587
00588
00589 SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0,
00590 SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
00591 }
00592
00593
00594
00595
00596
00597
00598
00599 void WinStatsPianoRoll::
00600 register_window_class(HINSTANCE application) {
00601 if (_window_class_registered) {
00602 return;
00603 }
00604
00605 WNDCLASS wc;
00606
00607 ZeroMemory(&wc, sizeof(WNDCLASS));
00608 wc.style = 0;
00609 wc.lpfnWndProc = (WNDPROC)static_window_proc;
00610 wc.hInstance = application;
00611 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00612 wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
00613 wc.lpszMenuName = NULL;
00614 wc.lpszClassName = _window_class_name;
00615
00616
00617 wc.cbWndExtra = sizeof(WinStatsPianoRoll *);
00618
00619 if (!RegisterClass(&wc)) {
00620 nout << "Could not register PianoRoll window class!\n";
00621 exit(1);
00622 }
00623
00624 _window_class_registered = true;
00625 }
00626
00627
00628
00629
00630
00631
00632 LONG WINAPI WinStatsPianoRoll::
00633 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
00634 WinStatsPianoRoll *self = (WinStatsPianoRoll *)GetWindowLongPtr(hwnd, 0);
00635 if (self != (WinStatsPianoRoll *)NULL && self->_window == hwnd) {
00636 return self->window_proc(hwnd, msg, wparam, lparam);
00637 } else {
00638 return DefWindowProc(hwnd, msg, wparam, lparam);
00639 }
00640 }