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