]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/testtool/win32/RunTestsSheet.cpp
Initial revision
[karo-tx-redboot.git] / tools / src / tools / testtool / win32 / RunTestsSheet.cpp
1 //####COPYRIGHTBEGIN####
2 //                                                                          
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
5 //
6 // This program is part of the eCos host tools.
7 //
8 // This program is free software; you can redistribute it and/or modify it 
9 // under the terms of the GNU General Public License as published by the Free 
10 // Software Foundation; either version 2 of the License, or (at your option) 
11 // any later version.
12 // 
13 // This program is distributed in the hope that it will be useful, but WITHOUT 
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
15 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for 
16 // more details.
17 // 
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc., 
20 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 //
22 // ----------------------------------------------------------------------------
23 //                                                                          
24 //####COPYRIGHTEND####
25 // RunTestsSheet.cpp : implementation file
26 //
27
28 #include "stdafx.h"
29
30 #include "eCosTest.h"
31 #include "eCosThreadUtils.h"
32 #include "eCosTrace.h"
33 #include "PropertiesDialog.h"
34 #include "ResetAttributes.h"
35 #include "RunTestsSheet.h"
36 #include "TestResource.h"
37 #include "X10.h"
38
39 #include <afxpriv.h>
40
41 static const UINT arIds []={IDOK,IDCANCEL,ID_APPLY_NOW,IDHELP};
42
43
44 #ifdef _DEBUG
45 #define new DEBUG_NEW
46 #undef THIS_FILE
47 static char THIS_FILE[] = __FILE__;
48 #endif
49
50
51 /////////////////////////////////////////////////////////////////////////////
52 // CRunTestsSheet
53
54 IMPLEMENT_DYNAMIC(CRunTestsSheet, CeCosPropertySheet)
55
56 CRunTestsSheet::CRunTestsSheet(LPCTSTR pszCaption, CWnd* pParentWnd, UINT iSelectPage, CBFunc pInitFunc, CRunTestsSheet **ppSheet)
57 :CeCosPropertySheet(pszCaption, pParentWnd, iSelectPage),
58   m_pResource(NULL),
59   m_pInitFunc(pInitFunc),
60   m_bAllowResizing(false),
61   m_cxMin(0),
62   m_cyMin(0),
63   m_Status(Stopped),
64   m_bHideTarget(false),
65   m_bHideRemoteControls(false),
66   m_bModal(false),
67   m_ppSheet(ppSheet),
68   m_ep(CeCosTest::ExecutionParameters::RUN),
69   m_nTimeout(900),
70   m_nDownloadTimeout(120),
71   m_nTimeoutType(TIMEOUT_AUTOMATIC),
72   m_nDownloadTimeoutType(TIMEOUT_SPECIFIED),
73   m_bRemote(false),
74   m_bSerial(true),
75   m_strPort(_T("COM1")),
76   m_nBaud(38400),
77   m_nLocalTCPIPPort(1),
78   m_nReset(RESET_MANUAL),
79   m_nResourcePort(1),
80   m_nRemotePort(1),
81   m_bFarmed(true)
82 {
83   InitializeCriticalSection(&m_CS);
84   AddPage(&executionpage);
85   AddPage(&outputpage);
86   AddPage(&summarypage);
87   
88 }
89
90 CRunTestsSheet::~CRunTestsSheet()
91 {
92   if(m_ppSheet){
93     *m_ppSheet=0;
94   }
95   delete m_pResource;
96   DeleteCriticalSection(&m_CS);
97 }
98
99
100 BEGIN_MESSAGE_MAP(CRunTestsSheet, CeCosPropertySheet)
101 //{{AFX_MSG_MAP(CRunTestsSheet)
102 ON_BN_CLICKED(IDOK, OnRun)
103 ON_BN_CLICKED(ID_APPLY_NOW, OnProperties)
104 ON_BN_CLICKED(IDCANCEL, OnClose)
105 ON_MESSAGE(WM_TESTOUTPUT, OnTestOutput)
106 ON_MESSAGE(WM_RUNCOMPLETE, OnTestsComplete)
107 ON_WM_SYSCOMMAND()
108 ON_WM_SIZE()
109 ON_WM_GETMINMAXINFO()
110 ON_WM_TIMER()
111 ON_MESSAGE(WM_KICKIDLE, OnKickIdle)
112 ON_WM_CREATE()
113 //}}AFX_MSG_MAP
114 END_MESSAGE_MAP()
115
116 /////////////////////////////////////////////////////////////////////////////
117 // CRunTestsSheet message handlers
118
119 BOOL CRunTestsSheet::OnInitDialog() 
120 {
121   if(!m_bHideTarget){
122     m_prop.Add(_T("Platform"),m_strTarget);
123   }
124   m_prop.Add(_T("Active timeout"),m_nTimeout);
125   m_prop.Add(_T("Download timeout"),m_nDownloadTimeout);
126   m_prop.Add(_T("Active timeout type"),m_nTimeoutType);
127   m_prop.Add(_T("Download timeout type"),m_nDownloadTimeoutType);
128   m_prop.Add(_T("Remote"),m_bRemote);
129   m_prop.Add(_T("Serial"),m_bSerial);
130   m_prop.Add(_T("Port"),m_strPort);
131   m_prop.Add(_T("Baud"),m_nBaud);
132   m_prop.Add(_T("Local TCPIP Host"),m_strLocalTCPIPHost);
133   m_prop.Add(_T("Local TCPIP Port"),m_nLocalTCPIPPort);
134   m_prop.Add(_T("Reset Type"),m_nReset);
135   m_prop.Add(_T("Reset String"),m_strReset);
136   m_prop.Add(_T("Resource Host"),m_strResourceHost);
137   m_prop.Add(_T("Resource Port"),m_nResourcePort);
138   m_prop.Add(_T("Remote Host"),m_strRemoteHost);
139   m_prop.Add(_T("Remote Port"),m_nRemotePort);
140   m_prop.Add(_T("Recurse"),executionpage.m_bRecurse);
141   //m_prop.Add(_T("Loadfromdir"),executionpage.m_strLoaddir);
142   m_prop.Add(_T("Farmed"),m_bFarmed);
143   m_prop.Add(_T("Extension"),executionpage.m_strExtension);
144   
145   CeCosTrace::SetOutput(TestOutputCallback,this);
146   CeCosTrace::SetError (TestOutputCallback,this);
147   
148   // m_psh can only be used to set the small icon.  Set the large one here.
149   m_psh.hIcon=AfxGetApp()->LoadIcon(IDR_TT_MAINFRAME);
150   //sheet.m_psh.dwFlags|=PSH_USEHICON/*|PSH_HASHELP*/;
151   if(m_psh.hIcon){
152     SetIcon(m_psh.hIcon,FALSE);
153     SetIcon(m_psh.hIcon,TRUE);
154   }
155   GetWindowRect(m_rcPrev);
156 #ifdef _DEBUG
157   CeCosTrace::EnableTracing(CeCosTrace::TRACE_LEVEL_TRACE);
158 #endif
159   CeCosTrace::SetInteractive(true);
160   
161   if(m_pInitFunc){
162     m_pInitFunc(&m_prop,false);
163   }
164   
165   GetDlgItem(IDCANCEL)->SetWindowText(_T("&Close"));
166   
167   m_nTestsToComplete=0;
168   BOOL bResult = CeCosPropertySheet::OnInitDialog();
169   SetDlgItemText(IDOK,_T("&Run"));
170   SetDlgItemText(ID_APPLY_NOW,_T("&Properties"));
171   GetDlgItem(ID_APPLY_NOW)->EnableWindow(TRUE);
172   GetDlgItem(IDCANCEL)->EnableWindow(TRUE); // required for modeless case
173   
174   SetActivePage(&outputpage);
175   SetActivePage(&summarypage);
176   SetActivePage(&executionpage);
177         
178   if(m_pInitFunc){
179     m_pInitFunc(&m_prop,false);
180     outputpage.UpdateData(FALSE);
181     summarypage.UpdateData(FALSE);
182     executionpage.UpdateData(FALSE);
183   }
184   /*
185   CString strCaption = _T("Output");
186   TC_ITEM tcItem;
187   tcItem.mask = TCIF_TEXT;
188   tcItem.pszText = (LPTSTR)((LPCTSTR)strCaption);
189   GetTabControl()->SetItem(2, &tcItem );
190   strCaption=_T("Summary");
191   GetTabControl()->SetItem(3, &tcItem );
192   */
193   // Allow resizing
194   
195   // WS_OVERLAPPEDWINDOW would preclude caption bar help button
196   ModifyStyle(0,WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME ,0);
197   
198   CRect rect;
199   GetWindowRect(rect);
200   m_rcPrev=rect;
201   
202   m_cxMin=rect.Width();
203   m_cyMin=rect.Height();
204   
205   m_bAllowResizing=true;
206   
207   WINDOWPLACEMENT wndpl;
208   if (5==_stscanf(m_strPlacement,_T("%d %d %d %d %d"),&rect.left,&rect.top,&rect.right,&rect.bottom,&wndpl.showCmd)){
209     CRect rcMax;
210     SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)(RECT *)rcMax, 0);
211     
212     if(rect.Width()<100 || rect.Height()<100 || rect.Width()>rcMax.Width() || rect.Height()>rcMax.Height()){
213       rect=CFrameWnd::rectDefault;
214     }
215     
216     wndpl.length = sizeof(WINDOWPLACEMENT);
217     wndpl.flags = 0;
218     
219     wndpl.ptMinPosition = CPoint(0, 0);
220     wndpl.ptMaxPosition =CPoint(-::GetSystemMetrics(SM_CXBORDER),-::GetSystemMetrics(SM_CYBORDER));
221     wndpl.rcNormalPosition = rect;
222     
223     // sets window's position and iconized/maximized status
224     SetWindowPlacement(&wndpl);
225   }
226   
227   // Hack: force an initial sizing (without which the tab control is badly sized)
228   m_rcOffset.left=m_rcOffset.right=m_rcOffset.top=0;
229   
230   m_rcOffset.bottom=m_bModal?50:-50;
231   MoveWindow(GetTabControl(),Stretch);
232   for(int i=0;i<GetPageCount();i++){
233     MoveWindow(GetPage(i),Stretch);
234   }
235 #ifdef _DEBUG
236     for(CWnd *p=GetWindow(GW_CHILD);p;p=p->GetWindow(GW_HWNDNEXT)){
237       TCHAR buf[256];
238       ::GetClassName(p->m_hWnd,buf,sizeof buf);
239       TRACE(_T("Window %x id=%d class=%s\n"),p,p->GetDlgCtrlID(),buf);
240     }
241 #endif
242   for(i=0;i<sizeof(arIds)/sizeof(arIds[0]);i++){
243     CWnd *pWnd=GetDlgItem(arIds[i]);
244     if(pWnd){
245       MoveWindow(pWnd,BottomRight);
246       pWnd->ShowWindow(SW_SHOW); // necessary in the modeless case
247     } else {
248       TRACE(_T("Failed to find window id=%x\n"),arIds[i]);
249     }
250   }
251
252   // hack to lay buttons out correctly in application case
253   if(this==AfxGetMainWnd()){
254     CRect rect1,rect2;
255     GetDlgItem(IDOK)->GetWindowRect(rect1);
256     GetDlgItem(IDCANCEL)->GetWindowRect(rect2);
257     CRect rect(rect1);
258     rect.left-=(rect2.left-rect1.left);
259     rect.right-=(rect2.right-rect1.right);
260     ScreenToClient(rect);
261     GetDlgItem(ID_APPLY_NOW)->MoveWindow(rect);
262     GetDlgItem(ID_APPLY_NOW)->ShowWindow(SW_SHOW);
263   }
264
265   if(!m_bModal){
266     SetTimer(0,100,0);
267   }
268   BringWindowToTop();
269   return bResult;
270 }
271
272 void CRunTestsSheet::OnRun()
273 {
274   
275   if(Running==m_Status){
276     outputpage.AddLogMsg(_T("Run canceled"));
277     m_Status=Stopping;
278     EnterCriticalSection(&m_CS);
279     m_nNextToSubmit=0x7fffffff;
280     LeaveCriticalSection(&m_CS);
281     CeCosTest::CancelAllInstances();  
282   } else {
283     outputpage.UpdateData(TRUE);
284     summarypage.UpdateData(TRUE);
285     executionpage.UpdateData(TRUE);
286     if(0==executionpage.SelectedTestCount()){
287       MessageBox(_T("No tests have selected for execution"));
288     } else {
289       m_ep=CeCosTest::ExecutionParameters(
290         CeCosTest::ExecutionParameters::RUN,
291         m_strTarget,
292         TIMEOUT_NONE==m_nTimeoutType?0x7fffffff:TIMEOUT_AUTOMATIC==m_nTimeoutType?900000:1000*m_nTimeout,
293         TIMEOUT_NONE==m_nDownloadTimeoutType?0x7fffffff:TIMEOUT_AUTOMATIC==m_nDownloadTimeoutType?0:1000*m_nDownloadTimeout);
294       if(m_bRemote){
295         CTestResource::SetResourceServer(CeCosSocket::HostPort(m_strResourceHost,m_nResourcePort));
296         if(!CTestResource::Load()){
297           MessageBox(_T("Could not connect to resource server"));
298           return;
299         }
300       } else {
301         const String strPort(m_bSerial?(LPCTSTR)m_strPort:CeCosSocket::HostPort(m_strLocalTCPIPHost,m_nLocalTCPIPPort));
302         if(0==strPort.size()){
303           m_pResource=new CTestResource(_T(""),m_ep.PlatformName());
304         } else {
305           int nBaud=m_bSerial?m_nBaud:0;
306           if (RESET_X10!=m_nReset) {
307             m_pResource=new CTestResource(_T(""),m_ep.PlatformName(),strPort,nBaud);
308           } else {
309             m_pResource=new CTestResource(_T(""),m_ep.PlatformName(),strPort,nBaud,m_strReset);
310           }
311         }
312       }
313       m_Status=Running;
314       SetDlgItemText(IDOK,_T("&Stop"));
315       m_nNextToSubmit=0;
316       outputpage.AddLogMsg(_T("Run started"));
317       SubmitTests();
318     }
319   }
320 }
321
322 struct Info {
323   CRunTestsSheet *pSheet;
324   CeCosTest      *pTest;
325 };
326
327 DWORD CRunTestsSheet::X10ThreadFunc (void *pParam)
328 {
329   Info *pInfo=(Info *)pParam;
330   String str;
331   bool bOk=false;
332   CResetAttributes::ResetResult n=pInfo->pSheet->m_pResource->Reset(str);
333   if(CResetAttributes::RESET_OK!=n){
334     str+=_T(">>> Could not reset target\n");
335   }
336   str+=_TCHAR('\n');
337   LPTSTR pszCopy=new TCHAR[1+str.size()];
338   _tcscpy(pszCopy,str);
339   pInfo->pSheet->PostMessage(WM_TESTOUTPUT,(WPARAM)pszCopy,0);
340   
341   if(bOk){
342     // we're already in a thread, so we can call the function directly
343     pInfo->pTest->RunLocal();
344   }
345   RunCallback(pInfo);
346   return 0;
347 }
348
349 void CALLBACK CRunTestsSheet::RunLocalFunc(void *pParam)
350 {
351   ((Info *)pParam)->pTest->RunLocal();
352 }
353
354 void CALLBACK CRunTestsSheet::RunRemoteFunc(void *pParam)
355 {
356   ((Info *)pParam)->pTest->RunRemote(NULL);
357 }
358
359 void CRunTestsSheet::SubmitTests()
360 {
361   int nResources=m_bRemote?max(1,CTestResource::GetMatchCount (m_ep)):1;
362   if(nResources>CeCosTest::InstanceCount){
363     if(m_nNextToSubmit>=executionpage.SelectedTestCount()){
364       return;
365     }
366     Info *pInfo=new Info;
367     pInfo->pTest=new CeCosTest(m_ep, executionpage.SelectedTest(m_nNextToSubmit++));
368     pInfo->pSheet=this;
369     m_nTestsToComplete++;
370     if(m_bRemote){
371       CeCosThreadUtils::RunThread(RunRemoteFunc,pInfo,RunCallback,_T("RunRemoteFunc"));
372     } else {
373       bool bRun=false;
374       switch((ResetType)m_nReset){
375         case RESET_NONE:
376           bRun=true;
377           break;
378         case RESET_X10:
379           // Resetting can take a while, so spawn a thread
380           bRun=false;
381           {
382             DWORD dwID;
383             CloseHandle(CreateThread(0,0,X10ThreadFunc, pInfo, 0, &dwID));
384           }
385           break;
386         case RESET_MANUAL:
387           bRun=(IDOK==MessageBox(_T("Press OK when target is reset - cancel to abort run"),NULL,MB_OKCANCEL));
388           if(!bRun){
389             m_nNextToSubmit=executionpage.SelectedTestCount();
390             RunCallback(pInfo);
391           }
392           break;
393       }
394       if(bRun){
395         CeCosThreadUtils::RunThread(RunLocalFunc,pInfo,RunCallback,_T("RunLocalFunc"));
396       }
397     }
398   }
399 }
400
401 void CRunTestsSheet::RunCallback(void *pParam)
402 {
403   Info *pInfo=(Info *)pParam;
404   CRunTestsSheet *pSheet=pInfo->pSheet;
405   if(::IsWindow(pSheet->m_hWnd)){ //FIXME
406     CeCosTest *pTest=pInfo->pTest;
407     EnterCriticalSection(&pSheet->m_CS);
408   
409     pSheet->summarypage.AddResult(pTest);
410     delete pTest;
411   
412     pSheet->m_nTestsToComplete--;
413     pSheet->SubmitTests();   
414   
415     if(0==pSheet->m_nTestsToComplete){
416       // It would be nice to do this in the handler for WM_RUNCOMPLETE, but we must be in the CS
417       delete pSheet->m_pResource;
418       pSheet->m_pResource=0;
419       pSheet->PostMessage(WM_RUNCOMPLETE,0,0);
420     }
421     LeaveCriticalSection(&pSheet->m_CS);
422   }
423   delete pInfo;
424 }
425
426 LRESULT CRunTestsSheet::OnTestsComplete(WPARAM wParam, LPARAM lParam)
427 {
428   UNUSED_ALWAYS(wParam);
429   UNUSED_ALWAYS(lParam);
430   m_Status=Stopped;
431   SetDlgItemText(IDOK,_T("&Run"));
432   outputpage.AddLogMsg(_T("Run complete"));
433   return 0;
434 }
435
436 void CALLBACK CRunTestsSheet::TestOutputCallback(void *pParam,LPCTSTR psz)
437 {
438   CRunTestsSheet*pWnd=(CRunTestsSheet*)pParam;
439   if(::IsWindow(pWnd->m_hWnd)){ //FIXME
440     LPTSTR pszCopy=new TCHAR[1+_tcslen(psz)];
441     _tcscpy(pszCopy,psz);
442     pWnd->PostMessage(WM_TESTOUTPUT,(WPARAM)pszCopy,0);
443   }
444 }
445
446 LRESULT CRunTestsSheet::OnTestOutput(WPARAM wParam, LPARAM lParam)
447 {
448   UNUSED_ALWAYS(lParam);
449   LPTSTR psz=(LPTSTR)wParam;
450   outputpage.AddText(psz);
451   delete [] psz;
452   return 0;
453 }
454
455 void CRunTestsSheet::OnProperties()
456 {
457   CPropertiesDialog dlg(m_bHideTarget,m_bHideRemoteControls);
458   dlg.m_strTarget=m_strTarget;
459   dlg.m_nTimeout=m_nTimeout;
460   dlg.m_nDownloadTimeout=m_nDownloadTimeout;
461   dlg.m_nTimeoutType=m_nTimeoutType;
462   dlg.m_nDownloadTimeoutType=m_nDownloadTimeoutType;
463   dlg.m_bRemote=m_bRemote;
464   dlg.m_bSerial=m_bSerial;
465   dlg.m_strPort=m_strPort;
466   dlg.m_nBaud=m_nBaud;
467   dlg.m_strLocalTCPIPHost=m_strLocalTCPIPHost;
468   dlg.m_nLocalTCPIPPort=m_nLocalTCPIPPort;
469   dlg.m_nReset=m_nReset;
470   dlg.m_strReset=m_strReset;
471   dlg.m_strResourceHost=m_strResourceHost;
472   dlg.m_nResourcePort=m_nResourcePort;
473   dlg.m_strRemoteHost=m_strRemoteHost;
474   dlg.m_nRemotePort=m_nRemotePort;
475   dlg.m_strPort=m_strPort;
476   dlg.m_bFarmed=m_bFarmed;
477   if(IDOK==dlg.DoModal()){
478     m_strTarget=(LPCTSTR)dlg.m_strTarget;
479     m_nTimeout=dlg.m_nTimeout;
480     m_nDownloadTimeout=dlg.m_nDownloadTimeout;
481     m_nTimeoutType=dlg.m_nTimeoutType;
482     m_nDownloadTimeoutType=dlg.m_nDownloadTimeoutType;
483     m_bRemote=dlg.m_bRemote;
484     m_bSerial=dlg.m_bSerial;
485     m_strPort=(LPCTSTR)dlg.m_strPort;
486     m_nBaud=dlg.m_nBaud;
487     m_strLocalTCPIPHost=(LPCTSTR)dlg.m_strLocalTCPIPHost;
488     m_nLocalTCPIPPort=dlg.m_nLocalTCPIPPort;
489     m_nReset=dlg.m_nReset;
490     m_strReset=(LPCTSTR)dlg.m_strReset;
491     m_strResourceHost=(LPCTSTR)dlg.m_strResourceHost;
492     m_nResourcePort=dlg.m_nResourcePort;
493     m_strRemoteHost=(LPCTSTR)dlg.m_strRemoteHost;
494     m_nRemotePort=dlg.m_nRemotePort;
495     m_bFarmed=dlg.m_bFarmed;
496     if(m_pInitFunc){
497       m_pInitFunc(&m_prop,true);
498     }
499   }
500 }
501
502 void CRunTestsSheet::OnClose()
503 {
504   if(m_pInitFunc){
505     WINDOWPLACEMENT wndpl;
506     wndpl.length = sizeof(WINDOWPLACEMENT);
507     GetWindowPlacement(&wndpl);
508     if(!IsWindowVisible()){
509                     wndpl.showCmd=SW_HIDE;
510     }
511     m_strPlacement.Format(_T("%d %d %d %d %d"),
512       wndpl.rcNormalPosition.left,
513       wndpl.rcNormalPosition.top,
514       wndpl.rcNormalPosition.right,
515       wndpl.rcNormalPosition.bottom,
516       wndpl.showCmd);
517     m_pInitFunc(&m_prop,true);
518   }
519   if(m_bModal){
520     EndDialog(IDOK);
521   } else {
522     DestroyWindow();
523   }
524 }
525
526
527
528 void CRunTestsSheet::OnSysCommand(UINT nID, LPARAM lParam) 
529 {
530   if(SC_CLOSE==nID){
531     OnClose();
532   } else {
533     CeCosPropertySheet::OnSysCommand(nID, lParam);
534   }
535 }
536
537 void CRunTestsSheet::OnSize(UINT nType, int cx, int cy) 
538 {
539   // WS_OVERLAPPEDWINDOW would preclude caption bar help button
540   ModifyStyle(0,WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME ,0);
541   CeCosPropertySheet::OnSize(nType, cx, cy);
542   if(SIZE_MINIMIZED!=nType){
543     CRect rect;
544     GetWindowRect(rect);
545     TRACE(_T("OnSize(%d) left=%d top=%d right=%d bottom=%d ar=%d\n"),nType,rect.left,rect.top,rect.right,rect.bottom,m_bAllowResizing);
546     
547     m_rcOffset.left  =rect.left-m_rcPrev.left;
548     m_rcOffset.right =rect.right-m_rcPrev.right;
549     m_rcOffset.top   =rect.top-m_rcPrev.top;
550     m_rcOffset.bottom=rect.bottom-m_rcPrev.bottom;
551     
552     m_rcPrev=rect;
553     
554     if(m_bAllowResizing){
555       cx=max(m_cxMin,cx); 
556       cy=max(m_cyMin,cy);
557       MoveWindow(GetTabControl(),Stretch);
558       CRect rc[sizeof(arIds)/sizeof(arIds[0])];
559       CRect rcSheet;
560       GetWindowRect(rcSheet);
561       for(int i=0;i<sizeof(arIds)/sizeof(arIds[0]);i++){
562         CWnd *pWnd=GetDlgItem(arIds[i]);
563         if(pWnd){
564           pWnd->GetWindowRect(rc[i]);
565           ScreenToClient(rc[i]);
566           MoveWindow(pWnd,BottomRight,FALSE);
567         }
568       }
569
570       for(i=0;i<sizeof(arIds)/sizeof(arIds[0]);i++){
571         CWnd *pWnd=GetDlgItem(arIds[i]);
572         if(pWnd){
573           pWnd->Invalidate();
574           InvalidateRect(rc[i]);
575         } else {
576           TRACE(_T("Failed to find window id=%x\n"),arIds[i]);
577         }
578       }
579       
580       for(i=0;i<GetPageCount();i++){
581         MoveWindow(GetPage(i),Stretch);
582       }
583       
584     }
585   }
586 }
587
588 void CRunTestsSheet::MoveWindow(CWnd *pWnd, AffinityType Affinity,bool bRepaint)
589 {
590   if(m_bAllowResizing&&pWnd){
591     TRACE(_T("MoveWindow left=%d top=%d right=%d bottom=%d\n"),m_rcOffset.left,m_rcOffset.top,m_rcOffset.right,m_rcOffset.bottom);
592     CRect rect;
593     pWnd->GetWindowRect(rect);
594     pWnd->GetParent()->ScreenToClient(rect);
595     TRACE(_T("           left=%d top=%d right=%d bottom=%d"),rect.left,rect.top,rect.right,rect.bottom);
596     int nHeight=rect.Height();
597     int nWidth=rect.Width();
598     
599     switch(Affinity){
600     case BottomRight:
601       rect.right +=m_rcOffset.Width();
602       rect.bottom+=m_rcOffset.Height();
603       rect.top =rect.bottom-nHeight;
604       rect.left=rect.right -nWidth;
605       break;
606     case TopRight:
607       rect.right +=m_rcOffset.Width();
608       rect.left=rect.right -nWidth;
609       break;
610     case BottomLeft:
611       rect.top +=m_rcOffset.Height();
612       rect.right=rect.left+nWidth;
613       break;
614     case TopLeft:
615       break;
616     case Stretch:
617       rect.right +=m_rcOffset.Width();
618       rect.bottom+=m_rcOffset.Height();
619       break;
620     }
621     TRACE(_T("        -> left=%d top=%d right=%d bottom=%d\n"),rect.left,rect.top,rect.right,rect.bottom);
622     pWnd->MoveWindow(rect,bRepaint);
623   }
624 }
625
626 void CRunTestsSheet::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) 
627 {
628   lpMMI->ptMinTrackSize.x = m_cxMin;
629   lpMMI->ptMinTrackSize.y = 175;
630   CeCosPropertySheet::OnGetMinMaxInfo(lpMMI);
631 }
632
633 LRESULT CRunTestsSheet::OnKickIdle(WPARAM, LPARAM)
634 {
635   // We could use WM_KICKIDLE to drive CMDUI messages, but in fact we just
636   // use an OnKickIdle handler directly (here and in the pages) to control
637   // button greying.
638   bool bEnableRunStop=false;
639   bool bEnableProperties=false;
640   switch(m_Status){
641   case Running:
642     bEnableRunStop=true;
643     break;
644   case Stopping:
645     bEnableProperties=true;
646     break;
647   case Stopped:
648     bEnableRunStop=executionpage.SomeTestsSelected();
649     bEnableProperties=true;
650     break;
651   }
652   GetDlgItem(IDOK)->EnableWindow(bEnableRunStop);
653   GetDlgItem(ID_APPLY_NOW)->EnableWindow(bEnableProperties);
654   SendMessageToDescendants(WM_KICKIDLE, 0, 0, FALSE, FALSE);
655   return 0;
656 }
657
658 BOOL CRunTestsSheet::PreTranslateMessage(MSG* pMsg) 
659 {
660   if(WM_KEYDOWN==pMsg->message && VK_ESCAPE==pMsg->wParam){
661     return TRUE;// escape character handled
662   }
663   return CeCosPropertySheet::PreTranslateMessage(pMsg);
664 }
665
666 void CRunTestsSheet::SetTarget(LPCTSTR pszTarget)
667 {
668   m_strTarget=pszTarget;
669   m_bHideTarget=true;
670 }
671
672 void CRunTestsSheet::HideRemoteControls()
673 {
674   m_bHideRemoteControls=true;
675 }
676
677 void CRunTestsSheet::Populate(LPCTSTR pszFile,bool bSelect/*=true*/)
678 {
679   executionpage.m_arstrPreLoad.SetAt(pszFile,bSelect?this:0);
680 }
681
682
683 int CRunTestsSheet::DoModal() 
684 {
685   m_bModal=true;
686   return CeCosPropertySheet::DoModal();
687 }
688
689 void CRunTestsSheet::PostNcDestroy() 
690 {
691   if(!m_bModal){
692     delete this;
693   } else {
694     CeCosPropertySheet::PostNcDestroy();
695   }
696 }
697
698 void CRunTestsSheet::OnTimer(UINT nIDEvent) 
699 {
700   SendMessage(WM_KICKIDLE,0,0); 
701   CeCosPropertySheet::OnTimer(nIDEvent);
702 }
703