Panda3D
winStatsStripChart.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file winStatsStripChart.cxx
10  * @author drose
11  * @date 2003-12-03
12  */
13 
14 #include "winStatsStripChart.h"
15 #include "winStatsMonitor.h"
16 #include "pStatCollectorDef.h"
17 #include "numeric_types.h"
18 
19 using std::string;
20 
21 static const int default_strip_chart_width = 400;
22 static const int default_strip_chart_height = 100;
23 
24 // Surely we aren't expected to hardcode the size of a normal checkbox. But
25 // Windows seems to require this data to be passed to CreateWindow(), so what
26 // else can I do?
27 size_t WinStatsStripChart::_check_box_height = 13;
28 size_t WinStatsStripChart::_check_box_width = 13;
29 
30 bool WinStatsStripChart::_window_class_registered = false;
31 const char * const WinStatsStripChart::_window_class_name = "strip";
32 
33 /**
34  *
35  */
36 WinStatsStripChart::
37 WinStatsStripChart(WinStatsMonitor *monitor, int thread_index,
38  int collector_index, bool show_level) :
39  PStatStripChart(monitor,
40  show_level ? monitor->get_level_view(collector_index, thread_index) : monitor->get_view(thread_index),
41  thread_index,
42  collector_index,
43  default_strip_chart_width,
44  default_strip_chart_height),
45  WinStatsGraph(monitor)
46 {
47  _brush_origin = 0;
48 
49  _left_margin = 96;
50  _right_margin = 32;
51  _top_margin = 16;
52  _bottom_margin = 8;
53 
54  if (show_level) {
55  // If it's a level-type graph, show the appropriate units.
56  if (_unit_name.empty()) {
57  set_guide_bar_units(GBU_named);
58  } else {
59  set_guide_bar_units(GBU_named | GBU_show_units);
60  }
61 
62  } else {
63  // If it's a time-type graph, show the msHz units.
64  set_guide_bar_units(get_guide_bar_units() | GBU_show_units);
65  }
66 
67  _smooth_check_box = 0;
68 
69  create_window();
70  clear_region();
71 }
72 
73 /**
74  *
75  */
76 WinStatsStripChart::
77 ~WinStatsStripChart() {
78 }
79 
80 /**
81  * Called whenever a new Collector definition is received from the client.
82  */
84 new_collector(int collector_index) {
85  WinStatsGraph::new_collector(collector_index);
86 }
87 
88 /**
89  * Called as each frame's data is made available. There is no gurantee the
90  * frames will arrive in order, or that all of them will arrive at all. The
91  * monitor should be prepared to accept frames received out-of-order or
92  * missing.
93  */
95 new_data(int thread_index, int frame_number) {
96  if (is_title_unknown()) {
97  string window_title = get_title_text();
98  if (!is_title_unknown()) {
99  SetWindowText(_window, window_title.c_str());
100  }
101  }
102 
103  if (!_pause) {
104  update();
105 
106  string text = format_number(get_average_net_value(), get_guide_bar_units(), get_guide_bar_unit_name());
107  if (_net_value_text != text) {
108  _net_value_text = text;
109  RECT rect;
110  GetClientRect(_window, &rect);
111  rect.bottom = _top_margin;
112  InvalidateRect(_window, &rect, TRUE);
113  }
114  }
115 }
116 
117 /**
118  * Called when it is necessary to redraw the entire graph.
119  */
122  PStatStripChart::force_redraw();
123 }
124 
125 /**
126  * Called when the user has resized the window, forcing a resize of the graph.
127  */
129 changed_graph_size(int graph_xsize, int graph_ysize) {
130  PStatStripChart::changed_size(graph_xsize, graph_ysize);
131 }
132 
133 /**
134  * Called when the user selects a new time units from the monitor pulldown
135  * menu, this should adjust the units for the graph to the indicated mask if
136  * it is a time-based graph.
137  */
139 set_time_units(int unit_mask) {
140  int old_unit_mask = get_guide_bar_units();
141  if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) {
142  unit_mask = unit_mask & (GBU_hz | GBU_ms);
143  unit_mask |= (old_unit_mask & GBU_show_units);
144  set_guide_bar_units(unit_mask);
145 
146  RECT rect;
147  GetClientRect(_window, &rect);
148  rect.left = _right_margin;
149  InvalidateRect(_window, &rect, TRUE);
150 
151  GetClientRect(_window, &rect);
152  rect.bottom = _top_margin;
153  InvalidateRect(_window, &rect, TRUE);
154  }
155 }
156 
157 /**
158  * Called when the user selects a new scroll speed from the monitor pulldown
159  * menu, this should adjust the speed for the graph to the indicated value.
160  */
162 set_scroll_speed(double scroll_speed) {
163  // The speed factor indicates chart widths per minute.
164  if (scroll_speed != 0.0f) {
165  set_horizontal_scale(60.0f / scroll_speed);
166  }
167 }
168 
169 /**
170  * Called when the user single-clicks on a label.
171  */
173 clicked_label(int collector_index) {
174  if (collector_index < 0) {
175  // Clicking on whitespace in the graph is the same as clicking on the top
176  // label.
177  collector_index = get_collector_index();
178  }
179 
180  if (collector_index == get_collector_index() && collector_index != 0) {
181  // Clicking on the top label means to go up to the parent level.
182  const PStatClientData *client_data =
183  WinStatsGraph::_monitor->get_client_data();
184  if (client_data->has_collector(collector_index)) {
185  const PStatCollectorDef &def =
186  client_data->get_collector_def(collector_index);
187  if (def._parent_index == 0 && get_view().get_show_level()) {
188  // Unless the parent is "Frame", and we're not a time collector.
189  } else {
190  set_collector_index(def._parent_index);
191  }
192  }
193 
194  } else {
195  // Clicking on any other label means to focus on that.
196  set_collector_index(collector_index);
197  }
198 }
199 
200 /**
201  * Changes the value the height of the vertical axis represents. This may
202  * force a redraw.
203  */
205 set_vertical_scale(double value_height) {
207 
208  RECT rect;
209  GetClientRect(_window, &rect);
210  rect.left = _right_margin;
211  InvalidateRect(_window, &rect, TRUE);
212 }
213 
214 /**
215  * Resets the list of labels.
216  */
217 void WinStatsStripChart::
218 update_labels() {
219  PStatStripChart::update_labels();
220 
221  _label_stack.clear_labels();
222  for (int i = 0; i < get_num_labels(); i++) {
223  _label_stack.add_label(WinStatsGraph::_monitor, this, _thread_index,
224  get_label_collector(i), false);
225  }
226  _labels_changed = false;
227 }
228 
229 /**
230  * Erases the chart area.
231  */
232 void WinStatsStripChart::
233 clear_region() {
234  RECT rect = { 0, 0, get_xsize(), get_ysize() };
235  FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
236 }
237 
238 /**
239  * Should be overridden by the user class to copy a region of the chart from
240  * one part of the chart to another. This is used to implement scrolling.
241  */
242 void WinStatsStripChart::
243 copy_region(int start_x, int end_x, int dest_x) {
244  BitBlt(_bitmap_dc, dest_x, 0,
245  end_x - start_x, get_ysize(),
246  _bitmap_dc, start_x, 0,
247  SRCCOPY);
248 
249  // Also shift the brush origin over, so we still get proper dithering.
250  _brush_origin += (dest_x - start_x);
251  SetBrushOrgEx(_bitmap_dc, _brush_origin, 0, nullptr);
252 
253  RECT rect = {
254  dest_x, 0, dest_x + end_x - start_x, get_ysize()
255  };
256  InvalidateRect(_graph_window, &rect, FALSE);
257 }
258 
259 /**
260  * Draws a single vertical slice of the strip chart, at the given pixel
261  * position, and corresponding to the indicated level data.
262  */
263 void WinStatsStripChart::
264 draw_slice(int x, int w, const PStatStripChart::FrameData &fdata) {
265  // Start by clearing the band first.
266  RECT rect = { x, 0, x + w, get_ysize() };
267  FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
268 
269  double overall_time = 0.0;
270  int y = get_ysize();
271 
272  FrameData::const_iterator fi;
273  for (fi = fdata.begin(); fi != fdata.end(); ++fi) {
274  const ColorData &cd = (*fi);
275  overall_time += cd._net_value;
276  HBRUSH brush = get_collector_brush(cd._collector_index);
277 
278  if (overall_time > get_vertical_scale()) {
279  // Off the top. Go ahead and clamp it by hand, in case it's so far off
280  // the top we'd overflow the 16-bit pixel value.
281  rect.top = 0;
282  rect.bottom = y;
283  FillRect(_bitmap_dc, &rect, brush);
284  // And we can consider ourselves done now.
285  return;
286  }
287 
288  int top_y = height_to_pixel(overall_time);
289  rect.top = top_y;
290  rect.bottom = y;
291  FillRect(_bitmap_dc, &rect, brush);
292  y = top_y;
293  }
294 }
295 
296 /**
297  * Draws a single vertical slice of background color.
298  */
299 void WinStatsStripChart::
300 draw_empty(int x, int w) {
301  RECT rect = { x, 0, x + w, get_ysize() };
302  FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
303 }
304 
305 /**
306  * Draws a single vertical slice of foreground color.
307  */
308 void WinStatsStripChart::
309 draw_cursor(int x) {
310  RECT rect = { x, 0, x + 1, get_ysize() };
311  FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
312 }
313 
314 /**
315  * Should be overridden by the user class. This hook will be called after
316  * drawing a series of color bars in the strip chart; it gives the pixel range
317  * that was just redrawn.
318  */
319 void WinStatsStripChart::
320 end_draw(int from_x, int to_x) {
321  // Draw in the guide bars.
322  int num_guide_bars = get_num_guide_bars();
323  for (int i = 0; i < num_guide_bars; i++) {
324  draw_guide_bar(_bitmap_dc, from_x, to_x, get_guide_bar(i));
325  }
326 
327  RECT rect = {
328  from_x, 0, to_x + 1, get_ysize()
329  };
330  InvalidateRect(_graph_window, &rect, FALSE);
331 }
332 
333 /**
334  *
335  */
336 LONG WinStatsStripChart::
337 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
338  switch (msg) {
339  case WM_LBUTTONDOWN:
340  if (_potential_drag_mode == DM_new_guide_bar) {
341  set_drag_mode(DM_new_guide_bar);
342  SetCapture(_graph_window);
343  return 0;
344  }
345  break;
346 
347  case WM_COMMAND:
348  switch (LOWORD(wparam)) {
349  case BN_CLICKED:
350  if ((HWND)lparam == _smooth_check_box) {
351  int result = SendMessage(_smooth_check_box, BM_GETCHECK, 0, 0);
352  set_average_mode(result == BST_CHECKED);
353  return 0;
354  }
355  break;
356  }
357  break;
358 
359  default:
360  break;
361  }
362 
363  return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam);
364 }
365 
366 /**
367  *
368  */
369 LONG WinStatsStripChart::
370 graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
371  switch (msg) {
372  case WM_LBUTTONDOWN:
373  if (_potential_drag_mode == DM_none) {
374  set_drag_mode(DM_scale);
375  int16_t y = HIWORD(lparam);
376  _drag_scale_start = pixel_to_height(y);
377  SetCapture(_graph_window);
378  return 0;
379 
380  } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) {
381  set_drag_mode(DM_guide_bar);
382  int16_t y = HIWORD(lparam);
383  _drag_start_y = y;
384  SetCapture(_graph_window);
385  return 0;
386  }
387  break;
388 
389  case WM_MOUSEMOVE:
390  if (_drag_mode == DM_none && _potential_drag_mode == DM_none) {
391  // When the mouse is over a color bar, highlight it.
392  int16_t x = LOWORD(lparam);
393  int16_t y = HIWORD(lparam);
394  _label_stack.highlight_label(get_collector_under_pixel(x, y));
395 
396  // Now we want to get a WM_MOUSELEAVE when the mouse leaves the graph
397  // window.
398  TRACKMOUSEEVENT tme = {
399  sizeof(TRACKMOUSEEVENT),
400  TME_LEAVE,
401  _graph_window,
402  0
403  };
404  TrackMouseEvent(&tme);
405 
406  } else {
407  // If the mouse is in some drag mode, stop highlighting.
408  _label_stack.highlight_label(-1);
409  }
410 
411  if (_drag_mode == DM_scale) {
412  int16_t y = HIWORD(lparam);
413  double ratio = 1.0f - ((double)y / (double)get_ysize());
414  if (ratio > 0.0f) {
415  set_vertical_scale(_drag_scale_start / ratio);
416  }
417  return 0;
418 
419  } else if (_drag_mode == DM_new_guide_bar) {
420  // We haven't created the new guide bar yet; we won't until the mouse
421  // comes within the graph's region.
422  int16_t y = HIWORD(lparam);
423  if (y >= 0 && y < get_ysize()) {
424  set_drag_mode(DM_guide_bar);
425  _drag_guide_bar = add_user_guide_bar(pixel_to_height(y));
426  return 0;
427  }
428 
429  } else if (_drag_mode == DM_guide_bar) {
430  int16_t y = HIWORD(lparam);
431  move_user_guide_bar(_drag_guide_bar, pixel_to_height(y));
432  return 0;
433  }
434  break;
435 
436  case WM_MOUSELEAVE:
437  // When the mouse leaves the graph, stop highlighting.
438  _label_stack.highlight_label(-1);
439  break;
440 
441  case WM_LBUTTONUP:
442  if (_drag_mode == DM_scale) {
443  set_drag_mode(DM_none);
444  ReleaseCapture();
445  return 0;
446 
447  } else if (_drag_mode == DM_guide_bar) {
448  int16_t y = HIWORD(lparam);
449  if (y < 0 || y >= get_ysize()) {
450  remove_user_guide_bar(_drag_guide_bar);
451  } else {
452  move_user_guide_bar(_drag_guide_bar, pixel_to_height(y));
453  }
454  set_drag_mode(DM_none);
455  ReleaseCapture();
456  return 0;
457  }
458  break;
459 
460  case WM_LBUTTONDBLCLK:
461  {
462  // Double-clicking on a color bar in the graph is the same as double-
463  // clicking on the corresponding label.
464  int16_t x = LOWORD(lparam);
465  int16_t y = HIWORD(lparam);
467  return 0;
468  }
469  break;
470 
471  default:
472  break;
473  }
474 
475  return WinStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam);
476 }
477 
478 /**
479  * This is called during the servicing of WM_PAINT; it gives a derived class
480  * opportunity to do some further painting into the window (the outer window,
481  * not the graph window).
482  */
483 void WinStatsStripChart::
484 additional_window_paint(HDC hdc) {
485  // Draw in the labels for the guide bars.
486  HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT);
487  SelectObject(hdc, hfnt);
488  SetTextAlign(hdc, TA_LEFT | TA_TOP);
489  SetBkMode(hdc, TRANSPARENT);
490 
491  RECT rect;
492  GetClientRect(_window, &rect);
493  int x = rect.right - _right_margin + 2;
494  int last_y = -100;
495 
496  int i;
497  int num_guide_bars = get_num_guide_bars();
498  for (i = 0; i < num_guide_bars; i++) {
499  last_y = draw_guide_label(hdc, x, get_guide_bar(i), last_y);
500  }
501 
502  GuideBar top_value = make_guide_bar(get_vertical_scale());
503  draw_guide_label(hdc, x, top_value, last_y);
504 
505  last_y = -100;
506  int num_user_guide_bars = get_num_user_guide_bars();
507  for (i = 0; i < num_user_guide_bars; i++) {
508  last_y = draw_guide_label(hdc, x, get_user_guide_bar(i), last_y);
509  }
510 
511  // Now draw the "net value" label at the top.
512  SetTextAlign(hdc, TA_RIGHT | TA_BOTTOM);
513  SetTextColor(hdc, RGB(0, 0, 0));
514  TextOut(hdc, rect.right - _right_margin, _top_margin,
515  _net_value_text.data(), _net_value_text.length());
516 
517  // Also draw the "Smooth" label on the check box. This isn't part of the
518  // check box itself, because doing that doesn't use the right font! Surely
519  // this isn't the correct Windows(tm) way to do this sort of thing, but I
520  // don't know any better for now.
521  SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
522  TextOut(hdc, _left_margin + _check_box_width + 2, _top_margin, "Smooth", 6);
523 }
524 
525 /**
526  * This is called during the servicing of WM_PAINT; it gives a derived class
527  * opportunity to do some further painting into the window (the outer window,
528  * not the graph window).
529  */
530 void WinStatsStripChart::
531 additional_graph_window_paint(HDC hdc) {
532  int num_user_guide_bars = get_num_user_guide_bars();
533  for (int i = 0; i < num_user_guide_bars; i++) {
534  draw_guide_bar(hdc, 0, get_xsize(), get_user_guide_bar(i));
535  }
536 }
537 
538 /**
539  * Based on the mouse position within the window's client area, look for
540  * draggable things the mouse might be hovering over and return the
541  * apprioprate DragMode enum or DM_none if nothing is indicated.
542  */
543 WinStatsGraph::DragMode WinStatsStripChart::
544 consider_drag_start(int mouse_x, int mouse_y, int width, int height) {
545  if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) {
546  if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) {
547  // See if the mouse is over a user-defined guide bar.
548  int y = mouse_y - _graph_top;
549  double from_height = pixel_to_height(y + 2);
550  double to_height = pixel_to_height(y - 2);
551  _drag_guide_bar = find_user_guide_bar(from_height, to_height);
552  if (_drag_guide_bar >= 0) {
553  return DM_guide_bar;
554  }
555 
556  } else {
557  // The mouse is above or below the graph; maybe create a new guide bar.
558  return DM_new_guide_bar;
559  }
560  }
561 
562  return WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height);
563 }
564 
565 /**
566  * This should be called whenever the drag mode needs to change state. It
567  * provides hooks for a derived class to do something special.
568  */
569 void WinStatsStripChart::
570 set_drag_mode(WinStatsGraph::DragMode drag_mode) {
571  WinStatsGraph::set_drag_mode(drag_mode);
572 
573  switch (_drag_mode) {
574  case DM_scale:
575  case DM_left_margin:
576  case DM_right_margin:
577  case DM_sizing:
578  // Disable smoothing for these expensive operations.
579  set_average_mode(false);
580  break;
581 
582  default:
583  // Restore smoothing according to the current setting of the check box.
584  int result = SendMessage(_smooth_check_box, BM_GETCHECK, 0, 0);
585  set_average_mode(result == BST_CHECKED);
586  }
587 }
588 
589 /**
590  * Repositions the graph child window within the parent window according to
591  * the _margin variables.
592  */
593 void WinStatsStripChart::
594 move_graph_window(int graph_left, int graph_top, int graph_xsize, int graph_ysize) {
595  WinStatsGraph::move_graph_window(graph_left, graph_top, graph_xsize, graph_ysize);
596  if (_smooth_check_box != 0) {
597  SetWindowPos(_smooth_check_box, 0,
598  _left_margin, _top_margin - _check_box_height - 1,
599  0, 0,
600  SWP_NOZORDER | SWP_NOSIZE | SWP_SHOWWINDOW);
601  InvalidateRect(_smooth_check_box, nullptr, TRUE);
602  }
603 }
604 
605 /**
606  * Draws the line for the indicated guide bar on the graph.
607  */
608 void WinStatsStripChart::
609 draw_guide_bar(HDC hdc, int from_x, int to_x,
610  const PStatGraph::GuideBar &bar) {
611  int y = height_to_pixel(bar._height);
612 
613  if (y > 0) {
614  // Only draw it if it's not too close to the top.
615  switch (bar._style) {
616  case GBS_target:
617  SelectObject(hdc, _light_pen);
618  break;
619 
620  case GBS_user:
621  SelectObject(hdc, _user_guide_bar_pen);
622  break;
623 
624  case GBS_normal:
625  SelectObject(hdc, _dark_pen);
626  break;
627  }
628  MoveToEx(hdc, from_x, y, nullptr);
629  LineTo(hdc, to_x + 1, y);
630  }
631 }
632 
633 /**
634  * Draws the text for the indicated guide bar label to the right of the graph,
635  * unless it would overlap with the indicated last label, whose top pixel
636  * value is given. Returns the top pixel value of the new label.
637  */
638 int WinStatsStripChart::
639 draw_guide_label(HDC hdc, int x, const PStatGraph::GuideBar &bar, int last_y) {
640  switch (bar._style) {
641  case GBS_target:
642  SetTextColor(hdc, _light_color);
643  break;
644 
645  case GBS_user:
646  SetTextColor(hdc, _user_guide_bar_color);
647  break;
648 
649  case GBS_normal:
650  SetTextColor(hdc, _dark_color);
651  break;
652  }
653 
654  int y = height_to_pixel(bar._height);
655  const string &label = bar._label;
656  SIZE size;
657  GetTextExtentPoint32(hdc, label.data(), label.length(), &size);
658 
659  if (bar._style != GBS_user) {
660  double from_height = pixel_to_height(y + size.cy);
661  double to_height = pixel_to_height(y - size.cy);
662  if (find_user_guide_bar(from_height, to_height) >= 0) {
663  // Omit the label: there's a user-defined guide bar in the same space.
664  return last_y;
665  }
666  }
667 
668  int this_y = _graph_top + y - size.cy / 2;
669  if (y >= 0 && y < get_ysize() &&
670  (last_y < this_y || last_y > this_y + size.cy)) {
671  TextOut(hdc, x, this_y,
672  label.data(), label.length());
673  last_y = this_y;
674  }
675 
676  return last_y;
677 }
678 
679 
680 /**
681  * Creates the window for this strip chart.
682  */
683 void WinStatsStripChart::
684 create_window() {
685  if (_window) {
686  return;
687  }
688 
689  HINSTANCE application = GetModuleHandle(nullptr);
690  register_window_class(application);
691 
692  string window_title = get_title_text();
693 
694  RECT win_rect = {
695  0, 0,
696  _left_margin + get_xsize() + _right_margin,
697  _top_margin + get_ysize() + _bottom_margin
698  };
699 
700  // compute window size based on desired client area size
701  AdjustWindowRect(&win_rect, graph_window_style, FALSE);
702 
703  _window =
704  CreateWindow(_window_class_name, window_title.c_str(), graph_window_style,
705  CW_USEDEFAULT, CW_USEDEFAULT,
706  win_rect.right - win_rect.left,
707  win_rect.bottom - win_rect.top,
708  WinStatsGraph::_monitor->get_window(), nullptr, application, 0);
709  if (!_window) {
710  nout << "Could not create StripChart window!\n";
711  exit(1);
712  }
713 
714  SetWindowLongPtr(_window, 0, (LONG_PTR)this);
715  setup_label_stack();
716 
717  _smooth_check_box =
718  CreateWindow("BUTTON", "",
719  WS_CHILD | BS_AUTOCHECKBOX,
720  0, 0, _check_box_width, _check_box_height,
721  _window, nullptr, application, 0);
722 
723  // Ensure that the window is on top of the stack.
724  SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0,
725  SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
726 }
727 
728 /**
729  * Registers the window class for the stripChart window, if it has not already
730  * been registered.
731  */
732 void WinStatsStripChart::
733 register_window_class(HINSTANCE application) {
734  if (_window_class_registered) {
735  return;
736  }
737 
738  WNDCLASS wc;
739 
740  ZeroMemory(&wc, sizeof(WNDCLASS));
741  wc.style = 0;
742  wc.lpfnWndProc = (WNDPROC)static_window_proc;
743  wc.hInstance = application;
744  wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
745  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
746  wc.lpszMenuName = nullptr;
747  wc.lpszClassName = _window_class_name;
748 
749  // Reserve space to associate the this pointer with the window.
750  wc.cbWndExtra = sizeof(WinStatsStripChart *);
751 
752  if (!RegisterClass(&wc)) {
753  nout << "Could not register StripChart window class!\n";
754  exit(1);
755  }
756 
757  _window_class_registered = true;
758 }
759 
760 /**
761  *
762  */
763 LONG WINAPI WinStatsStripChart::
764 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
765  WinStatsStripChart *self = (WinStatsStripChart *)GetWindowLongPtr(hwnd, 0);
766  if (self != nullptr && self->_window == hwnd) {
767  return self->window_proc(hwnd, msg, wparam, lparam);
768  } else {
769  return DefWindowProc(hwnd, msg, wparam, lparam);
770  }
771 }
void set_horizontal_scale(double time_width)
Changes the amount of time the width of the horizontal axis represents.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
int get_xsize() const
Returns the width of the chart in pixels.
Definition: pStatGraph.I:82
A window that draws a strip chart, given a view.
int get_guide_bar_units() const
Returns the units that are displayed for the guide bar labels.
Definition: pStatGraph.I:111
void set_guide_bar_units(int unit_mask)
Sets the units that are displayed for the guide bar labels.
Definition: pStatGraph.I:99
int get_ysize() const
Returns the height of the chart in pixels.
Definition: pStatGraph.I:90
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_labels() const
Returns the number of labels to be drawn for this chart.
Definition: pStatGraph.I:26
void move_user_guide_bar(int n, double height)
Adjusts the height of the nth user-defined guide bar.
Definition: pStatGraph.cxx:117
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...
The data associated with a particular client, but not with any one particular frame or thread: the li...
void set_vertical_scale(double value_height)
Changes the value the height of the vertical axis represents.
int find_user_guide_bar(double from_height, double to_height) const
Returns the index number of the first user guide bar found whose height is within the indicated range...
Definition: pStatGraph.cxx:144
const PStatCollectorDef & get_collector_def(int index) const
Returns the nth collector definition.
double pixel_to_height(int y) const
Converts a vertical pixel offset to a value (a "height" in the strip chart).
This is an abstract class that presents the interface for drawing a basic strip-chart,...
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 ...
int get_collector_under_pixel(int xpoint, int ypoint)
Return the collector index associated with the particular band of color at the indicated pixel locati...
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
int get_collector_index() const
Returns the particular collector whose data this strip chart reflects.
bool has_collector(int index) const
Returns true if the indicated collector has been defined by the client already, false otherwise.
const GuideBar & get_guide_bar(int n) const
Returns the nth horizontal guide bar.
Definition: pStatGraph.cxx:87
PStatView & get_view() const
Returns the View this chart represents.
void update()
Updates the chart with the latest data.
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
Definition: winStatsGraph.h:29
int height_to_pixel(double value) const
Converts a value (i.e.
void set_vertical_scale(double value_height)
Changes the value the height of the vertical axis represents.
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.
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.
int get_label_collector(int n) const
Returns the collector index associated with the nth label.
Definition: pStatGraph.I:34
This class represents a connection to a PStatsClient and manages the data exchange with the client.
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
int get_num_guide_bars() const
Returns the number of horizontal guide bars that should be drawn, based on the indicated target frame...
Definition: pStatGraph.cxx:75
const std::string & get_guide_bar_unit_name() const
Returns the name of the units to be used for the guide bars if the units type is set to GBU_named | G...
Definition: pStatGraph.I:129
bool is_title_unknown() const
Returns true if get_title_text() has never yet returned an answer, false if it has.
void set_average_mode(bool average_mode)
Changes the average_mode flag.
void set_collector_index(int collector_index)
Changes the collector represented by this strip chart.
double get_vertical_scale() const
Returns total value the height of the vertical axis represents.
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
Definition: pStatMonitor.I:26
HWND get_window() const
Returns the window handle to the monitor's window.
int add_user_guide_bar(double height)
Creates a new user guide bar and returns its index number.
Definition: pStatGraph.cxx:125
Defines the details about the Collectors: the name, the suggested color, etc.
static std::string format_number(double value)
Returns a string representing the value nicely formatted for its range.
Definition: pStatGraph.cxx:153
GuideBar get_user_guide_bar(int n) const
Returns the nth user-defined guide bar.
Definition: pStatGraph.cxx:108
virtual void force_redraw()
Called when it is necessary to redraw the entire graph.
int get_num_user_guide_bars() const
Returns the current number of user-defined guide bars.
Definition: pStatGraph.cxx:100
std::string get_title_text()
Returns the text suitable for the title label on the top line.
void remove_user_guide_bar(int n)
Removes the user guide bar with the indicated index number.
Definition: pStatGraph.cxx:134