18 static const int default_piano_roll_width = 400;
19 static const int default_piano_roll_height = 200;
21 bool WinStatsPianoRoll::_window_class_registered =
false;
22 const char *
const WinStatsPianoRoll::_window_class_name =
"piano";
30 default_piano_roll_width,
31 default_piano_roll_height),
40 set_guide_bar_units(get_guide_bar_units() | GBU_show_units);
50 ~WinStatsPianoRoll() {
71 PStatPianoRoll::force_redraw();
79 PStatPianoRoll::changed_size(graph_xsize, graph_ysize);
89 int old_unit_mask = get_guide_bar_units();
90 if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) {
91 unit_mask = unit_mask & (GBU_hz | GBU_ms);
92 unit_mask |= (old_unit_mask & GBU_show_units);
93 set_guide_bar_units(unit_mask);
96 GetClientRect(_window, &rect);
97 rect.left = _right_margin;
98 InvalidateRect(_window, &rect, TRUE);
107 if (collector_index >= 0) {
108 WinStatsGraph::_monitor->
open_strip_chart(_thread_index, collector_index,
false);
121 GetClientRect(_window, &rect);
122 rect.bottom = _top_margin;
123 InvalidateRect(_window, &rect, TRUE);
129 void WinStatsPianoRoll::
131 RECT rect = { 0, 0, get_xsize(), get_ysize() };
132 FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
138 void WinStatsPianoRoll::
143 int num_guide_bars = get_num_guide_bars();
144 for (
int i = 0; i < num_guide_bars; i++) {
145 draw_guide_bar(_bitmap_dc, get_guide_bar(i));
152 void WinStatsPianoRoll::
153 draw_bar(
int row,
int from_x,
int to_x) {
154 if (row >= 0 && row < _label_stack.get_num_labels()) {
155 int y = _label_stack.get_label_y(row) - _graph_top;
156 int height = _label_stack.get_label_height(row);
159 from_x, y - height + 2,
162 int collector_index = get_label_collector(row);
163 HBRUSH brush = get_collector_brush(collector_index);
164 FillRect(_bitmap_dc, &rect, brush);
172 void WinStatsPianoRoll::
174 InvalidateRect(_graph_window,
nullptr, FALSE);
180 void WinStatsPianoRoll::
182 if (_labels_changed) {
190 LONG WinStatsPianoRoll::
191 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
194 if (_potential_drag_mode == DM_new_guide_bar) {
195 set_drag_mode(DM_new_guide_bar);
196 SetCapture(_graph_window);
205 return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam);
211 LONG WinStatsPianoRoll::
212 graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
215 if (_potential_drag_mode == DM_none) {
216 set_drag_mode(DM_scale);
217 int16_t x = LOWORD(lparam);
218 _drag_scale_start = pixel_to_height(x);
219 SetCapture(_graph_window);
222 }
else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) {
223 set_drag_mode(DM_guide_bar);
224 int16_t x = LOWORD(lparam);
226 SetCapture(_graph_window);
232 if (_drag_mode == DM_none && _potential_drag_mode == DM_none) {
234 int16_t x = LOWORD(lparam);
235 int16_t y = HIWORD(lparam);
236 _label_stack.highlight_label(get_collector_under_pixel(x, y));
240 TRACKMOUSEEVENT tme = {
241 sizeof(TRACKMOUSEEVENT),
246 TrackMouseEvent(&tme);
250 _label_stack.highlight_label(-1);
253 if (_drag_mode == DM_scale) {
254 int16_t x = LOWORD(lparam);
255 double ratio = (double)x / (
double)get_xsize();
257 set_horizontal_scale(_drag_scale_start / ratio);
261 }
else if (_drag_mode == DM_new_guide_bar) {
264 int16_t x = LOWORD(lparam);
265 if (x >= 0 && x < get_xsize()) {
266 set_drag_mode(DM_guide_bar);
267 _drag_guide_bar = add_user_guide_bar(pixel_to_height(x));
271 }
else if (_drag_mode == DM_guide_bar) {
272 int16_t x = LOWORD(lparam);
273 move_user_guide_bar(_drag_guide_bar, pixel_to_height(x));
280 _label_stack.highlight_label(-1);
284 if (_drag_mode == DM_scale) {
285 set_drag_mode(DM_none);
289 }
else if (_drag_mode == DM_guide_bar) {
290 int16_t x = LOWORD(lparam);
291 if (x < 0 || x >= get_xsize()) {
292 remove_user_guide_bar(_drag_guide_bar);
294 move_user_guide_bar(_drag_guide_bar, pixel_to_height(x));
296 set_drag_mode(DM_none);
302 case WM_LBUTTONDBLCLK:
306 int16_t x = LOWORD(lparam);
307 int16_t y = HIWORD(lparam);
317 return WinStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam);
325 void WinStatsPianoRoll::
326 additional_window_paint(HDC hdc) {
328 HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT);
329 SelectObject(hdc, hfnt);
330 SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
331 SetBkMode(hdc, TRANSPARENT);
336 int num_guide_bars = get_num_guide_bars();
337 for (i = 0; i < num_guide_bars; i++) {
338 draw_guide_label(hdc, y, get_guide_bar(i));
341 int num_user_guide_bars = get_num_user_guide_bars();
342 for (i = 0; i < num_user_guide_bars; i++) {
343 draw_guide_label(hdc, y, get_user_guide_bar(i));
352 void WinStatsPianoRoll::
353 additional_graph_window_paint(HDC hdc) {
354 int num_user_guide_bars = get_num_user_guide_bars();
355 for (
int i = 0; i < num_user_guide_bars; i++) {
356 draw_guide_bar(hdc, get_user_guide_bar(i));
365 WinStatsGraph::DragMode WinStatsPianoRoll::
366 consider_drag_start(
int mouse_x,
int mouse_y,
int width,
int height) {
367 if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) {
368 if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) {
370 int x = mouse_x - _graph_left;
371 double from_height = pixel_to_height(x - 2);
372 double to_height = pixel_to_height(x + 2);
373 _drag_guide_bar = find_user_guide_bar(from_height, to_height);
374 if (_drag_guide_bar >= 0) {
378 }
else if (mouse_x < _left_margin - 2 ||
379 mouse_x > width - _right_margin + 2) {
382 return DM_new_guide_bar;
386 return WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height);
393 int WinStatsPianoRoll::
394 get_collector_under_pixel(
int xpoint,
int ypoint) {
395 if (_label_stack.get_num_labels() == 0) {
400 int height = _label_stack.get_label_height(0);
401 int row = (get_ysize() - ypoint) / height;
402 if (row >= 0 && row < _label_stack.get_num_labels()) {
403 return _label_stack.get_label_collector_index(row);
412 void WinStatsPianoRoll::
414 _label_stack.clear_labels();
415 for (
int i = 0; i < get_num_labels(); i++) {
417 _label_stack.add_label(WinStatsGraph::_monitor,
this,
419 get_label_collector(i),
true);
421 _labels_changed =
false;
427 void WinStatsPianoRoll::
429 int x = height_to_pixel(bar._height);
431 if (x > 0 && x < get_xsize() - 1) {
433 switch (bar._style) {
435 SelectObject(hdc, _light_pen);
439 SelectObject(hdc, _user_guide_bar_pen);
443 SelectObject(hdc, _dark_pen);
446 MoveToEx(hdc, x, 0,
nullptr);
447 LineTo(hdc, x, get_ysize());
454 void WinStatsPianoRoll::
456 switch (bar._style) {
458 SetTextColor(hdc, _light_color);
462 SetTextColor(hdc, _user_guide_bar_color);
466 SetTextColor(hdc, _dark_color);
470 int x = height_to_pixel(bar._height);
471 const std::string &label = bar._label;
473 GetTextExtentPoint32(hdc, label.data(), label.length(), &size);
475 if (bar._style != GBS_user) {
476 double from_height = pixel_to_height(x - size.cx);
477 double to_height = pixel_to_height(x + size.cx);
478 if (find_user_guide_bar(from_height, to_height) >= 0) {
484 int this_x = _graph_left + x - size.cx / 2;
485 if (x >= 0 && x < get_xsize()) {
486 TextOut(hdc, this_x, y,
487 label.data(), label.length());
494 void WinStatsPianoRoll::
500 HINSTANCE application = GetModuleHandle(
nullptr);
501 register_window_class(application);
506 std::string window_title = thread_name +
" thread piano roll";
511 _left_margin + get_xsize() + _right_margin,
512 _top_margin + get_ysize() + _bottom_margin
516 AdjustWindowRect(&win_rect, graph_window_style, FALSE);
519 CreateWindow(_window_class_name, window_title.c_str(), graph_window_style,
520 CW_USEDEFAULT, CW_USEDEFAULT,
521 win_rect.right - win_rect.left,
522 win_rect.bottom - win_rect.top,
523 WinStatsGraph::_monitor->
get_window(),
nullptr, application, 0);
525 nout <<
"Could not create PianoRoll window!\n";
529 SetWindowLongPtr(_window, 0, (LONG_PTR)
this);
533 SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0,
534 SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
541 void WinStatsPianoRoll::
542 register_window_class(HINSTANCE application) {
543 if (_window_class_registered) {
549 ZeroMemory(&wc,
sizeof(WNDCLASS));
551 wc.lpfnWndProc = (WNDPROC)static_window_proc;
552 wc.hInstance = application;
553 wc.hCursor = LoadCursor(
nullptr, IDC_ARROW);
554 wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
555 wc.lpszMenuName =
nullptr;
556 wc.lpszClassName = _window_class_name;
561 if (!RegisterClass(&wc)) {
562 nout <<
"Could not register PianoRoll window class!\n";
566 _window_class_registered =
true;
572 LONG WINAPI WinStatsPianoRoll::
573 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
575 if (
self !=
nullptr && self->_window == hwnd) {
576 return self->window_proc(hwnd, msg, wparam, lparam);
578 return DefWindowProc(hwnd, msg, wparam, lparam);
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is an abstract class that presents the interface for drawing a piano- roll type chart: it shows ...
void set_horizontal_scale(double time_width)
Changes the amount of time the width of the horizontal axis represents.
The data associated with a particular client, but not with any one particular frame or thread: the li...
void open_strip_chart(int thread_index, int collector_index, bool show_level)
Opens a new strip chart showing the indicated data.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void new_data(int thread_index, int frame_number)
Called as each frame's data is made available.
virtual void force_redraw()
Called when it is necessary to redraw the entire graph.
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void changed_graph_size(int graph_xsize, int graph_ysize)
Called when the user has resized the window, forcing a resize of the graph.
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 class represents a connection to a PStatsClient and manages the data exchange with the client.
A window that draws a piano-roll style chart, which shows the collectors explicitly stopping and star...
void set_horizontal_scale(double time_width)
Changes the amount of time the width of the horizontal axis represents.
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
HWND get_window() const
Returns the window handle to the monitor's window.
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.
std::string get_thread_name(int index) const
Returns the name of the indicated thread.