robustify graph placement logic

This commit is contained in:
David Rose 2004-01-08 20:34:23 +00:00
parent a85d8ca23e
commit 11ed7fc99b
6 changed files with 316 additions and 129 deletions

View File

@ -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);
}
}
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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();