#ifndef __cxxtest__X11Gui_h__ #define __cxxtest__X11Gui_h__ // // X11Gui displays a simple progress bar using X11 // // It accepts the following command-line arguments: // -title - Sets the application title // -fn or -font <font> - Sets the font // -bg or -background <color> - Sets the background color (default=Grey) // -fg or -foreground <color> - Sets the text color (default=Black) // -green/-yellow/-red <color> - Sets the colors of the bar // #include <cxxtest/Gui.h> #include <X11/Xlib.h> #include <X11/Xutil.h> #include <stdio.h> #include <stdlib.h> #include <string.h> namespace CxxTest { class X11Gui : public GuiListener { public: void enterGui( int &argc, char **argv ) { parseCommandLine( argc, argv ); } void enterWorld( const WorldDescription &wd ) { openDisplay(); if ( _display ) { createColors(); createWindow(); createGc(); createFont(); centerWindow(); initializeEvents(); initializeBar( wd ); processEvents(); } } void guiEnterTest( const char *suiteName, const char *testName ) { if ( _display ) { ++ _testsDone; setWindowName( suiteName, testName ); redraw(); } } void yellowBar() { if ( _display ) { _barColor = getColor( _yellowName ); getTotalTests(); processEvents(); } } void redBar() { if ( _display ) { _barColor = getColor( _redName ); getTotalTests(); processEvents(); } } void leaveGui() { if ( _display ) { freeFontInfo(); destroyGc(); destroyWindow(); closeDisplay(); } } private: const char *_programName; Display *_display; Window _window; unsigned _numTotalTests, _testsDone; char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS]; const char *_foregroundName, *_backgroundName; const char *_greenName, *_yellowName, *_redName; unsigned long _foreground, _background, _barColor; int _width, _height; GC _gc; const char *_fontName; XID _fontId; XFontStruct *_fontInfo; int _textHeight, _textDescent; long _eventMask; Colormap _colormap; void parseCommandLine( int &argc, char **argv ) { _programName = argv[0]; _fontName = 0; _foregroundName = "Black"; _backgroundName = "Grey"; _greenName = "Green"; _yellowName = "Yellow"; _redName = "Red"; for ( int i = 1; i + 1 < argc; ++ i ) { if ( !strcmp( argv[i], "-title" ) ) _programName = argv[++ i]; else if ( !strcmp( argv[i], "-fn" ) || !strcmp( argv[i], "-font" ) ) _fontName = argv[++ i]; else if ( !strcmp( argv[i], "-fg" ) || !strcmp( argv[i], "-foreground" ) ) _foregroundName = argv[++ i]; else if ( !strcmp( argv[i], "-bg" ) || !strcmp( argv[i], "-background" ) ) _backgroundName = argv[++ i]; else if ( !strcmp( argv[i], "-green" ) ) _greenName = argv[++ i]; else if ( !strcmp( argv[i], "-yellow" ) ) _yellowName = argv[++ i]; else if ( !strcmp( argv[i], "-red" ) ) _redName = argv[++ i]; } } void openDisplay() { _display = XOpenDisplay( NULL ); } void createColors() { _colormap = DefaultColormap( _display, 0 ); _foreground = getColor( _foregroundName ); _background = getColor( _backgroundName ); } unsigned long getColor( const char *colorName ) { XColor color; XParseColor( _display, _colormap, colorName, &color ); XAllocColor( _display, _colormap, &color ); return color.pixel; } void createWindow() { _window = XCreateSimpleWindow( _display, RootWindow( _display, 0 ), 0, 0, 1, 1, 0, 0, _background ); } void createGc() { _gc = XCreateGC( _display, _window, 0, 0 ); } void createFont() { if ( !loadFont() ) useDefaultFont(); getFontInfo(); _textHeight = _fontInfo->ascent + _fontInfo->descent; _textDescent = _fontInfo->descent; } bool loadFont() { if ( !_fontName ) return false; _fontId = XLoadFont( _display, _fontName ); return (XSetFont( _display, _gc, _fontId ) == Success); } void useDefaultFont() { _fontId = XGContextFromGC( _gc ); } void getFontInfo() { _fontInfo = XQueryFont( _display, _fontId ); } void freeFontInfo() { XFreeFontInfo( NULL, _fontInfo, 1 ); } void initializeEvents() { _eventMask = ExposureMask; XSelectInput( _display, _window, _eventMask ); } void initializeBar( const WorldDescription &wd ) { getTotalTests( wd ); _testsDone = 0; _barColor = getColor( _greenName ); } void getTotalTests() { getTotalTests( tracker().world() ); } void getTotalTests( const WorldDescription &wd ) { _numTotalTests = wd.numTotalTests(); wd.strTotalTests( _strTotalTests ); } void centerWindow() { XMapWindow( _display, _window ); Screen *screen = XDefaultScreenOfDisplay( _display ); int screenWidth = WidthOfScreen( screen ); int screenHeight = HeightOfScreen( screen ); int xCenter = screenWidth / 2; int yCenter = screenHeight / 2; _width = (screenWidth * 4) / 5; _height = screenHeight / 14; XMoveResizeWindow( _display, _window, xCenter - (_width / 2), yCenter - (_height / 2), _width, _height ); } void processEvents() { redraw(); XEvent event; while( XCheckMaskEvent( _display, _eventMask, &event ) ) redraw(); } void setWindowName( const char *suiteName, const char *testName ) { unsigned length = strlen( _programName ) + strlen( suiteName ) + strlen( testName ) + sizeof( " - ::()" ); char *name = (char *)malloc( length ); sprintf( name, "%s - %s::%s()", _programName, suiteName, testName ); XSetStandardProperties( _display, _window, name, 0, 0, 0, 0, 0 ); free( name ); } void redraw() { getWindowSize(); drawSolidBar(); drawDividers(); drawPercentage(); flush(); } void getWindowSize() { XWindowAttributes attributes; XGetWindowAttributes( _display, _window, &attributes ); _width = attributes.width; _height = attributes.height; } void drawSolidBar() { unsigned barWidth = (_width * _testsDone) / _numTotalTests; XSetForeground( _display, _gc, _barColor ); XFillRectangle( _display, _window, _gc, 0, 0, barWidth, _height ); XSetForeground( _display, _gc, _background ); XFillRectangle( _display, _window, _gc, barWidth, 0, _width + 1 - barWidth, _height ); } void drawDividers() { if(_width / _numTotalTests < 5) return; for ( unsigned i = 1; i < _testsDone; ++ i ) { int x = (_width * i) / _numTotalTests; XDrawLine( _display, _window, _gc, x, 0, x, _height); } } void drawPercentage() { XSetForeground( _display, _gc, _foreground ); char str[sizeof("1000000000 of ") + sizeof(_strTotalTests) + sizeof(" (100%)")]; sprintf( str, "%u of %s (%u%%)", _testsDone, _strTotalTests, (_testsDone * 100) / _numTotalTests ); unsigned len = strlen( str ); int textWidth = XTextWidth( _fontInfo, str, len ); XDrawString( _display, _window, _gc, (_width - textWidth) / 2, ((_height + _textHeight) / 2) - _textDescent, str, len ); } void flush() { XFlush( _display ); } void destroyGc() { XFreeGC( _display, _gc ); } void destroyWindow() { XDestroyWindow( _display, _window ); } void closeDisplay() { XCloseDisplay( _display ); } }; }; #endif //__cxxtest__X11Gui_h__