diff --git a/pandatool/src/pstatserver/pStatStripChart.cxx b/pandatool/src/pstatserver/pStatStripChart.cxx index 5306b51771..b832a3b886 100644 --- a/pandatool/src/pstatserver/pStatStripChart.cxx +++ b/pandatool/src/pstatserver/pStatStripChart.cxx @@ -346,25 +346,27 @@ get_frame_data(int frame_number) { void PStatStripChart:: changed_size(int xsize, int ysize) { if (xsize != _xsize || ysize != _ysize) { - _cursor_pixel = xsize * _cursor_pixel / _xsize; _xsize = xsize; _ysize = ysize; + if (_xsize > 0 && _ysize > 0) { + _cursor_pixel = xsize * _cursor_pixel / _xsize; - if (!_first_data) { - if (_scroll_mode) { - draw_pixels(0, _xsize); + if (!_first_data) { + if (_scroll_mode) { + draw_pixels(0, _xsize); - } else { - // Redraw the stats that were there before. - float old_start_time = _start_time; + } else { + // Redraw the stats that were there before. + float old_start_time = _start_time; - // Back up a bit to draw the stuff to the right of the cursor. - _start_time -= _time_width; - draw_pixels(_cursor_pixel, _xsize); + // Back up a bit to draw the stuff to the right of the cursor. + _start_time -= _time_width; + draw_pixels(_cursor_pixel, _xsize); - // Now draw the stuff to the left of the cursor. - _start_time = old_start_time; - draw_pixels(0, _cursor_pixel); + // Now draw the stuff to the left of the cursor. + _start_time = old_start_time; + draw_pixels(0, _cursor_pixel); + } } } } diff --git a/pandatool/src/win-stats/winStatsGraph.cxx b/pandatool/src/win-stats/winStatsGraph.cxx index e8ac53904f..45b5686de8 100644 --- a/pandatool/src/win-stats/winStatsGraph.cxx +++ b/pandatool/src/win-stats/winStatsGraph.cxx @@ -20,6 +20,9 @@ #include "winStatsMonitor.h" #include "winStatsLabelStack.h" +bool WinStatsGraph::_graph_window_class_registered = false; +const char * const WinStatsGraph::_graph_window_class_name = "graph"; + //////////////////////////////////////////////////////////////////// // Function: WinStatsGraph::Constructor // Access: Public @@ -30,6 +33,7 @@ WinStatsGraph(WinStatsMonitor *monitor) : _monitor(monitor) { _window = 0; + _graph_window = 0; _bitmap = 0; _bitmap_dc = 0; _bitmap_xsize = 0; @@ -56,6 +60,11 @@ WinStatsGraph:: DeleteObject(brush); } + if (_graph_window) { + DestroyWindow(_graph_window); + _graph_window = 0; + } + if (_window) { DestroyWindow(_window); _window = 0; @@ -81,6 +90,25 @@ void WinStatsGraph:: new_data(int thread_index, int frame_number) { } +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::force_redraw +// Access: Public, Virtual +// Description: Called when it is necessary to redraw the entire graph. +//////////////////////////////////////////////////////////////////// +void WinStatsGraph:: +force_redraw() { +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::changed_graph_size +// Access: Public, Virtual +// Description: Called when the user has resized the window, forcing +// a resize of the graph. +//////////////////////////////////////////////////////////////////// +void WinStatsGraph:: +changed_graph_size(int graph_xsize, int graph_ysize) { +} + //////////////////////////////////////////////////////////////////// // Function: WinStatsGraph::close // Access: Protected @@ -96,47 +124,6 @@ close() { } } -//////////////////////////////////////////////////////////////////// -// Function: WinStatsGraph::setup_bitmap -// Access: Protected -// Description: Sets up a backing-store bitmap of the indicated size. -//////////////////////////////////////////////////////////////////// -void WinStatsGraph:: -setup_bitmap(int xsize, int ysize) { - release_bitmap(); - _bitmap_xsize = max(xsize, 0); - _bitmap_ysize = max(ysize, 0); - - _frame_rect.left = _left_margin; - _frame_rect.top = _top_margin; - _frame_rect.right = _left_margin + _bitmap_xsize; - _frame_rect.bottom = _bottom_margin + _bitmap_ysize; - - HDC hdc = GetDC(_window); - _bitmap_dc = CreateCompatibleDC(hdc); - _bitmap = CreateCompatibleBitmap(hdc, _bitmap_xsize, _bitmap_ysize); - SelectObject(_bitmap_dc, _bitmap); - ReleaseDC(_window, hdc); -} - -//////////////////////////////////////////////////////////////////// -// Function: WinStatsGraph::release_bitmap -// Access: Protected -// Description: Frees the backing-store bitmap created by -// setup_bitmap(). -//////////////////////////////////////////////////////////////////// -void WinStatsGraph:: -release_bitmap() { - if (_bitmap) { - DeleteObject(_bitmap); - _bitmap = 0; - } - if (_bitmap_dc) { - DeleteDC(_bitmap_dc); - _bitmap_dc = 0; - } -} - //////////////////////////////////////////////////////////////////// // Function: WinStatsGraph::setup_label_stack // Access: Protected @@ -145,7 +132,8 @@ release_bitmap() { //////////////////////////////////////////////////////////////////// void WinStatsGraph:: setup_label_stack() { - _label_stack.setup(_window, 8, 8, _left_margin - 16, _top_margin + _bitmap_ysize + _bottom_margin - 16); + _label_stack.setup(_window); + move_label_stack(); /* if (_label_stack()->get_ideal_width() > _label_stack->get_width()) { _left_margin = _label_stack->get_ideal_width() + 16; @@ -162,7 +150,17 @@ setup_label_stack() { //////////////////////////////////////////////////////////////////// void WinStatsGraph:: move_label_stack() { - _label_stack.set_pos(8, 8, _left_margin - 16, _top_margin + _bitmap_ysize + _bottom_margin - 16); + if (_label_stack.is_setup()) { + RECT rect; + GetClientRect(_window, &rect); + + rect.left += 8; + rect.right = _left_margin - 8; + rect.bottom -= _bottom_margin; + + _label_stack.set_pos(rect.left, rect.top, + rect.right - rect.left, rect.bottom - rect.top); + } } //////////////////////////////////////////////////////////////////// @@ -191,48 +189,227 @@ get_collector_brush(int collector_index) { } //////////////////////////////////////////////////////////////////// -// Function: WinStatsGraph::draw_graph +// Function: WinStatsGraph::window_proc // Access: Protected -// Description: Draws the graph into the window by blitting the -// backing-store bitmap in, along with a suitable frame. +// Description: This window_proc should be called up to by the +// derived classes for any messages that are not +// specifically handled by the derived class. +//////////////////////////////////////////////////////////////////// +LONG WinStatsGraph:: +window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + switch (msg) { + case WM_DESTROY: + close(); + break; + + case WM_PAINT: + { + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + // First, draw a frame around the graph. + RECT rect; + GetClientRect(hwnd, &rect); + + rect.left += _left_margin; + rect.top += _top_margin; + rect.right -= _right_margin; + rect.bottom -= _bottom_margin; + + if (rect.right > rect.left && rect.bottom > rect.top) { + DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); + + int graph_xsize = rect.right - rect.left; + int graph_ysize = rect.bottom - rect.top; + if (_bitmap_dc == 0 || + graph_xsize != _bitmap_xsize || + graph_ysize != _bitmap_ysize) { + // Oops, we need to change the bitmap (and graph) size. + changed_graph_size(graph_xsize, graph_ysize); + move_graph_window(rect.left, rect.top, graph_xsize, graph_ysize); + move_label_stack(); + force_redraw(); + } + } + + EndPaint(hwnd, &ps); + return 0; + } + + default: + break; + } + + return DefWindowProc(hwnd, msg, wparam, lparam); +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::setup_bitmap +// Access: Private +// Description: Sets up a backing-store bitmap of the indicated size. //////////////////////////////////////////////////////////////////// void WinStatsGraph:: -draw_graph(HDC hdc) { - if (_bitmap_xsize == 0 || _bitmap_ysize == 0) { - // Never mind: nothing to draw. +setup_bitmap(int xsize, int ysize) { + release_bitmap(); + _bitmap_xsize = max(xsize, 0); + _bitmap_ysize = max(ysize, 0); + + HDC hdc = GetDC(_graph_window); + _bitmap_dc = CreateCompatibleDC(hdc); + _bitmap = CreateCompatibleBitmap(hdc, _bitmap_xsize, _bitmap_ysize); + SelectObject(_bitmap_dc, _bitmap); + ReleaseDC(_window, hdc); +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::release_bitmap +// Access: Private +// Description: Frees the backing-store bitmap created by +// setup_bitmap(). +//////////////////////////////////////////////////////////////////// +void WinStatsGraph:: +release_bitmap() { + if (_bitmap) { + DeleteObject(_bitmap); + _bitmap = 0; + } + if (_bitmap_dc) { + DeleteDC(_bitmap_dc); + _bitmap_dc = 0; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::move_graph_window +// Access: Private +// Description: Repositions the graph child window within the parent +// window according to the _margin variables. +//////////////////////////////////////////////////////////////////// +void WinStatsGraph:: +move_graph_window(int graph_left, int graph_top, int graph_xsize, int graph_ysize) { + if (_graph_window == 0) { + create_graph_window(); + } + + SetWindowPos(_graph_window, 0, + graph_left, graph_top, + graph_xsize, graph_ysize, + SWP_NOZORDER | SWP_SHOWWINDOW); + + if (graph_xsize != _bitmap_xsize || graph_ysize != _bitmap_ysize) { + setup_bitmap(graph_xsize, graph_ysize); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::create_graph_window +// Access: Private +// Description: Creates the child window that actually holds the graph. +//////////////////////////////////////////////////////////////////// +void WinStatsGraph:: +create_graph_window() { + if (_graph_window) { return; } - // First, draw a frame around the graph. + HINSTANCE application = GetModuleHandle(NULL); + register_graph_window_class(application); - // Windows doesn't seem to have an API to ask how big the outer - // frame will be before we draw it, only a way to draw the outer - // frame and return the size of the inner frame afterwards. + string window_title = "graph"; + DWORD window_style = WS_CHILD; - // So we have to make our best guess about the correct size of the - // outer frame before we draw it, then examine the size of the - // resulting inner frame. If it didn't come out to the correct size - // (that is, exactly large enough to frame our graph), we expand the - // outer frame by the difference, and redraw it. - - RECT rect = _frame_rect; - DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST); - - if (rect.left != _left_margin || - rect.top != _top_margin || - rect.right != _left_margin + _bitmap_xsize || - rect.bottom != _top_margin + _bitmap_ysize) { - _frame_rect.left = _left_margin - (rect.left - _frame_rect.left); - _frame_rect.top = _top_margin - (rect.top - _frame_rect.top); - _frame_rect.right = _left_margin + _bitmap_xsize + (_frame_rect.right - rect.right); - _frame_rect.bottom = _top_margin + _bitmap_ysize + (_frame_rect.bottom - rect.bottom); - - DrawEdge(hdc, &_frame_rect, EDGE_SUNKEN, BF_RECT); + _graph_window = + CreateWindow(_graph_window_class_name, window_title.c_str(), window_style, + 0, 0, 0, 0, + _window, NULL, application, 0); + if (!_graph_window) { + nout << "Could not create graph window!\n"; + exit(1); } - // Now fill in the graph. - BitBlt(hdc, _left_margin, _top_margin, - _bitmap_xsize, _bitmap_ysize, - _bitmap_dc, 0, 0, - SRCCOPY); + SetWindowLongPtr(_graph_window, 0, (LONG_PTR)this); +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::register_graph_window_class +// Access: Private, Static +// Description: Registers the window class for the stripChart window, if +// it has not already been registered. +//////////////////////////////////////////////////////////////////// +void WinStatsGraph:: +register_graph_window_class(HINSTANCE application) { + if (_graph_window_class_registered) { + return; + } + + WNDCLASS wc; + + ZeroMemory(&wc, sizeof(WNDCLASS)); + wc.style = 0; + wc.lpfnWndProc = (WNDPROC)static_graph_window_proc; + wc.hInstance = application; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = _graph_window_class_name; + + // Reserve space to associate the this pointer with the window. + wc.cbWndExtra = sizeof(WinStatsGraph *); + + if (!RegisterClass(&wc)) { + nout << "Could not register graph window class!\n"; + exit(1); + } + + _graph_window_class_registered = true; +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::static_graph_window_proc +// Access: Private, Static +// Description: +//////////////////////////////////////////////////////////////////// +LONG WINAPI WinStatsGraph:: +static_graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + WinStatsGraph *self = (WinStatsGraph *)GetWindowLongPtr(hwnd, 0); + if (self != (WinStatsGraph *)NULL && self->_graph_window == hwnd) { + return self->graph_window_proc(hwnd, msg, wparam, lparam); + } else { + return DefWindowProc(hwnd, msg, wparam, lparam); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsGraph::graph_window_proc +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +LONG WinStatsGraph:: +graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + switch (msg) { + case WM_DISPLAYCHANGE: + setup_bitmap(_bitmap_xsize, _bitmap_ysize); + force_redraw(); + break; + + case WM_PAINT: + { + // Repaint the graph by copying the backing pixmap in. + PAINTSTRUCT ps; + HDC hdc = BeginPaint(hwnd, &ps); + + BitBlt(hdc, 0, 0, + _bitmap_xsize, _bitmap_ysize, + _bitmap_dc, 0, 0, + SRCCOPY); + + EndPaint(hwnd, &ps); + return 0; + } + + default: + break; + } + + return DefWindowProc(hwnd, msg, wparam, lparam); } diff --git a/pandatool/src/win-stats/winStatsGraph.h b/pandatool/src/win-stats/winStatsGraph.h index df71d14f1d..96b448ec63 100644 --- a/pandatool/src/win-stats/winStatsGraph.h +++ b/pandatool/src/win-stats/winStatsGraph.h @@ -40,17 +40,18 @@ public: 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); protected: void close(); - void setup_bitmap(int xsize, int ysize); - void release_bitmap(); void setup_label_stack(); void move_label_stack(); HBRUSH get_collector_brush(int collector_index); - void draw_graph(HDC hdc); + + LONG WINAPI window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); protected: // Table of brushes for our various collectors. @@ -59,6 +60,7 @@ protected: WinStatsMonitor *_monitor; HWND _window; + HWND _graph_window; WinStatsLabelStack _label_stack; HBITMAP _bitmap; @@ -68,7 +70,19 @@ protected: int _left_margin, _right_margin; int _top_margin, _bottom_margin; - RECT _frame_rect; +private: + void setup_bitmap(int xsize, int ysize); + void release_bitmap(); + void move_graph_window(int graph_left, int graph_top, + int graph_xsize, int graph_ysize); + void create_graph_window(); + static void register_graph_window_class(HINSTANCE application); + + static LONG WINAPI static_graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + LONG WINAPI graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); + + static bool _graph_window_class_registered; + static const char * const _graph_window_class_name; }; #endif diff --git a/pandatool/src/win-stats/winStatsMonitor.cxx b/pandatool/src/win-stats/winStatsMonitor.cxx index bab8351373..db74566419 100644 --- a/pandatool/src/win-stats/winStatsMonitor.cxx +++ b/pandatool/src/win-stats/winStatsMonitor.cxx @@ -130,8 +130,6 @@ got_bad_version(int client_major, int client_minor, //////////////////////////////////////////////////////////////////// void WinStatsMonitor:: new_collector(int collector_index) { - cerr << "Got new collector " << get_collector_name(collector_index) - << "\n"; Graphs::iterator gi; for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) { WinStatsGraph *graph = (*gi); diff --git a/pandatool/src/win-stats/winStatsStripChart.cxx b/pandatool/src/win-stats/winStatsStripChart.cxx index 3002efbacc..ac8ab46a16 100644 --- a/pandatool/src/win-stats/winStatsStripChart.cxx +++ b/pandatool/src/win-stats/winStatsStripChart.cxx @@ -41,9 +41,8 @@ WinStatsStripChart(WinStatsMonitor *monitor, PStatView &view, cerr << "Constructing strip chart " << (void *)this << "\n"; _brush_origin = 0; - setup_bitmap(get_xsize(), get_ysize()); - clear_region(); create_window(); + clear_region(); } //////////////////////////////////////////////////////////////////// @@ -88,6 +87,27 @@ new_data(int thread_index, int frame_number) { update(); } +//////////////////////////////////////////////////////////////////// +// Function: WinStatsStripChart::force_redraw +// Access: Public, Virtual +// Description: Called when it is necessary to redraw the entire graph. +//////////////////////////////////////////////////////////////////// +void WinStatsStripChart:: +force_redraw() { + PStatStripChart::force_redraw(); +} + +//////////////////////////////////////////////////////////////////// +// Function: WinStatsStripChart::changed_graph_size +// Access: Public, Virtual +// Description: Called when the user has resized the window, forcing +// a resize of the graph. +//////////////////////////////////////////////////////////////////// +void WinStatsStripChart:: +changed_graph_size(int graph_xsize, int graph_ysize) { + PStatStripChart::changed_size(graph_xsize, graph_ysize); +} + //////////////////////////////////////////////////////////////////// // Function: WinStatsStripChart::update_labels // Access: Protected, Virtual @@ -135,10 +155,9 @@ copy_region(int start_x, int end_x, int dest_x) { SetBrushOrgEx(_bitmap_dc, _brush_origin, 0, NULL); RECT rect = { - _left_margin + dest_x, _top_margin, - _left_margin + dest_x + end_x - start_x, _top_margin + get_ysize() + dest_x, 0, dest_x + end_x - start_x, get_ysize() }; - InvalidateRect(_window, &rect, FALSE); + InvalidateRect(_graph_window, &rect, FALSE); } //////////////////////////////////////////////////////////////////// @@ -216,10 +235,9 @@ draw_cursor(int x) { void WinStatsStripChart:: end_draw(int from_x, int to_x) { RECT rect = { - _left_margin + from_x, _top_margin, - _left_margin + to_x, _top_margin + get_ysize() + from_x, 0, to_x, get_ysize() }; - InvalidateRect(_window, &rect, FALSE); + InvalidateRect(_graph_window, &rect, FALSE); } //////////////////////////////////////////////////////////////////// @@ -320,37 +338,13 @@ static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { LONG WinStatsStripChart:: window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) { - case WM_DESTROY: - close(); - break; - - case WM_DISPLAYCHANGE: - setup_bitmap(get_xsize(), get_ysize()); - force_redraw(); - break; - case WM_SIZE: - changed_size(LOWORD(lparam) - (_left_margin + _right_margin), - HIWORD(lparam) - (_top_margin + _bottom_margin)); - setup_bitmap(get_xsize(), get_ysize()); - force_redraw(); - move_label_stack(); InvalidateRect(hwnd, NULL, FALSE); break; - case WM_PAINT: - { - // Repaint the graph by copying the backing pixmap in. - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - draw_graph(hdc); - EndPaint(hwnd, &ps); - return 0; - } - default: break; } - return DefWindowProc(hwnd, msg, wparam, lparam); + return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam); } diff --git a/pandatool/src/win-stats/winStatsStripChart.h b/pandatool/src/win-stats/winStatsStripChart.h index 9a3bd5a324..5628b6bed7 100644 --- a/pandatool/src/win-stats/winStatsStripChart.h +++ b/pandatool/src/win-stats/winStatsStripChart.h @@ -41,6 +41,8 @@ public: 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); protected: virtual void update_labels();