Panda3D
Loading...
Searching...
No Matches
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
19using std::string;
20
21static const int default_strip_chart_width = 400;
22static 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?
27size_t WinStatsStripChart::_check_box_height = 13;
28size_t WinStatsStripChart::_check_box_width = 13;
29
30bool WinStatsStripChart::_window_class_registered = false;
31const char * const WinStatsStripChart::_window_class_name = "strip";
32
33/**
34 *
35 */
36WinStatsStripChart::
37WinStatsStripChart(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 */
76WinStatsStripChart::
77~WinStatsStripChart() {
78}
79
80/**
81 * Called whenever a new Collector definition is received from the client.
82 */
84new_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 */
95new_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 std::string text = get_total_text();
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 */
121force_redraw() {
122 PStatStripChart::force_redraw();
123}
124
125/**
126 * Called when the user has resized the window, forcing a resize of the graph.
127 */
129changed_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 */
139set_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 */
162set_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 */
173clicked_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 */
205set_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 */
217void WinStatsStripChart::
218update_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 */
232void WinStatsStripChart::
233clear_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 */
242void WinStatsStripChart::
243copy_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 */
263void WinStatsStripChart::
264draw_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 */
299void WinStatsStripChart::
300draw_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 */
308void WinStatsStripChart::
309draw_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 */
319void WinStatsStripChart::
320end_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 */
336LONG WinStatsStripChart::
337window_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 */
369LONG WinStatsStripChart::
370graph_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 */
483void WinStatsStripChart::
484additional_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 */
530void WinStatsStripChart::
531additional_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 */
543WinStatsGraph::DragMode WinStatsStripChart::
544consider_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 */
569void WinStatsStripChart::
570set_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 */
593void WinStatsStripChart::
594move_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 */
608void WinStatsStripChart::
609draw_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 */
638int WinStatsStripChart::
639draw_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 */
683void WinStatsStripChart::
684create_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 */
732void WinStatsStripChart::
733register_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 */
763LONG WINAPI WinStatsStripChart::
764static_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}
The data associated with a particular client, but not with any one particular frame or thread: the li...
const PStatCollectorDef & get_collector_def(int index) const
Returns the nth collector definition.
bool has_collector(int index) const
Returns true if the indicated collector has been defined by the client already, false otherwise.
Defines the details about the Collectors: the name, the suggested color, etc.
GuideBar get_user_guide_bar(int n) const
Returns the nth user-defined guide bar.
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...
int get_num_user_guide_bars() const
Returns the current number of user-defined guide bars.
int add_user_guide_bar(double height)
Creates a new user guide bar and returns its index number.
void move_user_guide_bar(int n, double height)
Adjusts the height of the nth user-defined guide bar.
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_guide_bar_units() const
Returns the units that are displayed for the guide bar labels.
Definition pStatGraph.I:111
void remove_user_guide_bar(int n)
Removes the user guide bar with the indicated index number.
int get_num_guide_bars() const
Returns the number of horizontal guide bars that should be drawn, based on the indicated target frame...
int get_num_labels() const
Returns the number of labels to be drawn for this chart.
Definition pStatGraph.I:26
int get_label_collector(int n) const
Returns the collector index associated with the nth label.
Definition pStatGraph.I:34
int get_xsize() const
Returns the width of the chart in pixels.
Definition pStatGraph.I:82
int get_ysize() const
Returns the height of the chart in pixels.
Definition pStatGraph.I:90
const GuideBar & get_guide_bar(int n) const
Returns the nth horizontal guide bar.
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
This is an abstract class that presents the interface for drawing a basic strip-chart,...
std::string get_title_text()
Returns the text suitable for the title label on the top line.
bool is_title_unknown() const
Returns true if get_title_text() has never yet returned an answer, false if it has.
double get_vertical_scale() const
Returns total value the height of the vertical axis represents.
int height_to_pixel(double value) const
Converts a value (i.e.
void set_average_mode(bool average_mode)
Changes the average_mode flag.
void set_horizontal_scale(double time_width)
Changes the amount of time the width of the horizontal axis represents.
void update()
Updates the chart with the latest data.
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...
std::string get_total_text()
Returns the text suitable for the total label above the graph.
void set_collector_index(int collector_index)
Changes the collector represented by this strip chart.
PStatView & get_view() const
Returns the View this chart represents.
double pixel_to_height(int y) const
Converts a vertical pixel offset to a value (a "height" in the strip chart).
int get_collector_index() const
Returns the particular collector whose data this strip chart reflects.
void set_vertical_scale(double value_height)
Changes the value the height of the vertical axis represents.
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
This class represents a connection to a PStatsClient and manages the data exchange with the client.
A window that draws a strip chart, given a view.
virtual void new_data(int thread_index, int frame_number)
Called as each frame's data is made available.
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 force_redraw()
Called when it is necessary to redraw the entire graph.
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
void set_vertical_scale(double value_height)
Changes the value the height of the vertical axis represents.
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...
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.
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 is our own Panda specialization on the default STL vector.
Definition pvector.h:42
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.