357 lines
12 KiB
C++
357 lines
12 KiB
C++
// Filename: winStatsStripChart.cxx
|
|
// Created by: drose (03Dec03)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PANDA 3D SOFTWARE
|
|
// Copyright (c) 2001, 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://www.panda3d.org/license.txt .
|
|
//
|
|
// To contact the maintainers of this program write to
|
|
// panda3d@yahoogroups.com .
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
#include "winStatsStripChart.h"
|
|
#include "winStatsMonitor.h"
|
|
|
|
static const int default_strip_chart_width = 400;
|
|
static const int default_strip_chart_height = 100;
|
|
|
|
bool WinStatsStripChart::_window_class_registered = false;
|
|
const char * const WinStatsStripChart::_window_class_name = "strip";
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::Constructor
|
|
// Access: Public
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
WinStatsStripChart::
|
|
WinStatsStripChart(WinStatsMonitor *monitor, PStatView &view,
|
|
int collector_index) :
|
|
PStatStripChart(monitor, view, collector_index,
|
|
default_strip_chart_width,
|
|
default_strip_chart_height),
|
|
WinStatsGraph(monitor)
|
|
{
|
|
cerr << "Constructing strip chart " << (void *)this << "\n";
|
|
_brush_origin = 0;
|
|
|
|
setup_bitmap(get_xsize(), get_ysize());
|
|
clear_region();
|
|
create_window();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::Destructor
|
|
// Access: Public, Virtual
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
WinStatsStripChart::
|
|
~WinStatsStripChart() {
|
|
cerr << "Destructing strip chart " << (void *)this << "\n";
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::new_collector
|
|
// Access: Public, Virtual
|
|
// Description: Called whenever a new Collector definition is
|
|
// received from the client.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
new_collector(int collector_index) {
|
|
if (is_title_unknown()) {
|
|
string window_title = get_title_text();
|
|
if (!is_title_unknown()) {
|
|
SetWindowText(_window, window_title.c_str());
|
|
}
|
|
}
|
|
|
|
WinStatsGraph::new_collector(collector_index);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::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 WinStatsStripChart::
|
|
new_data(int thread_index, int frame_number) {
|
|
update();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::update_labels
|
|
// Access: Protected, Virtual
|
|
// Description: Resets the list of labels.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
update_labels() {
|
|
PStatStripChart::update_labels();
|
|
|
|
_label_stack.clear_labels();
|
|
for (int i = 0; i < get_num_labels(); i++) {
|
|
_label_stack.add_label(WinStatsGraph::_monitor, get_label_collector(i));
|
|
}
|
|
_labels_changed = false;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::clear_region
|
|
// Access: Protected, Virtual
|
|
// Description: Erases the chart area.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
clear_region() {
|
|
RECT rect = { 0, 0, get_xsize(), get_ysize() };
|
|
FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::copy_region
|
|
// Access: Protected, Virtual
|
|
// Description: Should be overridden by the user class to copy a
|
|
// region of the chart from one part of the chart to
|
|
// another. This is used to implement scrolling.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
copy_region(int start_x, int end_x, int dest_x) {
|
|
BitBlt(_bitmap_dc, dest_x, 0,
|
|
end_x - start_x, get_ysize(),
|
|
_bitmap_dc, start_x, 0,
|
|
SRCCOPY);
|
|
|
|
// 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);
|
|
|
|
RECT rect = {
|
|
_left_margin + dest_x, _top_margin,
|
|
_left_margin + dest_x + end_x - start_x, _top_margin + get_ysize()
|
|
};
|
|
InvalidateRect(_window, &rect, FALSE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::draw_slice
|
|
// Access: Protected, Virtual
|
|
// Description: Draws a single vertical slice of the strip chart, at
|
|
// the given pixel position, and corresponding to the
|
|
// indicated level data.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
draw_slice(int x, int w, int frame_number) {
|
|
const FrameData &frame = get_frame_data(frame_number);
|
|
|
|
// Start by clearing the band first.
|
|
RECT rect = { x, 0, x + w, get_ysize() };
|
|
FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
|
|
|
|
float overall_time = 0.0;
|
|
int y = get_ysize();
|
|
|
|
FrameData::const_iterator fi;
|
|
for (fi = frame.begin(); fi != frame.end(); ++fi) {
|
|
const ColorData &cd = (*fi);
|
|
overall_time += cd._net_value;
|
|
HBRUSH brush = get_collector_brush(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.
|
|
rect.top = 0;
|
|
rect.bottom = y;
|
|
FillRect(_bitmap_dc, &rect, brush);
|
|
// And we can consider ourselves done now.
|
|
return;
|
|
}
|
|
|
|
int top_y = height_to_pixel(overall_time);
|
|
rect.top = top_y;
|
|
rect.bottom = y;
|
|
FillRect(_bitmap_dc, &rect, brush);
|
|
y = top_y;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::draw_empty
|
|
// Access: Protected, Virtual
|
|
// Description: Draws a single vertical slice of background color.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
draw_empty(int x, int w) {
|
|
RECT rect = { x, 0, x + w, get_ysize() };
|
|
FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::draw_cursor
|
|
// Access: Protected, Virtual
|
|
// Description: Draws a single vertical slice of foreground color.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
draw_cursor(int x) {
|
|
RECT rect = { x, 0, x + 1, get_ysize() };
|
|
FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::end_draw
|
|
// Access: Protected, Virtual
|
|
// Description: Should be overridden by the user class. This hook
|
|
// will be called after drawing a series of color bars
|
|
// in the strip chart; it gives the pixel range that
|
|
// was just redrawn.
|
|
////////////////////////////////////////////////////////////////////
|
|
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()
|
|
};
|
|
InvalidateRect(_window, &rect, FALSE);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::create_window
|
|
// Access: Private
|
|
// Description: Creates the window for this strip chart.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
create_window() {
|
|
if (_window) {
|
|
return;
|
|
}
|
|
|
|
HINSTANCE application = GetModuleHandle(NULL);
|
|
register_window_class(application);
|
|
|
|
string window_title = get_title_text();
|
|
DWORD window_style = WS_CHILD | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW | WS_VISIBLE;
|
|
|
|
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, window_style, FALSE);
|
|
|
|
_window =
|
|
CreateWindow(_window_class_name, window_title.c_str(), window_style,
|
|
CW_USEDEFAULT, 0,
|
|
win_rect.right - win_rect.left,
|
|
win_rect.bottom - win_rect.top,
|
|
WinStatsGraph::_monitor->get_window(), NULL, application, 0);
|
|
if (!_window) {
|
|
nout << "Could not create StripChart window!\n";
|
|
exit(1);
|
|
}
|
|
|
|
SetWindowLongPtr(_window, 0, (LONG_PTR)this);
|
|
setup_label_stack();
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::register_window_class
|
|
// Access: Private, Static
|
|
// Description: Registers the window class for the stripChart window, if
|
|
// it has not already been registered.
|
|
////////////////////////////////////////////////////////////////////
|
|
void WinStatsStripChart::
|
|
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(WinStatsStripChart *);
|
|
|
|
if (!RegisterClass(&wc)) {
|
|
nout << "Could not register StripChart window class!\n";
|
|
exit(1);
|
|
}
|
|
|
|
_window_class_registered = true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::static_window_proc
|
|
// Access: Private, Static
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
LONG WINAPI WinStatsStripChart::
|
|
static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
|
WinStatsStripChart *self = (WinStatsStripChart *)GetWindowLongPtr(hwnd, 0);
|
|
if (self != (WinStatsStripChart *)NULL && self->_window == hwnd) {
|
|
return self->window_proc(hwnd, msg, wparam, lparam);
|
|
} else {
|
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Function: WinStatsStripChart::window_proc
|
|
// Access: Private
|
|
// Description:
|
|
////////////////////////////////////////////////////////////////////
|
|
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);
|
|
}
|