Code

Translations. French translation minor update.
[inkscape.git] / cxxtest / cxxtest / Win32Gui.h
1 #ifndef __cxxtest__Win32Gui_h__
2 #define __cxxtest__Win32Gui_h__
4 //
5 // The Win32Gui displays a simple progress bar using the Win32 API.
6 //
7 // It accepts the following command line options:
8 //   -minimized    Start minimized, pop up on error
9 //   -keep         Don't close the window at the end
10 //   -title TITLE  Set the window caption
11 //
12 // If both -minimized and -keep are specified, GUI will only keep the
13 // window if it's in focus.
14 //
15 // N.B. If you're wondering why this class doesn't use any standard
16 // library or STL (<string> would have been nice) it's because it only
17 // uses "straight" Win32 API.
18 //
20 #include <cxxtest/Gui.h>
22 #include <windows.h>
23 #include <commctrl.h>
25 namespace CxxTest
26 {
27     class Win32Gui : public GuiListener
28     {
29     public:
30         void enterGui( int &argc, char **argv )
31         {
32             parseCommandLine( argc, argv );
33         }
34         
35         void enterWorld( const WorldDescription &wd )
36         {
37             getTotalTests( wd );
38             _testsDone = 0;
39             startGuiThread();
40         }
42         void guiEnterSuite( const char *suiteName )
43         {
44             showSuiteName( suiteName );
45             reset( _suiteStart );
46         }
48         void guiEnterTest( const char *suiteName, const char *testName )
49         {
50             ++ _testsDone;
51             setTestCaption( suiteName, testName );
52             showTestName( testName );
53             showTestsDone();
54             progressBarMessage( PBM_STEPIT );
55             reset( _testStart );
56         }
58         void yellowBar()
59         {
60             setColor( 255, 255, 0 );
61             setIcon( IDI_WARNING );
62             getTotalTests();
63         }
64         
65         void redBar()
66         {
67             if ( _startMinimized )
68                 showMainWindow( SW_SHOWNORMAL );
69             setColor( 255, 0, 0 );
70             setIcon( IDI_ERROR );
71             getTotalTests();
72         }
74         void leaveGui()
75         {
76             if ( keep() )
77             {
78                 showSummary();
79                 WaitForSingleObject( _gui, INFINITE );
80             }
81             DestroyWindow( _mainWindow );
82         }
84     private:
85         const char *_title;
86         bool _startMinimized, _keep;
87         HANDLE _gui;
88         WNDCLASSEX _windowClass;
89         HWND _mainWindow, _progressBar, _statusBar;
90         HANDLE _canStartTests;
91         unsigned _numTotalTests, _testsDone;
92         char _strTotalTests[WorldDescription::MAX_STRLEN_TOTAL_TESTS];
93         enum { 
94             STATUS_SUITE_NAME, STATUS_SUITE_TIME,
95             STATUS_TEST_NAME, STATUS_TEST_TIME,
96             STATUS_TESTS_DONE, STATUS_WORLD_TIME,
97             STATUS_TOTAL_PARTS 
98         };
99         int _statusWidths[STATUS_TOTAL_PARTS];
100         unsigned _statusOffsets[STATUS_TOTAL_PARTS];
101         unsigned _statusTotal;
102         char _statusTestsDone[sizeof("1000000000 of  (100%)") + WorldDescription::MAX_STRLEN_TOTAL_TESTS];
103         DWORD _worldStart, _suiteStart, _testStart;
104         char _timeString[sizeof("00:00:00")];
106         void parseCommandLine( int argc, char **argv )
107         {
108             _startMinimized = _keep = false;
109             _title = argv[0];
110             
111             for ( int i = 1; i < argc; ++ i )
112             {
113                 if ( !lstrcmpA( argv[i], "-minimized" ) )
114                     _startMinimized = true;
115                 else if ( !lstrcmpA( argv[i], "-keep" ) )
116                     _keep = true;
117                 else if ( !lstrcmpA( argv[i], "-title" ) && (i + 1 < argc) )
118                     _title = argv[++i];
119             }
120         }
121         
122         void getTotalTests()
123         {
124             getTotalTests( tracker().world() );
125         }
127         void getTotalTests( const WorldDescription &wd )
128         {
129             _numTotalTests = wd.numTotalTests();
130             wd.strTotalTests( _strTotalTests );
131         }
133         void startGuiThread()
134         {
135             _canStartTests = CreateEvent( NULL, TRUE, FALSE, NULL );
136                         DWORD threadId;
137             _gui = CreateThread( NULL, 0, &(Win32Gui::guiThread), (LPVOID)this, 0, &threadId );
138             WaitForSingleObject( _canStartTests, INFINITE );
139         }
141         static DWORD WINAPI guiThread( LPVOID parameter )
142         {
143             ((Win32Gui *)parameter)->gui();
144             return 0;
145         }
147         void gui()
148         {
149             registerWindowClass();
150             createMainWindow();
151             initCommonControls();
152             createProgressBar();
153             createStatusBar();
154             centerMainWindow();
155             showMainWindow();
156             startTimer();
157             startTests();
159             messageLoop();
160         }
162         void registerWindowClass()
163         {
164             _windowClass.cbSize = sizeof(_windowClass);
165             _windowClass.style = CS_HREDRAW | CS_VREDRAW;
166             _windowClass.lpfnWndProc = &(Win32Gui::windowProcedure);
167             _windowClass.cbClsExtra = 0;
168             _windowClass.cbWndExtra = sizeof(LONG);
169             _windowClass.hInstance = (HINSTANCE)NULL;
170             _windowClass.hIcon = (HICON)NULL;
171             _windowClass.hCursor = (HCURSOR)NULL;
172             _windowClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
173             _windowClass.lpszMenuName = NULL;
174             _windowClass.lpszClassName = TEXT("CxxTest Window Class");
175             _windowClass.hIconSm = (HICON)NULL;
177             RegisterClassEx( &_windowClass );
178         }
180         void createMainWindow()
181         {
182             _mainWindow = createWindow( _windowClass.lpszClassName, WS_OVERLAPPEDWINDOW );
183         }
185         void initCommonControls()
186         {
187             HMODULE dll = LoadLibraryA( "comctl32.dll" );
188             if ( !dll )
189                 return;
190                 
191             typedef void (WINAPI *FUNC)( void );
192             FUNC func = (FUNC)GetProcAddress( dll, "InitCommonControls" );
193             if ( !func )
194                 return;
196             func();
197         }
199         void createProgressBar()
200         {
201             _progressBar = createWindow( PROGRESS_CLASS, WS_CHILD | WS_VISIBLE | PBS_SMOOTH, _mainWindow );
203 #ifdef PBM_SETRANGE32
204             progressBarMessage( PBM_SETRANGE32, 0, _numTotalTests );
205 #else // No PBM_SETRANGE32, use PBM_SETRANGE
206             progressBarMessage( PBM_SETRANGE, 0, MAKELPARAM( 0, (WORD)_numTotalTests ) );
207 #endif // PBM_SETRANGE32
208             progressBarMessage( PBM_SETPOS, 0 );
209             progressBarMessage( PBM_SETSTEP, 1 );
210             greenBar();
211             UpdateWindow( _progressBar );
212         }
214         void createStatusBar()
215         {
216             _statusBar = createWindow( STATUSCLASSNAME, WS_CHILD | WS_VISIBLE, _mainWindow );
217             setRatios( 4, 1, 3, 1, 3, 1 );
218         }
220         void setRatios( unsigned suiteNameRatio, unsigned suiteTimeRatio,
221                         unsigned testNameRatio, unsigned testTimeRatio,
222                         unsigned testsDoneRatio, unsigned worldTimeRatio )
223         {
224             _statusTotal = 0;
225             _statusOffsets[STATUS_SUITE_NAME] = (_statusTotal += suiteNameRatio);
226             _statusOffsets[STATUS_SUITE_TIME] = (_statusTotal += suiteTimeRatio);
227             _statusOffsets[STATUS_TEST_NAME] = (_statusTotal += testNameRatio);
228             _statusOffsets[STATUS_TEST_TIME] = (_statusTotal += testTimeRatio);
229             _statusOffsets[STATUS_TESTS_DONE] = (_statusTotal += testsDoneRatio);
230             _statusOffsets[STATUS_WORLD_TIME] = (_statusTotal += worldTimeRatio);
231         }
233         HWND createWindow( LPCTSTR className, DWORD style, HWND parent = (HWND)NULL )
234         {
235             return CreateWindow( className, NULL, style, 0, 0, 0, 0, parent,
236                                  (HMENU)NULL, (HINSTANCE)NULL, (LPVOID)this );
237         }
239         void progressBarMessage( UINT message, WPARAM wParam = 0, LPARAM lParam = 0 )
240         {
241             SendMessage( _progressBar, message, wParam, lParam );
242         }
244         void centerMainWindow()
245         {
246             RECT screen;
247             getScreenArea( screen );
249             LONG screenWidth = screen.right - screen.left;
250             LONG screenHeight = screen.bottom - screen.top;
252             LONG xCenter = (screen.right + screen.left) / 2;
253             LONG yCenter = (screen.bottom + screen.top) / 2;
255             LONG windowWidth = (screenWidth * 4) / 5;
256             LONG windowHeight = screenHeight / 10;
257             LONG minimumHeight = 2 * (GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYFRAME ));
258             if ( windowHeight < minimumHeight )
259                 windowHeight = minimumHeight;
261             SetWindowPos( _mainWindow, HWND_TOP,
262                           xCenter - (windowWidth / 2), yCenter - (windowHeight / 2),
263                           windowWidth, windowHeight, 0 );
264         }
266         void getScreenArea( RECT &area )
267         {
268             if ( !getScreenAreaWithoutTaskbar( area ) )
269                 getWholeScreenArea( area );
270         }
272         bool getScreenAreaWithoutTaskbar( RECT &area )
273         {
274             return (SystemParametersInfo( SPI_GETWORKAREA, sizeof(RECT), &area, 0 ) != 0);
275         }
277         void getWholeScreenArea( RECT &area )
278         {
279             area.left = area.top = 0;
280             area.right = GetSystemMetrics( SM_CXSCREEN );
281             area.bottom = GetSystemMetrics( SM_CYSCREEN );
282         }
284         void showMainWindow()
285         {
286             showMainWindow( _startMinimized ? SW_MINIMIZE : SW_SHOWNORMAL );
287             UpdateWindow( _mainWindow );
288         }
290         void showMainWindow( int mode )
291         {
292             ShowWindow( _mainWindow, mode );
293         }
295         enum { TIMER_ID = 1, TIMER_DELAY = 1000 };
297         void startTimer()
298         {
299             reset( _worldStart );
300             reset( _suiteStart );
301             reset( _testStart );
302             SetTimer( _mainWindow, TIMER_ID, TIMER_DELAY, 0 );
303         }
305         void reset( DWORD &tick )
306         {
307             tick = GetTickCount();
308         }
310         void startTests()
311         {
312             SetEvent( _canStartTests );
313         }
315         void messageLoop()
316         {
317             MSG message;
318             while ( BOOL haveMessage = GetMessage( &message, NULL, 0, 0 ) )
319                 if ( haveMessage != -1 )
320                     DispatchMessage( &message );
321         }
323         static LRESULT CALLBACK windowProcedure( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
324         {
325             if ( message == WM_CREATE )
326                 setUp( window, (LPCREATESTRUCT)lParam );
328             Win32Gui *that = (Win32Gui *)GetWindowLong( window, GWL_USERDATA );
329             return that->handle( window, message, wParam, lParam );
330         }
332         static void setUp( HWND window, LPCREATESTRUCT create )
333         {
334             SetWindowLong( window, GWL_USERDATA, (LONG)create->lpCreateParams );
335         }
337         LRESULT handle( HWND window, UINT message, WPARAM wParam, LPARAM lParam )
338         {
339             switch ( message )
340             {
341             case WM_SIZE: resizeControls(); break;
343             case WM_TIMER: updateTime(); break;
345             case WM_CLOSE:
346             case WM_DESTROY:
347             case WM_QUIT:
348                 ExitProcess( 0 );
350             default: return DefWindowProc( window, message, wParam, lParam );
351             }
352             return 0;
353         }
355         void resizeControls()
356         {
357             RECT r;
358             GetClientRect( _mainWindow, &r );
359             LONG width = r.right - r.left;
360             LONG height = r.bottom - r.top;
362             GetClientRect( _statusBar, &r );
363             LONG statusHeight = r.bottom - r.top;
364             LONG resizeGripWidth = statusHeight;
365             LONG progressHeight = height - statusHeight;
367             SetWindowPos( _progressBar, HWND_TOP, 0, 0, width, progressHeight, 0 );
368             SetWindowPos( _statusBar, HWND_TOP, 0, progressHeight, width, statusHeight, 0 );
369             setStatusParts( width - resizeGripWidth );
370         }
372         void setStatusParts( LONG width )
373         {
374             for ( unsigned i = 0; i < STATUS_TOTAL_PARTS; ++ i )
375                 _statusWidths[i] = (width * _statusOffsets[i]) / _statusTotal;
377             statusBarMessage( SB_SETPARTS, STATUS_TOTAL_PARTS, _statusWidths );
378         }
380         void statusBarMessage( UINT message, WPARAM wParam = 0, const void *lParam = 0 )
381         {
382             SendMessage( _statusBar, message, wParam, (LPARAM)lParam );
383         }
385         void greenBar()
386         {
387             setColor( 0, 255, 0 );
388             setIcon( IDI_INFORMATION );
389         }
391 #ifdef PBM_SETBARCOLOR
392         void setColor( BYTE red, BYTE green, BYTE blue )
393         {
394             progressBarMessage( PBM_SETBARCOLOR, 0, RGB( red, green, blue ) );
395         }
396 #else // !PBM_SETBARCOLOR
397         void setColor( BYTE, BYTE, BYTE ) 
398         {
399         }
400 #endif // PBM_SETBARCOLOR
402         void setIcon( LPCTSTR icon )
403         {
404             SendMessage( _mainWindow, WM_SETICON, ICON_BIG, (LPARAM)loadStandardIcon( icon ) );
405         }
407         HICON loadStandardIcon( LPCTSTR icon )
408         {
409             return LoadIcon( (HINSTANCE)NULL, icon );
410         }
412         void setTestCaption( const char *suiteName, const char *testName )
413         {
414             setCaption( suiteName, "::", testName, "()" );
415         }
417         void setCaption( const char *a = "", const char *b = "", const char *c = "", const char *d = "" )
418         {
419             unsigned length = lstrlenA( _title ) + sizeof( " - " ) +
420                 lstrlenA( a ) + lstrlenA( b ) + lstrlenA( c ) + lstrlenA( d );
421             char *name = allocate( length );
422             lstrcpyA( name, _title );
423             lstrcatA( name, " - " );
424             lstrcatA( name, a );
425             lstrcatA( name, b );
426             lstrcatA( name, c );
427             lstrcatA( name, d );
428             SetWindowTextA( _mainWindow, name );
429             deallocate( name );
430         }
432         void showSuiteName( const char *suiteName )
433         {
434             setStatusPart( STATUS_SUITE_NAME, suiteName );
435         }
437         void showTestName( const char *testName )
438         {
439             setStatusPart( STATUS_TEST_NAME, testName );
440         }
442         void showTestsDone()
443         {
444             wsprintfA( _statusTestsDone, "%u of %s (%u%%)",
445                        _testsDone, _strTotalTests,
446                        (_testsDone * 100) / _numTotalTests );
447             setStatusPart( STATUS_TESTS_DONE, _statusTestsDone );
448         }
450         void updateTime()
451         {
452             setStatusTime( STATUS_WORLD_TIME, _worldStart );
453             setStatusTime( STATUS_SUITE_TIME, _suiteStart );
454             setStatusTime( STATUS_TEST_TIME, _testStart );
455         }
457         void setStatusTime( unsigned part, DWORD start )
458         {
459             unsigned total = (GetTickCount() - start) / 1000;
460             unsigned hours = total / 3600;
461             unsigned minutes = (total / 60) % 60;
462             unsigned seconds = total % 60;
464             if ( hours )
465                 wsprintfA( _timeString, "%u:%02u:%02u", hours, minutes, seconds );
466             else
467                 wsprintfA( _timeString, "%02u:%02u", minutes, seconds );
469             setStatusPart( part, _timeString );
470         }
472         bool keep()
473         {
474             if ( !_keep )
475                 return false;
476             if ( !_startMinimized )
477                 return true;
478             return (_mainWindow == GetForegroundWindow());
479         }
481         void showSummary()
482         {
483             stopTimer();
484             setSummaryStatusBar();
485             setSummaryCaption();
486         }
488         void setStatusPart( unsigned part, const char *text )
489         {
490             statusBarMessage( SB_SETTEXTA, part, text );
491         }
493         void stopTimer()
494         {
495             KillTimer( _mainWindow, TIMER_ID );
496             setStatusTime( STATUS_WORLD_TIME, _worldStart );
497         }
499         void setSummaryStatusBar()
500         {
501             setRatios( 0, 0, 0, 0, 1, 1 );
502             resizeControls();
503         
504             const char *tests = (_numTotalTests == 1) ? "test" : "tests";
505             if ( tracker().failedTests() )
506                 wsprintfA( _statusTestsDone, "Failed %u of %s %s",
507                           tracker().failedTests(), _strTotalTests, tests );
508             else
509                 wsprintfA( _statusTestsDone, "%s %s passed", _strTotalTests, tests );
511             setStatusPart( STATUS_TESTS_DONE, _statusTestsDone );
512         }
514         void setSummaryCaption()
515         {
516             setCaption( _statusTestsDone );
517         }
519         char *allocate( unsigned length )
520         {
521             return (char *)HeapAlloc( GetProcessHeap(), 0, length );
522         }
524         void deallocate( char *data )
525         {
526             HeapFree( GetProcessHeap(), 0, data );
527         }
528     };
529 };
531 #endif // __cxxtest__Win32Gui_h__