1 #ifndef __cxxtest__X11Gui_h__ 2 #define __cxxtest__X11Gui_h__ 3 4 // 5 // X11Gui displays a simple progress bar using X11 6 // 7 // It accepts the following command-line arguments: 8 // -title <title> - Sets the application title 9 // -fn or -font <font> - Sets the font 10 // -bg or -background <color> - Sets the background color (default=Grey) 11 // -fg or -foreground <color> - Sets the text color (default=Black) 12 // -green/-yellow/-red <color> - Sets the colors of the bar 13 // 14 15 #include <cxxtest/Gui.h> 16 17 #include <X11/Xlib.h> 18 #include <X11/Xutil.h> 19 #include <stdio.h> 20 #include <stdlib.h> 21 #include <string.h> 22 23 namespace CxxTest 24 { 25 class X11Gui : public GuiListener 26 { 27 public: enterGui(int & argc,char ** argv)28 void enterGui( int &argc, char **argv ) 29 { 30 parseCommandLine( argc, argv ); 31 } 32 enterWorld(const WorldDescription & wd)33 void enterWorld( const WorldDescription &wd ) 34 { 35 openDisplay(); 36 if ( _display ) { 37 createColors(); 38 createWindow(); 39 createGc(); 40 createFont(); 41 centerWindow(); 42 initializeEvents(); 43 initializeBar( wd ); 44 processEvents(); 45 } 46 } 47 guiEnterTest(const char * suiteName,const char * testName)48 void guiEnterTest( const char *suiteName, const char *testName ) 49 { 50 if ( _display ) { 51 ++ _testsDone; 52 setWindowName( suiteName, testName ); 53 redraw(); 54 } 55 } 56 yellowBar()57 void yellowBar() 58 { 59 if ( _display ) { 60 _barColor = getColor( _yellowName ); 61 getTotalTests(); 62 processEvents(); 63 } 64 } 65 redBar()66 void redBar() 67 { 68 if ( _display ) { 69 _barColor = getColor( _redName ); 70 getTotalTests(); 71 processEvents(); 72 } 73 } 74 leaveGui()75 void leaveGui() 76 { 77 if ( _display ) { 78 freeFontInfo(); 79 destroyGc(); 80 destroyWindow(); 81 closeDisplay(); 82 } 83 } 84 85 private: 86 const char *_programName; 87 Display *_display; 88 Window _window; 89 unsigned _numTotalTests, _testsDone; 90 char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS]; 91 const char *_foregroundName, *_backgroundName; 92 const char *_greenName, *_yellowName, *_redName; 93 unsigned long _foreground, _background, _barColor; 94 int _width, _height; 95 GC _gc; 96 const char *_fontName; 97 XID _fontId; 98 XFontStruct *_fontInfo; 99 int _textHeight, _textDescent; 100 long _eventMask; 101 Colormap _colormap; 102 parseCommandLine(int & argc,char ** argv)103 void parseCommandLine( int &argc, char **argv ) 104 { 105 _programName = argv[0]; 106 107 _fontName = 0; 108 _foregroundName = "Black"; 109 _backgroundName = "Grey"; 110 _greenName = "Green"; 111 _yellowName = "Yellow"; 112 _redName = "Red"; 113 114 for ( int i = 1; i + 1 < argc; ++ i ) { 115 if ( !strcmp( argv[i], "-title" ) ) 116 _programName = argv[++ i]; 117 else if ( !strcmp( argv[i], "-fn" ) || !strcmp( argv[i], "-font" ) ) 118 _fontName = argv[++ i]; 119 else if ( !strcmp( argv[i], "-fg" ) || !strcmp( argv[i], "-foreground" ) ) 120 _foregroundName = argv[++ i]; 121 else if ( !strcmp( argv[i], "-bg" ) || !strcmp( argv[i], "-background" ) ) 122 _backgroundName = argv[++ i]; 123 else if ( !strcmp( argv[i], "-green" ) ) 124 _greenName = argv[++ i]; 125 else if ( !strcmp( argv[i], "-yellow" ) ) 126 _yellowName = argv[++ i]; 127 else if ( !strcmp( argv[i], "-red" ) ) 128 _redName = argv[++ i]; 129 } 130 } 131 openDisplay()132 void openDisplay() 133 { 134 _display = XOpenDisplay( NULL ); 135 } 136 createColors()137 void createColors() 138 { 139 _colormap = DefaultColormap( _display, 0 ); 140 _foreground = getColor( _foregroundName ); 141 _background = getColor( _backgroundName ); 142 } 143 getColor(const char * colorName)144 unsigned long getColor( const char *colorName ) 145 { 146 XColor color; 147 XParseColor( _display, _colormap, colorName, &color ); 148 XAllocColor( _display, _colormap, &color ); 149 return color.pixel; 150 } 151 createWindow()152 void createWindow() 153 { 154 _window = XCreateSimpleWindow( _display, RootWindow( _display, 0 ), 0, 0, 1, 1, 0, 0, _background ); 155 } 156 createGc()157 void createGc() 158 { 159 _gc = XCreateGC( _display, _window, 0, 0 ); 160 } 161 createFont()162 void createFont() 163 { 164 if ( !loadFont() ) 165 useDefaultFont(); 166 getFontInfo(); 167 _textHeight = _fontInfo->ascent + _fontInfo->descent; 168 _textDescent = _fontInfo->descent; 169 } 170 loadFont()171 bool loadFont() 172 { 173 if ( !_fontName ) 174 return false; 175 _fontId = XLoadFont( _display, _fontName ); 176 return (XSetFont( _display, _gc, _fontId ) == Success); 177 } 178 useDefaultFont()179 void useDefaultFont() 180 { 181 _fontId = XGContextFromGC( _gc ); 182 } 183 getFontInfo()184 void getFontInfo() 185 { 186 _fontInfo = XQueryFont( _display, _fontId ); 187 } 188 freeFontInfo()189 void freeFontInfo() 190 { 191 XFreeFontInfo( NULL, _fontInfo, 1 ); 192 } 193 initializeEvents()194 void initializeEvents() 195 { 196 _eventMask = ExposureMask; 197 XSelectInput( _display, _window, _eventMask ); 198 } 199 initializeBar(const WorldDescription & wd)200 void initializeBar( const WorldDescription &wd ) 201 { 202 getTotalTests( wd ); 203 _testsDone = 0; 204 _barColor = getColor( _greenName ); 205 } 206 getTotalTests()207 void getTotalTests() 208 { 209 getTotalTests( tracker().world() ); 210 } 211 getTotalTests(const WorldDescription & wd)212 void getTotalTests( const WorldDescription &wd ) 213 { 214 _numTotalTests = wd.numTotalTests(); 215 wd.strTotalTests( _strTotalTests ); 216 } 217 centerWindow()218 void centerWindow() 219 { 220 XMapWindow( _display, _window ); 221 222 Screen *screen = XDefaultScreenOfDisplay( _display ); 223 int screenWidth = WidthOfScreen( screen ); 224 int screenHeight = HeightOfScreen( screen ); 225 int xCenter = screenWidth / 2; 226 int yCenter = screenHeight / 2; 227 228 _width = (screenWidth * 4) / 5; 229 _height = screenHeight / 14; 230 231 XMoveResizeWindow( _display, _window, xCenter - (_width / 2), yCenter - (_height / 2), _width, _height ); 232 } 233 processEvents()234 void processEvents() 235 { 236 redraw(); 237 238 XEvent event; 239 while( XCheckMaskEvent( _display, _eventMask, &event ) ) 240 redraw(); 241 } 242 setWindowName(const char * suiteName,const char * testName)243 void setWindowName( const char *suiteName, const char *testName ) 244 { 245 unsigned length = strlen( _programName ) + strlen( suiteName ) + strlen( testName ) + sizeof( " - ::()" ); 246 char *name = (char *)malloc( length ); 247 sprintf( name, "%s - %s::%s()", _programName, suiteName, testName ); 248 XSetStandardProperties( _display, _window, name, 0, 0, 0, 0, 0 ); 249 free( name ); 250 } 251 redraw()252 void redraw() 253 { 254 getWindowSize(); 255 drawSolidBar(); 256 drawDividers(); 257 drawPercentage(); 258 flush(); 259 } 260 getWindowSize()261 void getWindowSize() 262 { 263 XWindowAttributes attributes; 264 XGetWindowAttributes( _display, _window, &attributes ); 265 _width = attributes.width; 266 _height = attributes.height; 267 } 268 drawSolidBar()269 void drawSolidBar() 270 { 271 unsigned barWidth = (_width * _testsDone) / _numTotalTests; 272 273 XSetForeground( _display, _gc, _barColor ); 274 XFillRectangle( _display, _window, _gc, 0, 0, barWidth, _height ); 275 276 XSetForeground( _display, _gc, _background ); 277 XFillRectangle( _display, _window, _gc, barWidth, 0, _width + 1 - barWidth, _height ); 278 } 279 drawDividers()280 void drawDividers() 281 { 282 if(_width / _numTotalTests < 5) 283 return; 284 for ( unsigned i = 1; i < _testsDone; ++ i ) { 285 int x = (_width * i) / _numTotalTests; 286 XDrawLine( _display, _window, _gc, x, 0, x, _height); 287 } 288 } 289 drawPercentage()290 void drawPercentage() 291 { 292 XSetForeground( _display, _gc, _foreground ); 293 294 char str[sizeof("1000000000 of ") + sizeof(_strTotalTests) + sizeof(" (100%)")]; 295 sprintf( str, "%u of %s (%u%%)", _testsDone, _strTotalTests, (_testsDone * 100) / _numTotalTests ); 296 unsigned len = strlen( str ); 297 298 int textWidth = XTextWidth( _fontInfo, str, len ); 299 300 XDrawString( _display, _window, _gc, 301 (_width - textWidth) / 2, ((_height + _textHeight) / 2) - _textDescent, 302 str, len ); 303 } 304 flush()305 void flush() 306 { 307 XFlush( _display ); 308 } 309 destroyGc()310 void destroyGc() 311 { 312 XFreeGC( _display, _gc ); 313 } 314 destroyWindow()315 void destroyWindow() 316 { 317 XDestroyWindow( _display, _window ); 318 } 319 closeDisplay()320 void closeDisplay() 321 { 322 XCloseDisplay( _display ); 323 } 324 }; 325 } 326 327 #endif //__cxxtest__X11Gui_h__ 328