diff --git a/pandatool/src/gtk-stats/Sources.pp b/pandatool/src/gtk-stats/Sources.pp index 34aad99125..54efb53476 100644 --- a/pandatool/src/gtk-stats/Sources.pp +++ b/pandatool/src/gtk-stats/Sources.pp @@ -20,11 +20,10 @@ gtkStatsLabelStack.cxx gtkStatsLabelStack.h \ gtkStatsMenuId.h \ gtkStatsMonitor.cxx gtkStatsMonitor.h gtkStatsMonitor.I \ + gtkStatsPianoRoll.cxx gtkStatsPianoRoll.h \ gtkStatsServer.cxx gtkStatsServer.h \ gtkStatsStripChart.cxx gtkStatsStripChart.h -// gtkStatsPianoRoll.cxx gtkStatsPianoRoll.h \ - #if $[DEVELOP_GTKSTATS] #define EXTRA_CDEFS $[EXTRA_CDEFS] DEVELOP_GTKSTATS #endif diff --git a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx index 946371dcf7..6a524e12b8 100755 --- a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx +++ b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx @@ -136,7 +136,6 @@ do_update() { } } - /* // Also a menu item for a piano roll (following a separator). GtkWidget *sep = gtk_separator_menu_item_new(); gtk_widget_show(sep); @@ -151,7 +150,6 @@ do_update() { g_signal_connect_swapped(G_OBJECT(menu_item), "activate", G_CALLBACK(handle_menu), (void *)(const void *)menu_def); - */ } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/gtk-stats/gtkStatsLabel.cxx b/pandatool/src/gtk-stats/gtkStatsLabel.cxx index 97bdc59f6e..bf92fdb95c 100644 --- a/pandatool/src/gtk-stats/gtkStatsLabel.cxx +++ b/pandatool/src/gtk-stats/gtkStatsLabel.cxx @@ -89,6 +89,7 @@ GtkStatsLabel(GtkStatsMonitor *monitor, GtkStatsGraph *graph, _highlight = false; _mouse_within = false; + _height = height; } //////////////////////////////////////////////////////////////////// @@ -111,6 +112,16 @@ get_widget() const { 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 // Access: Public diff --git a/pandatool/src/gtk-stats/gtkStatsLabel.h b/pandatool/src/gtk-stats/gtkStatsLabel.h index f81f1d1b3e..9c8f81887b 100644 --- a/pandatool/src/gtk-stats/gtkStatsLabel.h +++ b/pandatool/src/gtk-stats/gtkStatsLabel.h @@ -40,6 +40,7 @@ public: ~GtkStatsLabel(); GtkWidget *get_widget() const; + int get_height() const; int get_collector_index() const; @@ -79,6 +80,7 @@ private: bool _highlight; bool _mouse_within; + int _height; static int _left_margin, _right_margin; static int _top_margin, _bottom_margin; diff --git a/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx b/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx index d38d9df5b6..815d2bdb07 100755 --- a/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx +++ b/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx @@ -51,6 +51,37 @@ get_widget() const { 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 // Access: Public diff --git a/pandatool/src/gtk-stats/gtkStatsLabelStack.h b/pandatool/src/gtk-stats/gtkStatsLabelStack.h index 4e8563d218..e6a8ecb77d 100755 --- a/pandatool/src/gtk-stats/gtkStatsLabelStack.h +++ b/pandatool/src/gtk-stats/gtkStatsLabelStack.h @@ -40,6 +40,8 @@ public: 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; void clear_labels(); diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx index 04b2d5586f..e5be25ee3c 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx @@ -21,7 +21,7 @@ #include "gtkStatsServer.h" #include "gtkStatsStripChart.h" #include "gtkStatsChartMenu.h" -//#include "gtkStatsPianoRoll.h" +#include "gtkStatsPianoRoll.h" #include "gtkStatsMenuId.h" #include "pStatGraph.h" #include "pStatCollectorDef.h" @@ -344,14 +344,12 @@ open_strip_chart(int thread_index, int collector_index, bool show_level) { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: open_piano_roll(int thread_index) { - /* GtkStatsPianoRoll *graph = new GtkStatsPianoRoll(this, thread_index); add_graph(graph); graph->set_time_units(_time_units); graph->set_scroll_speed(_scroll_speed); graph->set_pause(_pause); - */ } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx b/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx index 95e700c8a7..4e78477c0b 100644 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx +++ b/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx @@ -19,13 +19,11 @@ #include "gtkStatsPianoRoll.h" #include "gtkStatsMonitor.h" #include "numeric_types.h" +#include "gtkStatsLabelStack.h" static const int default_piano_roll_width = 400; 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 // Access: Public @@ -38,15 +36,30 @@ GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index) : default_piano_roll_height), 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. 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(); } @@ -112,10 +125,7 @@ set_time_units(int unit_mask) { unit_mask |= (old_unit_mask & GBU_show_units); 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) { 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:: 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. int num_guide_bars = get_num_guide_bars(); 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:: draw_bar(int row, int from_x, int to_x) { 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); - RECT rect = { - from_x, y - height + 2, - to_x, y - 2, - }; 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:: end_draw() { - InvalidateRect(_graph_window, NULL, FALSE); + gtk_widget_queue_draw(_graph_window); } //////////////////////////////////////////////////////////////////// @@ -219,203 +227,35 @@ 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; - } - - 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)); - } - 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; - } - break; - - default: - break; - } - - return GtkStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::additional_window_paint -// 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)); - } - - 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)); - } -} - //////////////////////////////////////////////////////////////////// // Function: GtkStatsPianoRoll::additional_graph_window_paint // 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). +// 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(HDC hdc) { +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(hdc, get_user_guide_bar(i)); + draw_guide_bar(_graph_window->window, get_user_guide_bar(i)); } } //////////////////////////////////////////////////////////////////// // Function: GtkStatsPianoRoll::consider_drag_start // 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. +// 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 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()) { +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 = mouse_x - _graph_left; + 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); @@ -423,15 +263,127 @@ consider_drag_start(int mouse_x, int mouse_y, int width, int height) { return DM_guide_bar; } - } else if (mouse_x < _left_margin - 2 || - mouse_x > width - _right_margin + 2) { + } else { // The mouse is left or right of the graph; maybe create a new // guide bar. return DM_new_guide_bar; } } - return GtkStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height); + return GtkStatsGraph::consider_drag_start(graph_x, graph_y); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::handle_button_press +// Access: Protected, Virtual +// 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; + } + + 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::handle_button_release +// Access: Protected, Virtual +// 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::ns_motion_notify_event_callback +// Access: Protected, Virtual +// 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 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::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; if (row >= 0 && row < _label_stack.get_num_labels()) { return _label_stack.get_label_collector_index(row); - } else { + } else { return -1; } } @@ -465,10 +417,9 @@ void GtkStatsPianoRoll:: update_labels() { _label_stack.clear_labels(); 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; } @@ -480,26 +431,44 @@ update_labels() { // graph. //////////////////////////////////////////////////////////////////// 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); 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) { case GBS_target: - SelectObject(hdc, _light_pen); + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_light_gray); break; case GBS_user: - SelectObject(hdc, _user_guide_bar_pen); + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_user_guide_bar); break; case GBS_normal: - SelectObject(hdc, _dark_pen); + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_dark_gray); 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. //////////////////////////////////////////////////////////////////// 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) { case GBS_target: - SetTextColor(hdc, _light_color); + gdk_gc_set_rgb_fg_color(gc, &rgb_light_gray); break; case GBS_user: - SetTextColor(hdc, _user_guide_bar_color); + gdk_gc_set_rgb_fg_color(gc, &rgb_user_guide_bar); break; case GBS_normal: - SetTextColor(hdc, _dark_color); + gdk_gc_set_rgb_fg_color(gc, &rgb_dark_gray); break; } int x = height_to_pixel(bar._height); 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) { - 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) { // Omit the label: there's a user-defined guide bar in the same space. + g_object_unref(layout); + g_object_unref(gc); return; } } - int this_x = _graph_left + x - size.cx / 2; if (x >= 0 && x < get_xsize()) { - TextOut(hdc, this_x, y, - label.data(), label.length()); + // 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); } + + g_object_unref(layout); + g_object_unref(gc); } //////////////////////////////////////////////////////////////////// -// 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); - } - - 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); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::register_window_class +// Function: GtkStatsPianoRoll::expose_event_callback // 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; } diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.h b/pandatool/src/gtk-stats/gtkStatsPianoRoll.h index 4d42dab846..30dc7506d8 100644 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.h +++ b/pandatool/src/gtk-stats/gtkStatsPianoRoll.h @@ -25,7 +25,7 @@ #include "pStatPianoRoll.h" #include "pointerTo.h" -#include +#include class GtkStatsMonitor; @@ -55,26 +55,23 @@ protected: virtual void end_draw(); 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: int get_collector_under_pixel(int xpoint, int ypoint); 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 draw_guide_bar(GdkDrawable *surface, const PStatGraph::GuideBar &bar); + void draw_guide_labels(); + void draw_guide_label(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); - - static bool _window_class_registered; - static const char * const _window_class_name; + static gboolean expose_event_callback(GtkWidget *widget, + GdkEventExpose *event, gpointer data); }; #endif diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx b/pandatool/src/gtk-stats/gtkStatsStripChart.cxx index 6e6db4c3cc..90d574511c 100644 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx +++ b/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(_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(_window); diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.h b/pandatool/src/gtk-stats/gtkStatsStripChart.h index b73ccef33d..7eae8579ef 100644 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.h +++ b/pandatool/src/gtk-stats/gtkStatsStripChart.h @@ -80,16 +80,12 @@ private: GdkEventExpose *event, gpointer data); private: - int _brush_origin; string _net_value_text; GtkWidget *_top_hbox; GtkWidget *_smooth_check_box; GtkWidget *_total_label; - - static bool _window_class_registered; - static const char * const _window_class_name; }; #endif