Panda3D
 All Classes Functions Variables Enumerations
winStatsLabel.cxx
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 }
 All Classes Functions Variables Enumerations