Panda3D
gtkStatsStripChart.cxx
1 // Filename: gtkStatsStripChart.cxx
2 // Created by: drose (16Jan06)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "gtkStatsStripChart.h"
16 #include "gtkStatsMonitor.h"
17 #include "pStatCollectorDef.h"
18 #include "numeric_types.h"
19 
20 static const int default_strip_chart_width = 400;
21 static const int default_strip_chart_height = 100;
22 
23 ////////////////////////////////////////////////////////////////////
24 // Function: GtkStatsStripChart::Constructor
25 // Access: Public
26 // Description:
27 ////////////////////////////////////////////////////////////////////
28 GtkStatsStripChart::
29 GtkStatsStripChart(GtkStatsMonitor *monitor, int thread_index,
30  int collector_index, bool show_level) :
31  PStatStripChart(monitor,
32  show_level ? monitor->get_level_view(collector_index, thread_index) : monitor->get_view(thread_index),
33  thread_index,
34  collector_index,
35  default_strip_chart_width,
36  default_strip_chart_height),
37  GtkStatsGraph(monitor)
38 {
39  _brush_origin = 0;
40 
41  if (show_level) {
42  // If it's a level-type graph, show the appropriate units.
43  if (_unit_name.empty()) {
44  set_guide_bar_units(GBU_named);
45  } else {
46  set_guide_bar_units(GBU_named | GBU_show_units);
47  }
48 
49  } else {
50  // If it's a time-type graph, show the ms/Hz units.
51  set_guide_bar_units(get_guide_bar_units() | GBU_show_units);
52  }
53 
54  // Put some stuff on top of the graph.
55  _top_hbox = gtk_hbox_new(FALSE, 0);
56  gtk_box_pack_start(GTK_BOX(_graph_vbox), _top_hbox,
57  FALSE, FALSE, 0);
58 
59  _smooth_check_box = gtk_check_button_new_with_label("Smooth");
60  g_signal_connect(G_OBJECT(_smooth_check_box), "toggled",
61  G_CALLBACK(toggled_callback), this);
62 
63  _total_label = gtk_label_new("");
64  gtk_box_pack_start(GTK_BOX(_top_hbox), _smooth_check_box,
65  FALSE, FALSE, 0);
66  gtk_box_pack_end(GTK_BOX(_top_hbox), _total_label,
67  FALSE, FALSE, 0);
68 
69  // Add a DrawingArea widget to the right of the graph, to display
70  // all of the scale units.
71  _scale_area = gtk_drawing_area_new();
72  g_signal_connect(G_OBJECT(_scale_area), "expose_event",
73  G_CALLBACK(expose_event_callback), this);
74  gtk_box_pack_start(GTK_BOX(_graph_hbox), _scale_area,
75  FALSE, FALSE, 0);
76  gtk_widget_set_size_request(_scale_area, 40, 0);
77 
78 
79  gtk_widget_set_size_request(_graph_window, default_strip_chart_width,
80  default_strip_chart_height);
81 
82  gtk_widget_show_all(_window);
83  gtk_widget_show(_window);
84 
85  // Allow the window to be resized as small as the user likes. We
86  // have to do this after the window has been shown; otherwise, it
87  // will affect the window's initial size.
88  gtk_widget_set_size_request(_window, 0, 0);
89 
90  clear_region();
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: GtkStatsStripChart::Destructor
95 // Access: Public, Virtual
96 // Description:
97 ////////////////////////////////////////////////////////////////////
98 GtkStatsStripChart::
99 ~GtkStatsStripChart() {
100 }
101 
102 ////////////////////////////////////////////////////////////////////
103 // Function: GtkStatsStripChart::new_collector
104 // Access: Public, Virtual
105 // Description: Called whenever a new Collector definition is
106 // received from the client.
107 ////////////////////////////////////////////////////////////////////
109 new_collector(int collector_index) {
110  GtkStatsGraph::new_collector(collector_index);
111 }
112 
113 ////////////////////////////////////////////////////////////////////
114 // Function: GtkStatsStripChart::new_data
115 // Access: Public, Virtual
116 // Description: Called as each frame's data is made available. There
117 // is no gurantee the frames will arrive in order, or
118 // that all of them will arrive at all. The monitor
119 // should be prepared to accept frames received
120 // out-of-order or missing.
121 ////////////////////////////////////////////////////////////////////
123 new_data(int thread_index, int frame_number) {
124  if (is_title_unknown()) {
125  string window_title = get_title_text();
126  if (!is_title_unknown()) {
127  gtk_window_set_title(GTK_WINDOW(_window), window_title.c_str());
128  }
129  }
130 
131  if (!_pause) {
132  update();
133 
134  string text = format_number(get_average_net_value(), get_guide_bar_units(), get_guide_bar_unit_name());
135  if (_net_value_text != text) {
136  _net_value_text = text;
137  gtk_label_set_text(GTK_LABEL(_total_label), _net_value_text.c_str());
138  }
139  }
140 }
141 
142 ////////////////////////////////////////////////////////////////////
143 // Function: GtkStatsStripChart::force_redraw
144 // Access: Public, Virtual
145 // Description: Called when it is necessary to redraw the entire graph.
146 ////////////////////////////////////////////////////////////////////
149  PStatStripChart::force_redraw();
150 }
151 
152 ////////////////////////////////////////////////////////////////////
153 // Function: GtkStatsStripChart::changed_graph_size
154 // Access: Public, Virtual
155 // Description: Called when the user has resized the window, forcing
156 // a resize of the graph.
157 ////////////////////////////////////////////////////////////////////
159 changed_graph_size(int graph_xsize, int graph_ysize) {
160  PStatStripChart::changed_size(graph_xsize, graph_ysize);
161 }
162 
163 ////////////////////////////////////////////////////////////////////
164 // Function: GtkStatsStripChart::set_time_units
165 // Access: Public, Virtual
166 // Description: Called when the user selects a new time units from
167 // the monitor pulldown menu, this should adjust the
168 // units for the graph to the indicated mask if it is a
169 // time-based graph.
170 ////////////////////////////////////////////////////////////////////
172 set_time_units(int unit_mask) {
173  int old_unit_mask = get_guide_bar_units();
174  if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) {
175  unit_mask = unit_mask & (GBU_hz | GBU_ms);
176  unit_mask |= (old_unit_mask & GBU_show_units);
177  set_guide_bar_units(unit_mask);
178 
179  gtk_widget_queue_draw(_scale_area);
180  }
181 }
182 
183 ////////////////////////////////////////////////////////////////////
184 // Function: GtkStatsStripChart::set_scroll_speed
185 // Access: Public
186 // Description: Called when the user selects a new scroll speed from
187 // the monitor pulldown menu, this should adjust the
188 // speed for the graph to the indicated value.
189 ////////////////////////////////////////////////////////////////////
191 set_scroll_speed(double scroll_speed) {
192  // The speed factor indicates chart widths per minute.
193  if (scroll_speed != 0.0f) {
194  set_horizontal_scale(60.0f / scroll_speed);
195  }
196 }
197 
198 ////////////////////////////////////////////////////////////////////
199 // Function: GtkStatsStripChart::clicked_label
200 // Access: Public, Virtual
201 // Description: Called when the user single-clicks on a label.
202 ////////////////////////////////////////////////////////////////////
204 clicked_label(int collector_index) {
205  if (collector_index < 0) {
206  // Clicking on whitespace in the graph is the same as clicking on
207  // the top label.
208  collector_index = get_collector_index();
209  }
210 
211  if (collector_index == get_collector_index() && collector_index != 0) {
212  // Clicking on the top label means to go up to the parent level.
213  const PStatClientData *client_data =
214  GtkStatsGraph::_monitor->get_client_data();
215  if (client_data->has_collector(collector_index)) {
216  const PStatCollectorDef &def =
217  client_data->get_collector_def(collector_index);
218  if (def._parent_index == 0 && get_view().get_show_level()) {
219  // Unless the parent is "Frame", and we're not a time collector.
220  } else {
221  set_collector_index(def._parent_index);
222  }
223  }
224 
225  } else {
226  // Clicking on any other label means to focus on that.
227  set_collector_index(collector_index);
228  }
229 }
230 
231 ////////////////////////////////////////////////////////////////////
232 // Function: GtkStatsStripChart::set_vertical_scale
233 // Access: Public
234 // Description: Changes the value the height of the vertical axis
235 // represents. This may force a redraw.
236 ////////////////////////////////////////////////////////////////////
238 set_vertical_scale(double value_height) {
240 
241  gtk_widget_queue_draw(_graph_window);
242  gtk_widget_queue_draw(_scale_area);
243 }
244 
245 ////////////////////////////////////////////////////////////////////
246 // Function: GtkStatsStripChart::update_labels
247 // Access: Protected, Virtual
248 // Description: Resets the list of labels.
249 ////////////////////////////////////////////////////////////////////
250 void GtkStatsStripChart::
251 update_labels() {
252  PStatStripChart::update_labels();
253 
254  _label_stack.clear_labels();
255  for (int i = 0; i < get_num_labels(); i++) {
256  _label_stack.add_label(GtkStatsGraph::_monitor, this, _thread_index,
257  get_label_collector(i), false);
258  }
259  _labels_changed = false;
260 }
261 
262 ////////////////////////////////////////////////////////////////////
263 // Function: GtkStatsStripChart::clear_region
264 // Access: Protected, Virtual
265 // Description: Erases the chart area.
266 ////////////////////////////////////////////////////////////////////
267 void GtkStatsStripChart::
268 clear_region() {
269  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white);
270  gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, 0, 0,
271  get_xsize(), get_ysize());
272 }
273 
274 ////////////////////////////////////////////////////////////////////
275 // Function: GtkStatsStripChart::copy_region
276 // Access: Protected, Virtual
277 // Description: Should be overridden by the user class to copy a
278 // region of the chart from one part of the chart to
279 // another. This is used to implement scrolling.
280 ////////////////////////////////////////////////////////////////////
281 void GtkStatsStripChart::
282 copy_region(int start_x, int end_x, int dest_x) {
283  gdk_draw_drawable(_pixmap, _pixmap_gc, _pixmap,
284  start_x, 0, dest_x, 0,
285  end_x - start_x, get_ysize());
286 
287  // Also shift the brush origin over, so we still get proper
288  // dithering.
289  _brush_origin += (dest_x - start_x);
290  // SetBrushOrgEx(_bitmap_dc, _brush_origin, 0, NULL);
291 
292  GdkRectangle rect = {
293  dest_x, 0, end_x - start_x, get_ysize()
294  };
295  gdk_window_invalidate_rect(_graph_window->window, &rect, FALSE);
296 }
297 
298 ////////////////////////////////////////////////////////////////////
299 // Function: GtkStatsStripChart::draw_slice
300 // Access: Protected, Virtual
301 // Description: Draws a single vertical slice of the strip chart, at
302 // the given pixel position, and corresponding to the
303 // indicated level data.
304 ////////////////////////////////////////////////////////////////////
305 void GtkStatsStripChart::
306 draw_slice(int x, int w, const PStatStripChart::FrameData &fdata) {
307  // Start by clearing the band first.
308  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white);
309  gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, x, 0,
310  w + 1, get_ysize());
311 
312  double overall_time = 0.0;
313  int y = get_ysize();
314 
315  FrameData::const_iterator fi;
316  for (fi = fdata.begin(); fi != fdata.end(); ++fi) {
317  const ColorData &cd = (*fi);
318  overall_time += cd._net_value;
319  GdkGC *gc = get_collector_gc(cd._collector_index);
320 
321  if (overall_time > get_vertical_scale()) {
322  // Off the top. Go ahead and clamp it by hand, in case it's so
323  // far off the top we'd overflow the 16-bit pixel value.
324  gdk_draw_rectangle(_pixmap, gc, TRUE, x, 0, w, y);
325  // And we can consider ourselves done now.
326  return;
327  }
328 
329  int top_y = height_to_pixel(overall_time);
330  gdk_draw_rectangle(_pixmap, gc, TRUE, x, top_y, w, y - top_y);
331  y = top_y;
332  }
333 }
334 
335 ////////////////////////////////////////////////////////////////////
336 // Function: GtkStatsStripChart::draw_empty
337 // Access: Protected, Virtual
338 // Description: Draws a single vertical slice of background color.
339 ////////////////////////////////////////////////////////////////////
340 void GtkStatsStripChart::
341 draw_empty(int x, int w) {
342  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white);
343  gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, x, 0,
344  w + 1, get_ysize());
345 }
346 
347 ////////////////////////////////////////////////////////////////////
348 // Function: GtkStatsStripChart::draw_cursor
349 // Access: Protected, Virtual
350 // Description: Draws a single vertical slice of foreground color.
351 ////////////////////////////////////////////////////////////////////
352 void GtkStatsStripChart::
353 draw_cursor(int x) {
354  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_black);
355  gdk_draw_line(_pixmap, _pixmap_gc, x, 0, x, get_ysize());
356 }
357 
358 ////////////////////////////////////////////////////////////////////
359 // Function: GtkStatsStripChart::end_draw
360 // Access: Protected, Virtual
361 // Description: Should be overridden by the user class. This hook
362 // will be called after drawing a series of color bars
363 // in the strip chart; it gives the pixel range that
364 // was just redrawn.
365 ////////////////////////////////////////////////////////////////////
366 void GtkStatsStripChart::
367 end_draw(int from_x, int to_x) {
368  // Draw in the guide bars.
369  int num_guide_bars = get_num_guide_bars();
370  for (int i = 0; i < num_guide_bars; i++) {
371  draw_guide_bar(_pixmap, from_x, to_x, get_guide_bar(i));
372  }
373 
374  GdkRectangle rect = {
375  from_x, 0, to_x - from_x + 1, get_ysize()
376  };
377  gdk_window_invalidate_rect(_graph_window->window, &rect, FALSE);
378 }
379 
380 ////////////////////////////////////////////////////////////////////
381 // Function: GtkStatsStripChart::additional_graph_window_paint
382 // Access: Protected, Virtual
383 // Description: This is called during the servicing of expose_event;
384 // it gives a derived class opportunity to do some
385 // further painting into the graph window.
386 ////////////////////////////////////////////////////////////////////
387 void GtkStatsStripChart::
388 additional_graph_window_paint() {
389  int num_user_guide_bars = get_num_user_guide_bars();
390  for (int i = 0; i < num_user_guide_bars; i++) {
391  draw_guide_bar(_graph_window->window, 0, get_xsize(), get_user_guide_bar(i));
392  }
393 }
394 
395 ////////////////////////////////////////////////////////////////////
396 // Function: GtkStatsStripChart::consider_drag_start
397 // Access: Protected, Virtual
398 // Description: Based on the mouse position within the graph window,
399 // look for draggable things the mouse might be hovering
400 // over and return the appropriate DragMode enum or
401 // DM_none if nothing is indicated.
402 ////////////////////////////////////////////////////////////////////
403 GtkStatsGraph::DragMode GtkStatsStripChart::
404 consider_drag_start(int graph_x, int graph_y) {
405  if (graph_x >= 0 && graph_x < get_xsize()) {
406  if (graph_y >= 0 && graph_y < get_ysize()) {
407  // See if the mouse is over a user-defined guide bar.
408  int y = graph_y;
409  double from_height = pixel_to_height(y + 2);
410  double to_height = pixel_to_height(y - 2);
411  _drag_guide_bar = find_user_guide_bar(from_height, to_height);
412  if (_drag_guide_bar >= 0) {
413  return DM_guide_bar;
414  }
415 
416  } else {
417  // The mouse is above or below the graph; maybe create a new
418  // guide bar.
419  return DM_new_guide_bar;
420  }
421  }
422 
423  return GtkStatsGraph::consider_drag_start(graph_x, graph_y);
424 }
425 
426 ////////////////////////////////////////////////////////////////////
427 // Function: GtkStatsStripChart::set_drag_mode
428 // Access: Protected, Virtual
429 // Description: This should be called whenever the drag mode needs to
430 // change state. It provides hooks for a derived class
431 // to do something special.
432 ////////////////////////////////////////////////////////////////////
433 void GtkStatsStripChart::
434 set_drag_mode(GtkStatsGraph::DragMode drag_mode) {
435  GtkStatsGraph::set_drag_mode(drag_mode);
436 
437  switch (_drag_mode) {
438  case DM_scale:
439  case DM_sizing:
440  // Disable smoothing for these expensive operations.
441  set_average_mode(false);
442  break;
443 
444  default:
445  // Restore smoothing according to the current setting of the check
446  // box.
447  bool active =
448  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(_smooth_check_box));
449  set_average_mode(active);
450  break;
451  }
452 }
453 
454 ////////////////////////////////////////////////////////////////////
455 // Function: GtkStatsStripChart::handle_button_press
456 // Access: Protected, Virtual
457 // Description: Called when the mouse button is depressed within the
458 // graph window.
459 ////////////////////////////////////////////////////////////////////
460 gboolean GtkStatsStripChart::
461 handle_button_press(GtkWidget *widget, int graph_x, int graph_y,
462  bool double_click) {
463  if (double_click) {
464  // Double-clicking on a color bar in the graph is the same as
465  // double-clicking on the corresponding label.
466  clicked_label(get_collector_under_pixel(graph_x, graph_y));
467  return TRUE;
468  }
469 
470  if (_potential_drag_mode == DM_none) {
471  set_drag_mode(DM_scale);
472  _drag_scale_start = pixel_to_height(graph_y);
473  //SetCapture(_graph_window);
474  return TRUE;
475 
476  } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) {
477  set_drag_mode(DM_guide_bar);
478  _drag_start_y = graph_y;
479  //SetCapture(_graph_window);
480  return TRUE;
481  }
482 
483  return GtkStatsGraph::handle_button_press(widget, graph_x, graph_y,
484  double_click);
485 }
486 
487 ////////////////////////////////////////////////////////////////////
488 // Function: GtkStatsStripChart::handle_button_release
489 // Access: Protected, Virtual
490 // Description: Called when the mouse button is released within the
491 // graph window.
492 ////////////////////////////////////////////////////////////////////
493 gboolean GtkStatsStripChart::
494 handle_button_release(GtkWidget *widget, int graph_x, int graph_y) {
495  if (_drag_mode == DM_scale) {
496  set_drag_mode(DM_none);
497  //ReleaseCapture();
498  return handle_motion(widget, graph_x, graph_y);
499 
500  } else if (_drag_mode == DM_guide_bar) {
501  if (graph_y < 0 || graph_y >= get_ysize()) {
502  remove_user_guide_bar(_drag_guide_bar);
503  } else {
504  move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_y));
505  }
506  set_drag_mode(DM_none);
507  //ReleaseCapture();
508  return handle_motion(widget, graph_x, graph_y);
509  }
510 
511  return GtkStatsGraph::handle_button_release(widget, graph_x, graph_y);
512 }
513 
514 ////////////////////////////////////////////////////////////////////
515 // Function: GtkStatsStripChart::ns_motion_notify_event_callback
516 // Access: Protected, Virtual
517 // Description: Called when the mouse is moved within the
518 // graph window.
519 ////////////////////////////////////////////////////////////////////
520 gboolean GtkStatsStripChart::
521 handle_motion(GtkWidget *widget, int graph_x, int graph_y) {
522  if (_drag_mode == DM_none && _potential_drag_mode == DM_none) {
523  // When the mouse is over a color bar, highlight it.
524  _label_stack.highlight_label(get_collector_under_pixel(graph_x, graph_y));
525 
526  /*
527  // Now we want to get a WM_MOUSELEAVE when the mouse leaves the
528  // graph window.
529  TRACKMOUSEEVENT tme = {
530  sizeof(TRACKMOUSEEVENT),
531  TME_LEAVE,
532  _graph_window,
533  0
534  };
535  TrackMouseEvent(&tme);
536  */
537 
538  } else {
539  // If the mouse is in some drag mode, stop highlighting.
540  _label_stack.highlight_label(-1);
541  }
542 
543  if (_drag_mode == DM_scale) {
544  double ratio = 1.0f - ((double)graph_y / (double)get_ysize());
545  if (ratio > 0.0f) {
546  set_vertical_scale(_drag_scale_start / ratio);
547  }
548  return TRUE;
549 
550  } else if (_drag_mode == DM_new_guide_bar) {
551  // We haven't created the new guide bar yet; we won't until the
552  // mouse comes within the graph's region.
553  if (graph_y >= 0 && graph_y < get_ysize()) {
554  set_drag_mode(DM_guide_bar);
555  _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_y));
556  return TRUE;
557  }
558 
559  } else if (_drag_mode == DM_guide_bar) {
560  move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_y));
561  return TRUE;
562  }
563 
564  return GtkStatsGraph::handle_motion(widget, graph_x, graph_y);
565 }
566 
567 ////////////////////////////////////////////////////////////////////
568 // Function: GtkStatsStripChart::draw_guide_bar
569 // Access: Private
570 // Description: Draws the line for the indicated guide bar on the
571 // graph.
572 ////////////////////////////////////////////////////////////////////
573 void GtkStatsStripChart::
574 draw_guide_bar(GdkDrawable *surface, int from_x, int to_x,
575  const PStatGraph::GuideBar &bar) {
576  int y = height_to_pixel(bar._height);
577 
578  if (y > 0) {
579  // Only draw it if it's not too close to the top.
580  switch (bar._style) {
581  case GBS_target:
582  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_light_gray);
583  break;
584 
585  case GBS_user:
586  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_user_guide_bar);
587  break;
588 
589  case GBS_normal:
590  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_dark_gray);
591  break;
592  }
593  gdk_draw_line(surface, _pixmap_gc, from_x, y, to_x, y);
594  }
595 }
596 
597 ////////////////////////////////////////////////////////////////////
598 // Function: GtkStatsStripChart::draw_guide_labels
599 // Access: Private
600 // Description: This is called during the servicing of expose_event.
601 ////////////////////////////////////////////////////////////////////
602 void GtkStatsStripChart::
603 draw_guide_labels() {
604  // Draw in the labels for the guide bars.
605  int last_y = -100;
606 
607  int i;
608  int num_guide_bars = get_num_guide_bars();
609  for (i = 0; i < num_guide_bars; i++) {
610  last_y = draw_guide_label(get_guide_bar(i), last_y);
611  }
612 
613  GuideBar top_value = make_guide_bar(get_vertical_scale());
614  draw_guide_label(top_value, last_y);
615 
616  last_y = -100;
617  int num_user_guide_bars = get_num_user_guide_bars();
618  for (i = 0; i < num_user_guide_bars; i++) {
619  last_y = draw_guide_label(get_user_guide_bar(i), last_y);
620  }
621 }
622 
623 ////////////////////////////////////////////////////////////////////
624 // Function: GtkStatsStripChart::draw_guide_label
625 // Access: Private
626 // Description: Draws the text for the indicated guide bar label to
627 // the right of the graph, unless it would overlap with
628 // the indicated last label, whose top pixel value is
629 // given. Returns the top pixel value of the new label.
630 ////////////////////////////////////////////////////////////////////
631 int GtkStatsStripChart::
632 draw_guide_label(const PStatGraph::GuideBar &bar, int last_y) {
633  GdkGC *gc = gdk_gc_new(_scale_area->window);
634 
635  switch (bar._style) {
636  case GBS_target:
637  gdk_gc_set_rgb_fg_color(gc, &rgb_light_gray);
638  break;
639 
640  case GBS_user:
641  gdk_gc_set_rgb_fg_color(gc, &rgb_user_guide_bar);
642  break;
643 
644  case GBS_normal:
645  gdk_gc_set_rgb_fg_color(gc, &rgb_dark_gray);
646  break;
647  }
648 
649  int y = height_to_pixel(bar._height);
650  const string &label = bar._label;
651 
652  PangoLayout *layout = gtk_widget_create_pango_layout(_window, label.c_str());
653  int width, height;
654  pango_layout_get_pixel_size(layout, &width, &height);
655 
656  if (bar._style != GBS_user) {
657  double from_height = pixel_to_height(y + height);
658  double to_height = pixel_to_height(y - height);
659  if (find_user_guide_bar(from_height, to_height) >= 0) {
660  // Omit the label: there's a user-defined guide bar in the same space.
661  g_object_unref(layout);
662  g_object_unref(gc);
663  return last_y;
664  }
665  }
666 
667  if (y >= 0 && y < get_ysize()) {
668  // Now convert our y to a coordinate within our drawing area.
669  int junk_x;
670 
671  // The y coordinate comes from the graph_window.
672  gtk_widget_translate_coordinates(_graph_window, _scale_area,
673  0, y,
674  &junk_x, &y);
675 
676  int this_y = y - height / 2;
677  if (last_y < this_y || last_y > this_y + height) {
678  gdk_draw_layout(_scale_area->window, gc, 0, this_y, layout);
679  last_y = this_y;
680  }
681  }
682 
683  g_object_unref(layout);
684  g_object_unref(gc);
685  return last_y;
686 }
687 
688 ////////////////////////////////////////////////////////////////////
689 // Function: GtkStatsStripChart::toggled_callback
690 // Access: Private, Static
691 // Description: Called when the smooth check box is toggled.
692 ////////////////////////////////////////////////////////////////////
693 void GtkStatsStripChart::
694 toggled_callback(GtkToggleButton *button, gpointer data) {
695  GtkStatsStripChart *self = (GtkStatsStripChart *)data;
696 
697  bool active = gtk_toggle_button_get_active(button);
698  self->set_average_mode(active);
699 }
700 
701 ////////////////////////////////////////////////////////////////////
702 // Function: GtkStatsStripChart::expose_event_callback
703 // Access: Private, Static
704 // Description: Draws in the scale labels.
705 ////////////////////////////////////////////////////////////////////
706 gboolean GtkStatsStripChart::
707 expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
708  GtkStatsStripChart *self = (GtkStatsStripChart *)data;
709  self->draw_guide_labels();
710 
711  return TRUE;
712 }
void set_horizontal_scale(double time_width)
Changes the amount of time the width of the horizontal axis represents.
int get_xsize() const
Returns the width of the chart in pixels.
Definition: pStatGraph.I:103
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:140
const 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:164
void set_guide_bar_units(int unit_mask)
Sets the units that are displayed for the guide bar labels.
Definition: pStatGraph.I:125
int get_ysize() const
Returns the height of the chart in pixels.
Definition: pStatGraph.I:113
int get_num_labels() const
Returns the number of labels to be drawn for this chart.
Definition: pStatGraph.I:33
void move_user_guide_bar(int n, double height)
Adjusts the height of the nth user-defined guide bar.
Definition: pStatGraph.cxx:137
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:172
const PStatCollectorDef & get_collector_def(int index) const
Returns the nth collector definition.
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
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, showing the relative value over an interval of time for several different collectors, differentiated by bands of color.
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:39
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
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:101
PStatView & get_view() const
Returns the View this chart represents.
void update()
Updates the chart with the latest data.
int height_to_pixel(double value) const
Converts a value (i.e.
string get_title_text()
Returns the text suitable for the title label on the top line.
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 ...
virtual void new_data(int thread_index, int frame_number)
Called as each frame&#39;s data is made available.
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
Definition: gtkStatsGraph.h:32
int get_label_collector(int n) const
Returns the collector index associated with the nth label.
Definition: pStatGraph.I:44
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:86
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.
This class represents a connection to a PStatsClient and manages the data exchange with the client...
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.
virtual void force_redraw()
Called when it is necessary to redraw the entire graph.
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...
double get_vertical_scale() const
Returns total 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.
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
Definition: pStatMonitor.I:32
int add_user_guide_bar(double height)
Creates a new user guide bar and returns its index number.
Definition: pStatGraph.cxx:148
Defines the details about the Collectors: the name, the suggested color, etc.
static string format_number(double value)
Returns a string representing the value nicely formatted for its range.
Definition: pStatGraph.cxx:184
GuideBar get_user_guide_bar(int n) const
Returns the nth user-defined guide bar.
Definition: pStatGraph.cxx:126
void set_vertical_scale(double value_height)
Changes the value the height of the vertical axis represents.
int get_num_user_guide_bars() const
Returns the current number of user-defined guide bars.
Definition: pStatGraph.cxx:116
void remove_user_guide_bar(int n)
Removes the user guide bar with the indicated index number.
Definition: pStatGraph.cxx:160