user guide bars

This commit is contained in:
David Rose 2004-01-12 22:41:06 +00:00
parent fa9a8c9982
commit 3089ac52d7
13 changed files with 810 additions and 94 deletions

View File

@ -130,10 +130,15 @@ begin_draw() {
if (x >= 5 && x <= get_xsize() - 5) {
// Only draw it if it's not too close to either edge.
if (bar._is_target) {
switch (bar._style) {
case GBS_target:
_pixmap.draw_line(_light_gc, x, text_height + 4, x, get_ysize());
} else {
break;
case GBS_normal:
default:
_pixmap.draw_line(_dark_gc, x, text_height + 4, x, get_ysize());
break;
}
}
}

View File

@ -255,10 +255,15 @@ end_draw(int from_x, int to_x) {
if (y >= 5) {
// Only draw it if it's not too close to the top.
if (bar._is_target) {
switch (bar._style) {
case GBS_target:
_pixmap.draw_line(_light_gc, from_x, y, to_x, y);
} else {
break;
case GBS_normal:
default:
_pixmap.draw_line(_dark_gc, from_x, y, to_x, y);
break;
}
}
}

View File

@ -130,6 +130,7 @@ set_guide_bar_units(int guide_bar_units) {
if (_guide_bar_units != guide_bar_units) {
_guide_bar_units = guide_bar_units;
normal_guide_bars();
user_guide_bar_labels();
}
}

View File

@ -31,10 +31,10 @@
// Description:
////////////////////////////////////////////////////////////////////
PStatGraph::GuideBar::
GuideBar(float height, const string &label, bool is_target) :
GuideBar(float height, const string &label, PStatGraph::GuideBarStyle style) :
_height(height),
_label(label),
_is_target(is_target)
_style(style)
{
}
@ -47,7 +47,7 @@ PStatGraph::GuideBar::
GuideBar(const PStatGraph::GuideBar &copy) :
_height(copy._height),
_label(copy._label),
_is_target(copy._is_target)
_style(copy._style)
{
}
@ -104,12 +104,101 @@ get_num_guide_bars() const {
const PStatGraph::GuideBar &PStatGraph::
get_guide_bar(int n) const {
#ifndef NDEBUG
static GuideBar bogus_bar(0.0, "bogus", false);
static GuideBar bogus_bar(0.0, "bogus", GBS_normal);
nassertr(n >= 0 && n < (int)_guide_bars.size(), bogus_bar);
#endif
return _guide_bars[n];
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::get_num_user_guide_bars
// Access: Public
// Description: Returns the current number of user-defined guide
// bars. Not all of these may be visible.
////////////////////////////////////////////////////////////////////
int PStatGraph::
get_num_user_guide_bars() const {
return _user_guide_bars.size();
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::get_user_guide_bar
// Access: Public
// Description: Returns the nth user-defined guide bar.
////////////////////////////////////////////////////////////////////
const PStatGraph::GuideBar &PStatGraph::
get_user_guide_bar(int n) const {
#ifndef NDEBUG
static GuideBar bogus_bar(0.0, "bogus", GBS_user);
nassertr(n >= 0 && n < (int)_user_guide_bars.size(), bogus_bar);
#endif
return _user_guide_bars[n];
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::move_user_guide_bar
// Access: Public
// Description: Adjusts the height of the nth user-defined guide bar.
////////////////////////////////////////////////////////////////////
void PStatGraph::
move_user_guide_bar(int n, float height) {
nassertv(n >= 0 && n < (int)_user_guide_bars.size());
string label = format_number(height, _guide_bar_units, _unit_name);
_user_guide_bars[n]._height = height;
_user_guide_bars[n]._label = label;
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::add_user_guide_bar
// Access: Public
// Description: Creates a new user guide bar and returns its index
// number.
////////////////////////////////////////////////////////////////////
int PStatGraph::
add_user_guide_bar(float height) {
int n = (int)_user_guide_bars.size();
GuideBar bar = make_guide_bar(height);
bar._style = GBS_user;
_user_guide_bars.push_back(bar);
return n;
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::remove_user_guide_bar
// Access: Public
// Description: Removes the user guide bar with the indicated index
// number. All subsequent index numbers are adjusted
// down one.
////////////////////////////////////////////////////////////////////
void PStatGraph::
remove_user_guide_bar(int n) {
nassertv(n >= 0 && n < (int)_user_guide_bars.size());
_user_guide_bars.erase(_user_guide_bars.begin() + n);
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::find_user_guide_bar
// Access: Public
// Description: Returns the index number of the first user guide bar
// found whose height is within the indicated range, or
// -1 if no user guide bars fall within the range.
////////////////////////////////////////////////////////////////////
int PStatGraph::
find_user_guide_bar(float from_height, float to_height) const {
GuideBars::const_iterator gbi;
for (gbi = _user_guide_bars.begin();
gbi != _user_guide_bars.end();
++gbi) {
const GuideBar &bar = (*gbi);
if (bar._height >= from_height && bar._height <= to_height) {
return (int)(gbi - _user_guide_bars.begin());
}
}
return -1;
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::format_number
@ -222,6 +311,22 @@ update_guide_bars(int num_bars, float scale) {
_guide_bars_changed = true;
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::user_guide_bar_labels
// Access: Protected
// Description: Rederives the labels for the user-defined guide bars.
////////////////////////////////////////////////////////////////////
void PStatGraph::
user_guide_bar_labels() {
GuideBars::iterator gbi;
for (gbi = _user_guide_bars.begin();
gbi != _user_guide_bars.end();
++gbi) {
GuideBar &bar = (*gbi);
bar._label = format_number(bar._height, _guide_bar_units, _unit_name);
}
}
////////////////////////////////////////////////////////////////////
// Function: PStatGraph::make_guide_bar
// Access: Protected
@ -232,14 +337,16 @@ PStatGraph::GuideBar PStatGraph::
make_guide_bar(float value) const {
string label = format_number(value, _guide_bar_units, _unit_name);
bool is_target = false;
GuideBarStyle style = GBS_normal;
if ((_guide_bar_units & GBU_named) == 0) {
// If it's a time unit, check to see if it matches our target
// frame rate.
float hz = 1.0 / value;
is_target = IS_NEARLY_EQUAL(hz, _target_frame_rate);
if (IS_THRESHOLD_EQUAL(hz, _target_frame_rate, 0.001)) {
style = GBS_target;
}
}
return GuideBar(value, label, is_target);
return GuideBar(value, label, style);
}

View File

@ -55,14 +55,20 @@ public:
INLINE int get_xsize() const;
INLINE int get_ysize() const;
enum GuideBarStyle {
GBS_normal,
GBS_target,
GBS_user,
};
class GuideBar {
public:
GuideBar(float height, const string &label, bool is_target);
GuideBar(float height, const string &label, GuideBarStyle style);
GuideBar(const GuideBar &copy);
float _height;
string _label;
bool _is_target;
GuideBarStyle _style;
};
enum GuideBarUnits {
@ -75,6 +81,13 @@ public:
int get_num_guide_bars() const;
const GuideBar &get_guide_bar(int n) const;
int get_num_user_guide_bars() const;
const GuideBar &get_user_guide_bar(int n) const;
void move_user_guide_bar(int n, float height);
int add_user_guide_bar(float height);
void remove_user_guide_bar(int n);
int find_user_guide_bar(float from_height, float to_height) const;
INLINE void set_guide_bar_units(int unit_mask);
INLINE int get_guide_bar_units() const;
INLINE void set_guide_bar_unit_name(const string &unit_name);
@ -87,6 +100,7 @@ public:
protected:
virtual void normal_guide_bars()=0;
void update_guide_bars(int num_bars, float scale);
void user_guide_bar_labels();
GuideBar make_guide_bar(float value) const;
bool _labels_changed;
@ -106,6 +120,7 @@ protected:
typedef pvector<GuideBar> GuideBars;
GuideBars _guide_bars;
GuideBars _user_guide_bars;
int _guide_bar_units;
string _unit_name;
};

View File

@ -39,6 +39,7 @@ WinStatsGraph(WinStatsMonitor *monitor, int thread_index) :
_window = 0;
_graph_window = 0;
_sizewe_cursor = LoadCursor(NULL, IDC_SIZEWE);
_hand_cursor = LoadCursor(NULL, IDC_HAND);
_bitmap = 0;
_bitmap_dc = 0;
@ -47,8 +48,12 @@ WinStatsGraph(WinStatsMonitor *monitor, int thread_index) :
_bitmap_xsize = 0;
_bitmap_ysize = 0;
_dark_pen = CreatePen(PS_SOLID, 1, RGB(51, 51, 51));
_light_pen = CreatePen(PS_SOLID, 1, RGB(154, 154, 154));
_dark_color = RGB(51, 51, 51);
_light_color = RGB(154, 154, 154);
_user_guide_bar_color = RGB(130, 150, 255);
_dark_pen = CreatePen(PS_SOLID, 1, _dark_color);
_light_pen = CreatePen(PS_SOLID, 1, _light_color);
_user_guide_bar_pen = CreatePen(PS_DASH, 1, _user_guide_bar_color);
_drag_mode = DM_none;
_potential_drag_mode = DM_none;
@ -67,6 +72,7 @@ WinStatsGraph::
DeleteObject(_dark_pen);
DeleteObject(_light_pen);
DeleteObject(_user_guide_bar_pen);
Brushes::iterator bi;
for (bi = _brushes.begin(); bi != _brushes.end(); ++bi) {
@ -85,6 +91,17 @@ WinStatsGraph::
}
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::get_thread_index
// Access: Public
// Description: Returns the thread index associated with this
// particular graph.
////////////////////////////////////////////////////////////////////
int WinStatsGraph::
get_thread_index() const {
return _thread_index;
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::new_collector
// Access: Public, Virtual
@ -135,6 +152,37 @@ void WinStatsGraph::
set_time_units(int unit_mask) {
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::move_user_guide_bar
// Access: Public, Virtual
// Description: Adjusts the height of the nth user-defined guide bar.
////////////////////////////////////////////////////////////////////
void WinStatsGraph::
move_user_guide_bar(int n, float height) {
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::add_user_guide_bar
// Access: Public, Virtual
// Description: Creates a new user guide bar and returns its index
// number.
////////////////////////////////////////////////////////////////////
int WinStatsGraph::
add_user_guide_bar(float height) {
return -1;
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::remove_user_guide_bar
// Access: Public, Virtual
// Description: Removes the user guide bar with the indicated index
// number. All subsequent index numbers are adjusted
// down one.
////////////////////////////////////////////////////////////////////
void WinStatsGraph::
remove_user_guide_bar(int n) {
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::close
// Access: Protected
@ -229,27 +277,34 @@ window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
case WM_SETCURSOR:
{
// Why is it so hard to ask what the cursor position within the
// window's client area is?
// Why is it so hard to ask for the cursor position within the
// window's client area?
POINT point;
GetCursorPos(&point);
WINDOWINFO winfo;
GetWindowInfo(hwnd, &winfo);
const RECT &rect = winfo.rcClient;
int x = point.x - rect.left;
int y = point.y - rect.top;
int width = rect.right - rect.left;
int height = rect.bottom - rect.top;
// Display a double-headed arrow to drag the left or right margins.
if (point.x >= rect.left + _left_margin - 1 && point.x <= rect.left + _left_margin + 1) {
SetCursor(_sizewe_cursor);
_potential_drag_mode = DM_left_margin;
return TRUE;
}
if (point.x >= rect.right - _right_margin - 2 && point.x <= rect.right - _right_margin) {
SetCursor(_sizewe_cursor);
_potential_drag_mode = DM_right_margin;
return TRUE;
}
_potential_drag_mode = consider_drag_start(x, y, width, height);
_potential_drag_mode = DM_none;
switch (_potential_drag_mode) {
case DM_left_margin:
case DM_right_margin:
SetCursor(_sizewe_cursor);
return TRUE;
case DM_guide_bar:
SetCursor(_hand_cursor);
return TRUE;
default:
case DM_none:
break;
}
}
break;
@ -340,6 +395,21 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
force_redraw();
break;
case WM_LBUTTONDOWN:
// Vector any uncaught WM_LBUTTONDOWN into the main window, so we
// can drag margins, etc.
if (_potential_drag_mode != DM_none) {
PN_int16 x = LOWORD(lparam) + _graph_left;
PN_int16 y = HIWORD(lparam) + _graph_top;
return window_proc(_window, msg, wparam, MAKELPARAM(x, y));
}
break;
case WM_LBUTTONUP:
_drag_mode = DM_none;
ReleaseCapture();
break;
case WM_PAINT:
{
// Repaint the graph by copying the backing pixmap in.
@ -351,6 +421,8 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
_bitmap_dc, 0, 0,
SRCCOPY);
additional_graph_window_paint(hdc);
EndPaint(hwnd, &ps);
return 0;
}
@ -374,6 +446,36 @@ void WinStatsGraph::
additional_window_paint(HDC hdc) {
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::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 graph window.
////////////////////////////////////////////////////////////////////
void WinStatsGraph::
additional_graph_window_paint(HDC hdc) {
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsGraph::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.
////////////////////////////////////////////////////////////////////
WinStatsGraph::DragMode WinStatsGraph::
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: WinStatsGraph::setup_bitmap
// Access: Private

View File

@ -34,10 +34,23 @@ class WinStatsMonitor;
// that may be created for a WinStatsMonitor.
////////////////////////////////////////////////////////////////////
class WinStatsGraph {
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,
};
public:
WinStatsGraph(WinStatsMonitor *monitor, int thread_index);
virtual ~WinStatsGraph();
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();
@ -45,6 +58,10 @@ public:
virtual void set_time_units(int unit_mask);
virtual void move_user_guide_bar(int n, float height);
virtual int add_user_guide_bar(float height);
virtual void remove_user_guide_bar(int n);
protected:
void close();
@ -57,7 +74,9 @@ protected:
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);
protected:
// Table of brushes for our various collectors.
@ -71,6 +90,7 @@ protected:
WinStatsLabelStack _label_stack;
HCURSOR _sizewe_cursor;
HCURSOR _hand_cursor;
HBITMAP _bitmap;
HDC _bitmap_dc;
@ -80,20 +100,18 @@ protected:
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;
// What is the user adjusting by dragging the mouse in a window?
enum DragMode {
DM_none,
DM_scale,
DM_left_margin,
DM_right_margin,
};
DragMode _drag_mode;
DragMode _potential_drag_mode;
int _drag_start_x, _drag_start_y;
float _drag_scale_start;
int _drag_guide_bar;
private:
void setup_bitmap(int xsize, int ysize);

View File

@ -365,6 +365,63 @@ set_time_units(int unit_mask) {
SetMenuItemInfo(_options_menu, MI_time_hz, FALSE, &mii);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsMonitor::move_user_guide_bar
// Access: Public
// Description: Adjusts the height of the nth user-defined guide bar
// for all graphs that share the indicated thread.
////////////////////////////////////////////////////////////////////
void WinStatsMonitor::
move_user_guide_bar(int thread_index, int n, float height) {
Graphs::iterator gi;
for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
WinStatsGraph *graph = (*gi);
if (graph->get_thread_index() == thread_index) {
graph->move_user_guide_bar(n, height);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsMonitor::add_user_guide_bar
// Access: Public
// Description: Creates a new user guide bar and returns its index
// number for all graphs that share the indicated
// thread.
////////////////////////////////////////////////////////////////////
int WinStatsMonitor::
add_user_guide_bar(int thread_index, float height) {
int result = -1;
Graphs::iterator gi;
for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
WinStatsGraph *graph = (*gi);
if (graph->get_thread_index() == thread_index) {
result = graph->add_user_guide_bar(height);
}
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsMonitor::remove_user_guide_bar
// Access: Public
// Description: Removes the user guide bar with the indicated index
// number, for all graphs that share the indicated
// thread.
////////////////////////////////////////////////////////////////////
void WinStatsMonitor::
remove_user_guide_bar(int thread_index, int n) {
Graphs::iterator gi;
for (gi = _graphs.begin(); gi != _graphs.end(); ++gi) {
WinStatsGraph *graph = (*gi);
if (graph->get_thread_index() == thread_index) {
graph->remove_user_guide_bar(n);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsMonitor::add_graph
// Access: Private

View File

@ -72,6 +72,10 @@ public:
int get_menu_id(const MenuDef &menu_def);
void set_time_units(int unit_mask);
void move_user_guide_bar(int thread_index, int n, float height);
int add_user_guide_bar(int thread_index, float height);
void remove_user_guide_bar(int thread_index, int n);
private:
void add_graph(WinStatsGraph *graph);

View File

@ -133,6 +133,56 @@ set_horizontal_scale(float time_width) {
InvalidateRect(_window, &rect, TRUE);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsPianoRoll::move_user_guide_bar
// Access: Public, Virtual
// Description: Adjusts the height of the nth user-defined guide bar.
////////////////////////////////////////////////////////////////////
void WinStatsPianoRoll::
move_user_guide_bar(int n, float height) {
RECT rect;
GetClientRect(_window, &rect);
rect.bottom = _top_margin;
InvalidateRect(_window, &rect, TRUE);
InvalidateRect(_graph_window, NULL, TRUE);
PStatPianoRoll::move_user_guide_bar(n, height);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsPianoRoll::add_user_guide_bar
// Access: Public, Virtual
// Description: Creates a new user guide bar and returns its index
// number.
////////////////////////////////////////////////////////////////////
int WinStatsPianoRoll::
add_user_guide_bar(float height) {
RECT rect;
GetClientRect(_window, &rect);
rect.bottom = _top_margin;
InvalidateRect(_window, &rect, TRUE);
return PStatPianoRoll::add_user_guide_bar(height);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsPianoRoll::remove_user_guide_bar
// Access: Public, Virtual
// Description: Removes the user guide bar with the indicated index
// number. All subsequent index numbers are adjusted
// down one.
////////////////////////////////////////////////////////////////////
void WinStatsPianoRoll::
remove_user_guide_bar(int n) {
RECT rect;
GetClientRect(_window, &rect);
rect.bottom = _top_margin;
InvalidateRect(_window, &rect, TRUE);
return PStatPianoRoll::remove_user_guide_bar(n);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsPianoRoll::clear_region
// Access: Protected
@ -157,19 +207,7 @@ begin_draw() {
// Draw in the guide bars.
int num_guide_bars = get_num_guide_bars();
for (int i = 0; i < num_guide_bars; i++) {
const GuideBar &bar = get_guide_bar(i);
int x = height_to_pixel(bar._height);
if (x > 0 && x < get_xsize() - 1) {
// Only draw it if it's not too close to either edge.
if (bar._is_target) {
SelectObject(_bitmap_dc, _light_pen);
} else {
SelectObject(_bitmap_dc, _dark_pen);
}
MoveToEx(_bitmap_dc, x, 0, NULL);
LineTo(_bitmap_dc, x, get_ysize());
}
draw_guide_bar(_bitmap_dc, get_guide_bar(i));
}
}
@ -224,12 +262,18 @@ idle() {
////////////////////////////////////////////////////////////////////
LONG WinStatsPianoRoll::
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
/*
switch (msg) {
case WM_LBUTTONDOWN:
if (_potential_drag_mode == DM_new_guide_bar) {
_drag_mode = DM_new_guide_bar;
SetCapture(_graph_window);
return 0;
}
break;
default:
break;
}
*/
return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam);
}
@ -243,13 +287,21 @@ LONG WinStatsPianoRoll::
graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
switch (msg) {
case WM_LBUTTONDOWN:
{
if (_potential_drag_mode == DM_none) {
_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) {
_drag_mode = DM_guide_bar;
PN_int16 x = LOWORD(lparam);
_drag_start_x = x;
SetCapture(_graph_window);
return 0;
}
return 0;
break;
case WM_MOUSEMOVE:
if (_drag_mode == DM_scale) {
@ -259,6 +311,22 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
set_horizontal_scale(_drag_scale_start / ratio);
}
return 0;
} else if (_drag_mode == DM_new_guide_bar) {
// We haven't created the new guide bar yet; we won't until the
// mouse comes within the graph's region.
PN_int16 x = LOWORD(lparam);
if (x >= 0 && x < get_xsize()) {
_drag_mode = DM_guide_bar;
_drag_guide_bar =
WinStatsGraph::_monitor->add_user_guide_bar(WinStatsGraph::_thread_index, pixel_to_height(x));
return 0;
}
} else if (_drag_mode == DM_guide_bar) {
PN_int16 x = LOWORD(lparam);
WinStatsGraph::_monitor->move_user_guide_bar(WinStatsGraph::_thread_index, _drag_guide_bar, pixel_to_height(x));
return 0;
}
break;
@ -267,6 +335,17 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
_drag_mode = DM_none;
ReleaseCapture();
return 0;
} else if (_drag_mode == DM_guide_bar) {
PN_int16 x = LOWORD(lparam);
if (x < 0 || x >= get_xsize()) {
WinStatsGraph::_monitor->remove_user_guide_bar(WinStatsGraph::_thread_index, _drag_guide_bar);
} else {
WinStatsGraph::_monitor->move_user_guide_bar(WinStatsGraph::_thread_index, _drag_guide_bar, pixel_to_height(x));
}
_drag_mode = DM_none;
ReleaseCapture();
return 0;
}
break;
@ -292,21 +371,66 @@ additional_window_paint(HDC hdc) {
SelectObject(hdc, hfnt);
SetTextAlign(hdc, TA_LEFT | TA_BOTTOM);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(0, 0, 0));
int y = _top_margin;
int i;
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 = height_to_pixel(bar._height);
const string &label = bar._label;
SIZE size;
GetTextExtentPoint32(hdc, label.data(), label.length(), &size);
x -= size.cx / 2;
TextOut(hdc, x + _graph_left, _top_margin,
label.data(), label.length());
for (i = 0; i < num_guide_bars; i++) {
draw_guide_label(hdc, y, get_guide_bar(i));
}
int num_user_guide_bars = get_num_user_guide_bars();
for (i = 0; i < num_user_guide_bars; i++) {
draw_guide_label(hdc, y, get_user_guide_bar(i));
}
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsPianoRoll::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 WinStatsPianoRoll::
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));
}
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsPianoRoll::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.
////////////////////////////////////////////////////////////////////
WinStatsGraph::DragMode WinStatsPianoRoll::
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 {
// The mouse is above or below the graph; maybe create a new
// guide bar.
return DM_new_guide_bar;
}
}
return WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height);
}
////////////////////////////////////////////////////////////////////
@ -326,6 +450,79 @@ update_labels() {
_labels_changed = false;
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsPianoRoll::draw_guide_bar
// Access: Private
// Description: Draws the line for the indicated guide bar on the
// graph.
////////////////////////////////////////////////////////////////////
void WinStatsPianoRoll::
draw_guide_bar(HDC hdc, const PStatGraph::GuideBar &bar) {
int x = height_to_pixel(bar._height);
if (x > 0 && x < get_xsize() - 1) {
// Only draw it if it's not too close to either edge.
switch (bar._style) {
case GBS_target:
SelectObject(hdc, _light_pen);
break;
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: WinStatsPianoRoll::draw_guide_label
// Access: Private
// Description: Draws the text for the indicated guide bar label at
// the top of the graph.
////////////////////////////////////////////////////////////////////
void WinStatsPianoRoll::
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 / 2 - 1);
float to_height = pixel_to_height(x + size.cx / 2 + 1);
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: WinStatsPianoRoll::create_window
// Access: Private

View File

@ -47,6 +47,10 @@ public:
virtual void set_time_units(int unit_mask);
void set_horizontal_scale(float time_width);
virtual void move_user_guide_bar(int n, float height);
virtual int add_user_guide_bar(float height);
virtual void remove_user_guide_bar(int n);
protected:
void clear_region();
virtual void begin_draw();
@ -57,9 +61,15 @@ protected:
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:
void update_labels();
void draw_guide_bar(HDC hdc, const GuideBar &bar);
void draw_guide_label(HDC hdc, int y, const PStatGraph::GuideBar &bar);
void create_window();
static void register_window_class(HINSTANCE application);

View File

@ -154,6 +154,56 @@ set_vertical_scale(float value_height) {
InvalidateRect(_window, &rect, TRUE);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsStripChart::move_user_guide_bar
// Access: Public, Virtual
// Description: Adjusts the height of the nth user-defined guide bar.
////////////////////////////////////////////////////////////////////
void WinStatsStripChart::
move_user_guide_bar(int n, float height) {
RECT rect;
GetClientRect(_window, &rect);
rect.left = _right_margin;
InvalidateRect(_window, &rect, TRUE);
InvalidateRect(_graph_window, NULL, TRUE);
PStatStripChart::move_user_guide_bar(n, height);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsStripChart::add_user_guide_bar
// Access: Public, Virtual
// Description: Creates a new user guide bar and returns its index
// number.
////////////////////////////////////////////////////////////////////
int WinStatsStripChart::
add_user_guide_bar(float height) {
RECT rect;
GetClientRect(_window, &rect);
rect.left = _right_margin;
InvalidateRect(_window, &rect, TRUE);
return PStatStripChart::add_user_guide_bar(height);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsStripChart::remove_user_guide_bar
// Access: Public, Virtual
// Description: Removes the user guide bar with the indicated index
// number. All subsequent index numbers are adjusted
// down one.
////////////////////////////////////////////////////////////////////
void WinStatsStripChart::
remove_user_guide_bar(int n) {
RECT rect;
GetClientRect(_window, &rect);
rect.left = _right_margin;
InvalidateRect(_window, &rect, TRUE);
return PStatStripChart::remove_user_guide_bar(n);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsStripChart::update_labels
// Access: Protected, Virtual
@ -284,19 +334,7 @@ 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 > 0) {
// Only draw it if it's not too close to the top.
if (bar._is_target) {
SelectObject(_bitmap_dc, _light_pen);
} else {
SelectObject(_bitmap_dc, _dark_pen);
}
MoveToEx(_bitmap_dc, from_x, y, NULL);
LineTo(_bitmap_dc, to_x + 1, y);
}
draw_guide_bar(_bitmap_dc, from_x, to_x, get_guide_bar(i));
}
RECT rect = {
@ -312,12 +350,18 @@ end_draw(int from_x, int to_x) {
////////////////////////////////////////////////////////////////////
LONG WinStatsStripChart::
window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
/*
switch (msg) {
case WM_LBUTTONDOWN:
if (_potential_drag_mode == DM_new_guide_bar) {
_drag_mode = DM_new_guide_bar;
SetCapture(_graph_window);
return 0;
}
break;
default:
break;
}
*/
return WinStatsGraph::window_proc(hwnd, msg, wparam, lparam);
}
@ -331,13 +375,21 @@ LONG WinStatsStripChart::
graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
switch (msg) {
case WM_LBUTTONDOWN:
{
if (_potential_drag_mode == DM_none) {
_drag_mode = DM_scale;
PN_int16 y = HIWORD(lparam);
_drag_scale_start = pixel_to_height(y);
SetCapture(_graph_window);
return 0;
} else if (_potential_drag_mode == DM_guide_bar && _drag_guide_bar >= 0) {
_drag_mode = DM_guide_bar;
PN_int16 y = HIWORD(lparam);
_drag_start_y = y;
SetCapture(_graph_window);
return 0;
}
return 0;
break;
case WM_MOUSEMOVE:
if (_drag_mode == DM_scale) {
@ -347,6 +399,22 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
set_vertical_scale(_drag_scale_start / ratio);
}
return 0;
} else if (_drag_mode == DM_new_guide_bar) {
// We haven't created the new guide bar yet; we won't until the
// mouse comes within the graph's region.
PN_int16 y = HIWORD(lparam);
if (y >= 0 && y < get_ysize()) {
_drag_mode = DM_guide_bar;
_drag_guide_bar =
WinStatsGraph::_monitor->add_user_guide_bar(_thread_index, pixel_to_height(y));
return 0;
}
} else if (_drag_mode == DM_guide_bar) {
PN_int16 y = HIWORD(lparam);
WinStatsGraph::_monitor->move_user_guide_bar(_thread_index, _drag_guide_bar, pixel_to_height(y));
return 0;
}
break;
@ -355,6 +423,17 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
_drag_mode = DM_none;
ReleaseCapture();
return 0;
} else if (_drag_mode == DM_guide_bar) {
PN_int16 y = HIWORD(lparam);
if (y < 0 || y >= get_ysize()) {
WinStatsGraph::_monitor->remove_user_guide_bar(_thread_index, _drag_guide_bar);
} else {
WinStatsGraph::_monitor->move_user_guide_bar(_thread_index, _drag_guide_bar, pixel_to_height(y));
}
_drag_mode = DM_none;
ReleaseCapture();
return 0;
}
break;
@ -375,24 +454,109 @@ graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
////////////////////////////////////////////////////////////////////
void WinStatsStripChart::
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_TOP);
SetBkMode(hdc, TRANSPARENT);
SetTextColor(hdc, RGB(0, 0, 0));
RECT rect;
GetClientRect(_window, &rect);
int x = rect.right - _right_margin + 2;
int last_y = -100;
int i;
int num_guide_bars = get_num_guide_bars();
for (int i = 0; i < num_guide_bars; i++) {
const GuideBar &bar = get_guide_bar(i);
last_y = draw_guide_label(hdc, x, bar._height, last_y);
for (i = 0; i < num_guide_bars; i++) {
last_y = draw_guide_label(hdc, x, get_guide_bar(i), last_y);
}
draw_guide_label(hdc, x, get_vertical_scale(), last_y);
last_y = -100;
int num_user_guide_bars = get_num_user_guide_bars();
for (i = 0; i < num_user_guide_bars; i++) {
last_y = draw_guide_label(hdc, x, get_user_guide_bar(i), last_y);
}
GuideBar top_value = make_guide_bar(get_vertical_scale());
draw_guide_label(hdc, x, top_value, last_y);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsStripChart::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 WinStatsStripChart::
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, 0, get_xsize(), get_user_guide_bar(i));
}
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsStripChart::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.
////////////////////////////////////////////////////////////////////
WinStatsGraph::DragMode WinStatsStripChart::
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;
}
} else {
// The mouse is above or below the graph; maybe create a new
// guide bar.
return DM_new_guide_bar;
}
}
return WinStatsGraph::consider_drag_start(mouse_x, mouse_y, width, height);
}
////////////////////////////////////////////////////////////////////
// Function: WinStatsStripChart::draw_guide_bar
// Access: Private
// Description: Draws the line for the indicated guide bar on the
// graph.
////////////////////////////////////////////////////////////////////
void WinStatsStripChart::
draw_guide_bar(HDC hdc, int from_x, int to_x,
const PStatGraph::GuideBar &bar) {
int y = height_to_pixel(bar._height);
if (y > 0) {
// Only draw it if it's not too close to the top.
switch (bar._style) {
case GBS_target:
SelectObject(hdc, _light_pen);
break;
case GBS_user:
SelectObject(hdc, _user_guide_bar_pen);
break;
case GBS_normal:
SelectObject(hdc, _dark_pen);
break;
}
MoveToEx(hdc, from_x, y, NULL);
LineTo(hdc, to_x + 1, y);
}
}
////////////////////////////////////////////////////////////////////
@ -404,15 +568,38 @@ additional_window_paint(HDC hdc) {
// given. Returns the top pixel value of the new label.
////////////////////////////////////////////////////////////////////
int WinStatsStripChart::
draw_guide_label(HDC hdc, int x, float value, int last_y) {
int y = height_to_pixel(value);
string label = format_number(value, get_guide_bar_units(),
get_guide_bar_unit_name());
draw_guide_label(HDC hdc, int x, const PStatGraph::GuideBar &bar, int last_y) {
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 y = 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(y + size.cy / 2 + 1);
float to_height = pixel_to_height(y - size.cy / 2 - 1);
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 last_y;
}
}
int this_y = _graph_top + y - size.cy / 2;
if (last_y < this_y || last_y > this_y + size.cy) {
if (y >= 0 && y < get_ysize() &&
(last_y < this_y || last_y > this_y + size.cy)) {
TextOut(hdc, x, this_y,
label.data(), label.length());
last_y = this_y;

View File

@ -47,6 +47,10 @@ public:
virtual void set_time_units(int unit_mask);
void set_vertical_scale(float value_height);
virtual void move_user_guide_bar(int n, float height);
virtual int add_user_guide_bar(float height);
virtual void remove_user_guide_bar(int n);
protected:
virtual void update_labels();
@ -60,9 +64,13 @@ protected:
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:
int draw_guide_label(HDC hdc, int x, float value, int last_y);
void draw_guide_bar(HDC hdc, int from_x, int to_x, const GuideBar &bar);
int draw_guide_label(HDC hdc, int x, const GuideBar &bar, int last_y);
void create_window();
static void register_window_class(HINSTANCE application);