Panda3D
|
00001 // Filename: winStatsLabel.cxx 00002 // Created by: drose (07Jan04) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "winStatsLabel.h" 00016 #include "winStatsMonitor.h" 00017 #include "winStatsGraph.h" 00018 00019 int WinStatsLabel::_left_margin = 2; 00020 int WinStatsLabel::_right_margin = 2; 00021 int WinStatsLabel::_top_margin = 2; 00022 int WinStatsLabel::_bottom_margin = 2; 00023 00024 bool WinStatsLabel::_window_class_registered = false; 00025 const char * const WinStatsLabel::_window_class_name = "label"; 00026 00027 //////////////////////////////////////////////////////////////////// 00028 // Function: WinStatsLabel::Constructor 00029 // Access: Public 00030 // Description: 00031 //////////////////////////////////////////////////////////////////// 00032 WinStatsLabel:: 00033 WinStatsLabel(WinStatsMonitor *monitor, WinStatsGraph *graph, 00034 int thread_index, int collector_index, bool use_fullname) : 00035 _monitor(monitor), 00036 _graph(graph), 00037 _thread_index(thread_index), 00038 _collector_index(collector_index) 00039 { 00040 _window = 0; 00041 if (use_fullname) { 00042 _text = _monitor->get_client_data()->get_collector_fullname(_collector_index); 00043 } else { 00044 _text = _monitor->get_client_data()->get_collector_name(_collector_index); 00045 } 00046 00047 LRGBColor rgb = _monitor->get_collector_color(_collector_index); 00048 int r = (int)(rgb[0] * 255.0f); 00049 int g = (int)(rgb[1] * 255.0f); 00050 int b = (int)(rgb[2] * 255.0f); 00051 _bg_color = RGB(r, g, b); 00052 _bg_brush = CreateSolidBrush(RGB(r, g, b)); 00053 00054 // Should our foreground be black or white? 00055 double bright = 00056 rgb[0] * 0.299 + 00057 rgb[1] * 0.587 + 00058 rgb[2] * 0.114; 00059 00060 if (bright >= 0.5) { 00061 _fg_color = RGB(0, 0, 0); 00062 _highlight_brush = (HBRUSH)GetStockObject(BLACK_BRUSH); 00063 } else { 00064 _fg_color = RGB(255, 255, 255); 00065 _highlight_brush = (HBRUSH)GetStockObject(WHITE_BRUSH); 00066 } 00067 00068 _x = 0; 00069 _y = 0; 00070 _width = 0; 00071 _height = 0; 00072 _ideal_width = 0; 00073 _highlight = false; 00074 _mouse_within = false; 00075 } 00076 00077 //////////////////////////////////////////////////////////////////// 00078 // Function: WinStatsLabel::Destructor 00079 // Access: Public 00080 // Description: 00081 //////////////////////////////////////////////////////////////////// 00082 WinStatsLabel:: 00083 ~WinStatsLabel() { 00084 if (_window) { 00085 DestroyWindow(_window); 00086 _window = 0; 00087 } 00088 DeleteObject(_bg_brush); 00089 } 00090 00091 //////////////////////////////////////////////////////////////////// 00092 // Function: WinStatsLabel::setup 00093 // Access: Public 00094 // Description: Creates the actual window. 00095 //////////////////////////////////////////////////////////////////// 00096 void WinStatsLabel:: 00097 setup(HWND parent_window) { 00098 if (_window) { 00099 DestroyWindow(_window); 00100 _window = 0; 00101 } 00102 00103 create_window(parent_window); 00104 00105 HDC hdc = GetDC(_window); 00106 HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT); 00107 SelectObject(hdc, hfnt); 00108 00109 SIZE size; 00110 GetTextExtentPoint32(hdc, _text.data(), _text.length(), &size); 00111 _height = size.cy + _top_margin + _bottom_margin; 00112 _ideal_width = size.cx + _left_margin + _right_margin; 00113 00114 ReleaseDC(_window, hdc); 00115 } 00116 00117 //////////////////////////////////////////////////////////////////// 00118 // Function: WinStatsLabel::set_pos 00119 // Access: Public 00120 // Description: Sets the position of the label on its parent. The 00121 // position describes the lower-left corner of the 00122 // rectangle, not the upper-left. 00123 //////////////////////////////////////////////////////////////////// 00124 void WinStatsLabel:: 00125 set_pos(int x, int y, int width) { 00126 _x = x; 00127 _y = y; 00128 _width = width; 00129 SetWindowPos(_window, 0, x, y - _height, _width, _height, 00130 SWP_NOZORDER | SWP_SHOWWINDOW); 00131 } 00132 00133 //////////////////////////////////////////////////////////////////// 00134 // Function: WinStatsLabel::get_x 00135 // Access: Public 00136 // Description: Returns the x position of the label on its parent. 00137 //////////////////////////////////////////////////////////////////// 00138 int WinStatsLabel:: 00139 get_x() const { 00140 return _x; 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: WinStatsLabel::get_y 00145 // Access: Public 00146 // Description: Returns the y position of the label on its parent. 00147 //////////////////////////////////////////////////////////////////// 00148 int WinStatsLabel:: 00149 get_y() const { 00150 return _y; 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: WinStatsLabel::get_width 00155 // Access: Public 00156 // Description: Returns the width of the label as we requested it. 00157 //////////////////////////////////////////////////////////////////// 00158 int WinStatsLabel:: 00159 get_width() const { 00160 return _width; 00161 } 00162 00163 //////////////////////////////////////////////////////////////////// 00164 // Function: WinStatsLabel::get_height 00165 // Access: Public 00166 // Description: Returns the height of the label as we requested it. 00167 //////////////////////////////////////////////////////////////////// 00168 int WinStatsLabel:: 00169 get_height() const { 00170 return _height; 00171 } 00172 00173 //////////////////////////////////////////////////////////////////// 00174 // Function: WinStatsLabel::get_ideal_width 00175 // Access: Public 00176 // Description: Returns the width the label would really prefer to be. 00177 //////////////////////////////////////////////////////////////////// 00178 int WinStatsLabel:: 00179 get_ideal_width() const { 00180 return _ideal_width; 00181 } 00182 00183 //////////////////////////////////////////////////////////////////// 00184 // Function: WinStatsLabel::get_collector_index 00185 // Access: Public 00186 // Description: Returns the collector this label represents. 00187 //////////////////////////////////////////////////////////////////// 00188 int WinStatsLabel:: 00189 get_collector_index() const { 00190 return _collector_index; 00191 } 00192 00193 //////////////////////////////////////////////////////////////////// 00194 // Function: WinStatsLabel::set_highlight 00195 // Access: Public 00196 // Description: Enables or disables the visual highlight for this 00197 // label. 00198 //////////////////////////////////////////////////////////////////// 00199 void WinStatsLabel:: 00200 set_highlight(bool highlight) { 00201 if (_highlight != highlight) { 00202 _highlight = highlight; 00203 InvalidateRect(_window, NULL, TRUE); 00204 } 00205 } 00206 00207 //////////////////////////////////////////////////////////////////// 00208 // Function: WinStatsLabel::get_highlight 00209 // Access: Public 00210 // Description: Returns true if the visual highlight for this 00211 // label is enabled. 00212 //////////////////////////////////////////////////////////////////// 00213 bool WinStatsLabel:: 00214 get_highlight() const { 00215 return _highlight; 00216 } 00217 00218 //////////////////////////////////////////////////////////////////// 00219 // Function: WinStatsLabel::set_mouse_within 00220 // Access: Private 00221 // Description: Used internally to indicate whether the mouse is 00222 // within the label's window. 00223 //////////////////////////////////////////////////////////////////// 00224 void WinStatsLabel:: 00225 set_mouse_within(bool mouse_within) { 00226 if (_mouse_within != mouse_within) { 00227 _mouse_within = mouse_within; 00228 InvalidateRect(_window, NULL, TRUE); 00229 } 00230 } 00231 00232 //////////////////////////////////////////////////////////////////// 00233 // Function: WinStatsLabel::create_window 00234 // Access: Private 00235 // Description: Creates the window for this label. 00236 //////////////////////////////////////////////////////////////////// 00237 void WinStatsLabel:: 00238 create_window(HWND parent_window) { 00239 if (_window) { 00240 return; 00241 } 00242 00243 HINSTANCE application = GetModuleHandle(NULL); 00244 register_window_class(application); 00245 00246 _window = 00247 CreateWindow(_window_class_name, _text.c_str(), WS_CHILD | WS_CLIPSIBLINGS, 00248 0, 0, 0, 0, 00249 parent_window, NULL, application, 0); 00250 if (!_window) { 00251 nout << "Could not create Label window!\n"; 00252 exit(1); 00253 } 00254 00255 SetWindowLongPtr(_window, 0, (LONG_PTR)this); 00256 } 00257 00258 //////////////////////////////////////////////////////////////////// 00259 // Function: WinStatsLabel::register_window_class 00260 // Access: Private, Static 00261 // Description: Registers the window class for the label window, if 00262 // it has not already been registered. 00263 //////////////////////////////////////////////////////////////////// 00264 void WinStatsLabel:: 00265 register_window_class(HINSTANCE application) { 00266 if (_window_class_registered) { 00267 return; 00268 } 00269 00270 WNDCLASS wc; 00271 00272 ZeroMemory(&wc, sizeof(WNDCLASS)); 00273 wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; 00274 wc.lpfnWndProc = (WNDPROC)static_window_proc; 00275 wc.hInstance = application; 00276 wc.hCursor = LoadCursor(NULL, IDC_ARROW); 00277 wc.hbrBackground = NULL; 00278 wc.lpszMenuName = NULL; 00279 wc.lpszClassName = _window_class_name; 00280 00281 // Reserve space to associate the this pointer with the window. 00282 wc.cbWndExtra = sizeof(WinStatsLabel *); 00283 00284 if (!RegisterClass(&wc)) { 00285 nout << "Could not register Label window class!\n"; 00286 exit(1); 00287 } 00288 00289 _window_class_registered = true; 00290 } 00291 00292 //////////////////////////////////////////////////////////////////// 00293 // Function: WinStatsLabel::static_window_proc 00294 // Access: Private, Static 00295 // Description: 00296 //////////////////////////////////////////////////////////////////// 00297 LONG WINAPI WinStatsLabel:: 00298 static_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 00299 WinStatsLabel *self = (WinStatsLabel *)GetWindowLongPtr(hwnd, 0); 00300 if (self != (WinStatsLabel *)NULL && self->_window == hwnd) { 00301 return self->window_proc(hwnd, msg, wparam, lparam); 00302 } else { 00303 return DefWindowProc(hwnd, msg, wparam, lparam); 00304 } 00305 } 00306 00307 //////////////////////////////////////////////////////////////////// 00308 // Function: WinStatsLabel::window_proc 00309 // Access: Private 00310 // Description: 00311 //////////////////////////////////////////////////////////////////// 00312 LONG WinStatsLabel:: 00313 window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { 00314 switch (msg) { 00315 case WM_LBUTTONDBLCLK: 00316 _graph->clicked_label(_collector_index); 00317 return 0; 00318 00319 case WM_MOUSEMOVE: 00320 { 00321 // When the mouse enters the label area, highlight the label. 00322 set_mouse_within(true); 00323 00324 // Now we want to get a WM_MOUSELEAVE when the mouse leaves the 00325 // label. 00326 TRACKMOUSEEVENT tme = { 00327 sizeof(TRACKMOUSEEVENT), 00328 TME_LEAVE, 00329 _window, 00330 0 00331 }; 00332 TrackMouseEvent(&tme); 00333 } 00334 break; 00335 00336 case WM_MOUSELEAVE: 00337 set_mouse_within(false); 00338 break; 00339 00340 case WM_PAINT: 00341 { 00342 PAINTSTRUCT ps; 00343 HDC hdc = BeginPaint(hwnd, &ps); 00344 00345 RECT rect = { 0, 0, _width, _height }; 00346 FillRect(hdc, &rect, _bg_brush); 00347 00348 if (_highlight || _mouse_within) { 00349 FrameRect(hdc, &rect, _highlight_brush); 00350 } 00351 00352 HFONT hfnt = (HFONT)GetStockObject(ANSI_VAR_FONT); 00353 SelectObject(hdc, hfnt); 00354 SetTextAlign(hdc, TA_RIGHT | TA_TOP); 00355 00356 SetBkColor(hdc, _bg_color); 00357 SetBkMode(hdc, OPAQUE); 00358 SetTextColor(hdc, _fg_color); 00359 00360 TextOut(hdc, _width - _right_margin, _top_margin, 00361 _text.data(), _text.length()); 00362 EndPaint(hwnd, &ps); 00363 return 0; 00364 } 00365 00366 default: 00367 break; 00368 } 00369 00370 return DefWindowProc(hwnd, msg, wparam, lparam); 00371 }