From d1f039f707bd84787d7c3075cb9ef9fabb0b16c9 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 17 Jan 2006 04:04:23 +0000 Subject: [PATCH] crude initial start of gtk-2.0 port of pstats server --- pandatool/src/gtk-stats/Sources.pp | 42 +- pandatool/src/gtk-stats/gtkStats.cxx | 124 +-- pandatool/src/gtk-stats/gtkStats.h | 24 +- .../gtk-stats/gtkStatsBadVersionWindow.cxx | 73 -- .../src/gtk-stats/gtkStatsBadVersionWindow.h | 45 -- pandatool/src/gtk-stats/gtkStatsChartMenu.cxx | 209 +++++ ...StatsPianoWindow.h => gtkStatsChartMenu.h} | 45 +- pandatool/src/gtk-stats/gtkStatsGraph.cxx | 395 ++++++++++ pandatool/src/gtk-stats/gtkStatsGraph.h | 142 ++++ pandatool/src/gtk-stats/gtkStatsGuide.cxx | 88 --- pandatool/src/gtk-stats/gtkStatsGuide.h | 47 -- pandatool/src/gtk-stats/gtkStatsLabel.cxx | 212 ++--- pandatool/src/gtk-stats/gtkStatsLabel.h | 59 +- .../src/gtk-stats/gtkStatsLabelStack.cxx | 147 ++++ pandatool/src/gtk-stats/gtkStatsLabelStack.h | 62 ++ .../src/gtk-stats/gtkStatsMainWindow.cxx | 141 ---- pandatool/src/gtk-stats/gtkStatsMainWindow.h | 51 -- .../gtkBase.h => gtk-stats/gtkStatsMenuId.h} | 42 +- pandatool/src/gtk-stats/gtkStatsMonitor.I | 47 ++ pandatool/src/gtk-stats/gtkStatsMonitor.cxx | 553 +++++++++++-- pandatool/src/gtk-stats/gtkStatsMonitor.h | 84 +- pandatool/src/gtk-stats/gtkStatsPianoRoll.I | 17 - pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx | 725 +++++++++++++----- pandatool/src/gtk-stats/gtkStatsPianoRoll.h | 73 +- .../src/gtk-stats/gtkStatsPianoWindow.cxx | 164 ---- pandatool/src/gtk-stats/gtkStatsServer.cxx | 3 +- pandatool/src/gtk-stats/gtkStatsServer.h | 8 +- pandatool/src/gtk-stats/gtkStatsStripChart.I | 17 - .../src/gtk-stats/gtkStatsStripChart.cxx | 600 ++++++++------- pandatool/src/gtk-stats/gtkStatsStripChart.h | 76 +- .../src/gtk-stats/gtkStatsStripWindow.cxx | 459 ----------- pandatool/src/gtk-stats/gtkStatsStripWindow.h | 78 -- pandatool/src/gtk-stats/gtkStatsWindow.cxx | 210 ----- pandatool/src/gtk-stats/gtkStatsWindow.h | 69 -- .../src/gtk-stats/gtkstats_composite1.cxx | 9 + pandatool/src/gtk-stats/scribble.cc | 201 ----- pandatool/src/gtkbase/Sources.pp | 18 - pandatool/src/gtkbase/basicGtkDialog.cxx | 69 -- pandatool/src/gtkbase/basicGtkDialog.h | 48 -- pandatool/src/gtkbase/basicGtkWindow.cxx | 140 ---- pandatool/src/gtkbase/basicGtkWindow.h | 60 -- pandatool/src/gtkbase/gtkBase.cxx | 76 -- .../src/gtkbase/request_initial_size.cxx | 46 -- pandatool/src/gtkbase/request_initial_size.h | 28 - 44 files changed, 2748 insertions(+), 3078 deletions(-) delete mode 100644 pandatool/src/gtk-stats/gtkStatsBadVersionWindow.cxx delete mode 100644 pandatool/src/gtk-stats/gtkStatsBadVersionWindow.h create mode 100755 pandatool/src/gtk-stats/gtkStatsChartMenu.cxx rename pandatool/src/gtk-stats/{gtkStatsPianoWindow.h => gtkStatsChartMenu.h} (52%) mode change 100644 => 100755 create mode 100755 pandatool/src/gtk-stats/gtkStatsGraph.cxx create mode 100755 pandatool/src/gtk-stats/gtkStatsGraph.h delete mode 100644 pandatool/src/gtk-stats/gtkStatsGuide.cxx delete mode 100644 pandatool/src/gtk-stats/gtkStatsGuide.h create mode 100755 pandatool/src/gtk-stats/gtkStatsLabelStack.cxx create mode 100755 pandatool/src/gtk-stats/gtkStatsLabelStack.h delete mode 100644 pandatool/src/gtk-stats/gtkStatsMainWindow.cxx delete mode 100644 pandatool/src/gtk-stats/gtkStatsMainWindow.h rename pandatool/src/{gtkbase/gtkBase.h => gtk-stats/gtkStatsMenuId.h} (58%) mode change 100644 => 100755 create mode 100755 pandatool/src/gtk-stats/gtkStatsMonitor.I delete mode 100644 pandatool/src/gtk-stats/gtkStatsPianoRoll.I delete mode 100644 pandatool/src/gtk-stats/gtkStatsPianoWindow.cxx delete mode 100644 pandatool/src/gtk-stats/gtkStatsStripChart.I delete mode 100644 pandatool/src/gtk-stats/gtkStatsStripWindow.cxx delete mode 100644 pandatool/src/gtk-stats/gtkStatsStripWindow.h delete mode 100644 pandatool/src/gtk-stats/gtkStatsWindow.cxx delete mode 100644 pandatool/src/gtk-stats/gtkStatsWindow.h create mode 100755 pandatool/src/gtk-stats/gtkstats_composite1.cxx delete mode 100644 pandatool/src/gtk-stats/scribble.cc delete mode 100644 pandatool/src/gtkbase/Sources.pp delete mode 100644 pandatool/src/gtkbase/basicGtkDialog.cxx delete mode 100644 pandatool/src/gtkbase/basicGtkDialog.h delete mode 100644 pandatool/src/gtkbase/basicGtkWindow.cxx delete mode 100644 pandatool/src/gtkbase/basicGtkWindow.h delete mode 100644 pandatool/src/gtkbase/gtkBase.cxx delete mode 100644 pandatool/src/gtkbase/request_initial_size.cxx delete mode 100644 pandatool/src/gtkbase/request_initial_size.h diff --git a/pandatool/src/gtk-stats/Sources.pp b/pandatool/src/gtk-stats/Sources.pp index 50eb05ddaf..db98d6b637 100644 --- a/pandatool/src/gtk-stats/Sources.pp +++ b/pandatool/src/gtk-stats/Sources.pp @@ -1,27 +1,33 @@ -#define BUILD_DIRECTORY $[and $[HAVE_GTKMM],$[HAVE_NET]] -#define USE_PACKAGES net gtkmm +#define BUILD_DIRECTORY $[and $[HAVE_GTK],$[HAVE_NET]] +#define USE_PACKAGES net gtk #begin bin_target - #define TARGET gtk-stats + // We rename TARGET to gtk-pstats on Windows, so it won't compete + // with Windows-native pstats. + #define TARGET $[if $[WINDOWS_PLATFORM],gtk-pstats,pstats] #define LOCAL_LIBS \ - gtkbase progbase pstatserver + progbase pstatserver #define OTHER_LIBS \ - pstatclient:c linmath:c putil:c net:c express:c panda:m \ - interrogatedb:c dtoolutil:c dtoolbase:c prc:c dconfig:c dtoolconfig:m dtool:m - #define UNIX_SYS_LIBS \ - m + pstatclient:c linmath:c putil:c net:c express:c pandaexpress:m panda:m \ + dtoolutil:c dtoolbase:c prc:c dconfig:c dtoolconfig:m dtool:m \ + pystub #define SOURCES \ - gtkStats.cxx gtkStats.h \ - gtkStatsBadVersionWindow.cxx gtkStatsBadVersionWindow.h \ - gtkStatsGuide.cxx gtkStatsGuide.h \ - gtkStatsLabel.cxx gtkStatsLabel.h gtkStatsMainWindow.cxx \ - gtkStatsMainWindow.h gtkStatsMonitor.cxx gtkStatsMonitor.h \ - gtkStatsPianoRoll.I gtkStatsPianoRoll.cxx gtkStatsPianoRoll.h \ - gtkStatsPianoWindow.cxx gtkStatsPianoWindow.h gtkStatsServer.cxx \ - gtkStatsServer.h gtkStatsStripChart.I gtkStatsStripChart.cxx \ - gtkStatsStripChart.h gtkStatsStripWindow.cxx gtkStatsStripWindow.h \ - gtkStatsWindow.cxx gtkStatsWindow.h + gtkStats.cxx \ + gtkStatsGraph.cxx gtkStatsGraph.h \ + gtkStatsLabel.cxx gtkStatsLabel.h \ + gtkStatsLabelStack.cxx gtkStatsLabelStack.h \ + gtkStatsMenuId.h \ + gtkStatsMonitor.cxx gtkStatsMonitor.h gtkStatsMonitor.I \ + gtkStatsServer.cxx gtkStatsServer.h \ + gtkStatsStripChart.cxx gtkStatsStripChart.h + +// gtkStatsChartMenu.cxx gtkStatsChartMenu.h \ +// gtkStatsPianoRoll.cxx gtkStatsPianoRoll.h \ + + #if $[DEVELOP_GTKSTATS] + #define EXTRA_CDEFS $[EXTRA_CDEFS] DEVELOP_GTKSTATS + #endif #end bin_target diff --git a/pandatool/src/gtk-stats/gtkStats.cxx b/pandatool/src/gtk-stats/gtkStats.cxx index 9e252ce93b..c93eecd59d 100644 --- a/pandatool/src/gtk-stats/gtkStats.cxx +++ b/pandatool/src/gtk-stats/gtkStats.cxx @@ -1,5 +1,5 @@ // Filename: gtkStats.cxx -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -16,67 +16,85 @@ // //////////////////////////////////////////////////////////////////// +#include "pandatoolbase.h" #include "gtkStats.h" -#include "gtkStatsMainWindow.h" - -#include "pStatServer.h" +#include "gtkStatsServer.h" #include "config_pstats.h" -#include +GtkWidget *main_window; +static GtkStatsServer *server = NULL; -GtkStatsMainWindow *GtkStats::_main_window = NULL; - -//////////////////////////////////////////////////////////////////// -// Function: GtkStats::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkStats:: -GtkStats() { - set_program_description - ("This is a fancy GUI PStats server that listens on a TCP port for a " - "connection from a PStatClient in a Panda player. It will then " - "draw strip charts illustrating the performance stats as reported " - "by the player."); - - add_option - ("p", "port", 0, - "Specify the TCP port to listen for connections on. By default, this " - "is taken from the pstats-host Config variable.", - &GtkStats::dispatch_int, NULL, &_port); - - _port = pstats_port; +static gboolean +delete_event(GtkWidget *widget, + GdkEvent *event, gpointer data) { + // Returning FALSE to indicate we should destroy the main window + // when the user selects "close". + return FALSE; } -//////////////////////////////////////////////////////////////////// -// Function: GtkStats::run -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStats:: -run() { - new GtkStatsMainWindow(_port); - - main_loop(); +static void +destroy(GtkWidget *widget, gpointer data) { + gtk_main_quit(); } -//////////////////////////////////////////////////////////////////// -// Function: GtkStats::quit -// Access: Public, Static -// Description: Call this to cleanly shut down the program. -//////////////////////////////////////////////////////////////////// -void GtkStats:: -quit() { - if (_main_window != (GtkStatsMainWindow *)NULL) { - _main_window->destruct(); +static gboolean +timer(gpointer data) { + server->poll(); + + return TRUE; +} + +int +main(int argc, char *argv[]) { + gtk_init(&argc, &argv); + + main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + gtk_window_set_title(GTK_WINDOW(main_window), "PStats"); + + // Connect the delete and destroy events, so the user can exit the + // application by closing the main window. + g_signal_connect(G_OBJECT(main_window), "delete_event", + G_CALLBACK(delete_event), NULL); + + g_signal_connect(G_OBJECT(main_window), "destroy", + G_CALLBACK(destroy), NULL); + + ostringstream stream; + stream << "Listening on port " << pstats_port; + string str = stream.str(); + GtkWidget *label = gtk_label_new(str.c_str()); + gtk_container_add(GTK_CONTAINER(main_window), label); + gtk_widget_show(label); + + // Create the server object. + server = new GtkStatsServer; + if (!server->listen()) { + ostringstream stream; + stream + << "Unable to open port " << pstats_port + << ". Try specifying a different\n" + << "port number using pstats-port in your Config file."; + string str = stream.str(); + + GtkWidget *dialog = + gtk_message_dialog_new(GTK_WINDOW(main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + str.c_str()); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + exit(1); } - Gtk::Main::quit(); -} + gtk_widget_show(main_window); -int main(int argc, char *argv[]) { - GtkStats prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; + // Set up a timer to poll the pstats every so often. + g_timeout_add(200, timer, NULL); + + // Now get lost in the message loop. + gtk_main(); + + return (0); } diff --git a/pandatool/src/gtk-stats/gtkStats.h b/pandatool/src/gtk-stats/gtkStats.h index 804b8bf16b..630594f3aa 100644 --- a/pandatool/src/gtk-stats/gtkStats.h +++ b/pandatool/src/gtk-stats/gtkStats.h @@ -1,5 +1,5 @@ // Filename: gtkStats.h -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -19,27 +19,11 @@ #ifndef GTKSTATS_H #define GTKSTATS_H -#include "pandatoolbase.h" +#include "pStatServer.h" -#include "gtkBase.h" +#include -class GtkStatsMainWindow; - -//////////////////////////////////////////////////////////////////// -// Class : GtkStats -// Description : A fancy graphical pstats server written using gtk+ -// (actually, Gtk--, the C++ layer over gtk+). -//////////////////////////////////////////////////////////////////// -class GtkStats : public GtkBase { -public: - GtkStats(); - - void run(); - static void quit(); - - int _port; - static GtkStatsMainWindow *_main_window; -}; +extern GtkWidget *main_window; #endif diff --git a/pandatool/src/gtk-stats/gtkStatsBadVersionWindow.cxx b/pandatool/src/gtk-stats/gtkStatsBadVersionWindow.cxx deleted file mode 100644 index 0095c75525..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsBadVersionWindow.cxx +++ /dev/null @@ -1,73 +0,0 @@ -// Filename: gtkStatsBadVersionWindow.cxx -// Created by: drose (18May01) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "gtkStatsBadVersionWindow.h" -#include "gtkStatsMonitor.h" - -#include "string_utils.h" - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsBadVersionWindow::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkStatsBadVersionWindow:: -GtkStatsBadVersionWindow(GtkStatsMonitor *monitor, - int client_major, int client_minor, - int server_major, int server_minor) { - set_title("Bad client"); - - Gtk::VBox *box1 = new Gtk::VBox; - box1->show(); - box1->set_border_width(8); - add(*manage(box1)); - - string message = - "Rejected connection by " + - monitor->get_client_progname() + " from " + - monitor->get_client_hostname() + ".\nClient uses PStats version " + - format_string(client_major) + "." + format_string(client_minor) + - ",\nwhile server expects PStats version " + - format_string(server_major) + "." + format_string(server_minor) + "."; - - Gtk::Label *label = new Gtk::Label(message); - label->show(); - box1->pack_start(*manage(label), true, false, 8); - - Gtk::HBox *box2 = new Gtk::HBox; - box2->show(); - box1->pack_start(*manage(box2), false, false, 0); - - Gtk::Button *close = new Gtk::Button("Close"); - close->set_usize(80, 30); - close->show(); - box2->pack_start(*manage(close), true, false, 0); - close->clicked.connect(slot(this, &GtkStatsBadVersionWindow::close_clicked)); - - setup(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsBadVersionWindow::close_clicked -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsBadVersionWindow:: -close_clicked() { - destruct(); -} diff --git a/pandatool/src/gtk-stats/gtkStatsBadVersionWindow.h b/pandatool/src/gtk-stats/gtkStatsBadVersionWindow.h deleted file mode 100644 index 2d10ac0da1..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsBadVersionWindow.h +++ /dev/null @@ -1,45 +0,0 @@ -// Filename: gtkStatsBadVersionWindow.h -// Created by: drose (18May01) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef GTKSTATSBADVERSIONWINDOW_H -#define GTKSTATSBADVERSIONWINDOW_H - -#include "pandatoolbase.h" - -#include "basicGtkWindow.h" - -class GtkStatsMonitor; - -//////////////////////////////////////////////////////////////////// -// Class : GtkStatsBadVersionWindow -// Description : This window is popped up to indicated an attempted -// connection from an invalid client. -//////////////////////////////////////////////////////////////////// -class GtkStatsBadVersionWindow : public BasicGtkWindow { -public: - GtkStatsBadVersionWindow(GtkStatsMonitor *monitor, - int client_major, int client_minor, - int server_major, int server_minor); - -private: - void close_clicked(); -}; - - -#endif - diff --git a/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx new file mode 100755 index 0000000000..eaa4cb7856 --- /dev/null +++ b/pandatool/src/gtk-stats/gtkStatsChartMenu.cxx @@ -0,0 +1,209 @@ +// Filename: gtkStatsChartMenu.cxx +// Created by: drose (16Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "gtkStatsChartMenu.h" +#include "gtkStatsMonitor.h" + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsChartMenu:: +GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index) : + _monitor(monitor), + _thread_index(thread_index) +{ + _menu = CreatePopupMenu(); + do_update(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsChartMenu:: +~GtkStatsChartMenu() { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::get_menu_handle +// Access: Public +// Description: Returns the Windows menu handle for this particular +// menu. +//////////////////////////////////////////////////////////////////// +HMENU GtkStatsChartMenu:: +get_menu_handle() { + return _menu; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::add_to_menu_bar +// Access: Public +// Description: Adds the menu to the end of the indicated menu bar. +//////////////////////////////////////////////////////////////////// +void GtkStatsChartMenu:: +add_to_menu_bar(HMENU menu_bar, int before_menu_id) { + const PStatClientData *client_data = _monitor->get_client_data(); + string thread_name; + if (_thread_index == 0) { + // A special case for the main thread. + thread_name = "Graphs"; + } else { + thread_name = client_data->get_thread_name(_thread_index); + } + + MENUITEMINFO mii; + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + + mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; + mii.fType = MFT_STRING; + mii.hSubMenu = _menu; + mii.dwTypeData = (char *)thread_name.c_str(); + InsertMenuItem(menu_bar, before_menu_id, FALSE, &mii); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::check_update +// Access: Public +// Description: Checks to see if the menu needs to be updated +// (e.g. because of new data from the client), and +// updates it if necessary. +//////////////////////////////////////////////////////////////////// +void GtkStatsChartMenu:: +check_update() { + PStatView &view = _monitor->get_view(_thread_index); + if (view.get_level_index() != _last_level_index) { + do_update(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::do_update +// Access: Public +// Description: Unconditionally updates the menu with the latest data +// from the client. +//////////////////////////////////////////////////////////////////// +void GtkStatsChartMenu:: +do_update() { + PStatView &view = _monitor->get_view(_thread_index); + _last_level_index = view.get_level_index(); + + // First, remove all of the old entries from the menu. + int num_items = GetMenuItemCount(_menu); + for (int i = num_items - 1; i >= 0; i--) { + DeleteMenu(_menu, i, MF_BYPOSITION); + } + + // Now rebuild the menu with the new set of entries. + + // The menu item(s) for the thread's frame time goes first. + add_view(_menu, view.get_top_level(), false); + + bool needs_separator = true; + MENUITEMINFO mii; + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + + // And then the menu item(s) for each of the level values. + const PStatClientData *client_data = _monitor->get_client_data(); + int num_toplevel_collectors = client_data->get_num_toplevel_collectors(); + for (int tc = 0; tc < num_toplevel_collectors; tc++) { + int collector = client_data->get_toplevel_collector(tc); + if (client_data->has_collector(collector) && + client_data->get_collector_has_level(collector)) { + + // We put a separator between the above frame collector and the + // first level collector. + if (needs_separator) { + mii.fMask = MIIM_FTYPE; + mii.fType = MFT_SEPARATOR; + InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); + + needs_separator = false; + } + + PStatView &level_view = _monitor->get_level_view(collector, _thread_index); + add_view(_menu, level_view.get_top_level(), true); + } + } + + // Also a menu item for a piano roll (following a separator). + mii.fMask = MIIM_FTYPE; + mii.fType = MFT_SEPARATOR; + InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); + + GtkStatsMonitor::MenuDef menu_def(_thread_index, -1, false); + int menu_id = _monitor->get_menu_id(menu_def); + + mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; + mii.fType = MFT_STRING; + mii.wID = menu_id; + mii.dwTypeData = "Piano Roll"; + InsertMenuItem(_menu, GetMenuItemCount(_menu), TRUE, &mii); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsChartMenu::add_view +// Access: Private +// Description: Adds a new entry or entries to the menu for the +// indicated view and its children. +//////////////////////////////////////////////////////////////////// +void GtkStatsChartMenu:: +add_view(HMENU parent_menu, const PStatViewLevel *view_level, bool show_level) { + int collector = view_level->get_collector(); + + const PStatClientData *client_data = _monitor->get_client_data(); + string collector_name = client_data->get_collector_name(collector); + + GtkStatsMonitor::MenuDef menu_def(_thread_index, collector, show_level); + int menu_id = _monitor->get_menu_id(menu_def); + + MENUITEMINFO mii; + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + + mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; + mii.fType = MFT_STRING; + mii.wID = menu_id; + mii.dwTypeData = (char *)collector_name.c_str(); + InsertMenuItem(parent_menu, GetMenuItemCount(parent_menu), TRUE, &mii); + + int num_children = view_level->get_num_children(); + if (num_children > 1) { + // If the collector has more than one child, add a menu entry to go + // directly to each of its children. + HMENU submenu = CreatePopupMenu(); + string submenu_name = collector_name + " components"; + + mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU; + mii.fType = MFT_STRING; + mii.hSubMenu = submenu; + mii.dwTypeData = (char *)submenu_name.c_str(); + InsertMenuItem(parent_menu, GetMenuItemCount(parent_menu), TRUE, &mii); + + // Reverse the order since the menus are listed from the top down; + // we want to be visually consistent with the graphs, which list + // these labels from the bottom up. + for (int c = num_children - 1; c >= 0; c--) { + add_view(submenu, view_level->get_child(c), show_level); + } + } +} diff --git a/pandatool/src/gtk-stats/gtkStatsPianoWindow.h b/pandatool/src/gtk-stats/gtkStatsChartMenu.h old mode 100644 new mode 100755 similarity index 52% rename from pandatool/src/gtk-stats/gtkStatsPianoWindow.h rename to pandatool/src/gtk-stats/gtkStatsChartMenu.h index 4ee2b5fe46..a31d893f09 --- a/pandatool/src/gtk-stats/gtkStatsPianoWindow.h +++ b/pandatool/src/gtk-stats/gtkStatsChartMenu.h @@ -1,5 +1,5 @@ -// Filename: gtkStatsPianoWindow.h -// Created by: drose (18Jul00) +// Filename: gtkStatsChartMenu.h +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -16,42 +16,43 @@ // //////////////////////////////////////////////////////////////////// -#ifndef GTKSTATSPIANOWINDOW_H -#define GTKSTATSPIANOWINDOW_H +#ifndef GTKSTATSCHARTMENU_H +#define GTKSTATSCHARTMENU_H #include "pandatoolbase.h" -#include "gtkStatsMonitor.h" -#include "gtkStatsWindow.h" +#include -class GtkStatsPianoRoll; +class GtkStatsMonitor; +class PStatView; +class PStatViewLevel; //////////////////////////////////////////////////////////////////// -// Class : GtkStatsPianoWindow -// Description : A window that contains a GtkStatsPianoRoll. +// Class : GtkStatsChartMenu +// Description : A pulldown menu of charts available for a particular +// thread. //////////////////////////////////////////////////////////////////// -class GtkStatsPianoWindow : public GtkStatsWindow { +class GtkStatsChartMenu { public: - GtkStatsPianoWindow(GtkStatsMonitor *monitor, int thread_index, - int chart_xsize, int chart_ysize); + GtkStatsChartMenu(GtkStatsMonitor *monitor, int thread_index); + ~GtkStatsChartMenu(); - virtual void mark_dead(); - virtual void idle(); + HMENU get_menu_handle(); + void add_to_menu_bar(HMENU menu_bar, int before_menu_id); -protected: - virtual void setup_menu(); - virtual void menu_new_window(); - void menu_hscale(float hz); + void check_update(); + void do_update(); private: - void layout_window(int chart_xsize, int chart_ysize); + void add_view(HMENU parent_menu, const PStatViewLevel *view_level, + bool show_level); -private: + GtkStatsMonitor *_monitor; int _thread_index; - GtkStatsPianoRoll *_chart; + int _last_level_index; + HMENU _menu; }; - #endif diff --git a/pandatool/src/gtk-stats/gtkStatsGraph.cxx b/pandatool/src/gtk-stats/gtkStatsGraph.cxx new file mode 100755 index 0000000000..9c3da2c19d --- /dev/null +++ b/pandatool/src/gtk-stats/gtkStatsGraph.cxx @@ -0,0 +1,395 @@ +// Filename: gtkStatsGraph.cxx +// Created by: drose (16Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "gtkStatsGraph.h" +#include "gtkStatsMonitor.h" +#include "gtkStatsLabelStack.h" + +const GdkColor GtkStatsGraph::rgb_white = { + 0, 0xffff, 0xffff, 0xffff +}; +const GdkColor GtkStatsGraph::rgb_light_gray = { + 0, 0x9a9a, 0x9a9a, 0x9a9a, +}; +const GdkColor GtkStatsGraph::rgb_dark_gray = { + 0, 0x3333, 0x3333, 0x3333, +}; +const GdkColor GtkStatsGraph::rgb_black = { + 0, 0x0000, 0x0000, 0x0000 +}; +const GdkColor GtkStatsGraph::rgb_user_guide_bar = { + 0, 0x8282, 0x9696, 0xffff +}; + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsGraph:: +GtkStatsGraph(GtkStatsMonitor *monitor, int thread_index) : + _monitor(monitor), + _thread_index(thread_index) +{ + _parent_window = NULL; + _window = NULL; + _graph_window = NULL; + // _sizewe_cursor = LoadCursor(NULL, IDC_SIZEWE); + // _hand_cursor = LoadCursor(NULL, IDC_HAND); + _pixmap = 0; + _pixmap_gc = 0; + + _graph_left = 0; + _graph_top = 0; + _pixmap_xsize = 0; + _pixmap_ysize = 0; + + _window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + GtkWidget *parent_window = monitor->get_window(); + + gtk_window_set_transient_for(GTK_WINDOW(_window), GTK_WINDOW(parent_window)); + gtk_window_set_destroy_with_parent(GTK_WINDOW(_window), TRUE); + g_signal_connect(G_OBJECT(_window), "delete_event", + G_CALLBACK(window_delete_event), this); + g_signal_connect(G_OBJECT(_window), "destroy", + G_CALLBACK(window_destroy), this); + + _graph_window = gtk_drawing_area_new(); + g_signal_connect(G_OBJECT(_graph_window), "expose_event", + G_CALLBACK(expose_event_callback), this); + g_signal_connect(G_OBJECT(_graph_window), "configure_event", + G_CALLBACK(configure_event_callback), this); + + gtk_widget_set_size_request(_graph_window, 400, 100); + + _drag_mode = DM_none; + _potential_drag_mode = DM_none; + _drag_scale_start = 0.0f; + + _pause = false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsGraph:: +~GtkStatsGraph() { + _monitor = (GtkStatsMonitor *)NULL; + release_pixmap(); + + /* + DeleteObject(_dark_pen); + DeleteObject(_light_pen); + DeleteObject(_user_guide_bar_pen); + */ + + Brushes::iterator bi; + for (bi = _brushes.begin(); bi != _brushes.end(); ++bi) { + GdkGC *gc = (*bi).second; + g_object_unref(gc); + } + + if (_graph_window != NULL) { + gtk_widget_destroy(_graph_window); + _graph_window = NULL; + } + + if (_window != NULL) { + gtk_widget_destroy(_window); + _window = NULL; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::get_thread_index +// Access: Public +// Description: Returns the thread index associated with this +// particular graph. +//////////////////////////////////////////////////////////////////// +int GtkStatsGraph:: +get_thread_index() const { + return _thread_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::new_collector +// Access: Public, Virtual +// Description: Called whenever a new Collector definition is +// received from the client. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +new_collector(int new_collector) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::new_data +// Access: Public, Virtual +// Description: Called whenever new data arrives. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +new_data(int thread_index, int frame_number) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::force_redraw +// Access: Public, Virtual +// Description: Called when it is necessary to redraw the entire graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +force_redraw() { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::changed_graph_size +// Access: Public, Virtual +// Description: Called when the user has resized the window, forcing +// a resize of the graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +changed_graph_size(int graph_xsize, int graph_ysize) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::set_time_units +// Access: Public, Virtual +// Description: Called when the user selects a new time units from +// the monitor pulldown menu, this should adjust the +// units for the graph to the indicated mask if it is a +// time-based graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +set_time_units(int unit_mask) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::set_scroll_speed +// Access: Public +// Description: Called when the user selects a new scroll speed from +// the monitor pulldown menu, this should adjust the +// speed for the graph to the indicated value. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +set_scroll_speed(float scroll_speed) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::set_pause +// Access: Public +// Description: Changes the pause flag for the graph. When this flag +// is true, the graph does not update in response to new +// data. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +set_pause(bool pause) { + _pause = pause; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::user_guide_bars_changed +// Access: Public +// Description: Called when the user guide bars have been changed. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +user_guide_bars_changed() { + /* + InvalidateRect(_window, NULL, TRUE); + InvalidateRect(_graph_window, NULL, TRUE); + */ +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::clicked_label +// Access: Public, Virtual +// Description: Called when the user single-clicks on a label. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +clicked_label(int collector_index) { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::close +// Access: Protected +// Description: Should be called when the user closes the associated +// window. This tells the monitor to remove the graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +close() { + GtkStatsMonitor *monitor = _monitor; + _monitor = (GtkStatsMonitor *)NULL; + if (monitor != (GtkStatsMonitor *)NULL) { + monitor->remove_graph(this); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::get_collector_gc +// Access: Protected +// Description: Returns a GC suitable for drawing in the indicated +// collector's color. +//////////////////////////////////////////////////////////////////// +GdkGC *GtkStatsGraph:: +get_collector_gc(int collector_index) { + Brushes::iterator bi; + bi = _brushes.find(collector_index); + if (bi != _brushes.end()) { + return (*bi).second; + } + + // Ask the monitor what color this guy should be. + RGBColorf rgb = _monitor->get_collector_color(collector_index); + + GdkColor c; + c.red = (int)(rgb[0] * 65535.0f); + c.green = (int)(rgb[1] * 65535.0f); + c.blue = (int)(rgb[2] * 65535.0f); + GdkGC *gc = gdk_gc_new(_pixmap); + g_object_ref(gc); + gdk_gc_set_rgb_fg_color(gc, &c); + + _brushes[collector_index] = gc; + return gc; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::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. +//////////////////////////////////////////////////////////////////// +GtkStatsGraph::DragMode GtkStatsGraph:: +consider_drag_start(int mouse_x, int mouse_y, int width, int height) { + if (mouse_x >= _left_margin - 2 && mouse_x <= _left_margin + 2) { + return DM_left_margin; + } else if (mouse_x >= width - _right_margin - 2 && mouse_x <= width - _right_margin + 2) { + return DM_right_margin; + } + + return DM_none; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::set_drag_mode +// Access: Protected, Virtual +// Description: This should be called whenever the drag mode needs to +// change state. It provides hooks for a derived class +// to do something special. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +set_drag_mode(GtkStatsGraph::DragMode drag_mode) { + _drag_mode = drag_mode; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::setup_pixmap +// Access: Private +// Description: Sets up a backing-store bitmap of the indicated size. +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +setup_pixmap(int xsize, int ysize) { + release_pixmap(); + + _pixmap_xsize = max(xsize, 0); + _pixmap_ysize = max(ysize, 0); + + _pixmap = gdk_pixmap_new(_graph_window->window, _pixmap_xsize, _pixmap_ysize, -1); + g_object_ref(_pixmap); + _pixmap_gc = gdk_gc_new(_pixmap); + g_object_ref(_pixmap_gc); + + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white); + gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, 0, 0, + _pixmap_xsize, _pixmap_ysize); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::release_pixmap +// Access: Private +// Description: Frees the backing-store bitmap created by +// setup_pixmap(). +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +release_pixmap() { + if (_pixmap != NULL) { + g_object_unref(_pixmap); + g_object_unref(_pixmap_gc); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::window_delete_event +// Access: Private, Static +// Description: Callback when the window is closed by the user. +//////////////////////////////////////////////////////////////////// +gboolean GtkStatsGraph:: +window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { + // Returning FALSE to indicate we should destroy the window + // when the user selects "close". + return FALSE; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::window_delete_event +// Access: Private, Static +// Description: Callback when the window is destroyed by the system +// (or by delete_event). +//////////////////////////////////////////////////////////////////// +void GtkStatsGraph:: +window_destroy(GtkWidget *widget, gpointer data) { + GtkStatsGraph *self = (GtkStatsGraph *)data; + self->close(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::expose_event_callback +// Access: Private, Static +// Description: Fills in the graph window. +//////////////////////////////////////////////////////////////////// +gboolean GtkStatsGraph:: +expose_event_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data) { + GtkStatsGraph *self = (GtkStatsGraph *)data; + + if (self->_pixmap != NULL) { + gdk_draw_drawable(self->_graph_window->window, + self->_graph_window->style->fg_gc[0], + self->_pixmap, 0, 0, 0, 0, + self->_pixmap_xsize, self->_pixmap_ysize); + } + + return TRUE; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsGraph::configure_event_callback +// Access: Private, Static +// Description: Changes the size of the graph window +//////////////////////////////////////////////////////////////////// +gboolean GtkStatsGraph:: +configure_event_callback(GtkWidget *widget, GdkEventConfigure *event, + gpointer data) { + GtkStatsGraph *self = (GtkStatsGraph *)data; + + self->changed_graph_size(event->width, event->height); + self->setup_pixmap(event->width, event->height); + self->force_redraw(); + + return TRUE; +} diff --git a/pandatool/src/gtk-stats/gtkStatsGraph.h b/pandatool/src/gtk-stats/gtkStatsGraph.h new file mode 100755 index 0000000000..46fa0bae15 --- /dev/null +++ b/pandatool/src/gtk-stats/gtkStatsGraph.h @@ -0,0 +1,142 @@ +// Filename: gtkStatsGraph.h +// Created by: drose (16Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef GTKSTATSGRAPH_H +#define GTKSTATSGRAPH_H + +#include "pandatoolbase.h" +#include "gtkStatsLabelStack.h" +#include "pmap.h" + +#include + +class GtkStatsMonitor; + +//////////////////////////////////////////////////////////////////// +// Class : GtkStatsGraph +// Description : This is just an abstract base class to provide a +// common pointer type for the various kinds of graphs +// that may be created for a GtkStatsMonitor. +//////////////////////////////////////////////////////////////////// +class GtkStatsGraph { +public: + // What is the user adjusting by dragging the mouse in a window? + enum DragMode { + DM_none, + DM_scale, + DM_left_margin, + DM_right_margin, + DM_guide_bar, + DM_new_guide_bar, + DM_sizing, + }; + +public: + GtkStatsGraph(GtkStatsMonitor *monitor, int thread_index); + virtual ~GtkStatsGraph(); + + int get_thread_index() const; + + virtual void new_collector(int collector_index); + virtual void new_data(int thread_index, int frame_number); + virtual void force_redraw(); + virtual void changed_graph_size(int graph_xsize, int graph_ysize); + + virtual void set_time_units(int unit_mask); + virtual void set_scroll_speed(float scroll_speed); + void set_pause(bool pause); + + void user_guide_bars_changed(); + virtual void clicked_label(int collector_index); + +protected: + void close(); + GdkGC *get_collector_gc(int collector_index); + + /* + 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 set_drag_mode(DragMode drag_mode); + +protected: + // Table of GC's for our various collectors. + typedef pmap Brushes; + Brushes _brushes; + + GtkStatsMonitor *_monitor; + int _thread_index; + GtkWidget *_parent_window; + GtkWidget *_window; + GtkWidget *_graph_window; + GtkStatsLabelStack _label_stack; + + /* + HCURSOR _sizewe_cursor; + HCURSOR _hand_cursor; + */ + + GdkPixmap *_pixmap; + GdkGC *_pixmap_gc; + + int _graph_left, _graph_top; + int _pixmap_xsize, _pixmap_ysize; + int _left_margin, _right_margin; + int _top_margin, _bottom_margin; + + /* + COLORREF _dark_color; + COLORREF _light_color; + COLORREF _user_guide_bar_color; + HPEN _dark_pen; + HPEN _light_pen; + HPEN _user_guide_bar_pen; + */ + + DragMode _drag_mode; + DragMode _potential_drag_mode; + int _drag_start_x, _drag_start_y; + float _drag_scale_start; + int _drag_guide_bar; + + bool _pause; + + static const GdkColor rgb_white; + static const GdkColor rgb_light_gray; + static const GdkColor rgb_dark_gray; + static const GdkColor rgb_black; + static const GdkColor rgb_user_guide_bar; + +private: + void setup_pixmap(int xsize, int ysize); + void release_pixmap(); + void create_graph_window(); + + static gboolean window_delete_event(GtkWidget *widget, GdkEvent *event, + gpointer data); + static void window_destroy(GtkWidget *widget, gpointer data); + static gboolean expose_event_callback(GtkWidget *widget, + GdkEventExpose *event, gpointer data); + static gboolean configure_event_callback(GtkWidget *widget, + GdkEventConfigure *event, gpointer data); +}; + +#endif + diff --git a/pandatool/src/gtk-stats/gtkStatsGuide.cxx b/pandatool/src/gtk-stats/gtkStatsGuide.cxx deleted file mode 100644 index d91498bc9c..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsGuide.cxx +++ /dev/null @@ -1,88 +0,0 @@ -// Filename: gtkStatsGuide.cxx -// Created by: drose (16Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "gtkStatsGuide.h" - -#include "pStatStripChart.h" - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsGuide::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkStatsGuide:: -GtkStatsGuide(PStatStripChart *chart) : - _chart(chart) -{ - set_events(GDK_EXPOSURE_MASK); - - // Choose a suitable minimum width. This requires knowing what the - // font will be. - Gdk_Font font = get_style()->gtkobj()->font; - int text_width = font.string_width("0000"); - set_usize(text_width, 0); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsGuide::configure_event_impl -// Access: Private, Virtual -// Description: Creates a new backing pixmap of the appropriate size. -//////////////////////////////////////////////////////////////////// -gint GtkStatsGuide:: -configure_event_impl(GdkEventConfigure *) { - Gdk_Window window = get_window(); - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsGuide::expose_event_impl -// Access: Private, Virtual -// Description: Redraw the text. We don't bother with clipping -// regions here, but just draw the whole thing every -// time. -//////////////////////////////////////////////////////////////////// -gint GtkStatsGuide:: -expose_event_impl(GdkEventExpose *event) { - Gdk_GC fg_gc = - get_style()->gtkobj()->fg_gc[GTK_WIDGET_STATE (GTK_WIDGET(gtkobj()))]; - Gdk_GC bg_gc = - get_style()->gtkobj()->bg_gc[GTK_WIDGET_STATE (GTK_WIDGET(gtkobj()))]; - - if (fg_gc && bg_gc) { - Gdk_Window window = get_window(); - window.draw_rectangle(bg_gc, true, 0, 0, width(), height()); - - Gdk_Font font = fg_gc.get_font(); - int text_ascent = font.ascent(); - - int num_guide_bars = _chart->get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - const PStatStripChart::GuideBar &bar = _chart->get_guide_bar(i); - int y = _chart->height_to_pixel(bar._height); - - if (y >= 5) { - // Only draw it if it's not too close to the top. - window.draw_string(font, fg_gc, 0, y + text_ascent / 2, - bar._label); - } - } - } - - return false; -} diff --git a/pandatool/src/gtk-stats/gtkStatsGuide.h b/pandatool/src/gtk-stats/gtkStatsGuide.h deleted file mode 100644 index 81b8233d71..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsGuide.h +++ /dev/null @@ -1,47 +0,0 @@ -// Filename: gtkStatsGuide.h -// Created by: drose (16Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef GTKSTATSGUIDE_H -#define GTKSTATSGUIDE_H - -#include "pandatoolbase.h" - -#include - -class PStatStripChart; - -//////////////////////////////////////////////////////////////////// -// Class : GtkStatsGuide -// Description : A widget designed to be drawn next to a -// GtkStatsStripChart that shows the labels associated -// with the strip chart's guide bars. -//////////////////////////////////////////////////////////////////// -class GtkStatsGuide : public Gtk::DrawingArea { -public: - GtkStatsGuide(PStatStripChart *chart); - -private: - virtual gint configure_event_impl(GdkEventConfigure *event); - virtual gint expose_event_impl(GdkEventExpose *event); - -private: - PStatStripChart *_chart; -}; - -#endif - diff --git a/pandatool/src/gtk-stats/gtkStatsLabel.cxx b/pandatool/src/gtk-stats/gtkStatsLabel.cxx index bda7decbde..1e12a246f4 100644 --- a/pandatool/src/gtk-stats/gtkStatsLabel.cxx +++ b/pandatool/src/gtk-stats/gtkStatsLabel.cxx @@ -1,5 +1,5 @@ // Filename: gtkStatsLabel.cxx -// Created by: drose (15Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -18,27 +18,40 @@ #include "gtkStatsLabel.h" #include "gtkStatsMonitor.h" +#include "gtkStatsGraph.h" -#include "pStatClientData.h" -#include "pStatMonitor.h" +int GtkStatsLabel::_left_margin = 2; +int GtkStatsLabel::_right_margin = 2; +int GtkStatsLabel::_top_margin = 2; +int GtkStatsLabel::_bottom_margin = 2; //////////////////////////////////////////////////////////////////// // Function: GtkStatsLabel::Constructor // Access: Public -// Description: This constructor automatically figures out the -// appropriate name and color for the label. +// Description: //////////////////////////////////////////////////////////////////// GtkStatsLabel:: -GtkStatsLabel(PStatMonitor *monitor, int collector_index, - Gdk_Font font) : - _collector_index(collector_index), - _font(font) +GtkStatsLabel(GtkStatsMonitor *monitor, GtkStatsGraph *graph, + int thread_index, int collector_index, bool use_fullname) : + _monitor(monitor), + _graph(graph), + _thread_index(thread_index), + _collector_index(collector_index) { - set_events(GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); + _widget = NULL; + if (use_fullname) { + _text = _monitor->get_client_data()->get_collector_fullname(_collector_index); + } else { + _text = _monitor->get_client_data()->get_collector_name(_collector_index); + } - _text = monitor->get_client_data()->get_collector_name(_collector_index); - RGBColorf rgb = monitor->get_collector_color(_collector_index); - _bg_color.set_rgb_p(rgb[0], rgb[1], rgb[2]); + /* + RGBColorf rgb = _monitor->get_collector_color(_collector_index); + int r = (int)(rgb[0] * 255.0f); + int g = (int)(rgb[1] * 255.0f); + int b = (int)(rgb[2] * 255.0f); + _bg_color = RGB(r, g, b); + _bg_brush = CreateSolidBrush(RGB(r, g, b)); // Should our foreground be black or white? float bright = @@ -47,96 +60,103 @@ GtkStatsLabel(PStatMonitor *monitor, int collector_index, rgb[2] * 0.114; if (bright >= 0.5) { - _fg_color.set_rgb_p(0, 0, 0); + _fg_color = RGB(0, 0, 0); + _highlight_brush = (HBRUSH)GetStockObject(BLACK_BRUSH); } else { - _fg_color.set_rgb_p(1, 1, 1); + _fg_color = RGB(255, 255, 255); + _highlight_brush = (HBRUSH)GetStockObject(WHITE_BRUSH); } + */ - Gdk_Colormap::get_system().alloc(_fg_color); - Gdk_Colormap::get_system().alloc(_bg_color); - - int text_width = _font.string_width(_text); - int text_height = _font.height(); - - _height = text_height + 4; - _width = text_width + 4; - - set_usize(_width, _height); + _highlight = false; + _mouse_within = false; } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsLabel::get_width +// Function: GtkStatsLabel::Destructor // Access: Public -// Description: Returns the width of the widget as we requested it. -//////////////////////////////////////////////////////////////////// -int GtkStatsLabel:: -get_width() const { - return _width; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsLabel::get_height -// Access: Public -// Description: Returns the height of the widget as we requested it. -//////////////////////////////////////////////////////////////////// -int GtkStatsLabel:: -get_height() const { - return _height; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsLabel::configure_event_impl -// Access: Private, Virtual -// Description: Creates a new backing pixmap of the appropriate size. -//////////////////////////////////////////////////////////////////// -gint GtkStatsLabel:: -configure_event_impl(GdkEventConfigure *) { - Gdk_Window window = get_window(); - - _gc = Gdk_GC(window); - _gc.set_foreground(_fg_color); - _gc.set_background(_bg_color); - _gc.set_font(_font); - - _reverse_gc = Gdk_GC(window); - _reverse_gc.set_foreground(_bg_color); - _reverse_gc.set_background(_fg_color); - _reverse_gc.set_font(_font); - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsLabel::expose_event_impl -// Access: Private, Virtual -// Description: Redraw the text. We don't bother with clipping -// regions here, but just draw the whole text every -// time. -//////////////////////////////////////////////////////////////////// -gint GtkStatsLabel:: -expose_event_impl(GdkEventExpose *event) { - int text_width = _font.string_width(_text); - int text_height = _font.height(); - - Gdk_Window window = get_window(); - - window.draw_rectangle(_reverse_gc, true, 0, 0, width(), height()); - window.draw_string(_font, _gc, width() - text_width - 2, - height() - (height() - text_height) / 2 - _font.descent(), - _text); - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsLabel::button_press_event_impl -// Access: Private, Virtual // Description: //////////////////////////////////////////////////////////////////// -gint GtkStatsLabel:: -button_press_event_impl(GdkEventButton *button) { - if (button->type == GDK_2BUTTON_PRESS && button->button == 1) { - collector_picked(_collector_index); - return true; - } - return false; +GtkStatsLabel:: +~GtkStatsLabel() { + // DeleteObject(_bg_brush); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabel::setup +// Access: Public +// Description: Creates the actual widget. +//////////////////////////////////////////////////////////////////// +GtkWidget *GtkStatsLabel:: +setup() { + _widget = gtk_event_box_new(); + GtkWidget *label = gtk_label_new(_text.c_str()); + gtk_container_add(GTK_CONTAINER(_widget), label); + gtk_widget_show(label); + gtk_widget_show(_widget); + + return _widget; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabel::get_widget +// Access: Public +// Description: Returns the widget for this label. +//////////////////////////////////////////////////////////////////// +GtkWidget *GtkStatsLabel:: +get_widget() const { + return _widget; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabel::get_collector_index +// Access: Public +// Description: Returns the collector this label represents. +//////////////////////////////////////////////////////////////////// +int GtkStatsLabel:: +get_collector_index() const { + return _collector_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabel::set_highlight +// Access: Public +// Description: Enables or disables the visual highlight for this +// label. +//////////////////////////////////////////////////////////////////// +void GtkStatsLabel:: +set_highlight(bool highlight) { + if (_highlight != highlight) { + _highlight = highlight; + /* + InvalidateRect(_widget, NULL, TRUE); + */ + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabel::get_highlight +// Access: Public +// Description: Returns true if the visual highlight for this +// label is enabled. +//////////////////////////////////////////////////////////////////// +bool GtkStatsLabel:: +get_highlight() const { + return _highlight; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabel::set_mouse_within +// Access: Private +// Description: Used internally to indicate whether the mouse is +// within the label's widget. +//////////////////////////////////////////////////////////////////// +void GtkStatsLabel:: +set_mouse_within(bool mouse_within) { + if (_mouse_within != mouse_within) { + _mouse_within = mouse_within; + /* + InvalidateRect(_widget, NULL, TRUE); + */ + } } diff --git a/pandatool/src/gtk-stats/gtkStatsLabel.h b/pandatool/src/gtk-stats/gtkStatsLabel.h index da8ba27e96..27960877b5 100644 --- a/pandatool/src/gtk-stats/gtkStatsLabel.h +++ b/pandatool/src/gtk-stats/gtkStatsLabel.h @@ -1,5 +1,5 @@ // Filename: gtkStatsLabel.h -// Created by: drose (15Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -21,47 +21,54 @@ #include "pandatoolbase.h" -#include +#include -class PStatMonitor; +class GtkStatsMonitor; +class GtkStatsGraph; //////////////////////////////////////////////////////////////////// // Class : GtkStatsLabel // Description : A text label that will draw in color appropriate for -// a particular collector, instead of referring to some -// dumb Gtk::Style. It also throws a signal when the -// user double-clicks on it, passing in the collector -// index. This is handy for putting colored labels on -// strip charts. +// a particular collector. It also responds when the +// user double-clicks on it. This is handy for putting +// colored labels on strip charts. //////////////////////////////////////////////////////////////////// -class GtkStatsLabel : public Gtk::DrawingArea { +class GtkStatsLabel { public: - GtkStatsLabel(PStatMonitor *monitor, int collector_index, - Gdk_Font font); + GtkStatsLabel(GtkStatsMonitor *monitor, GtkStatsGraph *graph, + int thread_index, int collector_index, bool use_fullname); + ~GtkStatsLabel(); - int get_width() const; - int get_height() const; + GtkWidget *setup(); + GtkWidget *get_widget() const; - SigC::Signal1 collector_picked; + int get_collector_index() const; + + void set_highlight(bool highlight); + bool get_highlight() const; private: - virtual gint configure_event_impl (GdkEventConfigure *event); - virtual gint expose_event_impl (GdkEventExpose *event); - virtual gint button_press_event_impl(GdkEventButton *button); + void set_mouse_within(bool mouse_within); -private: + GtkStatsMonitor *_monitor; + GtkStatsGraph *_graph; + int _thread_index; int _collector_index; - string _text; - Gdk_Font _font; - Gdk_Color _fg_color; - Gdk_Color _bg_color; + GtkWidget *_widget; - int _width; - int _height; + /* + COLORREF _bg_color; + COLORREF _fg_color; + HBRUSH _bg_brush; + HBRUSH _highlight_brush; + */ - Gdk_GC _gc; - Gdk_GC _reverse_gc; + bool _highlight; + bool _mouse_within; + + static int _left_margin, _right_margin; + static int _top_margin, _bottom_margin; }; #endif diff --git a/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx b/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx new file mode 100755 index 0000000000..f1183f091b --- /dev/null +++ b/pandatool/src/gtk-stats/gtkStatsLabelStack.cxx @@ -0,0 +1,147 @@ +// Filename: gtkStatsLabelStack.cxx +// Created by: drose (16Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#include "gtkStatsLabelStack.h" +#include "gtkStatsLabel.h" +#include "notify.h" + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsLabelStack:: +GtkStatsLabelStack() { + _widget = NULL; + + _highlight_label = -1; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::Destructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsLabelStack:: +~GtkStatsLabelStack() { + clear_labels(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::setup +// Access: Public +// Description: Creates the actual widget object. +//////////////////////////////////////////////////////////////////// +GtkWidget *GtkStatsLabelStack:: +setup() { + if (_widget == NULL) { + _widget = gtk_vbox_new(FALSE, 0); + } + + return _widget; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::is_setup +// Access: Public +// Description: Returns true if the label stack has been set up, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool GtkStatsLabelStack:: +is_setup() const { + return (_widget != NULL); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::get_label_collector_index +// Access: Public +// Description: Returns the collector index associated with the +// indicated label. +//////////////////////////////////////////////////////////////////// +int GtkStatsLabelStack:: +get_label_collector_index(int label_index) const { + nassertr(label_index >= 0 && label_index < (int)_labels.size(), -1); + return _labels[label_index]->get_collector_index(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::clear_labels +// Access: Public +// Description: Removes the set of labels and starts a new set. +//////////////////////////////////////////////////////////////////// +void GtkStatsLabelStack:: +clear_labels() { + Labels::iterator li; + for (li = _labels.begin(); li != _labels.end(); ++li) { + GtkStatsLabel *label = (*li); + gtk_container_remove(GTK_CONTAINER(_widget), label->get_widget()); + delete (*li); + } + _labels.clear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::add_label +// Access: Public +// Description: Adds a new label to the top of the stack; returns the +// new label index. +//////////////////////////////////////////////////////////////////// +int GtkStatsLabelStack:: +add_label(GtkStatsMonitor *monitor, GtkStatsGraph *graph, + int thread_index, int collector_index, bool use_fullname) { + GtkStatsLabel *label = + new GtkStatsLabel(monitor, graph, thread_index, collector_index, use_fullname); + + gtk_box_pack_start(GTK_BOX(_widget), label->setup(), + FALSE, FALSE, 0); + + int label_index = (int)_labels.size(); + _labels.push_back(label); + + return label_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::get_num_labels +// Access: Public +// Description: Returns the number of labels in the stack. +//////////////////////////////////////////////////////////////////// +int GtkStatsLabelStack:: +get_num_labels() const { + return _labels.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsLabelStack::highlight_label +// Access: Public +// Description: Draws a highlight around the label representing the +// indicated collector, and removes the highlight from +// any other label. Specify -1 to remove the highlight +// from all labels. +//////////////////////////////////////////////////////////////////// +void GtkStatsLabelStack:: +highlight_label(int collector_index) { + if (_highlight_label != collector_index) { + _highlight_label = collector_index; + Labels::iterator li; + for (li = _labels.begin(); li != _labels.end(); ++li) { + GtkStatsLabel *label = (*li); + label->set_highlight(label->get_collector_index() == _highlight_label); + } + } +} diff --git a/pandatool/src/gtk-stats/gtkStatsLabelStack.h b/pandatool/src/gtk-stats/gtkStatsLabelStack.h new file mode 100755 index 0000000000..91622aa314 --- /dev/null +++ b/pandatool/src/gtk-stats/gtkStatsLabelStack.h @@ -0,0 +1,62 @@ +// Filename: gtkStatsLabelStack.h +// Created by: drose (16Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + +#ifndef GTKSTATSLABELSTACK_H +#define GTKSTATSLABELSTACK_H + +#include "pandatoolbase.h" +#include "pvector.h" + +#include + +class GtkStatsLabel; +class GtkStatsMonitor; +class GtkStatsGraph; + +//////////////////////////////////////////////////////////////////// +// Class : GtkStatsLabelStack +// Description : A widget that contains a stack of labels from bottom +// to top. +//////////////////////////////////////////////////////////////////// +class GtkStatsLabelStack { +public: + GtkStatsLabelStack(); + ~GtkStatsLabelStack(); + + GtkWidget *setup(); + bool is_setup() const; + + int get_label_collector_index(int label_index) const; + + void clear_labels(); + int add_label(GtkStatsMonitor *monitor, GtkStatsGraph *graph, + int thread_index, int collector_index, bool use_fullname); + int get_num_labels() const; + + void highlight_label(int collector_index); + +private: + GtkWidget *_widget; + int _highlight_label; + + typedef pvector Labels; + Labels _labels; +}; + +#endif + diff --git a/pandatool/src/gtk-stats/gtkStatsMainWindow.cxx b/pandatool/src/gtk-stats/gtkStatsMainWindow.cxx deleted file mode 100644 index b20e1667d3..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsMainWindow.cxx +++ /dev/null @@ -1,141 +0,0 @@ -// Filename: gtkStatsMainWindow.cxx -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "gtkStatsMainWindow.h" -#include "gtkStats.h" -#include "gtkStatsServer.h" - -#include "string_utils.h" - -#include - -static bool user_interrupted = false; - -// This simple signal handler lets us know when the user has pressed -// control-C, so we can clean up nicely. -static void signal_handler(int) { - user_interrupted = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMainWindow::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkStatsMainWindow:: -GtkStatsMainWindow(int port) : _port(port) { - nassertv(GtkStats::_main_window == (GtkStatsMainWindow *)NULL); - GtkStats::_main_window = this; - - // Set up a global signal handler to catch Interrupt (Control-C) so - // we can clean up nicely if the user stops us. - signal(SIGINT, &signal_handler); - - _server = new GtkStatsServer; - if (!_server->listen(_port)) { - nout << "Unable to open port.\n"; - exit(1); - } - - layout_window(); - setup(); - - Gtk::Main::timeout. - connect(slot(this, &GtkStatsMainWindow::idle_callback), 200); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMainWindow::Destructor -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -GtkStatsMainWindow:: -~GtkStatsMainWindow() { - nassertv(GtkStats::_main_window == this); - GtkStats::_main_window = NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMainWindow::destruct -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool GtkStatsMainWindow:: -destruct() { - if (BasicGtkWindow::destruct()) { - nassertr(_server != (GtkStatsServer *)NULL, false); - delete _server; - GtkStats::quit(); - } - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMainWindow::layout_window -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsMainWindow:: -layout_window() { - set_title("Gtk Stats"); - - Gtk::VBox *box1 = new Gtk::VBox; - box1->show(); - box1->set_border_width(8); - add(*manage(box1)); - - Gtk::Label *listening = - new Gtk::Label("Listening on port " + format_string(_port)); - listening->show(); - box1->pack_start(*manage(listening), true, false, 8); - - Gtk::HBox *box2 = new Gtk::HBox; - box2->show(); - box1->pack_start(*manage(box2), false, false, 0); - - Gtk::Button *close = new Gtk::Button("Close"); - close->set_usize(80, 30); - close->show(); - box2->pack_start(*manage(close), true, false, 0); - close->clicked.connect(slot(this, &GtkStatsMainWindow::close_clicked)); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMainWindow::close_clicked -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsMainWindow:: -close_clicked() { - destruct(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMainWindow::idle_callback -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -gint GtkStatsMainWindow:: -idle_callback() { - if (user_interrupted) { - destruct(); - return false; - } - _server->poll(); - return true; -} diff --git a/pandatool/src/gtk-stats/gtkStatsMainWindow.h b/pandatool/src/gtk-stats/gtkStatsMainWindow.h deleted file mode 100644 index 50fa9f2071..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsMainWindow.h +++ /dev/null @@ -1,51 +0,0 @@ -// Filename: gtkStatsMainWindow.h -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef GTKSTATSMAINWINDOW_H -#define GTKSTATSMAINWINDOW_H - -#include "pandatoolbase.h" - -#include "basicGtkWindow.h" - -class GtkStatsServer; - -//////////////////////////////////////////////////////////////////// -// Class : GtkStatsMainWindow -// Description : This is the main window that's opened up and stays up -// all the time when you run gtk-stats. It just shows -// that it's running. -//////////////////////////////////////////////////////////////////// -class GtkStatsMainWindow : public BasicGtkWindow { -public: - GtkStatsMainWindow(int port); - virtual ~GtkStatsMainWindow(); - virtual bool destruct(); - -private: - void layout_window(); - void close_clicked(); - gint idle_callback(); - - int _port; - GtkStatsServer *_server; -}; - - -#endif - diff --git a/pandatool/src/gtkbase/gtkBase.h b/pandatool/src/gtk-stats/gtkStatsMenuId.h old mode 100644 new mode 100755 similarity index 58% rename from pandatool/src/gtkbase/gtkBase.h rename to pandatool/src/gtk-stats/gtkStatsMenuId.h index 7d0705a988..8f4e90d889 --- a/pandatool/src/gtkbase/gtkBase.h +++ b/pandatool/src/gtk-stats/gtkStatsMenuId.h @@ -1,5 +1,5 @@ -// Filename: gtkBase.h -// Created by: drose (14Jul00) +// Filename: gtkStatsMenuId.h +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -16,32 +16,32 @@ // //////////////////////////////////////////////////////////////////// -#ifndef GTKBASE_H -#define GTKBASE_H +#ifndef GTKSTATSMENUID_H +#define GTKSTATSMENUID_H #include "pandatoolbase.h" -#include "programBase.h" - -#include - //////////////////////////////////////////////////////////////////// -// Class : GtkBase -// Description : This is a specialization of ProgramBase for programs -// that use the Gtk-- GUI toolkit. +// Enum : GtkStatsMenuId +// Description : The enumerated values here are used for menu ID's for +// the various pulldown menus in the application. //////////////////////////////////////////////////////////////////// -class GtkBase : public ProgramBase { -public: - GtkBase(); - ~GtkBase(); +enum GtkStatsMenuId { + MI_none, + MI_time_ms, + MI_time_hz, + MI_frame_rate_label, + MI_speed_1, + MI_speed_2, + MI_speed_3, + MI_speed_6, + MI_speed_12, + MI_pause, - virtual void parse_command_line(int argc, char *argv[]); - void main_loop(); - -public: - static Gtk::Main *_gtk; + // This one is last and represents the beginning of the range for + // the various "new chart" menu options. + MI_new_chart }; #endif - diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.I b/pandatool/src/gtk-stats/gtkStatsMonitor.I new file mode 100755 index 0000000000..11a8d907b8 --- /dev/null +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.I @@ -0,0 +1,47 @@ +// Filename: gtkStatsMonitor.I +// Created by: drose (16Jan06) +// +//////////////////////////////////////////////////////////////////// +// +// PANDA 3D SOFTWARE +// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved +// +// All use of this software is subject to the terms of the Panda 3d +// Software license. You should have received a copy of this license +// along with this source code; you will also find a current copy of +// the license at http://etc.cmu.edu/panda3d/docs/license/ . +// +// To contact the maintainers of this program write to +// panda3d-general@lists.sourceforge.net . +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::MenuDef::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsMonitor::MenuDef:: +MenuDef(int thread_index, int collector_index, bool show_level) : + _thread_index(thread_index), + _collector_index(collector_index), + _show_level(show_level) +{ +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::MenuDef::operator < +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +bool GtkStatsMonitor::MenuDef:: +operator < (const MenuDef &other) const { + if (_thread_index != other._thread_index) { + return _thread_index < other._thread_index; + } + if (_collector_index != other._collector_index) { + return _collector_index < other._collector_index; + } + return (int)_show_level < (int)other._show_level; +} diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx index 6039941108..0baa01af63 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.cxx +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.cxx @@ -1,5 +1,5 @@ // Filename: gtkStatsMonitor.cxx -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -17,15 +17,36 @@ //////////////////////////////////////////////////////////////////// #include "gtkStatsMonitor.h" -#include "gtkStatsWindow.h" -#include "gtkStatsStripWindow.h" -#include "gtkStatsBadVersionWindow.h" +#include "gtkStats.h" #include "gtkStatsServer.h" - -#include "luse.h" +#include "gtkStatsStripChart.h" +/* +#include "gtkStatsPianoRoll.h" +#include "gtkStatsChartMenu.h" +*/ +#include "gtkStatsMenuId.h" +#include "pStatGraph.h" #include "pStatCollectorDef.h" +#include "indent.h" + +typedef void vc(); + +GtkItemFactoryEntry GtkStatsMonitor::menu_entries[] = { + { "/Options", NULL, NULL, 0, "" }, + { "/Options/Units", NULL, NULL, 0, "" }, + { "/Options/Units/ms", NULL, (vc *)&handle_menu_command, MI_time_ms, "" }, + { "/Options/Units/Hz", NULL, (vc *)&handle_menu_command, MI_time_hz, "/Options/Units/ms" }, + { "/Speed", NULL, NULL, 0, "" }, + { "/Speed/1", NULL, (vc *)&handle_menu_command, MI_speed_1, "" }, + { "/Speed/2", NULL, (vc *)&handle_menu_command, MI_speed_2, "/Speed/1" }, + { "/Speed/3", NULL, (vc *)&handle_menu_command, MI_speed_3, "/Speed/1" }, + { "/Speed/6", NULL, (vc *)&handle_menu_command, MI_speed_6, "/Speed/1" }, + { "/Speed/12", NULL, (vc *)&handle_menu_command, MI_speed_12, "/Speed/1" }, + { "/Speed/sep", NULL, NULL, 0, "" }, + { "/Speed/pause", NULL, (vc *)&handle_menu_command, MI_pause, "" }, +}; +int GtkStatsMonitor::num_menu_entries = sizeof(menu_entries) / sizeof(GtkItemFactoryEntry); -#include //////////////////////////////////////////////////////////////////// // Function: GtkStatsMonitor::Constructor @@ -34,44 +55,45 @@ //////////////////////////////////////////////////////////////////// GtkStatsMonitor:: GtkStatsMonitor(GtkStatsServer *server) : PStatMonitor(server) { - _destructing = false; - _new_collector = false; + _window = NULL; + _item_factory = NULL; + + // These will be filled in later when the menu is created. + _time_units = 0; + _scroll_speed = 0.0; + _pause = false; } //////////////////////////////////////////////////////////////////// // Function: GtkStatsMonitor::Destructor -// Access: Public +// Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// GtkStatsMonitor:: ~GtkStatsMonitor() { - _destructing = true; - - Windows::iterator wi; - for (wi = _windows.begin(); wi != _windows.end(); ++wi) { - GtkStatsWindow *window = (*wi); - window->destruct(); + Graphs::iterator gi; + for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { + delete (*gi); } -} + _graphs.clear(); -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsMonitor::close_all_windows -// Access: Public -// Description: Closes all the windows associated with this client. -// This returns a PointerTo itself, just to guarantee -// that the monitor won't destruct until the function -// returns (as it might, if there were no other pointers -// to it). -//////////////////////////////////////////////////////////////////// -PT(PStatMonitor) GtkStatsMonitor:: -close_all_windows() { - PT(PStatMonitor) temp = this; - Windows::iterator wi; - for (wi = _windows.begin(); wi != _windows.end(); ++wi) { - GtkStatsWindow *window = (*wi); - window->destruct(); + /* + ChartMenus::iterator mi; + for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { + delete (*mi); } - return temp; + _chart_menus.clear(); + */ + + if (_window != NULL) { + gtk_widget_destroy(_window); + _window = NULL; + } + +#ifdef DEVELOP_GTKSTATS + // For Gtkstats developers, exit when the first monitor closes. + gtk_main_quit(0); +#endif } //////////////////////////////////////////////////////////////////// @@ -82,7 +104,7 @@ close_all_windows() { //////////////////////////////////////////////////////////////////// string GtkStatsMonitor:: get_monitor_name() { - return "Gtk Stats"; + return "GtkStats"; } //////////////////////////////////////////////////////////////////// @@ -98,8 +120,6 @@ get_monitor_name() { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: initialized() { - // Create a default window: a strip chart for the main thread. - new GtkStatsStripWindow(this, 0, 0, false, 400, 100); } //////////////////////////////////////////////////////////////////// @@ -111,10 +131,8 @@ initialized() { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: got_hello() { - Windows::iterator wi; - for (wi = _windows.begin(); wi != _windows.end(); ++wi) { - (*wi)->update_title(); - } + create_window(); + open_strip_chart(0, 0, false); } //////////////////////////////////////////////////////////////////// @@ -131,9 +149,29 @@ got_hello() { void GtkStatsMonitor:: got_bad_version(int client_major, int client_minor, int server_major, int server_minor) { - new GtkStatsBadVersionWindow(this, client_major, client_minor, - server_major, server_minor); - close_all_windows(); + ostringstream str; + str << "Unable to honor connection attempt from " + << get_client_progname() << " on " << get_client_hostname() + << ": unsupported PStats version " + << client_major << "." << client_minor; + + if (server_minor == 0) { + str << " (server understands version " << server_major + << "." << server_minor << " only)."; + } else { + str << " (server understands versions " << server_major + << ".0 through " << server_major << "." << server_minor << ")."; + } + + string message = str.str(); + GtkWidget *dialog = + gtk_message_dialog_new(GTK_WINDOW(main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + message.c_str()); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); } //////////////////////////////////////////////////////////////////// @@ -148,8 +186,41 @@ got_bad_version(int client_major, int client_minor, // definitions midstream. //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: -new_collector(int) { - _new_collector = true; +new_collector(int collector_index) { + Graphs::iterator gi; + for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { + GtkStatsGraph *graph = (*gi); + graph->new_collector(collector_index); + } + + /* + // We might need to update our menus. + ChartMenus::iterator mi; + for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { + (*mi)->do_update(); + } + */ +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::new_thread +// Access: Public, Virtual +// Description: Called whenever a new Thread definition is +// received from the client. Generally, the client will +// send all of its threads over shortly after +// connecting, but there's no guarantee that they will +// all be received before the first frames are received. +// The monitor should be prepared to accept new Thread +// definitions midstream. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +new_thread(int thread_index) { + /* + GtkStatsChartMenu *chart_menu = new GtkStatsChartMenu(this, thread_index); + chart_menu->add_to_menu_bar(_menu_bar, MI_frame_rate_label); + _chart_menus.push_back(chart_menu); + DrawMenuBar(_window); + */ } //////////////////////////////////////////////////////////////////// @@ -163,6 +234,11 @@ new_collector(int) { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: new_data(int thread_index, int frame_number) { + Graphs::iterator gi; + for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { + GtkStatsGraph *graph = (*gi); + graph->new_data(thread_index, frame_number); + } } @@ -176,9 +252,11 @@ new_data(int thread_index, int frame_number) { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: lost_connection() { - Windows::iterator wi; - for (wi = _windows.begin(); wi != _windows.end(); ++wi) { - (*wi)->mark_dead(); + nout << "Lost connection to " << get_client_hostname() << "\n"; + + if (_window != NULL) { + gtk_widget_destroy(_window); + _window = NULL; } } @@ -191,11 +269,29 @@ lost_connection() { //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: idle() { - Windows::iterator wi; - for (wi = _windows.begin(); wi != _windows.end(); ++wi) { - (*wi)->idle(); + /* + // Check if any of our chart menus need updating. + ChartMenus::iterator mi; + for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { + (*mi)->check_update(); } - _new_collector = false; + + // Update the frame rate label from the main thread (thread 0). + const PStatThreadData *thread_data = get_client_data()->get_thread_data(0); + float frame_rate = thread_data->get_frame_rate(); + if (frame_rate != 0.0f) { + char buffer[128]; + sprintf(buffer, "%0.1f ms / %0.1f Hz", 1000.0f / frame_rate, frame_rate); + + MENUITEMINFO mii; + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STRING; + mii.dwTypeData = buffer; + SetMenuItemInfo(_menu_bar, MI_frame_rate_label, FALSE, &mii); + DrawMenuBar(_window); + } + */ } //////////////////////////////////////////////////////////////////// @@ -210,52 +306,339 @@ has_idle() { } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsMonitor::is_thread_safe +// Function: GtkStatsMonitor::user_guide_bars_changed // Access: Public, Virtual -// Description: Should be redefined to return true if this monitor -// class can handle running in a sub-thread. -// -// This is not related to the question of whether it can -// handle multiple different PStatThreadDatas; this is -// strictly a question of whether or not the monitor -// itself wants to run in a sub-thread. +// Description: Called when the user guide bars have been changed. //////////////////////////////////////////////////////////////////// -bool GtkStatsMonitor:: -is_thread_safe() { - return true; +void GtkStatsMonitor:: +user_guide_bars_changed() { + Graphs::iterator gi; + for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { + GtkStatsGraph *graph = (*gi); + graph->user_guide_bars_changed(); + } } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsMonitor::add_window +// Function: GtkStatsMonitor::get_window // Access: Public -// Description: Called only from the GtkStatsWindow constructor, this -// indicates a new window that we should track. +// Description: Returns the window handle to the monitor's window. //////////////////////////////////////////////////////////////////// -void GtkStatsMonitor:: -add_window(GtkStatsWindow *window) { - nassertv(!_destructing); - bool inserted = _windows.insert(window).second; - nassertv(inserted); +GtkWidget *GtkStatsMonitor:: +get_window() const { + return _window; } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsMonitor::remove_window +// Function: GtkStatsMonitor::open_strip_chart // Access: Public -// Description: Called only from the GtkStatsWindow destructor, this -// indicates the end of a window that we should now no -// longer track. -// -// When the last window is deleted, this automatically -// closes the connection. +// Description: Opens a new strip chart showing the indicated data. //////////////////////////////////////////////////////////////////// void GtkStatsMonitor:: -remove_window(GtkStatsWindow *window) { - if (!_destructing) { - bool removed = (_windows.erase(window) != 0); - nassertv(removed); +open_strip_chart(int thread_index, int collector_index, bool show_level) { + GtkStatsStripChart *graph = + new GtkStatsStripChart(this, thread_index, collector_index, show_level); + add_graph(graph); - if (_windows.empty()) { - close(); + graph->set_time_units(_time_units); + graph->set_scroll_speed(_scroll_speed); + graph->set_pause(_pause); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::open_piano_roll +// Access: Public +// Description: Opens a new piano roll showing the indicated data. +//////////////////////////////////////////////////////////////////// +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); + */ +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::lookup_menu +// Access: Public +// Description: Returns the MenuDef properties associated with the +// indicated menu ID. This specifies what we expect to +// do when the given menu has been selected. +//////////////////////////////////////////////////////////////////// +const GtkStatsMonitor::MenuDef &GtkStatsMonitor:: +lookup_menu(int menu_id) const { + static MenuDef invalid(0, 0, false); + int menu_index = menu_id - MI_new_chart; + nassertr(menu_index >= 0 && menu_index < (int)_menu_by_id.size(), invalid); + return _menu_by_id[menu_index]; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::get_menu_id +// Access: Public +// Description: Returns the menu ID that is reserved for the +// indicated MenuDef properties. If this is the first +// time these particular properties have been requested, +// a new menu ID is returned; otherwise, the existing +// menu ID is returned. +//////////////////////////////////////////////////////////////////// +int GtkStatsMonitor:: +get_menu_id(const MenuDef &menu_def) { + MenuByDef::iterator mi; + mi = _menu_by_def.find(menu_def); + if (mi != _menu_by_def.end()) { + return (*mi).second; + } + + // Slot a new id. + int menu_id = (int)_menu_by_id.size() + MI_new_chart; + _menu_by_id.push_back(menu_def); + _menu_by_def[menu_def] = menu_id; + + return menu_id; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::set_time_units +// Access: Public +// Description: Called when the user selects a new time units from +// the monitor pulldown menu, this should adjust the +// units for all graphs to the indicated mask if it is a +// time-based graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +set_time_units(int unit_mask) { + _time_units = unit_mask; + + // First, change all of the open graphs appropriately. + Graphs::iterator gi; + for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { + GtkStatsGraph *graph = (*gi); + graph->set_time_units(_time_units); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::set_scroll_speed +// Access: Public +// Description: Called when the user selects a new scroll speed from +// the monitor pulldown menu, this should adjust the +// speeds for all graphs to the indicated value. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +set_scroll_speed(float scroll_speed) { + _scroll_speed = scroll_speed; + + // First, change all of the open graphs appropriately. + Graphs::iterator gi; + for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { + GtkStatsGraph *graph = (*gi); + graph->set_scroll_speed(_scroll_speed); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::set_pause +// Access: Public +// Description: Called when the user selects a pause on or pause off +// option from the menu. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +set_pause(bool pause) { + _pause = pause; + + // First, change all of the open graphs appropriately. + Graphs::iterator gi; + for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { + GtkStatsGraph *graph = (*gi); + graph->set_pause(_pause); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::add_graph +// Access: Private +// Description: Adds the newly-created graph to the list of managed +// graphs. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +add_graph(GtkStatsGraph *graph) { + _graphs.insert(graph); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::remove_graph +// Access: Private +// Description: Deletes the indicated graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +remove_graph(GtkStatsGraph *graph) { + Graphs::iterator gi = _graphs.find(graph); + if (gi != _graphs.end()) { + _graphs.erase(gi); + delete graph; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::create_window +// Access: Private +// Description: Creates the window for this monitor. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +create_window() { + if (_window != NULL) { + return; + } + + _window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + + g_signal_connect(G_OBJECT(_window), "delete_event", + G_CALLBACK(window_delete_event), this); + g_signal_connect(G_OBJECT(_window), "destroy", + G_CALLBACK(window_destroy), this); + + _window_title = get_client_progname() + " on " + get_client_hostname(); + gtk_window_set_title(GTK_WINDOW(_window), _window_title.c_str()); + + gtk_window_set_default_size(GTK_WINDOW(_window), 500, 360); + + // Set up the menu. + GtkAccelGroup *accel_group = gtk_accel_group_new(); + _item_factory = + gtk_item_factory_new(GTK_TYPE_MENU_BAR, "", accel_group); + gtk_item_factory_create_items(_item_factory, num_menu_entries, menu_entries, + this); + gtk_window_add_accel_group(GTK_WINDOW(_window), accel_group); + GtkWidget *menubar = gtk_item_factory_get_widget(_item_factory, ""); + + /* + ChartMenus::iterator mi; + for (mi = _chart_menus.begin(); mi != _chart_menus.end(); ++mi) { + (*mi)->add_to_menu_bar(_menu_bar, MI_frame_rate_label); + } + */ + + // Pack the menu into the window. + GtkWidget *main_vbox = gtk_vbox_new(FALSE, 1); + // gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 1); + gtk_container_add(GTK_CONTAINER(_window), main_vbox); + gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0); + + gtk_widget_show_all(_window); + gtk_widget_show(_window); + + set_time_units(PStatGraph::GBU_ms); + set_scroll_speed(3); + set_pause(false); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::window_delete_event +// Access: Private, Static +// Description: Callback when the window is closed by the user. +//////////////////////////////////////////////////////////////////// +gboolean GtkStatsMonitor:: +window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) { + // Returning FALSE to indicate we should destroy the window + // when the user selects "close". + return FALSE; +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::window_delete_event +// Access: Private, Static +// Description: Callback when the window is destroyed by the system +// (or by delete_event). +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +window_destroy(GtkWidget *widget, gpointer data) { + GtkStatsMonitor *self = (GtkStatsMonitor *)data; + self->close(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::setup_frame_rate_label +// Access: Private +// Description: Creates the frame rate label on the right end of the +// menu bar. This is used as a text label to display +// the main thread's frame rate to the user, although it +// is implemented as a right-justified toplevel menu +// item that doesn't open to anything. +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +setup_frame_rate_label() { + /* + MENUITEMINFO mii; + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + + mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; + mii.fType = MFT_STRING | MFT_RIGHTJUSTIFY; + mii.wID = MI_frame_rate_label; + mii.dwTypeData = ""; + InsertMenuItem(_menu_bar, GetMenuItemCount(_menu_bar), TRUE, &mii); + */ +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsMonitor::handle_menu_command +// Access: Private, Static +// Description: +//////////////////////////////////////////////////////////////////// +void GtkStatsMonitor:: +handle_menu_command(gpointer callback_data, guint menu_id, GtkWidget *widget) { + GtkStatsMonitor *self = (GtkStatsMonitor *)callback_data; + switch (menu_id) { + case MI_none: + break; + + case MI_time_ms: + self->set_time_units(PStatGraph::GBU_ms); + break; + + case MI_time_hz: + self->set_time_units(PStatGraph::GBU_hz); + break; + + case MI_speed_1: + self->set_scroll_speed(1); + break; + + case MI_speed_2: + self->set_scroll_speed(2); + break; + + case MI_speed_3: + self->set_scroll_speed(3); + break; + + case MI_speed_6: + self->set_scroll_speed(6); + break; + + case MI_speed_12: + self->set_scroll_speed(12); + break; + + case MI_pause: + self->set_pause(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))); + break; + + default: + if (menu_id >= MI_new_chart) { + const MenuDef &menu_def = self->lookup_menu(menu_id); + if (menu_def._collector_index < 0) { + self->open_piano_roll(menu_def._thread_index); + } else { + self->open_strip_chart(menu_def._thread_index, + menu_def._collector_index, + menu_def._show_level); + } } } } diff --git a/pandatool/src/gtk-stats/gtkStatsMonitor.h b/pandatool/src/gtk-stats/gtkStatsMonitor.h index e7acb06c44..84a1f350a9 100644 --- a/pandatool/src/gtk-stats/gtkStatsMonitor.h +++ b/pandatool/src/gtk-stats/gtkStatsMonitor.h @@ -1,5 +1,5 @@ // Filename: gtkStatsMonitor.h -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -21,25 +21,37 @@ #include "pandatoolbase.h" +#include "gtkStatsGraph.h" #include "pStatMonitor.h" #include "pointerTo.h" - #include "pset.h" +#include "pvector.h" +#include "pmap.h" + +#include class GtkStatsServer; -class GtkStatsWindow; -class Gdk_Color; +class GtkStatsChartMenu; //////////////////////////////////////////////////////////////////// // Class : GtkStatsMonitor -// Description : +// Description : This class represents a connection to a PStatsClient +// and manages the data exchange with the client. //////////////////////////////////////////////////////////////////// class GtkStatsMonitor : public PStatMonitor { public: - GtkStatsMonitor(GtkStatsServer *server); - ~GtkStatsMonitor(); + class MenuDef { + public: + INLINE MenuDef(int thread_index, int collector_index, bool show_level); + INLINE bool operator < (const MenuDef &other) const; - PT(PStatMonitor) close_all_windows(); + int _thread_index; + int _collector_index; + bool _show_level; + }; + + GtkStatsMonitor(GtkStatsServer *server); + virtual ~GtkStatsMonitor(); virtual string get_monitor_name(); @@ -48,21 +60,61 @@ public: virtual void got_bad_version(int client_major, int client_minor, int server_major, int server_minor); virtual void new_collector(int collector_index); + virtual void new_thread(int thread_index); virtual void new_data(int thread_index, int frame_number); virtual void lost_connection(); virtual void idle(); virtual bool has_idle(); - virtual bool is_thread_safe(); -public: - void add_window(GtkStatsWindow *window); - void remove_window(GtkStatsWindow *window); + virtual void user_guide_bars_changed(); - typedef pset Windows; - Windows _windows; + GtkWidget *get_window() const; + void open_strip_chart(int thread_index, int collector_index, bool show_level); + void open_piano_roll(int thread_index); - bool _destructing; - bool _new_collector; + const MenuDef &lookup_menu(int menu_id) const; + int get_menu_id(const MenuDef &menu_def); + + void set_time_units(int unit_mask); + void set_scroll_speed(float scroll_speed); + void set_pause(bool pause); + +private: + void add_graph(GtkStatsGraph *graph); + void remove_graph(GtkStatsGraph *graph); + + void create_window(); + static gboolean window_delete_event(GtkWidget *widget, GdkEvent *event, + gpointer data); + static void window_destroy(GtkWidget *widget, gpointer data); + void setup_frame_rate_label(); + + static void handle_menu_command(gpointer callback_data, guint menu_id, GtkWidget *widget); + + typedef pset Graphs; + Graphs _graphs; + + typedef pvector ChartMenus; + ChartMenus _chart_menus; + + typedef pvector MenuById; + typedef pmap MenuByDef; + MenuById _menu_by_id; + MenuByDef _menu_by_def; + + GtkWidget *_window; + GtkItemFactory *_item_factory; + string _window_title; + int _time_units; + float _scroll_speed; + bool _pause; + + static GtkItemFactoryEntry menu_entries[]; + static int num_menu_entries; + + friend class GtkStatsGraph; }; +#include "gtkStatsMonitor.I" + #endif diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.I b/pandatool/src/gtk-stats/gtkStatsPianoRoll.I deleted file mode 100644 index 706976742b..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.I +++ /dev/null @@ -1,17 +0,0 @@ -// Filename: gtkStatsPianoRoll.I -// Created by: drose (18Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx b/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx index e97b3baeb6..95e700c8a7 100644 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx +++ b/pandatool/src/gtk-stats/gtkStatsPianoRoll.cxx @@ -1,5 +1,5 @@ // Filename: gtkStatsPianoRoll.cxx -// Created by: drose (18Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -17,16 +17,14 @@ //////////////////////////////////////////////////////////////////// #include "gtkStatsPianoRoll.h" -#include "gtkStatsLabel.h" -#include "gtkStatsGuide.h" +#include "gtkStatsMonitor.h" +#include "numeric_types.h" -#include "request_initial_size.h" -#include "pStatThreadData.h" -#include "pStatFrameData.h" -#include "pStatView.h" - -#include +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 @@ -34,115 +32,147 @@ // Description: //////////////////////////////////////////////////////////////////// GtkStatsPianoRoll:: -GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index, - int xsize, int ysize) : - PStatPianoRoll(monitor, thread_index, xsize, ysize) +GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index) : + PStatPianoRoll(monitor, thread_index, + default_piano_roll_width, + default_piano_roll_height), + GtkStatsGraph(monitor, thread_index) { - _is_dead = false; - set_events(GDK_EXPOSURE_MASK); + _left_margin = 128; + _right_margin = 8; + _top_margin = 16; + _bottom_margin = 8; - _label_align = manage(new Gtk::Alignment(1.0, 1.0)); - _label_align->show(); + // Let's show the units on the guide bar labels. There's room. + set_guide_bar_units(get_guide_bar_units() | GBU_show_units); - _label_box = NULL; - pack_labels(); - - request_initial_size(*this, get_xsize(), get_ysize()); + create_window(); + clear_region(); } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::mark_dead -// Access: Public -// Description: Called when the client's connection has been lost, -// this should update the window in some obvious way to -// indicate that the window is no longer live. +// Function: GtkStatsPianoRoll::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsPianoRoll:: +~GtkStatsPianoRoll() { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::idle +// Access: Public, Virtual +// Description: Called as each frame's data is made available. There +// is no gurantee the frames will arrive in order, or +// that all of them will arrive at all. The monitor +// should be prepared to accept frames received +// out-of-order or missing. //////////////////////////////////////////////////////////////////// void GtkStatsPianoRoll:: -mark_dead() { - _is_dead = true; - - setup_white_gc(); - force_redraw(); -} - - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::get_labels -// Access: Public -// Description: Returns an alignment widget that contains all of the -// labels appropriate to this chart, already formatted -// and stacked up bottom-to-top. The window should pack -// this widget suitably near the strip chart. -//////////////////////////////////////////////////////////////////// -Gtk::Alignment *GtkStatsPianoRoll:: -get_labels() { - return _label_align; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::get_collector_gc -// Access: Public -// Description: Returns a graphics context suitable for drawing in -// the indicated collector's color. -//////////////////////////////////////////////////////////////////// -Gdk_GC GtkStatsPianoRoll:: -get_collector_gc(int collector_index) { - GCs::iterator gi; - gi = _gcs.find(collector_index); - if (gi != _gcs.end()) { - return (*gi).second; +new_data(int thread_index, int frame_number) { + if (!_pause) { + update(); } +} - // Ask the monitor what color this guy should be. - RGBColorf rgb = get_monitor()->get_collector_color(collector_index); - Gdk_Color color; - color.set_rgb_p(rgb[0], rgb[1], rgb[2]); +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::force_redraw +// Access: Public, Virtual +// Description: Called when it is necessary to redraw the entire graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsPianoRoll:: +force_redraw() { + PStatPianoRoll::force_redraw(); +} - // Now allocate the color from the system colormap. - Gdk_Colormap::get_system().alloc(color); +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::changed_graph_size +// Access: Public, Virtual +// Description: Called when the user has resized the window, forcing +// a resize of the graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsPianoRoll:: +changed_graph_size(int graph_xsize, int graph_ysize) { + PStatPianoRoll::changed_size(graph_xsize, graph_ysize); +} - // Allocate a new graphics context. - Gdk_GC gc(_pixmap); - gc.set_foreground(color); +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::set_time_units +// Access: Public, Virtual +// Description: Called when the user selects a new time units from +// the monitor pulldown menu, this should adjust the +// units for the graph to the indicated mask if it is a +// time-based graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsPianoRoll:: +set_time_units(int unit_mask) { + int old_unit_mask = get_guide_bar_units(); + if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { + unit_mask = unit_mask & (GBU_hz | GBU_ms); + unit_mask |= (old_unit_mask & GBU_show_units); + set_guide_bar_units(unit_mask); - _gcs[collector_index] = gc; - return gc; + RECT rect; + GetClientRect(_window, &rect); + rect.left = _right_margin; + InvalidateRect(_window, &rect, TRUE); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::clicked_label +// Access: Public, Virtual +// Description: Called when the user single-clicks on a label. +//////////////////////////////////////////////////////////////////// +void GtkStatsPianoRoll:: +clicked_label(int collector_index) { + if (collector_index >= 0) { + GtkStatsGraph::_monitor->open_strip_chart(GtkStatsGraph::_thread_index, collector_index, false); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::set_horizontal_scale +// Access: Public +// Description: Changes the amount of time the width of the +// horizontal axis represents. This may force a redraw. +//////////////////////////////////////////////////////////////////// +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); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::clear_region +// Access: Protected +// Description: Erases the chart area. +//////////////////////////////////////////////////////////////////// +void GtkStatsPianoRoll:: +clear_region() { + RECT rect = { 0, 0, get_xsize(), get_ysize() }; + FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH)); } //////////////////////////////////////////////////////////////////// // Function: GtkStatsPianoRoll::begin_draw // Access: Protected, Virtual -// Description: Erases the chart area in preparation for drawing it -// full of bars. +// Description: Erases the chart area in preparation for drawing a +// bunch of bars. //////////////////////////////////////////////////////////////////// void GtkStatsPianoRoll:: begin_draw() { - _pixmap.draw_rectangle(_white_gc, true, 0, 0, get_xsize(), get_ysize()); - - Gdk_Font font = get_style()->gtkobj()->font; - int text_height = font.height(); + clear_region(); // Draw in the guide bars. int num_guide_bars = get_num_guide_bars(); for (int i = 0; i < num_guide_bars; i++) { - const GuideBar &bar = get_guide_bar(i); - int x = (int)((float)get_xsize() * bar._height / get_horizontal_scale()); - - if (x >= 5 && x <= get_xsize() - 5) { - // Only draw it if it's not too close to either edge. - switch (bar._style) { - case GBS_target: - _pixmap.draw_line(_light_gc, x, text_height + 4, x, get_ysize()); - break; - - case GBS_normal: - default: - _pixmap.draw_line(_dark_gc, x, text_height + 4, x, get_ysize()); - break; - } - } + draw_guide_bar(_bitmap_dc, get_guide_bar(i)); } - } //////////////////////////////////////////////////////////////////// @@ -152,10 +182,17 @@ begin_draw() { //////////////////////////////////////////////////////////////////// void GtkStatsPianoRoll:: draw_bar(int row, int from_x, int to_x) { - if (row >= 0 && row < (int)_y_positions.size()) { - int y = height() - _y_positions[row]; - _pixmap.draw_rectangle(get_collector_gc(get_label_collector(row)), - true, from_x, y - 6, to_x - from_x, 12); + if (row >= 0 && row < _label_stack.get_num_labels()) { + int y = _label_stack.get_label_y(row) - _graph_top; + 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); } } @@ -167,31 +204,7 @@ draw_bar(int row, int from_x, int to_x) { //////////////////////////////////////////////////////////////////// void GtkStatsPianoRoll:: end_draw() { - // Draw in the labels for the guide bars. We do this in end_draw() - // instead of in begin_draw() so the labels will appear on top of - // any of the color bars. - Gdk_Font font = get_style()->gtkobj()->font; - int text_ascent = font.ascent(); - - int num_guide_bars = get_num_guide_bars(); - for (int i = 0; i < num_guide_bars; i++) { - const GuideBar &bar = get_guide_bar(i); - int x = (int)((float)get_xsize() * bar._height / get_horizontal_scale()); - - if (x >= 5 && x <= get_xsize() - 5) { - // Only draw it if it's not too close to either edge. - int width = font.string_measure(bar._label); - _pixmap.draw_string(font, _black_gc, x - width / 2, text_ascent + 2, - bar._label); - } - } - - GdkRectangle update_rect; - update_rect.x = 0; - update_rect.y = 0; - update_rect.width = get_xsize(); - update_rect.height = get_ysize(); - draw(&update_rect); + InvalidateRect(_graph_window, NULL, FALSE); } //////////////////////////////////////////////////////////////////// @@ -202,126 +215,430 @@ end_draw() { void GtkStatsPianoRoll:: idle() { if (_labels_changed) { - pack_labels(); + update_labels(); } } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::configure_event_impl -// Access: Private, Virtual -// Description: Creates a new backing pixmap of the appropriate size. +// Function: GtkStatsPianoRoll::window_proc +// Access: Protected +// Description: //////////////////////////////////////////////////////////////////// -gint GtkStatsPianoRoll:: -configure_event_impl(GdkEventConfigure *) { - if (width() != get_xsize() || height() != get_ysize() || - _pixmap.gdkobj() == (GdkDrawable *)NULL) { - if (_pixmap) { - _pixmap.release(); +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); } - _pixmap.create(get_window(), width(), height()); + 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; - Gdk_Colormap system_colormap = Gdk_Colormap::get_system(); + } 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; + } - _white_gc = Gdk_GC(_pixmap); - setup_white_gc(); + } 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; - _black_gc = Gdk_GC(_pixmap); - _black_gc.set_foreground(system_colormap.black()); + case WM_MOUSELEAVE: + // When the mouse leaves the graph, stop highlighting. + _label_stack.highlight_label(-1); + break; - _dark_gc = Gdk_GC(_pixmap); - Gdk_Color dark; - dark.set_grey_p(0.2); - system_colormap.alloc(dark); - _dark_gc.set_foreground(dark); + case WM_LBUTTONUP: + if (_drag_mode == DM_scale) { + set_drag_mode(DM_none); + ReleaseCapture(); + return 0; - _light_gc = Gdk_GC(_pixmap); - Gdk_Color light; - light.set_grey_p(0.6); - system_colormap.alloc(light); - _light_gc.set_foreground(light); + } 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; - _pixmap.draw_rectangle(_white_gc, true, 0, 0, width(), height()); + 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; - changed_size(width(), height()); + default: + break; } - return true; + + return GtkStatsGraph::graph_window_proc(hwnd, msg, wparam, lparam); } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::expose_event_impl -// Access: Private, Virtual -// Description: Redraw the screen from the backing pixmap. -//////////////////////////////////////////////////////////////////// -gint GtkStatsPianoRoll:: -expose_event_impl(GdkEventExpose *event) { - get_window().draw_pixmap(_white_gc, _pixmap, - event->area.x, event->area.y, - event->area.x, event->area.y, - event->area.width, event->area.height); - - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::pack_labels -// Access: Private -// Description: +// 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:: -pack_labels() { - // First, remove the old labels. - _label_align->remove(); +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); - // Now add the new labels back in. - _label_box = manage(new Gtk::VBox); - _label_box->show(); - _label_align->add(*_label_box); + int y = _top_margin; - Gdk_Font font = get_style()->gtkobj()->font; - int num_labels = get_num_labels(); - - while ((int)_y_positions.size() < num_labels) { - _y_positions.push_back(0); + 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 y = 0; - for (int i = 0; i < num_labels; i++) { - int collector_index = get_label_collector(i); - GtkStatsLabel *label = - new GtkStatsLabel(get_monitor(), collector_index, font); - label->show(); + 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)); + } +} - _label_box->pack_end(*manage(label), false, false); - _y_positions[i] = y + label->get_height() / 2; +//////////////////////////////////////////////////////////////////// +// 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). +//////////////////////////////////////////////////////////////////// +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)); + } +} - y += label->get_height(); +//////////////////////////////////////////////////////////////////// +// 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. +//////////////////////////////////////////////////////////////////// +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; + } + + } 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; + } } + return GtkStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::get_collector_under_pixel +// Access: Private +// Description: Returns the collector index associated with the +// indicated vertical row, or -1. +//////////////////////////////////////////////////////////////////// +int GtkStatsPianoRoll:: +get_collector_under_pixel(int xpoint, int ypoint) { + if (_label_stack.get_num_labels() == 0) { + return -1; + } + + // Assume all of the labels are the same height. + int height = _label_stack.get_label_height(0); + int row = (get_ysize() - ypoint) / height; + if (row >= 0 && row < _label_stack.get_num_labels()) { + return _label_stack.get_label_collector_index(row); + } else { + return -1; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::update_labels +// Access: Private +// Description: Resets the list of labels. +//////////////////////////////////////////////////////////////////// +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); + } _labels_changed = false; } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoRoll::setup_white_gc +// Function: GtkStatsPianoRoll::draw_guide_bar // Access: Private -// Description: Sets the color on _white_gc to be either actually -// white (if the chart is still alive) or a light gray -// (if the chart is dead). +// Description: Draws the line for the indicated guide bar on the +// graph. //////////////////////////////////////////////////////////////////// void GtkStatsPianoRoll:: -setup_white_gc() { - Gdk_Colormap system_colormap = Gdk_Colormap::get_system(); +draw_guide_bar(HDC hdc, const PStatGraph::GuideBar &bar) { + int x = height_to_pixel(bar._height); - if (_is_dead) { - Gdk_Color death; - death.set_grey_p(0.8); - system_colormap.alloc(death); + if (x > 0 && x < get_xsize() - 1) { + // Only draw it if it's not too close to either edge. + switch (bar._style) { + case GBS_target: + SelectObject(hdc, _light_pen); + break; - _white_gc.set_foreground(death); - - } else { - _white_gc.set_foreground(system_colormap.white()); + case GBS_user: + SelectObject(hdc, _user_guide_bar_pen); + break; + + case GBS_normal: + SelectObject(hdc, _dark_pen); + break; + } + MoveToEx(hdc, x, 0, NULL); + LineTo(hdc, x, get_ysize()); } - } +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsPianoRoll::draw_guide_label +// Access: Private +// Description: Draws the text for the indicated guide bar label at +// the top of the graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsPianoRoll:: +draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar) { + switch (bar._style) { + case GBS_target: + SetTextColor(hdc, _light_color); + break; + + case GBS_user: + SetTextColor(hdc, _user_guide_bar_color); + break; + + case GBS_normal: + SetTextColor(hdc, _dark_color); + break; + } + + int x = height_to_pixel(bar._height); + const string &label = bar._label; + SIZE size; + GetTextExtentPoint32(hdc, label.data(), label.length(), &size); + + if (bar._style != GBS_user) { + float from_height = pixel_to_height(x - size.cx); + float to_height = pixel_to_height(x + size.cx); + if (find_user_guide_bar(from_height, to_height) >= 0) { + // Omit the label: there's a user-defined guide bar in the same space. + 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()); + } +} + +//////////////////////////////////////////////////////////////////// +// 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 +// Access: Private, Static +// Description: Registers the window class for the pianoRoll window, if +// it has not already been registered. +//////////////////////////////////////////////////////////////////// +void GtkStatsPianoRoll:: +register_window_class(HINSTANCE application) { + if (_window_class_registered) { + return; + } + + 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); + } +} diff --git a/pandatool/src/gtk-stats/gtkStatsPianoRoll.h b/pandatool/src/gtk-stats/gtkStatsPianoRoll.h index e972270897..4d42dab846 100644 --- a/pandatool/src/gtk-stats/gtkStatsPianoRoll.h +++ b/pandatool/src/gtk-stats/gtkStatsPianoRoll.h @@ -1,5 +1,5 @@ // Filename: gtkStatsPianoRoll.h -// Created by: drose (18Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -21,72 +21,61 @@ #include "pandatoolbase.h" -#include "gtkStatsMonitor.h" - +#include "gtkStatsGraph.h" #include "pStatPianoRoll.h" #include "pointerTo.h" -#include -#include "pmap.h" +#include -class PStatView; -class GtkStatsGuide; +class GtkStatsMonitor; //////////////////////////////////////////////////////////////////// // Class : GtkStatsPianoRoll -// Description : A special widget that draws a piano-roll style chart, +// Description : A window that draws a piano-roll style chart, // which shows the collectors explicitly stopping and // starting, one frame at a time. //////////////////////////////////////////////////////////////////// -class GtkStatsPianoRoll : public Gtk::DrawingArea, public PStatPianoRoll { +class GtkStatsPianoRoll : public PStatPianoRoll, public GtkStatsGraph { public: - GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index, - int xsize, int ysize); + GtkStatsPianoRoll(GtkStatsMonitor *monitor, int thread_index); + virtual ~GtkStatsPianoRoll(); - void mark_dead(); + virtual void new_data(int thread_index, int frame_number); + virtual void force_redraw(); + virtual void changed_graph_size(int graph_xsize, int graph_ysize); - Gtk::Alignment *get_labels(); + virtual void set_time_units(int unit_mask); + virtual void clicked_label(int collector_index); + void set_horizontal_scale(float time_width); - Gdk_GC get_collector_gc(int collector_index); - -private: +protected: + void clear_region(); virtual void begin_draw(); virtual void draw_bar(int row, int from_x, int to_x); virtual void end_draw(); virtual void idle(); - virtual gint configure_event_impl(GdkEventConfigure *event); - virtual gint expose_event_impl(GdkEventExpose *event); - - void pack_labels(); - void setup_white_gc(); + 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); private: - // Backing pixmap for drawing area. - Gdk_Pixmap _pixmap; + 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); - // Graphics contexts for fg/bg. We don't use the contexts defined - // in the style, because that would probably interfere with the - // visibility of the chart. - Gdk_GC _white_gc; - Gdk_GC _black_gc; - Gdk_GC _dark_gc; - Gdk_GC _light_gc; + void create_window(); + static void register_window_class(HINSTANCE application); - // Table of graphics contexts for our various collectors. - typedef pmap GCs; - GCs _gcs; + static LONG GTKAPI static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); - // Table of Y-positions for each of our rows, measured from the - // bottom. - vector_int _y_positions; - - Gtk::Alignment *_label_align; - Gtk::VBox *_label_box; - bool _is_dead; + static bool _window_class_registered; + static const char * const _window_class_name; }; -#include "gtkStatsPianoRoll.I" - #endif diff --git a/pandatool/src/gtk-stats/gtkStatsPianoWindow.cxx b/pandatool/src/gtk-stats/gtkStatsPianoWindow.cxx deleted file mode 100644 index cf3a5f9a6b..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsPianoWindow.cxx +++ /dev/null @@ -1,164 +0,0 @@ -// Filename: gtkStatsPianoWindow.cxx -// Created by: drose (18Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "gtkStatsPianoWindow.h" -#include "gtkStatsPianoRoll.h" - -using Gtk::Menu_Helpers::MenuElem; -using Gtk::Menu_Helpers::SeparatorElem; - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoWindow::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkStatsPianoWindow:: -GtkStatsPianoWindow(GtkStatsMonitor *monitor, int thread_index, - int chart_xsize, int chart_ysize) : - GtkStatsWindow(monitor), - _thread_index(thread_index) -{ - setup_menu(); - layout_window(chart_xsize, chart_ysize); - show(); -} - - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoWindow::mark_dead -// Access: Public, Virtual -// Description: Called when the client's connection has been lost, -// this should update the window in some obvious way to -// indicate that the window is no longer live. -//////////////////////////////////////////////////////////////////// -void GtkStatsPianoWindow:: -mark_dead() { - GtkStatsWindow::mark_dead(); - _chart->mark_dead(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoWindow::idle -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsPianoWindow:: -idle() { - GtkStatsWindow::idle(); - _chart->update(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoWindow::setup_menu -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsPianoWindow:: -setup_menu() { - GtkStatsWindow::setup_menu(); - - Gtk::Menu *scale_menu = new Gtk::Menu; - - scale_menu->items().push_back - (MenuElem("0.1 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 0.1f))); - scale_menu->items().push_back - (MenuElem("1 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 1.0f))); - scale_menu->items().push_back - (MenuElem("5 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 5.0f))); - scale_menu->items().push_back - (MenuElem("10 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 10.0f))); - scale_menu->items().push_back - (MenuElem("20 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 20.0f))); - scale_menu->items().push_back - (MenuElem("30 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 30.0f))); - scale_menu->items().push_back - (MenuElem("60 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 60.0f))); - scale_menu->items().push_back - (MenuElem("120 Hz", - bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 120.0f))); - - _menu->items().push_back(MenuElem("Scale", *manage(scale_menu))); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoWindow::menu_new_window -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsPianoWindow:: -menu_new_window() { - new GtkStatsPianoWindow(_monitor, _thread_index, - _chart->get_xsize(), _chart->get_ysize()); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoWindow::menu_hscale -// Access: Protected -// Description: Selects a new horizontal scale for the piano roll. -// This is done from the menu called "Scale". -// -// The units is in Hz. -//////////////////////////////////////////////////////////////////// -void GtkStatsPianoWindow:: -menu_hscale(float hz) { - _chart->set_horizontal_scale(1.0 / hz); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsPianoWindow::layout_window -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsPianoWindow:: -layout_window(int chart_xsize, int chart_ysize) { - Gtk::HBox *hbox = new Gtk::HBox; - hbox = new Gtk::HBox; - hbox->show(); - _main_box->pack_start(*manage(hbox), true, true, 8); - - Gtk::Table *chart_table = new Gtk::Table(1, 2); - chart_table->show(); - hbox->pack_start(*manage(chart_table), true, true, 8); - - Gtk::Frame *frame = new Gtk::Frame; - frame->set_shadow_type(GTK_SHADOW_ETCHED_OUT); - frame->show(); - chart_table->attach(*manage(frame), 1, 2, 0, 1); - - _chart = new GtkStatsPianoRoll(_monitor, _thread_index, - chart_xsize, chart_ysize); - frame->add(*manage(_chart)); - - // We put the labels in a frame, too, so they'll line up vertically. - Gtk::Frame *label_frame = new Gtk::Frame; - label_frame->set_shadow_type(GTK_SHADOW_NONE); - label_frame->show(); - label_frame->add(*manage(_chart->get_labels())); - - chart_table->attach(*manage(label_frame), 0, 1, 0, 1, - 0, (GTK_FILL|GTK_EXPAND), 4, 0); - - _chart->show(); -} diff --git a/pandatool/src/gtk-stats/gtkStatsServer.cxx b/pandatool/src/gtk-stats/gtkStatsServer.cxx index dea01047ed..b978951224 100644 --- a/pandatool/src/gtk-stats/gtkStatsServer.cxx +++ b/pandatool/src/gtk-stats/gtkStatsServer.cxx @@ -1,5 +1,5 @@ // Filename: gtkStatsServer.cxx -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -19,7 +19,6 @@ #include "gtkStatsServer.h" #include "gtkStatsMonitor.h" - //////////////////////////////////////////////////////////////////// // Function: GtkStatsServer::make_monitor // Access: Public diff --git a/pandatool/src/gtk-stats/gtkStatsServer.h b/pandatool/src/gtk-stats/gtkStatsServer.h index 2345512e82..7e1aeebf36 100644 --- a/pandatool/src/gtk-stats/gtkStatsServer.h +++ b/pandatool/src/gtk-stats/gtkStatsServer.h @@ -1,5 +1,5 @@ // Filename: gtkStatsServer.h -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -20,13 +20,12 @@ #define GTKSTATSSERVER_H #include "pandatoolbase.h" - #include "pStatServer.h" - //////////////////////////////////////////////////////////////////// // Class : GtkStatsServer -// Description : +// Description : The class that owns the main loop, waiting for client +// connections. //////////////////////////////////////////////////////////////////// class GtkStatsServer : public PStatServer { public: @@ -34,3 +33,4 @@ public: }; #endif + diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.I b/pandatool/src/gtk-stats/gtkStatsStripChart.I deleted file mode 100644 index 88097429f1..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.I +++ /dev/null @@ -1,17 +0,0 @@ -// Filename: gtkStatsStripChart.I -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx b/pandatool/src/gtk-stats/gtkStatsStripChart.cxx index eea0a8282a..cfb2fd18fa 100644 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.cxx +++ b/pandatool/src/gtk-stats/gtkStatsStripChart.cxx @@ -1,5 +1,5 @@ // Filename: gtkStatsStripChart.cxx -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -17,16 +17,12 @@ //////////////////////////////////////////////////////////////////// #include "gtkStatsStripChart.h" -#include "gtkStatsLabel.h" -#include "gtkStatsGuide.h" - -#include "request_initial_size.h" -#include "pStatThreadData.h" -#include "pStatFrameData.h" -#include "pStatView.h" - -#include +#include "gtkStatsMonitor.h" +#include "pStatCollectorDef.h" +#include "numeric_types.h" +static const int default_strip_chart_width = 400; +static const int default_strip_chart_height = 100; //////////////////////////////////////////////////////////////////// // Function: GtkStatsStripChart::Constructor @@ -34,99 +30,234 @@ // Description: //////////////////////////////////////////////////////////////////// GtkStatsStripChart:: -GtkStatsStripChart(GtkStatsMonitor *monitor, PStatView &view, - int collector_index, int xsize, int ysize) : - PStatStripChart(monitor, view, collector_index, xsize, ysize) +GtkStatsStripChart(GtkStatsMonitor *monitor, int thread_index, + int collector_index, bool show_level) : + PStatStripChart(monitor, + show_level ? monitor->get_level_view(collector_index, thread_index) : monitor->get_view(thread_index), + collector_index, + default_strip_chart_width, + default_strip_chart_height), + GtkStatsGraph(monitor, thread_index) { - _is_dead = false; - set_events(GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK); + _brush_origin = 0; - _label_align = manage(new Gtk::Alignment(1.0, 1.0)); - _label_align->show(); + _left_margin = 96; + _right_margin = 32; + _top_margin = 16; + _bottom_margin = 8; - _label_box = NULL; - pack_labels(); + if (show_level) { + // If it's a level-type graph, show the appropriate units. + if (_unit_name.empty()) { + set_guide_bar_units(GBU_named); + } else { + set_guide_bar_units(GBU_named | GBU_show_units); + } - _guide = manage(new GtkStatsGuide(this)); - _guide->show(); + } else { + // If it's a time-type graph, show the ms/Hz units. + set_guide_bar_units(get_guide_bar_units() | GBU_show_units); + } - request_initial_size(*this, get_xsize(), get_ysize()); + _smooth_check_box = 0; + + GtkWidget *hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), _label_stack.setup(), + FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), _graph_window, + FALSE, FALSE, 0); + + gtk_container_add(GTK_CONTAINER(_window), hbox); + + gtk_widget_show_all(_window); + gtk_widget_show(_window); + + clear_region(); } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::mark_dead -// Access: Public -// Description: Called when the client's connection has been lost, -// this should update the window in some obvious way to -// indicate that the window is no longer live. +// Function: GtkStatsStripChart::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +GtkStatsStripChart:: +~GtkStatsStripChart() { +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsStripChart::new_collector +// Access: Public, Virtual +// Description: Called whenever a new Collector definition is +// received from the client. //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: -mark_dead() { - _is_dead = true; +new_collector(int collector_index) { + GtkStatsGraph::new_collector(collector_index); +} - setup_white_gc(); +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsStripChart::new_data +// Access: Public, Virtual +// Description: Called as each frame's data is made available. There +// is no gurantee the frames will arrive in order, or +// that all of them will arrive at all. The monitor +// should be prepared to accept frames received +// out-of-order or missing. +//////////////////////////////////////////////////////////////////// +void GtkStatsStripChart:: +new_data(int thread_index, int frame_number) { + if (is_title_unknown()) { + string window_title = get_title_text(); + if (!is_title_unknown()) { + gtk_window_set_title(GTK_WINDOW(_window), window_title.c_str()); + } + } + + if (!_pause) { + update(); + + /* + string text = format_number(get_average_net_value(), get_guide_bar_units(), get_guide_bar_unit_name()); + if (_net_value_text != text) { + _net_value_text = text; + RECT rect; + GetClientRect(_window, &rect); + rect.bottom = _top_margin; + InvalidateRect(_window, &rect, TRUE); + } + */ + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsStripChart::force_redraw +// Access: Public, Virtual +// Description: Called when it is necessary to redraw the entire graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsStripChart:: +force_redraw() { + PStatStripChart::force_redraw(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsStripChart::changed_graph_size +// Access: Public, Virtual +// Description: Called when the user has resized the window, forcing +// a resize of the graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsStripChart:: +changed_graph_size(int graph_xsize, int graph_ysize) { + PStatStripChart::changed_size(graph_xsize, graph_ysize); +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsStripChart::set_time_units +// Access: Public, Virtual +// Description: Called when the user selects a new time units from +// the monitor pulldown menu, this should adjust the +// units for the graph to the indicated mask if it is a +// time-based graph. +//////////////////////////////////////////////////////////////////// +void GtkStatsStripChart:: +set_time_units(int unit_mask) { + int old_unit_mask = get_guide_bar_units(); + if ((old_unit_mask & (GBU_hz | GBU_ms)) != 0) { + unit_mask = unit_mask & (GBU_hz | GBU_ms); + 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); + + GetClientRect(_window, &rect); + rect.bottom = _top_margin; + InvalidateRect(_window, &rect, TRUE); + */ + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsStripChart::set_scroll_speed +// Access: Public +// Description: Called when the user selects a new scroll speed from +// the monitor pulldown menu, this should adjust the +// speed for the graph to the indicated value. +//////////////////////////////////////////////////////////////////// +void GtkStatsStripChart:: +set_scroll_speed(float scroll_speed) { + // The speed factor indicates chart widths per minute. + if (scroll_speed != 0.0f) { + set_horizontal_scale(60.0f / scroll_speed); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: GtkStatsStripChart::clicked_label +// Access: Public, Virtual +// Description: Called when the user single-clicks on a label. +//////////////////////////////////////////////////////////////////// +void GtkStatsStripChart:: +clicked_label(int collector_index) { + if (collector_index < 0) { + // Clicking on whitespace in the graph is the same as clicking on + // the top label. + collector_index = get_collector_index(); + } + + if (collector_index == get_collector_index() && collector_index != 0) { + // Clicking on the top label means to go up to the parent level. + const PStatClientData *client_data = + GtkStatsGraph::_monitor->get_client_data(); + if (client_data->has_collector(collector_index)) { + const PStatCollectorDef &def = + client_data->get_collector_def(collector_index); + if (def._parent_index == 0 && get_view().get_show_level()) { + // Unless the parent is "Frame", and we're not a time collector. + } else { + set_collector_index(def._parent_index); + } + } - if (!first_data()) { - force_redraw(); } else { - clear_region(); + // Clicking on any other label means to focus on that. + set_collector_index(collector_index); } } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::get_labels +// Function: GtkStatsStripChart::set_vertical_scale // Access: Public -// Description: Returns an alignment widget that contains all of the -// labels appropriate to this chart, already formatted -// and stacked up bottom-to-top. The window should pack -// this widget suitably near the strip chart. +// Description: Changes the value the height of the vertical axis +// represents. This may force a redraw. //////////////////////////////////////////////////////////////////// -Gtk::Alignment *GtkStatsStripChart:: -get_labels() { - return _label_align; +void GtkStatsStripChart:: +set_vertical_scale(float value_height) { + PStatStripChart::set_vertical_scale(value_height); + + GdkRectangle rect = { + 0, 0, get_xsize(), get_ysize() + }; + gdk_window_invalidate_rect(_graph_window->window, &rect, FALSE); } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::get_guide -// Access: Public -// Description: Returns a widget that contains the numeric labels for -// the guide bars. The window should pack this widget -// suitably near the strip chart. +// Function: GtkStatsStripChart::update_labels +// Access: Protected, Virtual +// Description: Resets the list of labels. //////////////////////////////////////////////////////////////////// -GtkStatsGuide *GtkStatsStripChart:: -get_guide() { - return _guide; -} +void GtkStatsStripChart:: +update_labels() { + PStatStripChart::update_labels(); - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::get_collector_gc -// Access: Public -// Description: Returns a graphics context suitable for drawing in -// the indicated collector's color. -//////////////////////////////////////////////////////////////////// -Gdk_GC GtkStatsStripChart:: -get_collector_gc(int collector_index) { - GCs::iterator gi; - gi = _gcs.find(collector_index); - if (gi != _gcs.end()) { - return (*gi).second; + _label_stack.clear_labels(); + for (int i = 0; i < get_num_labels(); i++) { + _label_stack.add_label(GtkStatsGraph::_monitor, this, _thread_index, + get_label_collector(i), false); } - - // Ask the monitor what color this guy should be. - RGBColorf rgb = get_monitor()->get_collector_color(collector_index); - Gdk_Color color; - color.set_rgb_p(rgb[0], rgb[1], rgb[2]); - - // Now allocate the color from the system colormap. - Gdk_Colormap::get_system().alloc(color); - - // Allocate a new graphics context. - Gdk_GC gc(_pixmap); - gc.set_foreground(color); - - _gcs[collector_index] = gc; - return gc; + _labels_changed = false; } //////////////////////////////////////////////////////////////////// @@ -136,8 +267,9 @@ get_collector_gc(int collector_index) { //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: clear_region() { - _pixmap.draw_rectangle(_white_gc, true, 0, 0, get_xsize(), get_ysize()); - end_draw(0, get_xsize()); + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white); + gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, 0, 0, + get_xsize(), get_ysize()); } //////////////////////////////////////////////////////////////////// @@ -149,28 +281,19 @@ clear_region() { //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: copy_region(int start_x, int end_x, int dest_x) { - _pixmap.copy_area(_white_gc, 0, 0, - _pixmap, start_x, 0, - end_x - start_x + 1, get_ysize()); + gdk_draw_drawable(_pixmap, _pixmap_gc, _pixmap, + start_x, 0, dest_x, 0, + end_x - start_x, get_ysize()); + + // Also shift the brush origin over, so we still get proper + // dithering. + _brush_origin += (dest_x - start_x); + // SetBrushOrgEx(_bitmap_dc, _brush_origin, 0, NULL); - // We could make a window-to-window copy to implement scrolling in - // the window. But this leads to trouble if the scrolling window - // isn't on top. Instead, we'll just do the scroll in the pixmap, - // and then blt the pixmap back out--in principle, this ought to be - // just as fast. - /* - Gdk_Window window = get_window(); - window.copy_area(_white_gc, 0, 0, - window, start_x, 0, - end_x - start_x + 1, get_ysize()); - */ - - GdkRectangle update_rect; - update_rect.x = dest_x; - update_rect.y = 0; - update_rect.width = end_x - start_x + 1; - update_rect.height = get_ysize(); - draw(&update_rect); + GdkRectangle rect = { + dest_x, 0, end_x - start_x, get_ysize() + }; + gdk_window_invalidate_rect(_graph_window->window, &rect, FALSE); } //////////////////////////////////////////////////////////////////// @@ -182,32 +305,32 @@ copy_region(int start_x, int end_x, int dest_x) { //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: draw_slice(int x, int w, const PStatStripChart::FrameData &fdata) { - while (w > 0) { - // Start by clearing the band first. - _pixmap.draw_line(_white_gc, x, 0, x, get_ysize()); + // Start by clearing the band first. + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white); + gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, x, 0, + w + 1, get_ysize()); - float overall_time = 0.0; - int y = get_ysize(); + float overall_time = 0.0; + int y = get_ysize(); - FrameData::const_iterator fi; - for (fi = fdata.begin(); fi != fdata.end(); ++fi) { - const ColorData &cd = (*fi); - overall_time += cd._net_value; + FrameData::const_iterator fi; + for (fi = fdata.begin(); fi != fdata.end(); ++fi) { + const ColorData &cd = (*fi); + overall_time += cd._net_value; + GdkGC *gc = get_collector_gc(cd._collector_index); - if (overall_time > get_vertical_scale()) { - // Off the top. Go ahead and clamp it by hand, in case it's so - // far off the top we'd overflow the 16-bit pixel value. - _pixmap.draw_line(get_collector_gc(cd._collector_index), x, y, x, 0); - // And we can consider ourselves done now. - break; - } + if (overall_time > get_vertical_scale()) { + // Off the top. Go ahead and clamp it by hand, in case it's so + // far off the top we'd overflow the 16-bit pixel value. + gdk_draw_rectangle(_pixmap, gc, TRUE, x, 0, w + 1, y); - int top_y = height_to_pixel(overall_time); - _pixmap.draw_line(get_collector_gc(cd._collector_index), x, y, x, top_y); - y = top_y; + // And we can consider ourselves done now. + return; } - x++; - w--; + + int top_y = height_to_pixel(overall_time); + gdk_draw_rectangle(_pixmap, gc, TRUE, x, top_y, w + 1, y); + y = top_y; } } @@ -218,11 +341,9 @@ draw_slice(int x, int w, const PStatStripChart::FrameData &fdata) { //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: draw_empty(int x, int w) { - while (w > 0) { - _pixmap.draw_line(_white_gc, x, 0, x, get_ysize()); - x++; - w--; - } + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_white); + gdk_draw_rectangle(_pixmap, _pixmap_gc, TRUE, x, 0, + w + 1, get_ysize()); } //////////////////////////////////////////////////////////////////// @@ -232,7 +353,8 @@ draw_empty(int x, int w) { //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: draw_cursor(int x) { - _pixmap.draw_line(_black_gc, x, 0, x, get_ysize()); + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_black); + gdk_draw_line(_pixmap, _pixmap_gc, x, 0, x, get_ysize()); } //////////////////////////////////////////////////////////////////// @@ -248,181 +370,103 @@ end_draw(int from_x, int to_x) { // Draw in the guide bars. int num_guide_bars = get_num_guide_bars(); for (int i = 0; i < num_guide_bars; i++) { - const GuideBar &bar = get_guide_bar(i); - int y = height_to_pixel(bar._height); - - if (y >= 5) { - // Only draw it if it's not too close to the top. - switch (bar._style) { - case GBS_target: - _pixmap.draw_line(_light_gc, from_x, y, to_x, y); - break; - - case GBS_normal: - default: - _pixmap.draw_line(_dark_gc, from_x, y, to_x, y); - break; - } - } + draw_guide_bar(from_x, to_x, get_guide_bar(i)); } - GdkRectangle update_rect; - update_rect.x = from_x; - update_rect.y = 0; - update_rect.width = to_x - from_x + 1; - update_rect.height = get_ysize(); - draw(&update_rect); + GdkRectangle rect = { + from_x, 0, to_x - from_x + 1, get_ysize() + }; + gdk_window_invalidate_rect(_graph_window->window, &rect, FALSE); } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::idle +// Function: GtkStatsStripChart::consider_drag_start // Access: Protected, Virtual -// Description: Called at the end of the draw cycle. +// 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. //////////////////////////////////////////////////////////////////// -void GtkStatsStripChart:: -idle() { - if (_labels_changed) { - pack_labels(); - } - if (_guide_bars_changed) { - GdkRectangle update_rect; - update_rect.x = 0; - update_rect.y = 0; - update_rect.width = _guide->width(); - update_rect.height = _guide->height(); - _guide->draw(&update_rect); - _guide_bars_changed = false; - } -} +GtkStatsGraph::DragMode GtkStatsStripChart:: +consider_drag_start(int mouse_x, int mouse_y, int width, int height) { + if (mouse_x >= _graph_left && mouse_x < _graph_left + get_xsize()) { + if (mouse_y >= _graph_top && mouse_y < _graph_top + get_ysize()) { + // See if the mouse is over a user-defined guide bar. + int y = mouse_y - _graph_top; + float from_height = pixel_to_height(y + 2); + float to_height = pixel_to_height(y - 2); + _drag_guide_bar = find_user_guide_bar(from_height, to_height); + if (_drag_guide_bar >= 0) { + return DM_guide_bar; + } -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::configure_event_impl -// Access: Private, Virtual -// Description: Creates a new backing pixmap of the appropriate size. -//////////////////////////////////////////////////////////////////// -gint GtkStatsStripChart:: -configure_event_impl(GdkEventConfigure *) { - if (width() != get_xsize() || height() != get_ysize() || - _pixmap.gdkobj() == (GdkDrawable *)NULL) { - bool is_initial = true; - if (_pixmap) { - is_initial = false; - _pixmap.release(); + } else { + // The mouse is above or below the graph; maybe create a new + // guide bar. + return DM_new_guide_bar; } - - _pixmap.create(get_window(), width(), height()); - - Gdk_Colormap system_colormap = Gdk_Colormap::get_system(); - - _white_gc = Gdk_GC(_pixmap); - setup_white_gc(); - - _black_gc = Gdk_GC(_pixmap); - _black_gc.set_foreground(system_colormap.black()); - - _dark_gc = Gdk_GC(_pixmap); - Gdk_Color dark; - dark.set_grey_p(0.2); - system_colormap.alloc(dark); - _dark_gc.set_foreground(dark); - - _light_gc = Gdk_GC(_pixmap); - Gdk_Color light; - light.set_grey_p(0.6); - system_colormap.alloc(light); - _light_gc.set_foreground(light); - - _pixmap.draw_rectangle(_white_gc, true, 0, 0, width(), height()); - - changed_size(width(), height()); } - return true; + + return GtkStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height); } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::expose_event_impl -// Access: Private, Virtual -// Description: Redraw the screen from the backing pixmap. -//////////////////////////////////////////////////////////////////// -gint GtkStatsStripChart:: -expose_event_impl(GdkEventExpose *event) { - get_window().draw_pixmap(_white_gc, _pixmap, - event->area.x, event->area.y, - event->area.x, event->area.y, - event->area.width, event->area.height); - - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::button_press_event_impl -// Access: Private, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -gint GtkStatsStripChart:: -button_press_event_impl(GdkEventButton *button) { - if (button->type == GDK_2BUTTON_PRESS && button->button == 1) { - int collector_index = get_collector_under_pixel((int)button->x, (int)button->y); - collector_picked(collector_index); - return true; - } - return false; -} - - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::pack_labels -// Access: Private -// Description: +// Function: GtkStatsStripChart::set_drag_mode +// Access: Protected, Virtual +// Description: This should be called whenever the drag mode needs to +// change state. It provides hooks for a derived class +// to do something special. //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: -pack_labels() { - // First, remove the old labels. - _label_align->remove(); +set_drag_mode(GtkStatsGraph::DragMode drag_mode) { + GtkStatsGraph::set_drag_mode(drag_mode); - // Now add the new labels back in. - _label_box = manage(new Gtk::VBox); - _label_box->show(); - _label_align->add(*_label_box); + switch (_drag_mode) { + case DM_scale: + case DM_left_margin: + case DM_right_margin: + case DM_sizing: + // Disable smoothing for these expensive operations. + set_average_mode(false); + break; - Gdk_Font font = get_style()->gtkobj()->font; - - int num_labels = get_num_labels(); - for (int i = 0; i < num_labels; i++) { - int collector_index = get_label_collector(i); - GtkStatsLabel *label = - new GtkStatsLabel(get_monitor(), collector_index, font); - label->show(); - - label->collector_picked.connect(collector_picked.slot()); - - _label_box->pack_end(*manage(label), false, false); + default: + // Restore smoothing according to the current setting of the check + // box. + /* + int result = SendMessage(_smooth_check_box, BM_GETCHECK, 0, 0); + set_average_mode(result == BST_CHECKED); + */ + break; } - - _labels_changed = false; } //////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripChart::setup_white_gc +// Function: GtkStatsStripChart::draw_guide_bar // Access: Private -// Description: Sets the color on _white_gc to be either actually -// white (if the chart is still alive) or a light gray -// (if the chart is dead). +// Description: Draws the line for the indicated guide bar on the +// graph. //////////////////////////////////////////////////////////////////// void GtkStatsStripChart:: -setup_white_gc() { - Gdk_Colormap system_colormap = Gdk_Colormap::get_system(); +draw_guide_bar(int from_x, int to_x, + const PStatGraph::GuideBar &bar) { + int y = height_to_pixel(bar._height); - if (_is_dead) { - Gdk_Color death; - death.set_grey_p(0.8); - system_colormap.alloc(death); + if (y > 0) { + // Only draw it if it's not too close to the top. + switch (bar._style) { + case GBS_target: + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_light_gray); + break; - _white_gc.set_foreground(death); - - } else { - _white_gc.set_foreground(system_colormap.white()); + case GBS_user: + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_user_guide_bar); + break; + + case GBS_normal: + gdk_gc_set_rgb_fg_color(_pixmap_gc, &rgb_dark_gray); + break; + } + gdk_draw_line(_pixmap, _pixmap_gc, from_x, y, to_x, y); } - } - diff --git a/pandatool/src/gtk-stats/gtkStatsStripChart.h b/pandatool/src/gtk-stats/gtkStatsStripChart.h index b5033ed3f0..760b865654 100644 --- a/pandatool/src/gtk-stats/gtkStatsStripChart.h +++ b/pandatool/src/gtk-stats/gtkStatsStripChart.h @@ -1,5 +1,5 @@ // Filename: gtkStatsStripChart.h -// Created by: drose (14Jul00) +// Created by: drose (16Jan06) // //////////////////////////////////////////////////////////////////// // @@ -21,40 +21,37 @@ #include "pandatoolbase.h" -#include "gtkStatsMonitor.h" - +#include "gtkStatsGraph.h" #include "pStatStripChart.h" #include "pointerTo.h" -#include -#include "pmap.h" +#include -class PStatView; -class GtkStatsGuide; +class GtkStatsMonitor; //////////////////////////////////////////////////////////////////// // Class : GtkStatsStripChart -// Description : A special widget that draws a strip chart, given a -// view. +// Description : A window that draws a strip chart, given a view. //////////////////////////////////////////////////////////////////// -class GtkStatsStripChart : public Gtk::DrawingArea, public PStatStripChart { +class GtkStatsStripChart : public PStatStripChart, public GtkStatsGraph { public: GtkStatsStripChart(GtkStatsMonitor *monitor, - PStatView &view, int collector_index, - int xsize, int ysize); + int thread_index, int collector_index, bool show_level); + virtual ~GtkStatsStripChart(); - void mark_dead(); + virtual void new_collector(int collector_index); + virtual void new_data(int thread_index, int frame_number); + virtual void force_redraw(); + virtual void changed_graph_size(int graph_xsize, int graph_ysize); - Gtk::Alignment *get_labels(); - GtkStatsGuide *get_guide(); + virtual void set_time_units(int unit_mask); + virtual void set_scroll_speed(float scroll_speed); + virtual void clicked_label(int collector_index); + void set_vertical_scale(float value_height); - Gdk_GC get_collector_gc(int collector_index); +protected: + virtual void update_labels(); - // This signal is thrown when the user float-clicks on a label or - // on a band of color. - SigC::Signal1 collector_picked; - -private: virtual void clear_region(); virtual void copy_region(int start_x, int end_x, int dest_x); virtual void draw_slice(int x, int w, @@ -62,38 +59,25 @@ private: virtual void draw_empty(int x, int w); virtual void draw_cursor(int x); virtual void end_draw(int from_x, int to_x); - virtual void idle(); - virtual gint configure_event_impl(GdkEventConfigure *event); - virtual gint expose_event_impl(GdkEventExpose *event); - virtual gint button_press_event_impl(GdkEventButton *button); - - void pack_labels(); - void setup_white_gc(); + virtual DragMode consider_drag_start(int mouse_x, int mouse_y, + int width, int height); + virtual void set_drag_mode(DragMode drag_mode); private: - // Backing pixmap for drawing area. - Gdk_Pixmap _pixmap; + void draw_guide_bar(int from_x, int to_x, + const PStatGraph::GuideBar &bar); - // Graphics contexts for fg/bg. We don't use the contexts defined - // in the style, because that would probably interfere with the - // visibility of the strip chart. - Gdk_GC _white_gc; - Gdk_GC _black_gc; - Gdk_GC _dark_gc; - Gdk_GC _light_gc; +private: - // Table of graphics contexts for our various collectors. - typedef pmap GCs; - GCs _gcs; + int _brush_origin; + string _net_value_text; - Gtk::Alignment *_label_align; - Gtk::VBox *_label_box; - GtkStatsGuide *_guide; - bool _is_dead; + GtkWidget *_smooth_check_box; + + static bool _window_class_registered; + static const char * const _window_class_name; }; -#include "gtkStatsStripChart.I" - #endif diff --git a/pandatool/src/gtk-stats/gtkStatsStripWindow.cxx b/pandatool/src/gtk-stats/gtkStatsStripWindow.cxx deleted file mode 100644 index 20454451cb..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsStripWindow.cxx +++ /dev/null @@ -1,459 +0,0 @@ -// Filename: gtkStatsStripWindow.cxx -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "gtkStatsStripWindow.h" -#include "gtkStatsStripChart.h" -#include "gtkStatsGuide.h" - -#include "pStatCollectorDef.h" -#include "string_utils.h" - -#include // for sprintf - - -using Gtk::Menu_Helpers::MenuElem; -using Gtk::Menu_Helpers::CheckMenuElem; -using Gtk::Menu_Helpers::SeparatorElem; - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkStatsStripWindow:: -GtkStatsStripWindow(GtkStatsMonitor *monitor, int thread_index, - int collector_index, bool show_level, - int chart_xsize, int chart_ysize) : - GtkStatsWindow(monitor), - _thread_index(thread_index), - _collector_index(collector_index), - _show_level(show_level) -{ - _title_unknown = false; - _setup_scale_menu = false; - _smooth = false; - - setup_menu(); - layout_window(chart_xsize, chart_ysize); - - new_collector(); // To set up the menus in case we can. - show(); -} - - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::mark_dead -// Access: Public, Virtual -// Description: Called when the client's connection has been lost, -// this should update the window in some obvious way to -// indicate that the window is no longer live. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -mark_dead() { - GtkStatsWindow::mark_dead(); - _chart->mark_dead(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::new_collector -// Access: Public, Virtual -// Description: Called when a new collector has become known. -// -// For the GtkStatsStripWindow, this forces a rebuild of -// the menu that selects the collectors available for -// picking levels. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -new_collector() { - const PStatClientData *client_data = _monitor->get_client_data(); - - // Determine the set of collectors that display level data. We'll - // want to put these on the "Levels" pull-down menu. - - pset levels; - - int num_collectors = client_data->get_num_collectors(); - for (int i = 0; i < num_collectors; i++) { - if (client_data->has_collector(i) && - client_data->get_collector_has_level(i)) { - // We only put top-level entries on the menu. Thus, walk up - // from this collector to its top level (the one below Frame). - int collector_index = i; - const PStatCollectorDef &def = - client_data->get_collector_def(collector_index); - int parent_index = def._parent_index; - - while (parent_index != 0) { - collector_index = parent_index; - const PStatCollectorDef &def = - client_data->get_collector_def(collector_index); - parent_index = def._parent_index; - } - - levels.insert(collector_index); - } - } - - // Now put the collectors we found on the menu. - _levels_menu->items().clear(); - pset::const_iterator li; - for (li = levels.begin(); li != levels.end(); ++li) { - int collector_index = (*li); - _levels_menu->items().push_back - (MenuElem(client_data->get_collector_name(collector_index), - bind(slot(this, &GtkStatsStripWindow::menu_show_levels), collector_index))); - } - - // Also re-set-up the scale menu, in case the properties have changed. - setup_scale_menu(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::idle -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -idle() { - GtkStatsWindow::idle(); - _chart->update(); - - const PStatThreadData *thread_data = _chart->get_view().get_thread_data(); - if (!thread_data->is_empty()) { - float frame_rate = thread_data->get_frame_rate(); - char buffer[128]; - sprintf(buffer, "Frame rate: %0.1f Hz", frame_rate); - _frame_rate_label->set_text(buffer); - } - - if (_title_unknown) { - _title_label->set_text(get_title_text()); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::setup_menu -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -setup_menu() { - GtkStatsWindow::setup_menu(); - - Gtk::Menu *speed_menu = new Gtk::Menu; - - speed_menu->items().push_back - (MenuElem("1", // 1 chart width scrolls by per minute. - bind(slot(this, &GtkStatsStripWindow::menu_hscale), 1.0f))); - speed_menu->items().push_back - (MenuElem("2", // 2 chart widths scroll by per minute. - bind(slot(this, &GtkStatsStripWindow::menu_hscale), 2.0f))); - speed_menu->items().push_back - (MenuElem("3", - bind(slot(this, &GtkStatsStripWindow::menu_hscale), 3.0f))); - speed_menu->items().push_back - (MenuElem("6", - bind(slot(this, &GtkStatsStripWindow::menu_hscale), 6.0f))); - speed_menu->items().push_back - (MenuElem("12", - bind(slot(this, &GtkStatsStripWindow::menu_hscale), 12.0f))); - - _menu->items().push_back(MenuElem("Speed", *manage(speed_menu))); - - _scale_menu = new Gtk::Menu; - _scale_menu->items().push_back - (CheckMenuElem("Smooth", - slot(this, &GtkStatsStripWindow::menu_smooth))); - _scale_menu->items().push_back(SeparatorElem()); - _scale_menu->items().push_back - (MenuElem("Auto scale", - slot(this, &GtkStatsStripWindow::menu_auto_vscale))); - - _menu->items().push_back(MenuElem("Scale", *manage(_scale_menu))); - - _levels_menu = new Gtk::Menu; - _menu->items().push_back(MenuElem("Levels", *manage(_levels_menu))); -} - - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::setup_scale_menu -// Access: Protected -// Description: Sets up the options on the scale menu. We can't do -// this until we have initialized the _chart member and -// we have gotten our first collector_index. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -setup_scale_menu() { - if (_setup_scale_menu) { - // Already done it. - return; - } - - const PStatClientData *client_data = _monitor->get_client_data(); - if (!client_data->has_collector(_collector_index)) { - // Can't set up the scale menu yet. - return; - } - - const PStatCollectorDef &def = client_data->get_collector_def(_collector_index); - float base_scale = 1.0; - string unit_name = def._level_units; - - if (_show_level) { - _chart->set_guide_bar_unit_name(unit_name); - _chart->set_guide_bar_units(PStatGraph::GBU_named); - - } else { - _chart->set_guide_bar_units(PStatGraph::GBU_ms); - } - - if (def._suggested_scale != 0.0) { - base_scale = def._suggested_scale; - } else if (!_show_level) { - base_scale = 1.0 / _chart->get_target_frame_rate(); - } - - static const float scales[] = { - 50.0, - 10.0, - 5.0, - 2.0, - 1.0, - 0.5, - 0.2, - 0.1, - 0.02, - }; - static const int num_scales = sizeof(scales) / sizeof(float); - - for (int i = 0; i < num_scales; i++) { - float scale = base_scale * scales[i]; - string label; - - if (_show_level) { - label = _chart->format_number(scale, PStatGraph::GBU_named | PStatGraph::GBU_show_units, unit_name); - } else { - label = _chart->format_number(scale, PStatGraph::GBU_ms | PStatGraph::GBU_hz | PStatGraph::GBU_show_units); - } - - _scale_menu->items().push_back - (MenuElem(label, - bind(slot(this, &GtkStatsStripWindow::menu_vscale), scale))); - } - - _setup_scale_menu = true; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::menu_new_window -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -menu_new_window() { - new GtkStatsStripWindow(_monitor, _thread_index, _collector_index, - _show_level, - _chart->get_xsize(), _chart->get_ysize()); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::menu_hscale -// Access: Protected -// Description: Selects a new horizontal scale for the strip chart. -// This is done from the menu called "Speed", since -// changing the horizontal scale most obviously affects -// the scrolling speed. -// -// The units is in chart width per minute. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -menu_hscale(float wpm) { - _chart->set_horizontal_scale(60.0 / wpm); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::menu_vscale -// Access: Protected -// Description: Selects a new vertical scale for the strip chart. -// This is done from the menu called "Scale". -// -// The units is in seconds, or whatever the units -// of choice are. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -menu_vscale(float max_height) { - _chart->set_vertical_scale(max_height); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::menu_smooth -// Access: Protected -// Description: Toggles the "smooth" state of the check menu. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -menu_smooth() { - _smooth = !_smooth; - - _chart->set_average_mode(_smooth); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::menu_auto_vscale -// Access: Protected -// Description: Selects a suitable vertical scale based on the data -// already visible in the chart. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -menu_auto_vscale() { - _chart->set_auto_vertical_scale(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::menu_show_levels -// Access: Protected -// Description: Shows the level values known for the indicated -// collector. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -menu_show_levels(int collector_index) { - new GtkStatsStripWindow(_monitor, _thread_index, collector_index, - true, - _chart->get_xsize(), _chart->get_ysize()); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::open_subchart -// Access: Protected -// Description: This is called in response to the collector_picked -// signal from the strip chart, which is generated when -// the user double-clicks on a band of color or a label. -// -// This opens up a new window focusing just on the -// indicated collector. -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -open_subchart(int collector_index) { - new GtkStatsStripWindow(_monitor, _thread_index, collector_index, - _show_level, - _chart->get_xsize(), _chart->get_ysize()); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::layout_window -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsStripWindow:: -layout_window(int chart_xsize, int chart_ysize) { - Gtk::HBox *hbox = new Gtk::HBox; - hbox = new Gtk::HBox; - hbox->show(); - _main_box->pack_start(*manage(hbox), true, true, 8); - - Gtk::Table *chart_table = new Gtk::Table(3, 2); - chart_table->show(); - hbox->pack_start(*manage(chart_table), true, true, 8); - - Gtk::HBox *title_hbox = new Gtk::HBox; - title_hbox->show(); - chart_table->attach(*manage(title_hbox), 1, 2, 0, 1, - (GTK_FILL|GTK_EXPAND), 0); - - _title_label = new Gtk::Label(get_title_text()); - if (_collector_index != 0 || _thread_index != 0) { - _title_label->show(); - _title_label->set_alignment(0.0, 0.5); - title_hbox->pack_start(*manage(_title_label), true, true); - } - - _frame_rate_label = new Gtk::Label; - if (_collector_index == 0) { - _frame_rate_label->show(); - _frame_rate_label->set_alignment(1.0, 0.5); - title_hbox->pack_start(*manage(_frame_rate_label), true, true); - } - - Gtk::Frame *frame = new Gtk::Frame; - frame->set_shadow_type(GTK_SHADOW_ETCHED_OUT); - frame->show(); - chart_table->attach(*manage(frame), 1, 2, 1, 2); - - if (_show_level) { - _chart = new GtkStatsStripChart(_monitor, - _monitor->get_level_view(_collector_index, _thread_index), - _collector_index, - chart_xsize, chart_ysize); - } else { - _chart = new GtkStatsStripChart(_monitor, - _monitor->get_view(_thread_index), - _collector_index, - chart_xsize, chart_ysize); - } - - _chart->collector_picked. - connect(slot(this, &GtkStatsStripWindow::open_subchart)); - frame->add(*manage(_chart)); - - chart_table->attach(*_chart->get_labels(), 0, 1, 1, 2, - 0, (GTK_FILL|GTK_EXPAND), 4, 0); - chart_table->attach(*_chart->get_guide(), 2, 3, 1, 2, - 0, (GTK_FILL|GTK_EXPAND), 4, 0); - _chart->show(); -} - - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsStripWindow::get_title_text -// Access: Private -// Description: Returns the text suitable for the title label on the -// top line. -//////////////////////////////////////////////////////////////////// -string GtkStatsStripWindow:: -get_title_text() { - string text; - - _title_unknown = false; - - const PStatClientData *client_data = _monitor->get_client_data(); - if (client_data->has_collector(_collector_index)) { - const PStatCollectorDef &def = client_data->get_collector_def(_collector_index); - if (_show_level) { - if (def._level_units.empty()) { - text = def._name; - } else { - text = def._name + " (" + def._level_units + ")"; - } - } else { - text = def._name + " time"; - } - } else { - _title_unknown = true; - } - - if (_thread_index != 0) { - if (client_data->has_thread(_thread_index)) { - text += "(" + client_data->get_thread_name(_thread_index) + " thread)"; - } else { - _title_unknown = true; - } - } - - return text; -} - diff --git a/pandatool/src/gtk-stats/gtkStatsStripWindow.h b/pandatool/src/gtk-stats/gtkStatsStripWindow.h deleted file mode 100644 index 747c8f4550..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsStripWindow.h +++ /dev/null @@ -1,78 +0,0 @@ -// Filename: gtkStatsStripWindow.h -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef GTKSTATSSTRIPWINDOW_H -#define GTKSTATSSTRIPWINDOW_H - -#include "pandatoolbase.h" - -#include "gtkStatsMonitor.h" -#include "gtkStatsWindow.h" - -class GtkStatsStripChart; - -//////////////////////////////////////////////////////////////////// -// Class : GtkStatsStripWindow -// Description : A window that contains your basic one-thread, -// one-level strip chart. -//////////////////////////////////////////////////////////////////// -class GtkStatsStripWindow : public GtkStatsWindow { -public: - GtkStatsStripWindow(GtkStatsMonitor *monitor, int thread_index, - int collector_index, bool show_level, - int chart_xsize, int chart_ysize); - - virtual void mark_dead(); - virtual void new_collector(); - virtual void idle(); - -protected: - virtual void setup_menu(); - void setup_scale_menu(); - virtual void menu_new_window(); - void menu_hscale(float wpm); - void menu_vscale(float max_height); - void menu_smooth(); - void menu_auto_vscale(); - void menu_show_levels(int collector_index); - void open_subchart(int collector_index); - -private: - void layout_window(int chart_xsize, int chart_ysize); - string get_title_text(); - -private: - int _thread_index; - int _collector_index; - bool _show_level; - bool _title_unknown; - bool _setup_scale_menu; - - Gtk::Label *_title_label; - Gtk::Label *_frame_rate_label; - GtkStatsStripChart *_chart; - - Gtk::Menu *_scale_menu; - Gtk::Menu *_levels_menu; - - bool _smooth; -}; - - -#endif - diff --git a/pandatool/src/gtk-stats/gtkStatsWindow.cxx b/pandatool/src/gtk-stats/gtkStatsWindow.cxx deleted file mode 100644 index 4c55c8ee9b..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsWindow.cxx +++ /dev/null @@ -1,210 +0,0 @@ -// Filename: gtkStatsWindow.cxx -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "gtkStatsWindow.h" -#include "gtkStatsMonitor.h" -#include "gtkStatsStripWindow.h" -#include "gtkStatsPianoWindow.h" - -using Gtk::Menu_Helpers::MenuElem; -using Gtk::Menu_Helpers::SeparatorElem; - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkStatsWindow:: -GtkStatsWindow(GtkStatsMonitor *monitor) : _monitor(monitor) { - _monitor->add_window(this); - update_title(); - setup(); - - _main_box = new Gtk::VBox; - _main_box->show(); - add(*manage(_main_box)); - - _menu = manage(new Gtk::MenuBar); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::destruct -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -bool GtkStatsWindow:: -destruct() { - if (BasicGtkWindow::destruct()) { - _monitor->remove_window(this); - _monitor.clear(); - return true; - } - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::update_title -// Access: Public, Virtual -// Description: Sets the title bar appropriately, once the client's -// information is known. -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -update_title() { - if (_monitor->is_client_known()) { - string title = - _monitor->get_client_progname() + " from " + _monitor->get_client_hostname(); - if (!_monitor->is_alive()) { - title += " (closed)"; - } - set_title(title); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::mark_dead -// Access: Public, Virtual -// Description: Called when the client's connection has been lost, -// this should update the window in some obvious way to -// indicate that the window is no longer live. -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -mark_dead() { - update_title(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::new_collector -// Access: Public, Virtual -// Description: Called when a new collector has become known, in case -// the window cares. -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -new_collector() { -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::idle -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -idle() { - if (_monitor->_new_collector) { - new_collector(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::setup_menu -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -setup_menu() { - _file_menu = new Gtk::Menu; - - _file_menu->items().push_back - (MenuElem("New strip chart", - slot(this, &GtkStatsWindow::menu_open_strip_chart))); - _file_menu->items().push_back - (MenuElem("New piano roll", - slot(this, &GtkStatsWindow::menu_open_piano_roll))); - - /* - _file_menu->items().push_back - (MenuElem("New window", - slot(this, &GtkStatsWindow::menu_new_window))); - */ - - _file_menu->items().push_back(SeparatorElem()); - - _file_menu->items().push_back - (MenuElem("Disconnect from client", - slot(this, &GtkStatsWindow::menu_disconnect))); - _file_menu->items().push_back - (MenuElem("Close window", - slot(this, &GtkStatsWindow::menu_close_window))); - _file_menu->items().push_back - (MenuElem("Close all windows this client", - slot(this, &GtkStatsWindow::menu_close_all_windows))); - - _menu->items().push_back(MenuElem("File", *manage(_file_menu))); - _menu->show(); - _main_box->pack_start(*_menu, false, false); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::menu_open_strip_chart -// Access: Protected -// Description: Open up a new strip-chart style window for the main -// thread. -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -menu_open_strip_chart() { - new GtkStatsStripWindow(_monitor, 0, 0, false, 400, 100); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::menu_open_piano_roll -// Access: Protected -// Description: Open up a new piano-roll style window for the main -// thread. -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -menu_open_piano_roll() { - new GtkStatsPianoWindow(_monitor, 0, 400, 100); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::menu_new_window -// Access: Protected, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -menu_new_window() { -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::menu_close_window -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -menu_close_window() { - destruct(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::menu_close_all_windows -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -menu_close_all_windows() { - _monitor->close_all_windows(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkStatsWindow::menu_disconnect -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void GtkStatsWindow:: -menu_disconnect() { - _monitor->close(); -} diff --git a/pandatool/src/gtk-stats/gtkStatsWindow.h b/pandatool/src/gtk-stats/gtkStatsWindow.h deleted file mode 100644 index 890ead50d7..0000000000 --- a/pandatool/src/gtk-stats/gtkStatsWindow.h +++ /dev/null @@ -1,69 +0,0 @@ -// Filename: gtkStatsWindow.h -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef GTKSTATSWINDOW_H -#define GTKSTATSWINDOW_H - -#include "pandatoolbase.h" - -#include "gtkStatsMonitor.h" - -#include "basicGtkWindow.h" - -#include "pointerTo.h" - -//////////////////////////////////////////////////////////////////// -// Class : GtkStatsWindow -// Description : This is the base class for a family of windows that -// are associated with one particular stats client. -// Each window keeps a pointer back to the -// GtkStatsMonitor object, which in turn knows about all -// of the windows; when the last window is closed, the -// monitor object goes away and ends the session. -//////////////////////////////////////////////////////////////////// -class GtkStatsWindow : public BasicGtkWindow { -public: - GtkStatsWindow(GtkStatsMonitor *monitor); - virtual bool destruct(); - - virtual void update_title(); - virtual void mark_dead(); - virtual void new_collector(); - virtual void idle(); - -protected: - virtual void setup_menu(); - - void menu_open_strip_chart(); - void menu_open_piano_roll(); - virtual void menu_new_window(); - void menu_close_window(); - void menu_close_all_windows(); - void menu_disconnect(); - -protected: - PT(GtkStatsMonitor) _monitor; - - Gtk::VBox *_main_box; - Gtk::MenuBar *_menu; - Gtk::Menu *_file_menu; -}; - - -#endif - diff --git a/pandatool/src/gtk-stats/gtkstats_composite1.cxx b/pandatool/src/gtk-stats/gtkstats_composite1.cxx new file mode 100755 index 0000000000..61e1fa7ab7 --- /dev/null +++ b/pandatool/src/gtk-stats/gtkstats_composite1.cxx @@ -0,0 +1,9 @@ +#include "gtkStats.cxx" +#include "gtkStatsChartMenu.cxx" +#include "gtkStatsGraph.cxx" +#include "gtkStatsLabel.cxx" +#include "gtkStatsLabelStack.cxx" +#include "gtkStatsMonitor.cxx" +#include "gtkStatsPianoRoll.cxx" +#include "gtkStatsServer.cxx" +#include "gtkStatsStripChart.cxx" diff --git a/pandatool/src/gtk-stats/scribble.cc b/pandatool/src/gtk-stats/scribble.cc deleted file mode 100644 index b517a72d99..0000000000 --- a/pandatool/src/gtk-stats/scribble.cc +++ /dev/null @@ -1,201 +0,0 @@ - - - -/* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -/* Modifed for gtk-- by sac@transmeta.com */ -/* Modified (slightly) for gdk-- by freyd@uni-muenster.de */ -#include -#include -#include -#include -#include -#include -#include - - -class ScribbleDrawingArea : public Gtk::DrawingArea -{ - /* Backing pixmap for drawing area */ - - Gdk_Pixmap pixmap; - Gdk_GC gc; - Gdk_Window win; - Gdk_Visual visual; - - virtual gint configure_event_impl (GdkEventConfigure *event); - virtual gint expose_event_impl (GdkEventExpose *event); - virtual gint button_press_event_impl (GdkEventButton *event); - virtual gint motion_notify_event_impl (GdkEventMotion *event); - void draw_brush (gdouble x, gdouble y); - -public: - ScribbleDrawingArea (); - -}; - -ScribbleDrawingArea::ScribbleDrawingArea() - : Gtk::DrawingArea(), pixmap (0) - { - set_events (GDK_EXPOSURE_MASK - | GDK_LEAVE_NOTIFY_MASK - | GDK_BUTTON_PRESS_MASK - | GDK_POINTER_MOTION_MASK - | GDK_POINTER_MOTION_HINT_MASK); - } - - -/* Create a new backing pixmap of the appropriate size */ -int ScribbleDrawingArea::configure_event_impl (GdkEventConfigure * /* event */) - { - win = get_window(); - visual = win.get_visual(); - - if (pixmap) - pixmap.release(); - gc = get_style()->gtkobj()->white_gc; - // Gtk::Style has no access to its data members, so use gtk objekt. - // Some access functions would be nice like GtkStyle::get_white_gc() etc. - pixmap.create(get_window(), width(), height()); - - pixmap.draw_rectangle (gc, - TRUE, - 0, 0, - width(), - height()); - - return TRUE; - } - -/* Redraw the screen from the backing pixmap */ -int ScribbleDrawingArea::expose_event_impl (GdkEventExpose *event) - { - - gc = get_style()->gtkobj()->fg_gc[GTK_WIDGET_STATE (GTK_WIDGET(gtkobj()))]; - // Same like above, + Gtk::Widget has set_state function but no get_state - // function. - win.draw_pixmap(gc , - pixmap, - event->area.x, event->area.y, - event->area.x, event->area.y, - event->area.width, event->area.height); - - return FALSE; - } - -/* Draw a rectangle on the screen */ -void ScribbleDrawingArea::draw_brush (gdouble x, gdouble y) - { - GdkRectangle update_rect; - update_rect.x = (int)x - 5; - update_rect.y = (int)y - 5; - update_rect.width = 10; - update_rect.height = 10; - gc = get_style()->gtkobj()->black_gc; - pixmap.draw_rectangle( - gc, - TRUE, - update_rect.x, update_rect.y, - update_rect.width, update_rect.height); - draw(&update_rect); - //draw (&update_rect); - } - -gint ScribbleDrawingArea::button_press_event_impl (GdkEventButton *event) - { - if (event->button == 1 && pixmap) - draw_brush (event->x, event->y); - - return TRUE; - } - -gint ScribbleDrawingArea::motion_notify_event_impl (GdkEventMotion *event) - { - int x, y; - GdkModifierType state; - if (event->is_hint) - gdk_window_get_pointer (event->window, &x, &y, &state); - else - { - x = (int)event->x; - y = (int)event->y; - state = (GdkModifierType) event->state; - } - - if (state & GDK_BUTTON1_MASK && pixmap) - draw_brush (x, y); - - return TRUE; - } - - -class ScribbleWindow : public Gtk::Window -{ - - Gtk::VBox vbox; - ScribbleDrawingArea drawing_area; - Gtk::Button button; - void quit (); -public: - ScribbleWindow (); -}; - -void ScribbleWindow::quit () - { - Gtk::Main::quit(); - } - -ScribbleWindow::ScribbleWindow () - : Gtk::Window(GTK_WINDOW_TOPLEVEL), - vbox (FALSE, 0), - button ("quit") - { - add (vbox); - - /* Create the drawing area */ - drawing_area.size (400, 400); - vbox.pack_start (drawing_area, TRUE, TRUE, 0); - - - /* Add the button */ - vbox.pack_start (button, FALSE, FALSE, 0); - - button.clicked.connect(slot(*this, &ScribbleWindow::quit)); - destroy.connect(slot(*this, &ScribbleWindow::quit)); - - drawing_area.show(); - button.show(); - vbox.show(); - } - -int -main (int argc, char *argv[]) -{ - ScribbleWindow *window; - Gtk::Main myapp(argc, argv); - - window = new ScribbleWindow; - window->show(); - - myapp.run(); - - return 0; -} diff --git a/pandatool/src/gtkbase/Sources.pp b/pandatool/src/gtkbase/Sources.pp deleted file mode 100644 index 65d71cd823..0000000000 --- a/pandatool/src/gtkbase/Sources.pp +++ /dev/null @@ -1,18 +0,0 @@ -#define BUILD_DIRECTORY $[HAVE_GTKMM] -#define USE_PACKAGES gtkmm - -#begin ss_lib_target - #define TARGET gtkbase - #define LOCAL_LIBS \ - progbase - - #define SOURCES \ - basicGtkDialog.cxx basicGtkDialog.h basicGtkWindow.cxx \ - basicGtkWindow.h gtkBase.cxx gtkBase.h request_initial_size.cxx \ - request_initial_size.h - - #define INSTALL_HEADERS \ - basicGtkDialog.h basicGtkWindow.h gtkBase.h request_initial_size.h - -#end ss_lib_target - diff --git a/pandatool/src/gtkbase/basicGtkDialog.cxx b/pandatool/src/gtkbase/basicGtkDialog.cxx deleted file mode 100644 index b3d584cfa8..0000000000 --- a/pandatool/src/gtkbase/basicGtkDialog.cxx +++ /dev/null @@ -1,69 +0,0 @@ -// Filename: basicGtkDialog.cxx -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "basicGtkDialog.h" - - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkDialog::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -BasicGtkDialog:: -BasicGtkDialog(bool free_store) : BasicGtkWindow(free_store) { - _vbox = manage(new Gtk::VBox); - _action_area = manage(new Gtk::HBox); - - Gtk::VBox *box0 = manage(new Gtk::VBox); - Gtk::HSeparator *hsep = manage(new Gtk::HSeparator); - - add(*box0); - box0->show(); - box0->pack_start(*_vbox); - _vbox->show(); - - box0->pack_start(*hsep); - hsep->show(); - - _action_area->set_border_width(10); - box0->pack_start(*_action_area, false); - _action_area->show(); -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkDialog::get_vbox -// Access: Public -// Description: Returns a pointer to the main part of the dialog -// window. -//////////////////////////////////////////////////////////////////// -Gtk::VBox *BasicGtkDialog:: -get_vbox() const { - return _vbox; -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkDialog::get_action_area -// Access: Public -// Description: Returns a pointer to part of the dialog reserved for -// action buttons. -//////////////////////////////////////////////////////////////////// -Gtk::HBox *BasicGtkDialog:: -get_action_area() const { - return _action_area; -} - diff --git a/pandatool/src/gtkbase/basicGtkDialog.h b/pandatool/src/gtkbase/basicGtkDialog.h deleted file mode 100644 index c48a33f2dc..0000000000 --- a/pandatool/src/gtkbase/basicGtkDialog.h +++ /dev/null @@ -1,48 +0,0 @@ -// Filename: basicGtkDialog.h -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef BASICGTKDIALOG_H -#define BASICGTKDIALOG_H - -#include "basicGtkWindow.h" - -#include - - -//////////////////////////////////////////////////////////////////// -// Class : BasicGtkDialog -// Description : This looks like a wrapper around Gtk::Dialog. -// Actually, it doesn't inherit from Gtk::Dialog at all, -// but instead (indirectly) from Gtk::Window; it just -// duplicates the default functionality of Gtk::Dialog -// by defining get_vbox() and a get_action_area(). -//////////////////////////////////////////////////////////////////// -class BasicGtkDialog : public BasicGtkWindow { -public: - BasicGtkDialog(bool free_store = true); - - Gtk::VBox *get_vbox() const; - Gtk::HBox *get_action_area() const; - -private: - Gtk::VBox *_vbox; - Gtk::HBox *_action_area; -}; - - -#endif diff --git a/pandatool/src/gtkbase/basicGtkWindow.cxx b/pandatool/src/gtkbase/basicGtkWindow.cxx deleted file mode 100644 index 34ae75e33d..0000000000 --- a/pandatool/src/gtkbase/basicGtkWindow.cxx +++ /dev/null @@ -1,140 +0,0 @@ -// Filename: basicGtkWindow.cxx -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "basicGtkWindow.h" -#include "gtkBase.h" - - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkWindow::Constructor -// Access: Public -// Description: The free_store parameter should be true if the window -// object has been allocated from the free store (using -// new) and can be safely deleted using delete when the -// window is destroyed by the user, or false if this is -// not the case. -//////////////////////////////////////////////////////////////////// -BasicGtkWindow:: -BasicGtkWindow(bool free_store) : _free_store(free_store) { - _destroyed = false; - _state = S_virgin; -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkWindow::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -BasicGtkWindow:: -~BasicGtkWindow() { - destruct(); -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkWindow::setup -// Access: Public -// Description: Call this after initializing the window. -//////////////////////////////////////////////////////////////////// -void BasicGtkWindow:: -setup() { - _state = S_setup; - _destroy_connection = - destroy.connect(slot(this, &BasicGtkWindow::window_destroyed)); - show(); - - // Calling show() sets in motion some X events that must flow - // completely through the queue before we can safely hide() the - // thing again. To measure when this has happened, we'll drop our - // own event into the queue. When this event makes it through the - // queue, we'll assume all relevant X events have also, and it will - // be safe to hide the window. - Gtk::Main::idle.connect(slot(this, &BasicGtkWindow::idle_event)); -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkWindow::destruct -// Access: Public, Virtual -// Description: Call this to remove the window, etc. It's not tied -// directly to the real destructor because that seems to -// just lead to trouble. This returns true if it -// actually destructed, or false if it had already -// destructed previously and did nothing this time. -//////////////////////////////////////////////////////////////////// -bool BasicGtkWindow:: -destruct() { - if (_state != S_gone) { - // We must hide the window before we destruct, or it won't disappear - // from the screen. Strange. But we also don't want to try to hide - // the window if we're destructing because of a window_destroyed - // event, so we check our little flag. - if (!_destroyed && _state != S_virgin) { - // Now, in case the window was never completely shown, we must - // wait for that to happen before we can hide it. - while (!_destroyed && _state == S_setup) { - GtkBase::_gtk->iteration(); - } - - if (!_destroyed) { - hide(); - } - } - _state = S_gone; - return true; - } - - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkWindow::delete_self -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void BasicGtkWindow:: -delete_self() { - destruct(); -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkWindow::window_destroyed -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -void BasicGtkWindow:: -window_destroyed() { - _destroyed = true; - destruct(); - - // We should probably also delete the pointer here. But maybe not. - // Gtk-- is very mysterious about this, so we'll just let it maybe - // leak. -} - -//////////////////////////////////////////////////////////////////// -// Function: BasicGtkWindow::idle_event -// Access: Private -// Description: -//////////////////////////////////////////////////////////////////// -gint BasicGtkWindow:: -idle_event() { - // Now, we're finally a bona fide window with all rights thereunto - // appertaining. - _state = S_ready; - return false; -} - diff --git a/pandatool/src/gtkbase/basicGtkWindow.h b/pandatool/src/gtkbase/basicGtkWindow.h deleted file mode 100644 index eb0dcdc8a6..0000000000 --- a/pandatool/src/gtkbase/basicGtkWindow.h +++ /dev/null @@ -1,60 +0,0 @@ -// Filename: basicGtkWindow.h -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef BASICGTKWINDOW_H -#define BASICGTKWINDOW_H - -#include - - -//////////////////////////////////////////////////////////////////// -// Class : BasicGtkWindow -// Description : This is just a handy wrapper around Gtk::Window that -// provides some convenient setup functions. -//////////////////////////////////////////////////////////////////// -class BasicGtkWindow : public Gtk::Window { -public: - BasicGtkWindow(bool free_store = true); - virtual ~BasicGtkWindow(); - void setup(); - virtual bool destruct(); - -protected: - void delete_self(); - static gint static_delete(BasicGtkWindow *window); - -private: - void window_destroyed(); - gint idle_event(); - - enum State { - S_virgin, - S_setup, - S_ready, - S_gone, - }; - - bool _destroyed; - bool _free_store; - State _state; - SigC::Connection _destroy_connection; -}; - - -#endif - diff --git a/pandatool/src/gtkbase/gtkBase.cxx b/pandatool/src/gtkbase/gtkBase.cxx deleted file mode 100644 index d61b615cc7..0000000000 --- a/pandatool/src/gtkbase/gtkBase.cxx +++ /dev/null @@ -1,76 +0,0 @@ -// Filename: gtkBase.cxx -// Created by: drose (14Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "gtkBase.h" - -#include "notify.h" - -Gtk::Main *GtkBase::_gtk = NULL; - -//////////////////////////////////////////////////////////////////// -// Function: GtkBase::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkBase:: -GtkBase() { - if (_gtk != (Gtk::Main *)NULL) { - nout << "Invalid attempt to create multiple instances of GtkBase!\n"; - abort(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkBase::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -GtkBase:: -~GtkBase() { - nassertv(_gtk != (Gtk::Main *)NULL); - delete _gtk; - _gtk = NULL; -} - - -//////////////////////////////////////////////////////////////////// -// Function: GtkBase::parse_command_line -// Access: Public, Virtual -// Description: This is overridden for GtkBase to give Gtk a chance -// to pull out its X-related parameters. -//////////////////////////////////////////////////////////////////// -void GtkBase:: -parse_command_line(int argc, char *argv[]) { - nassertv(_gtk == (Gtk::Main *)NULL); - _gtk = new Gtk::Main(argc, argv); - ProgramBase::parse_command_line(argc, argv); -} - -//////////////////////////////////////////////////////////////////// -// Function: GtkBase::main_loop -// Access: Public -// Description: Call this after all is set up to yield control of the -// main loop to Gtk. This normally doesn't return. -//////////////////////////////////////////////////////////////////// -void GtkBase:: -main_loop() { - nassertv(_gtk != NULL); - - _gtk->run(); -} - diff --git a/pandatool/src/gtkbase/request_initial_size.cxx b/pandatool/src/gtkbase/request_initial_size.cxx deleted file mode 100644 index 8f34356ee9..0000000000 --- a/pandatool/src/gtkbase/request_initial_size.cxx +++ /dev/null @@ -1,46 +0,0 @@ -// Filename: request_initial_size.cxx -// Created by: drose (15Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "request_initial_size.h" - -static int -restore_usize(Gtk::Widget *widget) { - widget->set_usize(0, 0); - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: request_initial_size -// Description: Gtk-- hack to request an initial size for a widget, -// while still allowing the user to resize it smaller. -//////////////////////////////////////////////////////////////////// -void -request_initial_size(Gtk::Widget &widget, int xsize, int ysize) { - if (xsize != 0 || ysize != 0) { - // I can't find a way to request an initial size for a general - // widget. The best I can do is specify its minimum size. - widget.set_usize(xsize, ysize); - - // However, I don't want the minimum size to be enforced forever; - // the user should be able to resize the window smaller if he wants - // to. Thus, this ugly hack: at the first idle signal, we return - // the usize to 0. - Gtk::Main::idle.connect(bind(slot(&restore_usize), &widget)); - } -} - diff --git a/pandatool/src/gtkbase/request_initial_size.h b/pandatool/src/gtkbase/request_initial_size.h deleted file mode 100644 index b5ca025c9d..0000000000 --- a/pandatool/src/gtkbase/request_initial_size.h +++ /dev/null @@ -1,28 +0,0 @@ -// Filename: request_initial_size.h -// Created by: drose (15Jul00) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef REQUEST_INITIAL_SIZE_H -#define REQUEST_INITIAL_SIZE_H - -#include "pandatoolbase.h" - -#include - -void request_initial_size(Gtk::Widget &widget, int xsize, int ysize); - -#endif