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  */
89 void WinStatsLabel::
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  */
114 void WinStatsLabel::
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  */
126 int WinStatsLabel::
127 get_x() const {
128  return _x;
129 }
130 
131 /**
132  * Returns the y position of the label on its parent.
133  */
134 int WinStatsLabel::
135 get_y() const {
136  return _y;
137 }
138 
139 /**
140  * Returns the width of the label as we requested it.
141  */
142 int WinStatsLabel::
143 get_width() const {
144  return _width;
145 }
146 
147 /**
148  * Returns the height of the label as we requested it.
149  */
150 int WinStatsLabel::
151 get_height() const {
152  return _height;
153 }
154 
155 /**
156  * Returns the width the label would really prefer to be.
157  */
158 int WinStatsLabel::
160  return _ideal_width;
161 }
162 
163 /**
164  * Returns the collector this label represents.
165  */
166 int WinStatsLabel::
168  return _collector_index;
169 }
170 
171 /**
172  * Enables or disables the visual highlight for this label.
173  */
174 void WinStatsLabel::
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  */
185 bool WinStatsLabel::
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 }
int get_x() const
Returns the x position of the label on its parent.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const LRGBColor & get_collector_color(int collector_index)
Returns the color associated with the indicated collector.
int get_height() const
Returns the height of the label as we requested it.
std::string get_collector_fullname(int index) const
Returns the "full name" of the indicated collector.
A text label that will draw in color appropriate for a particular collector.
Definition: winStatsLabel.h:29
std::string get_collector_name(int index) const
Returns the name of the indicated collector.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_width() const
Returns the width of the label as we requested it.
void set_highlight(bool highlight)
Enables or disables the visual highlight for this label.
bool get_highlight() const
Returns true if the visual highlight for this label is enabled.
int get_ideal_width() const
Returns the width the label would really prefer to be.
This is just an abstract base class to provide a common pointer type for the various kinds of graphs ...
Definition: winStatsGraph.h:29
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This class represents a connection to a PStatsClient and manages the data exchange with the client.
int get_collector_index() const
Returns the collector this label represents.
int get_y() const
Returns the y position of the label on its parent.
const PStatClientData * get_client_data() const
Returns the client data associated with this monitor.
Definition: pStatMonitor.I:26
void setup(HWND parent_window)
Creates the actual window.
void set_pos(int x, int y, int width)
Sets the position of the label on its parent.
virtual void clicked_label(int collector_index)
Called when the user single-clicks on a label.