Panda3D
winStatsLabel.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file winStatsLabel.cxx
10  * @author drose
11  * @date 2004-01-07
12  */
13 
14 #include "winStatsLabel.h"
15 #include "winStatsMonitor.h"
16 #include "winStatsGraph.h"
17 
18 int WinStatsLabel::_left_margin = 2;
19 int WinStatsLabel::_right_margin = 2;
20 int WinStatsLabel::_top_margin = 2;
21 int WinStatsLabel::_bottom_margin = 2;
22 
23 bool WinStatsLabel::_window_class_registered = false;
24 const char * const WinStatsLabel::_window_class_name = "label";
25 
26 /**
27  *
28  */
29 WinStatsLabel::
30 WinStatsLabel(WinStatsMonitor *monitor, WinStatsGraph *graph,
31  int thread_index, int collector_index, bool use_fullname) :
32  _monitor(monitor),
33  _graph(graph),
34  _thread_index(thread_index),
35  _collector_index(collector_index)
36 {
37  _window = 0;
38  if (use_fullname) {
39  _text = _monitor->get_client_data()->get_collector_fullname(_collector_index);
40  } else {
41  _text = _monitor->get_client_data()->get_collector_name(_collector_index);
42  }
43 
44  LRGBColor rgb = _monitor->get_collector_color(_collector_index);
45  int r = (int)(rgb[0] * 255.0f);
46  int g = (int)(rgb[1] * 255.0f);
47  int b = (int)(rgb[2] * 255.0f);
48  _bg_color = RGB(r, g, b);
49  _bg_brush = CreateSolidBrush(RGB(r, g, b));
50 
51  // Should our foreground be black or white?
52  double bright =
53  rgb[0] * 0.299 +
54  rgb[1] * 0.587 +
55  rgb[2] * 0.114;
56 
57  if (bright >= 0.5) {
58  _fg_color = RGB(0, 0, 0);
59  _highlight_brush = (HBRUSH)GetStockObject(BLACK_BRUSH);
60  } else {
61  _fg_color = RGB(255, 255, 255);
62  _highlight_brush = (HBRUSH)GetStockObject(WHITE_BRUSH);
63  }
64 
65  _x = 0;
66  _y = 0;
67  _width = 0;
68  _height = 0;
69  _ideal_width = 0;
70  _highlight = false;
71  _mouse_within = false;
72 }
73 
74 /**
75  *
76  */
77 WinStatsLabel::
78 ~WinStatsLabel() {
79  if (_window) {
80  DestroyWindow(_window);
81  _window = 0;
82  }
83  DeleteObject(_bg_brush);
84 }
85 
86 /**
87  * Creates the actual window.
88  */
90 setup(HWND parent_window) {
91  if (_window) {
92  DestroyWindow(_window);
93  _window = 0;
94  }
95 
96  create_window(parent_window);
97 
98  HDC hdc = GetDC(_window);
99  HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT);
100  SelectObject(hdc, hfnt);
101 
102  SIZE size;
103  GetTextExtentPoint32(hdc, _text.data(), _text.length(), &size);
104  _height = size.cy + _top_margin + _bottom_margin;
105  _ideal_width = size.cx + _left_margin + _right_margin;
106 
107  ReleaseDC(_window, hdc);
108 }
109 
110 /**
111  * Sets the position of the label on its parent. The position describes the
112  * lower-left corner of the rectangle, not the upper-left.
113  */
115 set_pos(int x, int y, int width) {
116  _x = x;
117  _y = y;
118  _width = width;
119  SetWindowPos(_window, 0, x, y - _height, _width, _height,
120  SWP_NOZORDER | SWP_SHOWWINDOW);
121 }
122 
123 /**
124  * Returns the x position of the label on its parent.
125  */
127 get_x() const {
128  return _x;
129 }
130 
131 /**
132  * Returns the y position of the label on its parent.
133  */
135 get_y() const {
136  return _y;
137 }
138 
139 /**
140  * Returns the width of the label as we requested it.
141  */
143 get_width() const {
144  return _width;
145 }
146 
147 /**
148  * Returns the height of the label as we requested it.
149  */
151 get_height() const {
152  return _height;
153 }
154 
155 /**
156  * Returns the width the label would really prefer to be.
157  */
159 get_ideal_width() const {
160  return _ideal_width;
161 }
162 
163 /**
164  * Returns the collector this label represents.
165  */
167 get_collector_index() const {
168  return _collector_index;
169 }
170 
171 /**
172  * Enables or disables the visual highlight for this label.
173  */
175 set_highlight(bool highlight) {
176  if (_highlight != highlight) {
177  _highlight = highlight;
178  InvalidateRect(_window, nullptr, TRUE);
179  }
180 }
181 
182 /**
183  * Returns true if the visual highlight for this label is enabled.
184  */
186 get_highlight() const {
187  return _highlight;
188 }
189 
190 /**
191  * Used internally to indicate whether the mouse is within the label's window.
192  */
193 void WinStatsLabel::
194 set_mouse_within(bool mouse_within) {
195  if (_mouse_within != mouse_within) {
196  _mouse_within = mouse_within;
197  InvalidateRect(_window, nullptr, TRUE);
198  }
199 }
200 
201 /**
202  * Creates the window for this label.
203  */
204 void WinStatsLabel::
205 create_window(HWND parent_window) {
206  if (_window) {
207  return;
208  }
209 
210  HINSTANCE application = GetModuleHandle(nullptr);
211  register_window_class(application);
212 
213  _window =
214  CreateWindow(_window_class_name, _text.c_str(), WS_CHILD | WS_CLIPSIBLINGS,
215  0, 0, 0, 0,
216  parent_window, nullptr, application, 0);
217  if (!_window) {
218  nout << "Could not create Label window!\n";
219  exit(1);
220  }
221 
222  SetWindowLongPtr(_window, 0, (LONG_PTR)this);
223 }
224 
225 /**
226  * Registers the window class for the label window, if it has not already been
227  * registered.
228  */
229 void WinStatsLabel::
230 register_window_class(HINSTANCE application) {
231  if (_window_class_registered) {
232  return;
233  }
234 
235  WNDCLASS wc;
236 
237  ZeroMemory(&wc, sizeof(WNDCLASS));
238  wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
239  wc.lpfnWndProc = (WNDPROC)static_window_proc;
240  wc.hInstance = application;
241  wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
242  wc.hbrBackground = nullptr;
243  wc.lpszMenuName = nullptr;
244  wc.lpszClassName = _window_class_name;
245 
246  // Reserve space to associate the this pointer with the window.
247  wc.cbWndExtra = sizeof(WinStatsLabel *);
248 
249  if (!RegisterClass(&wc)) {
250  nout << "Could not register Label window class!\n";
251  exit(1);
252  }
253 
254  _window_class_registered = true;
255 }
256 
257 /**
258  *
259  */
260 LONG WINAPI WinStatsLabel::
261 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
262  WinStatsLabel *self = (WinStatsLabel *)GetWindowLongPtr(hwnd, 0);
263  if (self != nullptr && self->_window == hwnd) {
264  return self->window_proc(hwnd, msg, wparam, lparam);
265  } else {
266  return DefWindowProc(hwnd, msg, wparam, lparam);
267  }
268 }
269 
270 /**
271  *
272  */
273 LONG WinStatsLabel::
274 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
275  switch (msg) {
276  case WM_LBUTTONDBLCLK:
277  _graph->clicked_label(_collector_index);
278  return 0;
279 
280  case WM_MOUSEMOVE:
281  {
282  // When the mouse enters the label area, highlight the label.
283  set_mouse_within(true);
284 
285  // Now we want to get a WM_MOUSELEAVE when the mouse leaves the label.
286  TRACKMOUSEEVENT tme = {
287  sizeof(TRACKMOUSEEVENT),
288  TME_LEAVE,
289  _window,
290  0
291  };
292  TrackMouseEvent(&tme);
293  }
294  break;
295 
296  case WM_MOUSELEAVE:
297  set_mouse_within(false);
298  break;
299 
300  case WM_PAINT:
301  {
302  PAINTSTRUCT ps;
303  HDC hdc = BeginPaint(hwnd, &ps);
304 
305  RECT rect = { 0, 0, _width, _height };
306  FillRect(hdc, &rect, _bg_brush);
307 
308  if (_highlight || _mouse_within) {
309  FrameRect(hdc, &rect, _highlight_brush);
310  }
311 
312  HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT);
313  SelectObject(hdc, hfnt);
314  SetTextAlign(hdc, TA_RIGHT | TA_TOP);
315 
316  SetBkColor(hdc, _bg_color);
317  SetBkMode(hdc, OPAQUE);
318  SetTextColor(hdc, _fg_color);
319 
320  TextOut(hdc, _width - _right_margin, _top_margin,
321  _text.data(), _text.length());
322  EndPaint(hwnd, &ps);
323  return 0;
324  }
325 
326  default:
327  break;
328  }
329 
330  return DefWindowProc(hwnd, msg, wparam, lparam);
331 }
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
Definition: winStatsGraph.h:32
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.
A text label that will draw in color appropriate for a particular collector.
Definition: winStatsLabel.h:32
void setup(HWND parent_window)
Creates the actual window.
int get_y() const
Returns the y position of the label on its parent.
int get_ideal_width() const
Returns the width the label would really prefer to be.
int get_width() const
Returns the width of the label as we requested it.
int get_x() const
Returns the x position of the label on its parent.
bool get_highlight() const
Returns true if the visual highlight for this label is enabled.
int get_collector_index() const
Returns the collector this label represents.
int get_height() const
Returns the height of the label as we requested it.
void set_pos(int x, int y, int width)
Sets the position of the label on its parent.
void set_highlight(bool highlight)
Enables or disables the visual highlight for this label.
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.