Browse Source

piano roll

David Rose 20 years ago
parent
commit
fdf8e075a8

+ 1 - 2
pandatool/src/gtk-stats/Sources.pp

@@ -20,11 +20,10 @@
     gtkStatsLabelStack.cxx gtkStatsLabelStack.h \
     gtkStatsLabelStack.cxx gtkStatsLabelStack.h \
     gtkStatsMenuId.h \
     gtkStatsMenuId.h \
     gtkStatsMonitor.cxx gtkStatsMonitor.h gtkStatsMonitor.I \
     gtkStatsMonitor.cxx gtkStatsMonitor.h gtkStatsMonitor.I \
+    gtkStatsPianoRoll.cxx gtkStatsPianoRoll.h \
     gtkStatsServer.cxx gtkStatsServer.h \
     gtkStatsServer.cxx gtkStatsServer.h \
     gtkStatsStripChart.cxx gtkStatsStripChart.h
     gtkStatsStripChart.cxx gtkStatsStripChart.h
 
 
-//     gtkStatsPianoRoll.cxx gtkStatsPianoRoll.h \
-
   #if $[DEVELOP_GTKSTATS]
   #if $[DEVELOP_GTKSTATS]
     #define EXTRA_CDEFS $[EXTRA_CDEFS] DEVELOP_GTKSTATS
     #define EXTRA_CDEFS $[EXTRA_CDEFS] DEVELOP_GTKSTATS
   #endif
   #endif

+ 0 - 2
pandatool/src/gtk-stats/gtkStatsChartMenu.cxx

@@ -136,7 +136,6 @@ do_update() {
     }
     }
   }
   }
 
 
-  /*
   // Also a menu item for a piano roll (following a separator).
   // Also a menu item for a piano roll (following a separator).
   GtkWidget *sep = gtk_separator_menu_item_new();
   GtkWidget *sep = gtk_separator_menu_item_new();
   gtk_widget_show(sep);
   gtk_widget_show(sep);
@@ -151,7 +150,6 @@ do_update() {
 
 
   g_signal_connect_swapped(G_OBJECT(menu_item), "activate", 
   g_signal_connect_swapped(G_OBJECT(menu_item), "activate", 
 			   G_CALLBACK(handle_menu), (void *)(const void *)menu_def);
 			   G_CALLBACK(handle_menu), (void *)(const void *)menu_def);
-  */
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 11 - 0
pandatool/src/gtk-stats/gtkStatsLabel.cxx

@@ -89,6 +89,7 @@ GtkStatsLabel(GtkStatsMonitor *monitor, GtkStatsGraph *graph,
 
 
   _highlight = false;
   _highlight = false;
   _mouse_within = false;
   _mouse_within = false;
+  _height = height;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -111,6 +112,16 @@ get_widget() const {
   return _widget;
   return _widget;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GtkStatsLabel::get_height
+//       Access: Public
+//  Description: Returns the height of the label as we requested it.
+////////////////////////////////////////////////////////////////////
+int GtkStatsLabel::
+get_height() const {
+  return _height;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GtkStatsLabel::get_collector_index
 //     Function: GtkStatsLabel::get_collector_index
 //       Access: Public
 //       Access: Public

+ 2 - 0
pandatool/src/gtk-stats/gtkStatsLabel.h

@@ -40,6 +40,7 @@ public:
   ~GtkStatsLabel();
   ~GtkStatsLabel();
 
 
   GtkWidget *get_widget() const;
   GtkWidget *get_widget() const;
+  int get_height() const;
 
 
   int get_collector_index() const;
   int get_collector_index() const;
 
 
@@ -79,6 +80,7 @@ private:
 
 
   bool _highlight;
   bool _highlight;
   bool _mouse_within;
   bool _mouse_within;
+  int _height;
 
 
   static int _left_margin, _right_margin;
   static int _left_margin, _right_margin;
   static int _top_margin, _bottom_margin;
   static int _top_margin, _bottom_margin;

+ 31 - 0
pandatool/src/gtk-stats/gtkStatsLabelStack.cxx

@@ -51,6 +51,37 @@ get_widget() const {
   return _widget;
   return _widget;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GtkStatsLabelStack::get_label_y
+//       Access: Public
+//  Description: Returns the y position of the indicated label's bottom
+//               edge, relative to the indicated target widget.
+////////////////////////////////////////////////////////////////////
+int GtkStatsLabelStack::
+get_label_y(int label_index, GtkWidget *target_widget) const {
+  nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0);
+
+  // Assume all labels have the same height.
+  int height = _labels[0]->get_height();
+  int start_y = _widget->allocation.height - height * label_index;
+
+  int x, y;
+  gtk_widget_translate_coordinates(_widget, target_widget,
+				   0, start_y, &x, &y);
+  return y;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GtkStatsLabelStack::get_label_height
+//       Access: Public
+//  Description: Returns the height of the indicated label.
+////////////////////////////////////////////////////////////////////
+int GtkStatsLabelStack::
+get_label_height(int label_index) const {
+  nassertr(label_index >= 0 && label_index < (int)_labels.size(), 0);
+  return _labels[label_index]->get_height();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GtkStatsLabelStack::get_label_collector_index
 //     Function: GtkStatsLabelStack::get_label_collector_index
 //       Access: Public
 //       Access: Public

+ 2 - 0
pandatool/src/gtk-stats/gtkStatsLabelStack.h

@@ -40,6 +40,8 @@ public:
 
 
   GtkWidget *get_widget() const;
   GtkWidget *get_widget() const;
 
 
+  int get_label_y(int label_index, GtkWidget *target_widget) const;
+  int get_label_height(int label_index) const;
   int get_label_collector_index(int label_index) const;
   int get_label_collector_index(int label_index) const;
 
 
   void clear_labels();
   void clear_labels();

+ 1 - 3
pandatool/src/gtk-stats/gtkStatsMonitor.cxx

@@ -21,7 +21,7 @@
 #include "gtkStatsServer.h"
 #include "gtkStatsServer.h"
 #include "gtkStatsStripChart.h"
 #include "gtkStatsStripChart.h"
 #include "gtkStatsChartMenu.h"
 #include "gtkStatsChartMenu.h"
-//#include "gtkStatsPianoRoll.h"
+#include "gtkStatsPianoRoll.h"
 #include "gtkStatsMenuId.h"
 #include "gtkStatsMenuId.h"
 #include "pStatGraph.h"
 #include "pStatGraph.h"
 #include "pStatCollectorDef.h"
 #include "pStatCollectorDef.h"
@@ -344,14 +344,12 @@ open_strip_chart(int thread_index, int collector_index, bool show_level) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GtkStatsMonitor::
 void GtkStatsMonitor::
 open_piano_roll(int thread_index) {
 open_piano_roll(int thread_index) {
-  /*
   GtkStatsPianoRoll *graph = new GtkStatsPianoRoll(this, thread_index);
   GtkStatsPianoRoll *graph = new GtkStatsPianoRoll(this, thread_index);
   add_graph(graph);
   add_graph(graph);
 
 
   graph->set_time_units(_time_units);
   graph->set_time_units(_time_units);
   graph->set_scroll_speed(_scroll_speed);
   graph->set_scroll_speed(_scroll_speed);
   graph->set_pause(_pause);
   graph->set_pause(_pause);
-  */
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 227 - 325
pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx

@@ -19,13 +19,11 @@
 #include "gtkStatsPianoRoll.h"
 #include "gtkStatsPianoRoll.h"
 #include "gtkStatsMonitor.h"
 #include "gtkStatsMonitor.h"
 #include "numeric_types.h"
 #include "numeric_types.h"
+#include "gtkStatsLabelStack.h"
 
 
 static const int default_piano_roll_width = 400;
 static const int default_piano_roll_width = 400;
 static const int default_piano_roll_height = 200;
 static const int default_piano_roll_height = 200;
 
 
-bool GtkStatsPianoRoll::_window_class_registered = false;
-const char * const GtkStatsPianoRoll::_window_class_name = "piano";
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GtkStatsPianoRoll::Constructor
 //     Function: GtkStatsPianoRoll::Constructor
 //       Access: Public
 //       Access: Public
@@ -38,15 +36,30 @@ GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index) :
                  default_piano_roll_height),
                  default_piano_roll_height),
   GtkStatsGraph(monitor, thread_index)
   GtkStatsGraph(monitor, thread_index)
 {
 {
-  _left_margin = 128;
-  _right_margin = 8;
-  _top_margin = 16;
-  _bottom_margin = 8;
-
   // Let's show the units on the guide bar labels.  There's room.
   // Let's show the units on the guide bar labels.  There's room.
   set_guide_bar_units(get_guide_bar_units() | GBU_show_units);
   set_guide_bar_units(get_guide_bar_units() | GBU_show_units);
 
 
-  create_window();
+  // Add a DrawingArea widget on top of the graph, to display all of
+  // the scale units.
+  _scale_area = gtk_drawing_area_new();
+  g_signal_connect(G_OBJECT(_scale_area), "expose_event",  
+		   G_CALLBACK(expose_event_callback), this);
+  gtk_box_pack_start(GTK_BOX(_graph_vbox), _scale_area,
+		     FALSE, FALSE, 0);
+  gtk_widget_set_size_request(_scale_area, 0, 20);
+
+
+  gtk_widget_set_size_request(_graph_window, default_piano_roll_width,
+			      default_piano_roll_height);
+
+  gtk_widget_show_all(_window);  
+  gtk_widget_show(_window);
+
+  // Allow the window to be resized as small as the user likes.  We
+  // have to do this after the window has been shown; otherwise, it
+  // will affect the window's initial size.
+  gtk_widget_set_size_request(_window, 0, 0);
+
   clear_region();
   clear_region();
 }
 }
 
 
@@ -112,10 +125,7 @@ set_time_units(int unit_mask) {
     unit_mask |= (old_unit_mask & GBU_show_units);
     unit_mask |= (old_unit_mask & GBU_show_units);
     set_guide_bar_units(unit_mask);
     set_guide_bar_units(unit_mask);
 
 
-    RECT rect;
-    GetClientRect(_window, &rect);
-    rect.left = _right_margin;
-    InvalidateRect(_window, &rect, TRUE);
+    gtk_widget_queue_draw(_scale_area);
   }
   }
 }
 }
 
 
@@ -141,10 +151,8 @@ void GtkStatsPianoRoll::
 set_horizontal_scale(float time_width) {
 set_horizontal_scale(float time_width) {
   PStatPianoRoll::set_horizontal_scale(time_width);
   PStatPianoRoll::set_horizontal_scale(time_width);
 
 
-  RECT rect;
-  GetClientRect(_window, &rect);
-  rect.bottom = _top_margin;
-  InvalidateRect(_window, &rect, TRUE);
+  gtk_widget_queue_draw(_graph_window);
+  gtk_widget_queue_draw(_scale_area);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -154,8 +162,9 @@ set_horizontal_scale(float time_width) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GtkStatsPianoRoll::
 void GtkStatsPianoRoll::
 clear_region() {
 clear_region() {
-  RECT rect = { 0, 0, get_xsize(), get_ysize() };
-  FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
+  gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white);
+  gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, 0, 0, 
+		     get_xsize(), get_ysize());
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -171,7 +180,7 @@ begin_draw() {
   // Draw in the guide bars.
   // Draw in the guide bars.
   int num_guide_bars = get_num_guide_bars();
   int num_guide_bars = get_num_guide_bars();
   for (int i = 0; i < num_guide_bars; i++) {
   for (int i = 0; i < num_guide_bars; i++) {
-    draw_guide_bar(_bitmap_dc, get_guide_bar(i));
+    draw_guide_bar(_pixmap, get_guide_bar(i));
   }
   }
 }
 }
 
 
@@ -183,16 +192,15 @@ begin_draw() {
 void GtkStatsPianoRoll::
 void GtkStatsPianoRoll::
 draw_bar(int row, int from_x, int to_x) {
 draw_bar(int row, int from_x, int to_x) {
   if (row >= 0 && row < _label_stack.get_num_labels()) {
   if (row >= 0 && row < _label_stack.get_num_labels()) {
-    int y = _label_stack.get_label_y(row) - _graph_top;
+    int y = _label_stack.get_label_y(row, _graph_window);
     int height = _label_stack.get_label_height(row);
     int height = _label_stack.get_label_height(row);
 
 
-    RECT rect = { 
-      from_x, y - height + 2,
-      to_x, y - 2,
-    };
     int collector_index = get_label_collector(row);
     int collector_index = get_label_collector(row);
-    HBRUSH brush = get_collector_brush(collector_index);
-    FillRect(_bitmap_dc, &rect, brush);
+    GdkGC *gc = get_collector_gc(collector_index);
+    
+    gdk_draw_rectangle(_pixmap, gc, TRUE, 
+		       from_x, y - height + 2, 
+		       to_x - from_x, height - 4);
   }
   }
 }
 }
 
 
@@ -204,7 +212,7 @@ draw_bar(int row, int from_x, int to_x) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GtkStatsPianoRoll::
 void GtkStatsPianoRoll::
 end_draw() {
 end_draw() {
-  InvalidateRect(_graph_window, NULL, FALSE);
+  gtk_widget_queue_draw(_graph_window);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -220,218 +228,162 @@ idle() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::window_proc
-//       Access: Protected
-//  Description: 
-////////////////////////////////////////////////////////////////////
-LONG GtkStatsPianoRoll::
-window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
-  switch (msg) {
-  case WM_LBUTTONDOWN:
-    if (_potential_drag_mode == DM_new_guide_bar) {
-      set_drag_mode(DM_new_guide_bar);
-      SetCapture(_graph_window);
-      return 0;
-    }
-    break;
-
-  default:
-    break;
+//     Function: GtkStatsPianoRoll::additional_graph_window_paint
+//       Access: Protected, Virtual
+//  Description: This is called during the servicing of expose_event;
+//               it gives a derived class opportunity to do some
+//               further painting into the graph window.
+////////////////////////////////////////////////////////////////////
+void GtkStatsPianoRoll::
+additional_graph_window_paint() {
+  int num_user_guide_bars = get_num_user_guide_bars();
+  for (int i = 0; i < num_user_guide_bars; i++) {
+    draw_guide_bar(_graph_window->window, get_user_guide_bar(i));
   }
   }
-
-  return GtkStatsGraph::window_proc(hwnd, msg, wparam, lparam);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::graph_window_proc
-//       Access: Protected
-//  Description: 
-////////////////////////////////////////////////////////////////////
-LONG GtkStatsPianoRoll::
-graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
-  switch (msg) {
-  case WM_LBUTTONDOWN:
-    if (_potential_drag_mode == DM_none) {
-      set_drag_mode(DM_scale);
-      PN_int16 x = LOWORD(lparam);
-      _drag_scale_start = pixel_to_height(x);
-      SetCapture(_graph_window);
-      return 0;
-
-    } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) {
-      set_drag_mode(DM_guide_bar);
-      PN_int16 x = LOWORD(lparam);
-      _drag_start_x = x;
-      SetCapture(_graph_window);
-      return 0;
-    }
-    break;
-
-  case WM_MOUSEMOVE: 
-    if (_drag_mode == DM_none && _potential_drag_mode == DM_none) {
-      // When the mouse is over a color bar, highlight it.
-      PN_int16 x = LOWORD(lparam);
-      PN_int16 y = HIWORD(lparam);
-      _label_stack.highlight_label(get_collector_under_pixel(x, y));
-
-      // Now we want to get a WM_MOUSELEAVE when the mouse leaves the
-      // graph window.
-      TRACKMOUSEEVENT tme = {
-        sizeof(TRACKMOUSEEVENT),
-        TME_LEAVE,
-        _graph_window,
-        0
-      };
-      TrackMouseEvent(&tme);
-
-    } else {
-      // If the mouse is in some drag mode, stop highlighting.
-      _label_stack.highlight_label(-1);
-    }
-
-    if (_drag_mode == DM_scale) {
-      PN_int16 x = LOWORD(lparam);
-      float ratio = (float)x / (float)get_xsize();
-      if (ratio > 0.0f) {
-        set_horizontal_scale(_drag_scale_start / ratio);
-      }
-      return 0;
-
-    } else if (_drag_mode == DM_new_guide_bar) {
-      // We haven't created the new guide bar yet; we won't until the
-      // mouse comes within the graph's region.
-      PN_int16 x = LOWORD(lparam);
-      if (x >= 0 && x < get_xsize()) {
-        set_drag_mode(DM_guide_bar);
-        _drag_guide_bar = add_user_guide_bar(pixel_to_height(x));
-        return 0;
-      }
-
-    } else if (_drag_mode == DM_guide_bar) {
-      PN_int16 x = LOWORD(lparam);
-      move_user_guide_bar(_drag_guide_bar, pixel_to_height(x));
-      return 0;
-    }
-    break;
-
-  case WM_MOUSELEAVE:
-    // When the mouse leaves the graph, stop highlighting.
-    _label_stack.highlight_label(-1);
-    break;
-
-  case WM_LBUTTONUP:
-    if (_drag_mode == DM_scale) {
-      set_drag_mode(DM_none);
-      ReleaseCapture();
-      return 0;
-
-    } else if (_drag_mode == DM_guide_bar) {
-      PN_int16 x = LOWORD(lparam);
-      if (x < 0 || x >= get_xsize()) {
-        remove_user_guide_bar(_drag_guide_bar);
-      } else {
-        move_user_guide_bar(_drag_guide_bar, pixel_to_height(x));
+//     Function: GtkStatsPianoRoll::consider_drag_start
+//       Access: Protected, Virtual
+//  Description: Based on the mouse position within the graph window,
+//               look for draggable things the mouse might be hovering
+//               over and return the appropriate DragMode enum or
+//               DM_none if nothing is indicated.
+////////////////////////////////////////////////////////////////////
+GtkStatsGraph::DragMode GtkStatsPianoRoll::
+consider_drag_start(int graph_x, int graph_y) {
+  if (graph_y >= 0 && graph_y < get_ysize()) {
+    if (graph_x >= 0 && graph_x < get_xsize()) {
+      // See if the mouse is over a user-defined guide bar.
+      int x = graph_x;
+      float from_height = pixel_to_height(x - 2);
+      float to_height = pixel_to_height(x + 2);
+      _drag_guide_bar = find_user_guide_bar(from_height, to_height);
+      if (_drag_guide_bar >= 0) {
+        return DM_guide_bar;
       }
       }
-      set_drag_mode(DM_none);
-      ReleaseCapture();
-      return 0;
-    }
-    break;
 
 
-  case WM_LBUTTONDBLCLK:
-    {
-      // Double-clicking on a color bar in the graph is the same as
-      // double-clicking on the corresponding label.
-      PN_int16 x = LOWORD(lparam);
-      PN_int16 y = HIWORD(lparam);
-      clicked_label(get_collector_under_pixel(x, y));
-      return 0;
+    } else {
+      // The mouse is left or right of the graph; maybe create a new
+      // guide bar.
+      return DM_new_guide_bar;
     }
     }
-    break;
-
-  default:
-    break;
   }
   }
 
 
-  return GtkStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam);
+  return GtkStatsGraph::consider_drag_start(graph_x, graph_y);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::additional_window_paint
+//     Function: GtkStatsPianoRoll::handle_button_press
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: This is called during the servicing of WM_PAINT; it
-//               gives a derived class opportunity to do some further
-//               painting into the window (the outer window, not the
-//               graph window).
-////////////////////////////////////////////////////////////////////
-void GtkStatsPianoRoll::
-additional_window_paint(HDC hdc) {
-  // Draw in the labels for the guide bars.
-  HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT); 
-  SelectObject(hdc, hfnt);
-  SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
-  SetBkMode(hdc, TRANSPARENT);
-
-  int y = _top_margin;
-
-  int i;
-  int num_guide_bars = get_num_guide_bars();
-  for (i = 0; i < num_guide_bars; i++) {
-    draw_guide_label(hdc, y, get_guide_bar(i));
+//  Description: Called when the mouse button is depressed within the
+//               graph window.
+////////////////////////////////////////////////////////////////////
+gboolean GtkStatsPianoRoll::
+handle_button_press(GtkWidget *widget, int graph_x, int graph_y,
+		    bool double_click) {
+  if (double_click) {
+    // Double-clicking on a color bar in the graph is the same as
+    // double-clicking on the corresponding label.
+    clicked_label(get_collector_under_pixel(graph_x, graph_y));
+    return TRUE;
   }
   }
 
 
-  int num_user_guide_bars = get_num_user_guide_bars();
-  for (i = 0; i < num_user_guide_bars; i++) {
-    draw_guide_label(hdc, y, get_user_guide_bar(i));
+  if (_potential_drag_mode == DM_none) {
+    set_drag_mode(DM_scale);
+    _drag_scale_start = pixel_to_height(graph_x);
+    //SetCapture(_graph_window);
+    return TRUE;
+
+  } else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) {
+    set_drag_mode(DM_guide_bar);
+    _drag_start_x = graph_x;
+    //SetCapture(_graph_window);
+    return TRUE;
   }
   }
+
+  return GtkStatsGraph::handle_button_press(widget, graph_x, graph_y, 
+					    double_click);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::additional_graph_window_paint
+//     Function: GtkStatsPianoRoll::handle_button_release
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: This is called during the servicing of WM_PAINT; it
-//               gives a derived class opportunity to do some further
-//               painting into the window (the outer window, not the
-//               graph window).
-////////////////////////////////////////////////////////////////////
-void GtkStatsPianoRoll::
-additional_graph_window_paint(HDC hdc) {
-  int num_user_guide_bars = get_num_user_guide_bars();
-  for (int i = 0; i < num_user_guide_bars; i++) {
-    draw_guide_bar(hdc, get_user_guide_bar(i));
+//  Description: Called when the mouse button is released within the
+//               graph window.
+////////////////////////////////////////////////////////////////////
+gboolean GtkStatsPianoRoll::
+handle_button_release(GtkWidget *widget, int graph_x, int graph_y) {
+  if (_drag_mode == DM_scale) {
+    set_drag_mode(DM_none);
+    //ReleaseCapture();
+    return handle_motion(widget, graph_x, graph_y);
+    
+  } else if (_drag_mode == DM_guide_bar) {
+    if (graph_x < 0 || graph_x >= get_xsize()) {
+      remove_user_guide_bar(_drag_guide_bar);
+    } else {
+      move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x));
+    }
+    set_drag_mode(DM_none);
+    //ReleaseCapture();
+    return handle_motion(widget, graph_x, graph_y);
   }
   }
+
+  return GtkStatsGraph::handle_button_release(widget, graph_x, graph_y);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::consider_drag_start
+//     Function: GtkStatsPianoRoll::ns_motion_notify_event_callback
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: Based on the mouse position within the window's
-//               client area, look for draggable things the mouse
-//               might be hovering over and return the apprioprate
-//               DragMode enum or DM_none if nothing is indicated.
-////////////////////////////////////////////////////////////////////
-GtkStatsGraph::DragMode GtkStatsPianoRoll::
-consider_drag_start(int mouse_x, int mouse_y, int width, int height) {
-  if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) {
-    if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) {
-      // See if the mouse is over a user-defined guide bar.
-      int x = mouse_x - _graph_left;
-      float from_height = pixel_to_height(x - 2);
-      float to_height = pixel_to_height(x + 2);
-      _drag_guide_bar = find_user_guide_bar(from_height, to_height);
-      if (_drag_guide_bar >= 0) {
-        return DM_guide_bar;
-      }
+//  Description: Called when the mouse is moved within the
+//               graph window.
+////////////////////////////////////////////////////////////////////
+gboolean GtkStatsPianoRoll::
+handle_motion(GtkWidget *widget, int graph_x, int graph_y) {
+  if (_drag_mode == DM_none && _potential_drag_mode == DM_none) {
+    // When the mouse is over a color bar, highlight it.
+    _label_stack.highlight_label(get_collector_under_pixel(graph_x, graph_y));
+
+    /*
+    // Now we want to get a WM_MOUSELEAVE when the mouse leaves the
+    // graph window.
+    TRACKMOUSEEVENT tme = {
+      sizeof(TRACKMOUSEEVENT),
+      TME_LEAVE,
+      _graph_window,
+      0
+    };
+    TrackMouseEvent(&tme);
+    */
 
 
-    } else if (mouse_x < _left_margin - 2 ||
-               mouse_x > width - _right_margin + 2) {
-      // The mouse is left or right of the graph; maybe create a new
-      // guide bar.
-      return DM_new_guide_bar;
+  } else {
+    // If the mouse is in some drag mode, stop highlighting.
+    _label_stack.highlight_label(-1);
+  }
+
+  if (_drag_mode == DM_scale) {
+    float ratio = (float)graph_x / (float)get_xsize();
+    if (ratio > 0.0f) {
+      set_horizontal_scale(_drag_scale_start / ratio);
+    }
+    return TRUE;
+
+  } else if (_drag_mode == DM_new_guide_bar) {
+    // We haven't created the new guide bar yet; we won't until the
+    // mouse comes within the graph's region.
+    if (graph_x >= 0 && graph_x < get_xsize()) {
+      set_drag_mode(DM_guide_bar);
+      _drag_guide_bar = add_user_guide_bar(pixel_to_height(graph_x));
+      return TRUE;
     }
     }
+
+  } else if (_drag_mode == DM_guide_bar) {
+    move_user_guide_bar(_drag_guide_bar, pixel_to_height(graph_x));
+    return TRUE;
   }
   }
 
 
-  return GtkStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height);
+  return GtkStatsGraph::handle_motion(widget, graph_x, graph_y);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -451,7 +403,7 @@ get_collector_under_pixel(int xpoint, int ypoint) {
   int row = (get_ysize() - ypoint) / height;
   int row = (get_ysize() - ypoint) / height;
   if (row >= 0 && row < _label_stack.get_num_labels()) {
   if (row >= 0 && row < _label_stack.get_num_labels()) {
     return _label_stack.get_label_collector_index(row);
     return _label_stack.get_label_collector_index(row);
-  } else {
+  } else  {
     return -1;
     return -1;
   }
   }
 }
 }
@@ -465,10 +417,9 @@ void GtkStatsPianoRoll::
 update_labels() {
 update_labels() {
   _label_stack.clear_labels();
   _label_stack.clear_labels();
   for (int i = 0; i < get_num_labels(); i++) {
   for (int i = 0; i < get_num_labels(); i++) {
-    int label_index = 
-      _label_stack.add_label(GtkStatsGraph::_monitor, this,
-                             GtkStatsGraph::_thread_index,
-                             get_label_collector(i), true);
+    _label_stack.add_label(GtkStatsGraph::_monitor, this,
+			   GtkStatsGraph::_thread_index,
+			   get_label_collector(i), true);
   }
   }
   _labels_changed = false;
   _labels_changed = false;
 }
 }
@@ -480,26 +431,44 @@ update_labels() {
 //               graph.
 //               graph.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GtkStatsPianoRoll::
 void GtkStatsPianoRoll::
-draw_guide_bar(HDC hdc, const PStatGraph::GuideBar &bar) {
+draw_guide_bar(GdkDrawable *surface, const PStatGraph::GuideBar &bar) {
   int x = height_to_pixel(bar._height);
   int x = height_to_pixel(bar._height);
 
 
   if (x > 0 && x < get_xsize() - 1) {
   if (x > 0 && x < get_xsize() - 1) {
-    // Only draw it if it's not too close to either edge.
+    // Only draw it if it's not too close to the top.
     switch (bar._style) {
     switch (bar._style) {
     case GBS_target:
     case GBS_target:
-      SelectObject(hdc, _light_pen);
+      gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_light_gray);
       break;
       break;
 
 
     case GBS_user:
     case GBS_user:
-      SelectObject(hdc, _user_guide_bar_pen);
+      gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_user_guide_bar);
       break;
       break;
       
       
     case GBS_normal:
     case GBS_normal:
-      SelectObject(hdc, _dark_pen);
+      gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_dark_gray);
       break;
       break;
     }
     }
-    MoveToEx(hdc, x, 0, NULL);
-    LineTo(hdc, x, get_ysize());
+    gdk_draw_line(surface, _pixmap_gc, x, 0, x, get_ysize());
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GtkStatsPianoRoll::draw_guide_labels
+//       Access: Private
+//  Description: This is called during the servicing of expose_event.
+////////////////////////////////////////////////////////////////////
+void GtkStatsPianoRoll::
+draw_guide_labels() {
+  int i;
+  int num_guide_bars = get_num_guide_bars();
+  for (i = 0; i < num_guide_bars; i++) {
+    draw_guide_label(get_guide_bar(i));
+  }
+
+  int num_user_guide_bars = get_num_user_guide_bars();
+  for (i = 0; i < num_user_guide_bars; i++) {
+    draw_guide_label(get_user_guide_bar(i));
   }
   }
 }
 }
 
 
@@ -510,135 +479,68 @@ draw_guide_bar(HDC hdc, const PStatGraph::GuideBar &bar) {
 //               the top of the graph.
 //               the top of the graph.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GtkStatsPianoRoll::
 void GtkStatsPianoRoll::
-draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar) {
+draw_guide_label(const PStatGraph::GuideBar &bar) {
+  GdkGC *gc = gdk_gc_new(_scale_area->window);
+
   switch (bar._style) {
   switch (bar._style) {
   case GBS_target:
   case GBS_target:
-    SetTextColor(hdc, _light_color);
+    gdk_gc_set_rgb_fg_color(gc, &rgb_light_gray);
     break;
     break;
     
     
   case GBS_user:
   case GBS_user:
-    SetTextColor(hdc, _user_guide_bar_color);
+    gdk_gc_set_rgb_fg_color(gc, &rgb_user_guide_bar);
     break;
     break;
     
     
   case GBS_normal:
   case GBS_normal:
-    SetTextColor(hdc, _dark_color);
+    gdk_gc_set_rgb_fg_color(gc, &rgb_dark_gray);
     break;
     break;
   }
   }
 
 
   int x = height_to_pixel(bar._height);
   int x = height_to_pixel(bar._height);
   const string &label = bar._label;
   const string &label = bar._label;
-  SIZE size;
-  GetTextExtentPoint32(hdc, label.data(), label.length(), &size);
+
+  PangoLayout *layout = gtk_widget_create_pango_layout(_window, label.c_str());
+  int width, height;
+  pango_layout_get_pixel_size(layout, &width, &height);
 
 
   if (bar._style != GBS_user) {
   if (bar._style != GBS_user) {
-    float from_height = pixel_to_height(x - size.cx);
-    float to_height = pixel_to_height(x + size.cx);
+    float from_height = pixel_to_height(x - width);
+    float to_height = pixel_to_height(x + width);
     if (find_user_guide_bar(from_height, to_height) >= 0) {
     if (find_user_guide_bar(from_height, to_height) >= 0) {
       // Omit the label: there's a user-defined guide bar in the same space.
       // Omit the label: there's a user-defined guide bar in the same space.
+      g_object_unref(layout);
+      g_object_unref(gc);
       return;
       return;
     }
     }
   }
   }
 
 
-  int this_x = _graph_left + x - size.cx / 2;
   if (x >= 0 && x < get_xsize()) {
   if (x >= 0 && x < get_xsize()) {
-    TextOut(hdc, this_x, y,
-            label.data(), label.length()); 
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::create_window
-//       Access: Private
-//  Description: Creates the window for this strip chart.
-////////////////////////////////////////////////////////////////////
-void GtkStatsPianoRoll::
-create_window() {
-  if (_window) {
-    return;
-  }
-
-  HINSTANCE application = GetModuleHandle(NULL);
-  register_window_class(application);
-
-  const PStatClientData *client_data = 
-    GtkStatsGraph::_monitor->get_client_data();
-  string thread_name = client_data->get_thread_name(GtkStatsGraph::_thread_index);
-  string window_title = thread_name + " thread piano roll";
-
-
-  RECT win_rect = { 
-    0, 0,
-    _left_margin + get_xsize() + _right_margin, 
-    _top_margin + get_ysize() + _bottom_margin
-  };  
-  
-  // compute window size based on desired client area size
-  AdjustWindowRect(&win_rect, graph_window_style, FALSE);
-
-  _window = 
-    CreateWindow(_window_class_name, window_title.c_str(), graph_window_style,
-                 CW_USEDEFAULT, CW_USEDEFAULT,
-                 win_rect.right - win_rect.left,
-                 win_rect.bottom - win_rect.top,
-                 GtkStatsGraph::_monitor->get_window(), NULL, application, 0);
-  if (!_window) {
-    nout << "Could not create PianoRoll window!\n";
-    exit(1);
+    // Now convert our x to a coordinate within our drawing area.
+    int junk_y;
+    
+    // The x coordinate comes from the graph_window.
+    gtk_widget_translate_coordinates(_graph_window, _scale_area,
+				     x, 0,
+				     &x, &junk_y);
+    
+    int this_x = x - width / 2;
+    gdk_draw_layout(_scale_area->window, gc, this_x, 
+		    _scale_area->allocation.height - height, layout);
   }
   }
-
-  SetWindowLongPtr(_window, 0, (LONG_PTR)this);
-  setup_label_stack();
-
-  // Ensure that the window is on top of the stack.
-  SetWindowPos(_window, HWND_TOP, 0, 0, 0, 0, 
-               SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
+    
+  g_object_unref(layout);
+  g_object_unref(gc);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::register_window_class
+//     Function: GtkStatsPianoRoll::expose_event_callback
 //       Access: Private, Static
 //       Access: Private, Static
-//  Description: Registers the window class for the pianoRoll window, if
-//               it has not already been registered.
+//  Description: Draws in the scale labels.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void GtkStatsPianoRoll::
-register_window_class(HINSTANCE application) {
-  if (_window_class_registered) {
-    return;
-  }
+gboolean GtkStatsPianoRoll::
+expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
+  GtkStatsPianoRoll *self = (GtkStatsPianoRoll *)data;
+  self->draw_guide_labels();
 
 
-  WNDCLASS wc;
-
-  ZeroMemory(&wc, sizeof(WNDCLASS));
-  wc.style = 0;
-  wc.lpfnWndProc = (WNDPROC)static_window_proc;
-  wc.hInstance = application;
-  wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-  wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
-  wc.lpszMenuName = NULL;
-  wc.lpszClassName = _window_class_name;
-
-  // Reserve space to associate the this pointer with the window.
-  wc.cbWndExtra = sizeof(GtkStatsPianoRoll *);
-  
-  if (!RegisterClass(&wc)) {
-    nout << "Could not register PianoRoll window class!\n";
-    exit(1);
-  }
-
-  _window_class_registered = true;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: GtkStatsPianoRoll::static_window_proc
-//       Access: Private, Static
-//  Description: 
-////////////////////////////////////////////////////////////////////
-LONG WINAPI GtkStatsPianoRoll::
-static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
-  GtkStatsPianoRoll *self = (GtkStatsPianoRoll *)GetWindowLongPtr(hwnd, 0);
-  if (self != (GtkStatsPianoRoll *)NULL && self->_window == hwnd) {
-    return self->window_proc(hwnd, msg, wparam, lparam);
-  } else {
-    return DefWindowProc(hwnd, msg, wparam, lparam);
-  }
+  return TRUE;
 }
 }

+ 13 - 16
pandatool/src/gtk-stats/gtkStatsPianoRoll.h

@@ -25,7 +25,7 @@
 #include "pStatPianoRoll.h"
 #include "pStatPianoRoll.h"
 #include "pointerTo.h"
 #include "pointerTo.h"
 
 
-#include <windows.h>
+#include <gtk/gtk.h>
 
 
 class GtkStatsMonitor;
 class GtkStatsMonitor;
 
 
@@ -55,26 +55,23 @@ protected:
   virtual void end_draw();
   virtual void end_draw();
   virtual void idle();
   virtual void idle();
 
 
-  LONG window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
-  virtual LONG graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
-  virtual void additional_window_paint(HDC hdc);
-  virtual void additional_graph_window_paint(HDC hdc);
-  virtual DragMode consider_drag_start(int mouse_x, int mouse_y, 
-                                       int width, int height);
+  virtual void additional_graph_window_paint();
+  virtual DragMode consider_drag_start(int graph_x, int graph_y);
+
+  virtual gboolean handle_button_press(GtkWidget *widget, int graph_x, int graph_y,
+				       bool double_click);
+  virtual gboolean handle_button_release(GtkWidget *widget, int graph_x, int graph_y);
+  virtual gboolean handle_motion(GtkWidget *widget, int graph_x, int graph_y);
 
 
 private:
 private:
   int get_collector_under_pixel(int xpoint, int ypoint);
   int get_collector_under_pixel(int xpoint, int ypoint);
   void update_labels();
   void update_labels();
-  void draw_guide_bar(HDC hdc, const GuideBar &bar);
-  void draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar);
-
-  void create_window();
-  static void register_window_class(HINSTANCE application);
-
-  static LONG GTKAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+  void draw_guide_bar(GdkDrawable *surface, const PStatGraph::GuideBar &bar);
+  void draw_guide_labels();
+  void draw_guide_label(const PStatGraph::GuideBar &bar);
 
 
-  static bool _window_class_registered;
-  static const char * const _window_class_name;
+  static gboolean expose_event_callback(GtkWidget *widget, 
+					GdkEventExpose *event, gpointer data);
 };
 };
 
 
 #endif
 #endif

+ 2 - 1
pandatool/src/gtk-stats/gtkStatsStripChart.cxx

@@ -79,7 +79,8 @@ GtkStatsStripChart(GtkStatsMonitor *monitor, int thread_index,
   gtk_widget_set_size_request(_scale_area, 40, 0);
   gtk_widget_set_size_request(_scale_area, 40, 0);
 
 
 
 
-  gtk_widget_set_size_request(_graph_window, 400, 100);
+  gtk_widget_set_size_request(_graph_window, default_strip_chart_width,
+			      default_strip_chart_height);
 
 
   gtk_widget_show_all(_window);  
   gtk_widget_show_all(_window);  
   gtk_widget_show(_window);
   gtk_widget_show(_window);

+ 0 - 4
pandatool/src/gtk-stats/gtkStatsStripChart.h

@@ -80,16 +80,12 @@ private:
 					GdkEventExpose *event, gpointer data);
 					GdkEventExpose *event, gpointer data);
 
 
 private:
 private:
-
   int _brush_origin;
   int _brush_origin;
   string _net_value_text;
   string _net_value_text;
 
 
   GtkWidget *_top_hbox;
   GtkWidget *_top_hbox;
   GtkWidget *_smooth_check_box;
   GtkWidget *_smooth_check_box;
   GtkWidget *_total_label;
   GtkWidget *_total_label;
-
-  static bool _window_class_registered;
-  static const char * const _window_class_name;
 };
 };
 
 
 #endif
 #endif