18 bool WinStatsGraph::_graph_window_class_registered =
false;
19 const char *
const WinStatsGraph::_graph_window_class_name =
"graph";
21 DWORD WinStatsGraph::graph_window_style =
22 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_OVERLAPPEDWINDOW | WS_VISIBLE;
33 _sizewe_cursor = LoadCursor(
nullptr, IDC_SIZEWE);
34 _hand_cursor = LoadCursor(
nullptr, IDC_HAND);
43 _dark_color = RGB(51, 51, 51);
44 _light_color = RGB(154, 154, 154);
45 _user_guide_bar_color = RGB(130, 150, 255);
46 _dark_pen = CreatePen(PS_SOLID, 1, _dark_color);
47 _light_pen = CreatePen(PS_SOLID, 1, _light_color);
48 _user_guide_bar_pen = CreatePen(PS_DASH, 1, _user_guide_bar_color);
51 _potential_drag_mode = DM_none;
52 _drag_scale_start = 0.0f;
65 DeleteObject(_dark_pen);
66 DeleteObject(_light_pen);
67 DeleteObject(_user_guide_bar_pen);
70 for (bi = _brushes.begin(); bi != _brushes.end(); ++bi) {
71 HBRUSH brush = (*bi).second;
76 DestroyWindow(_graph_window);
81 DestroyWindow(_window);
97 new_data(
int thread_index,
int frame_number) {
145 InvalidateRect(_window,
nullptr, TRUE);
146 InvalidateRect(_graph_window,
nullptr, TRUE);
164 if (monitor !=
nullptr) {
165 monitor->remove_graph(
this);
173 setup_label_stack() {
174 _label_stack.
setup(_window);
185 GetClientRect(_window, &rect);
188 rect.right = _left_margin - 8;
189 rect.bottom -= _bottom_margin;
191 _label_stack.
set_pos(rect.left, rect.top,
192 rect.right - rect.left, rect.bottom - rect.top);
199 HBRUSH WinStatsGraph::
200 get_collector_brush(
int collector_index) {
201 Brushes::iterator bi;
202 bi = _brushes.find(collector_index);
203 if (bi != _brushes.end()) {
209 int r = (int)(rgb[0] * 255.0f);
210 int g = (int)(rgb[1] * 255.0f);
211 int b = (int)(rgb[2] * 255.0f);
212 HBRUSH brush = CreateSolidBrush(RGB(r, g, b));
214 _brushes[collector_index] = brush;
223 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
231 InvalidateRect(hwnd,
nullptr, TRUE);
235 set_drag_mode(DM_sizing);
238 case WM_EXITSIZEMOVE:
239 set_drag_mode(DM_none);
247 GetCursorPos(&point);
249 GetWindowInfo(hwnd, &winfo);
250 const RECT &rect = winfo.rcClient;
251 int x = point.x - rect.left;
252 int y = point.y - rect.top;
253 int width = rect.right - rect.left;
254 int height = rect.bottom - rect.top;
256 _potential_drag_mode = consider_drag_start(x, y, width, height);
258 switch (_potential_drag_mode) {
260 case DM_right_margin:
261 SetCursor(_sizewe_cursor);
265 SetCursor(_hand_cursor);
276 if (_potential_drag_mode != DM_none) {
277 set_drag_mode(_potential_drag_mode);
278 _drag_start_x = (int16_t)LOWORD(lparam);
279 _drag_start_y = (int16_t)HIWORD(lparam);
285 if (_drag_mode == DM_left_margin) {
286 int16_t x = LOWORD(lparam);
287 _left_margin += (x - _drag_start_x);
289 InvalidateRect(hwnd,
nullptr, TRUE);
293 }
else if (_drag_mode == DM_right_margin) {
294 int16_t x = LOWORD(lparam);
295 _right_margin += (_drag_start_x - x);
297 InvalidateRect(hwnd,
nullptr, TRUE);
303 set_drag_mode(DM_none);
310 HDC hdc = BeginPaint(hwnd, &ps);
314 GetClientRect(hwnd, &rect);
316 rect.left += _left_margin;
317 rect.top += _top_margin;
318 rect.right -= _right_margin;
319 rect.bottom -= _bottom_margin;
321 if (rect.right > rect.left && rect.bottom > rect.top) {
322 DrawEdge(hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
324 int graph_xsize = rect.right - rect.left;
325 int graph_ysize = rect.bottom - rect.top;
326 if (_bitmap_dc == 0 ||
327 graph_xsize != _bitmap_xsize ||
328 graph_ysize != _bitmap_ysize) {
331 move_graph_window(rect.left, rect.top, graph_xsize, graph_ysize);
336 additional_window_paint(hdc);
346 return DefWindowProc(hwnd, msg, wparam, lparam);
353 graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
355 case WM_DISPLAYCHANGE:
356 setup_bitmap(_bitmap_xsize, _bitmap_ysize);
363 if (_potential_drag_mode != DM_none) {
364 int16_t x = LOWORD(lparam) + _graph_left;
365 int16_t y = HIWORD(lparam) + _graph_top;
366 return window_proc(_window, msg, wparam, MAKELPARAM(x, y));
371 set_drag_mode(DM_none);
379 HDC hdc = BeginPaint(hwnd, &ps);
382 _bitmap_xsize, _bitmap_ysize,
386 additional_graph_window_paint(hdc);
396 return DefWindowProc(hwnd, msg, wparam, lparam);
405 additional_window_paint(HDC hdc) {
413 additional_graph_window_paint(HDC hdc) {
421 WinStatsGraph::DragMode WinStatsGraph::
422 consider_drag_start(
int mouse_x,
int mouse_y,
int width,
int height) {
423 if (mouse_x >= _left_margin - 2 && mouse_x <= _left_margin + 2) {
424 return DM_left_margin;
425 }
else if (mouse_x >= width - _right_margin - 2 && mouse_x <= width - _right_margin + 2) {
426 return DM_right_margin;
437 set_drag_mode(WinStatsGraph::DragMode drag_mode) {
438 _drag_mode = drag_mode;
446 move_graph_window(
int graph_left,
int graph_top,
int graph_xsize,
int graph_ysize) {
447 if (_graph_window == 0) {
448 create_graph_window();
451 _graph_left = graph_left;
452 _graph_top = graph_top;
454 SetWindowPos(_graph_window, 0,
455 _graph_left, _graph_top,
456 graph_xsize, graph_ysize,
457 SWP_NOZORDER | SWP_SHOWWINDOW);
459 if (graph_xsize != _bitmap_xsize || graph_ysize != _bitmap_ysize) {
460 setup_bitmap(graph_xsize, graph_ysize);
468 setup_bitmap(
int xsize,
int ysize) {
470 _bitmap_xsize = std::max(xsize, 0);
471 _bitmap_ysize = std::max(ysize, 0);
473 HDC hdc = GetDC(_graph_window);
474 _bitmap_dc = CreateCompatibleDC(hdc);
475 _bitmap = CreateCompatibleBitmap(hdc, _bitmap_xsize, _bitmap_ysize);
476 SelectObject(_bitmap_dc, _bitmap);
478 RECT rect = { 0, 0, _bitmap_xsize, _bitmap_ysize };
479 FillRect(_bitmap_dc, &rect, (HBRUSH)GetStockObject(WHITE_BRUSH));
481 ReleaseDC(_window, hdc);
490 DeleteObject(_bitmap);
494 DeleteDC(_bitmap_dc);
503 create_graph_window() {
508 HINSTANCE application = GetModuleHandle(
nullptr);
509 register_graph_window_class(application);
511 std::string window_title =
"graph";
512 DWORD window_style = WS_CHILD | WS_CLIPSIBLINGS;
515 CreateWindow(_graph_window_class_name, window_title.c_str(), window_style,
517 _window,
nullptr, application, 0);
518 if (!_graph_window) {
519 nout <<
"Could not create graph window!\n";
523 SetWindowLongPtr(_graph_window, 0, (LONG_PTR)
this);
531 register_graph_window_class(HINSTANCE application) {
532 if (_graph_window_class_registered) {
538 ZeroMemory(&wc,
sizeof(WNDCLASS));
539 wc.style = CS_DBLCLKS;
540 wc.lpfnWndProc = (WNDPROC)static_graph_window_proc;
541 wc.hInstance = application;
542 wc.hCursor = LoadCursor(
nullptr, IDC_ARROW);
543 wc.hbrBackground =
nullptr;
544 wc.lpszMenuName =
nullptr;
545 wc.lpszClassName = _graph_window_class_name;
550 if (!RegisterClass(&wc)) {
551 nout <<
"Could not register graph window class!\n";
555 _graph_window_class_registered =
true;
561 LONG WINAPI WinStatsGraph::
562 static_graph_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
564 if (
self !=
nullptr && self->_graph_window == hwnd) {
565 return self->graph_window_proc(hwnd, msg, wparam, lparam);
567 return DefWindowProc(hwnd, msg, wparam, lparam);
const LRGBColor & get_collector_color(int collector_index)
Returns the color associated with the indicated collector.
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
void set_pause(bool pause)
Changes the pause flag for the graph.
virtual void set_scroll_speed(double scroll_speed)
Called when the user selects a new scroll speed from the monitor pulldown menu, this should adjust th...
virtual void set_time_units(int unit_mask)
Called when the user selects a new time units from the monitor pulldown menu, this should adjust the ...
virtual void new_collector(int collector_index)
Called whenever a new Collector definition is received from the client.
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.
void user_guide_bars_changed()
Called when the user guide bars have been changed.
virtual void new_data(int thread_index, int frame_number)
Called whenever new data arrives.
virtual void force_redraw()
Called when it is necessary to redraw the entire graph.
virtual void changed_graph_size(int graph_xsize, int graph_ysize)
Called when the user has resized the window, forcing a resize of the graph.
bool is_setup() const
Returns true if the label stack has been set up, false otherwise.
void setup(HWND parent_window)
Creates the actual window object.
void set_pos(int x, int y, int width, int height)
Sets the position and size of the label stack on its parent.
This class represents a connection to a PStatsClient and manages the data exchange with the client.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.