unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / tools / src / tools / configtool / standalone / wxwin / runtestsdlg.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 // runtestsdlg.cpp :
26 //
27 //===========================================================================
28 //#####DESCRIPTIONBEGIN####
29 //
30 // Author(s):   julians
31 // Contact(s):  julians
32 // Date:        2000/09/29
33 // Version:     $Id$
34 // Purpose:
35 // Description: Implementation file for ecRunTestsDialog
36 // Requires:
37 // Provides:
38 // See also:
39 // Known bugs:
40 // Usage:
41 //
42 //####DESCRIPTIONEND####
43 //
44 //===========================================================================
45
46 #ifdef __GNUG__
47     #pragma implementation "runtestsdlg.cpp"
48 #endif
49
50 #include "ecpch.h"
51
52 #ifdef __BORLANDC__
53     #pragma hdrstop
54 #endif
55
56 #include "wx/notebook.h"
57 #include "wx/cshelp.h"
58 #include "wx/checklst.h"
59 #include "wx/listctrl.h"
60 #include "wx/tokenzr.h"
61
62 #include "TestResource.h"
63 #include "runtestsdlg.h"
64 #include "configtool.h"
65 #include "settingsdlg.h"
66 #include "eCosThreadUtils.h"
67 #include "eCosTrace.h"
68
69 void ecRunTestsTimer::Notify()
70 {
71     static bool s_inNotify = FALSE;
72
73     if (s_inNotify)
74         return;
75
76     s_inNotify = TRUE;
77
78     // On Windows, simply having the timer going will ping the message queue
79     // and cause idle processing to happen.
80     // On Unix, this doesn't happen so we have to do the processing explicitly.
81 #ifdef __WXMSW__
82     // Nothing to do
83 #else
84     if ( ecRunTestsDialog::m_runTestsDialog )
85     {
86         wxIdleEvent event;
87         ecRunTestsDialog::m_runTestsDialog->OnIdle(event);
88     }
89 #endif
90
91     s_inNotify = FALSE;
92 }
93
94 /*
95  * Run Tests dialog
96  */
97
98 IMPLEMENT_CLASS(ecRunTestsDialog, wxDialog)
99
100 BEGIN_EVENT_TABLE(ecRunTestsDialog, wxDialog)
101     EVT_BUTTON(wxID_OK, ecRunTestsDialog::OnOK)
102     EVT_BUTTON(ecID_RUN_TESTS_RUN, ecRunTestsDialog::OnRun)
103     EVT_BUTTON(ecID_RUN_TESTS_PROPERTIES, ecRunTestsDialog::OnProperties)
104     //EVT_BUTTON(wxID_HELP, ecRunTestsDialog::OnHelp)
105     EVT_NOTEBOOK_PAGE_CHANGED(-1, ecRunTestsDialog::OnPageChange)
106     EVT_SIZE(ecRunTestsDialog::OnSize)
107     EVT_IDLE(ecRunTestsDialog::OnIdle)
108     EVT_CLOSE(ecRunTestsDialog::OnCloseWindow)
109 END_EVENT_TABLE()
110
111 #define PROPERTY_DIALOG_WIDTH   600
112 #define PROPERTY_DIALOG_HEIGHT  550
113
114 ecRunTestsDialog* ecRunTestsDialog::m_runTestsDialog = NULL;
115
116 // For 400x400 settings dialog, size your panels to about 375x325 in dialog editor
117 // (209 x 162 dialog units)
118
119 ecRunTestsDialog::ecRunTestsDialog(wxWindow* parent):
120     wxDialog(),
121     m_runStatus(ecStopped),
122     m_nNextToSubmit(-1),
123     m_pResource(NULL),
124     m_testsAreComplete(FALSE)
125 {
126     m_runTestsDialog = this;
127
128     SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);
129
130     wxDialog::Create(parent, ecID_RUN_TESTS_DIALOG, _("Run Tests"), wxPoint(0, 0), wxSize(PROPERTY_DIALOG_WIDTH, PROPERTY_DIALOG_HEIGHT),
131         wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER);
132
133     // Under MSW, we don't seem to be able to react to a click on the dialog background (no
134     // event is generated).
135     SetHelpText(_("Run tests from this dialog."));
136
137     wxScreenDC dc;
138     wxSize ppi = dc.GetPPI();
139
140     //double scaleFactor = ((double) charH) / 13.0;
141     double scaleFactor = ((double) ppi.y) / 96.0;
142     // Fudge the scale factor to make the dialog slightly smaller,
143     // otherwise it's a bit big. (We're assuming that most displays
144     // are 96 or 120 ppi).
145     if (ppi.y == 120)
146         scaleFactor = 1.14;
147     int dialogWidth = (int)(PROPERTY_DIALOG_WIDTH * scaleFactor);
148     int dialogHeight = (int)(PROPERTY_DIALOG_HEIGHT * scaleFactor);
149     SetSize(dialogWidth, dialogHeight);
150         
151     m_notebook = new wxNotebook(this, ecID_RUN_TESTS_NOTEBOOK,
152          wxPoint(2, 2), wxSize(PROPERTY_DIALOG_WIDTH - 4, PROPERTY_DIALOG_HEIGHT - 4));
153
154     m_executables = new ecRunTestsExecutablesDialog(m_notebook);
155     m_notebook->AddPage(m_executables, wxT("Executables"));
156     m_executables->TransferDataToWindow();
157
158     m_output = new ecRunTestsOutputDialog(m_notebook);
159     m_notebook->AddPage(m_output, wxT("Output"));
160     m_output->TransferDataToWindow();
161
162     m_summary = new ecRunTestsSummaryDialog(m_notebook);
163     m_notebook->AddPage(m_summary, wxT("Summary"));
164     m_summary->TransferDataToWindow();
165
166     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
167
168     item0->Add( m_notebook, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxTOP, 5 );
169
170     wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
171
172     wxButton *runButton = new wxButton( this, ecID_RUN_TESTS_RUN, "&Run", wxDefaultPosition, wxDefaultSize, 0 );
173     item1->Add( runButton, 0, wxALIGN_CENTRE|wxALL, 5 );
174
175     wxButton *okButton = new wxButton( this, wxID_OK, "&Close", wxDefaultPosition, wxDefaultSize, 0 );
176     item1->Add( okButton, 0, wxALIGN_CENTRE|wxALL, 5 );
177
178     wxButton *propertiesButton = new wxButton( this, ecID_RUN_TESTS_PROPERTIES, "&Properties...", wxDefaultPosition, wxDefaultSize, 0 );
179     item1->Add( propertiesButton, 0, wxALIGN_CENTRE|wxALL, 5 );
180
181 /*
182     wxButton *helpButton = new wxButton( this, wxID_HELP, "&Help", wxDefaultPosition, wxDefaultSize, 0 );
183     item1->Add( helpButton, 0, wxALIGN_CENTRE|wxALL, 5 );
184 */
185
186 #ifdef __WXGTK__
187     // Context-sensitive help button (question mark)
188     wxButton *contextButton = new wxContextHelpButton( this );
189     item1->Add( contextButton, 0, wxALIGN_CENTRE|wxALL, 5 );
190 #endif
191
192     // Necessary to add a spacer or the button highlight interferes with the notebook under wxGTK
193     item0->Add( 4, 4, 0, wxALIGN_CENTRE|wxALL, 0 );
194
195     item0->Add( item1, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 0 );
196
197     this->SetAutoLayout( TRUE );
198     this->SetSizer( item0 );
199
200     okButton->SetDefault();
201     okButton->SetFocus();
202
203     Layout();
204
205     m_executables->Layout();
206     m_output->Layout();
207     m_summary->Layout();
208
209     okButton->SetHelpText(_("Closes the dialog."));
210     runButton->SetHelpText(_("Runs one or more tests selected in the Executables window."));
211     propertiesButton->SetHelpText(_("Shows timeout and connection properties."));
212     //helpButton->SetHelpText(_("Invokes help for the selected dialog."));
213
214     Centre(wxBOTH);
215
216     // TODO: Is this necessary?
217 #if 0
218     m_prop.Add(_T("Active timeout"),        wxGetApp().GetSettings().GetRunTestsSettings().m_nTimeout);
219     m_prop.Add(_T("Download timeout"),      wxGetApp().GetSettings().GetRunTestsSettings().m_nDownloadTimeout);
220     m_prop.Add(_T("Active timeout type"),   wxGetApp().GetSettings().GetRunTestsSettings().m_nTimeoutType);
221     m_prop.Add(_T("Download timeout type"), wxGetApp().GetSettings().GetRunTestsSettings().m_nDownloadTimeoutType);
222     m_prop.Add(_T("Remote"),                wxGetApp().GetSettings().GetRunTestsSettings().m_bRemote);
223     m_prop.Add(_T("Serial"),                wxGetApp().GetSettings().GetRunTestsSettings().m_bSerial);
224     m_prop.Add(_T("Port"),                  wxGetApp().GetSettings().GetRunTestsSettings().m_strPort);
225     m_prop.Add(_T("Baud"),                  wxGetApp().GetSettings().GetRunTestsSettings().m_nBaud);
226     m_prop.Add(_T("Local TCPIP Host"),      wxGetApp().GetSettings().GetRunTestsSettings().m_strLocalTCPIPHost);
227     m_prop.Add(_T("Local TCPIP Port"),      wxGetApp().GetSettings().GetRunTestsSettings().m_nLocalTCPIPPort);
228     m_prop.Add(_T("Reset Type"),            wxGetApp().GetSettings().GetRunTestsSettings().m_nReset);
229     m_prop.Add(_T("Reset String"),          wxGetApp().GetSettings().GetRunTestsSettings().m_strReset);
230     m_prop.Add(_T("Resource Host"),         wxGetApp().GetSettings().GetRunTestsSettings().m_strResourceHost);
231     m_prop.Add(_T("Resource Port"),         wxGetApp().GetSettings().GetRunTestsSettings().m_nResourcePort);
232     m_prop.Add(_T("Remote Host"),           wxGetApp().GetSettings().GetRunTestsSettings().m_strRemoteHost);
233     m_prop.Add(_T("Remote Port"),           wxGetApp().GetSettings().GetRunTestsSettings().m_nRemotePort);
234     // TODO
235     //m_prop.Add(_T("Recurse"),   executionpage.m_bRecurse);
236     m_prop.Add(_T("Farmed"),                wxGetApp().GetSettings().GetRunTestsSettings().m_bFarmed);
237     // TODO
238     // m_prop.Add(_T("Extension"),executionpage.m_strExtension);
239 #endif
240
241 #ifdef _DEBUG
242     CeCosTrace::EnableTracing(CeCosTrace::TRACE_LEVEL_TRACE);
243 #endif
244     CeCosTrace::SetInteractive(TRUE);
245     CeCosTrace::SetOutput(TestOutputCallback, this);
246     CeCosTrace::SetError (TestOutputCallback, this);
247
248     m_timer.Start(200);
249 }
250
251 ecRunTestsDialog::~ecRunTestsDialog()
252 {
253     m_timer.Stop();
254     CeCosTrace::SetInteractive(FALSE);
255     m_runTestsDialog = NULL;
256     if (m_pResource)
257     {
258         delete m_pResource;
259     }
260 }
261
262 void ecRunTestsDialog::OnOK(wxCommandEvent& event)
263 {
264     if (ecRunning == m_runStatus)
265     {
266         wxMessageBox(_("Tests are running. Please press Stop before quitting this dialog."),
267             wxGetApp().GetSettings().GetAppName(), wxICON_INFORMATION|wxOK, this);
268         return;
269     }
270
271     wxDialog::OnOK(event);
272 }
273
274 void ecRunTestsDialog::OnCloseWindow(wxCloseEvent& event)
275 {
276     if (ecRunning == m_runStatus)
277     {
278         wxMessageBox(_("Tests are running. Please press Stop before quitting this dialog."),
279             wxGetApp().GetSettings().GetAppName(), wxICON_INFORMATION|wxOK, this);
280         event.Veto();
281         return;
282     }
283
284     this->EndModal(wxID_CANCEL);
285     this->Destroy();
286 }
287
288 void ecRunTestsDialog::OnProperties(wxCommandEvent& event)
289 {
290     ecSettingsDialog dialog(this);
291     dialog.SetSelection(3);
292     dialog.ShowModal();
293 }
294
295 void ecRunTestsDialog::OnRun(wxCommandEvent& event)
296 {  
297     if (ecRunning == m_runStatus)
298     {
299         m_output->AddLogMsg(_("Run cancelled"));
300         m_runStatus = ecStopping;
301         m_CS.Enter();
302         m_nNextToSubmit=0x7fffffff;
303         m_CS.Leave();
304         CeCosTest::CancelAllInstances();  
305     }
306     else
307     {
308         if ( 0 == m_executables->SelectedTestCount())
309         {
310             wxMessageBox(_("No tests have been selected for execution."),
311                 wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK, this);
312             return ;
313         }
314         else
315         {
316             m_ep = CeCosTest::ExecutionParameters(
317                 CeCosTest::ExecutionParameters::RUN,
318                 wxGetApp().GetSettings().GetRunTestsSettings().m_strTarget,
319                 TIMEOUT_NONE==wxGetApp().GetSettings().GetRunTestsSettings().m_nTimeoutType?0x7fffffff:TIMEOUT_AUTOMATIC==wxGetApp().GetSettings().GetRunTestsSettings().m_nTimeoutType?900000:1000*wxGetApp().GetSettings().GetRunTestsSettings().m_nTimeout,
320                 TIMEOUT_NONE==wxGetApp().GetSettings().GetRunTestsSettings().m_nDownloadTimeoutType?0x7fffffff:TIMEOUT_AUTOMATIC==wxGetApp().GetSettings().GetRunTestsSettings().m_nDownloadTimeoutType?0:1000*wxGetApp().GetSettings().GetRunTestsSettings().m_nDownloadTimeout);
321             
322             if ( wxGetApp().GetSettings().GetRunTestsSettings().m_bRemote )
323             {
324                 CTestResource::SetResourceServer(CeCosSocket::HostPort(wxGetApp().GetSettings().GetRunTestsSettings().m_strResourceHost, wxGetApp().GetSettings().GetRunTestsSettings().m_nResourcePort));
325                 if (!CTestResource::Load())
326                 {
327                     wxMessageBox(_("Could not connect to resource server."),
328                         wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK, this);
329                     return;
330                 }
331             }
332             else
333             {
334                 wxString strPort;
335                 if (wxGetApp().GetSettings().GetRunTestsSettings().m_bSerial)
336                     strPort = wxGetApp().GetSettings().GetRunTestsSettings().m_strPort;
337                 else
338                     strPort = (const wxChar*) CeCosSocket::HostPort(wxGetApp().GetSettings().GetRunTestsSettings().m_strLocalTCPIPHost,wxGetApp().GetSettings().GetRunTestsSettings().m_nLocalTCPIPPort);
339                 if(0==strPort.Length()){
340                     m_pResource=new CTestResource(_T(""),m_ep.PlatformName());
341                 } else
342                 {
343                     // Translate from e.g. COM2 to /dev/ttyS1 on Unix.
344                     // Let's assume the Windows notation is the 'standard'.
345                     strPort = TranslatePort(strPort);
346                     int nBaud = wxGetApp().GetSettings().GetRunTestsSettings().m_bSerial ? wxGetApp().GetSettings().GetRunTestsSettings().m_nBaud:0;
347                     if (RESET_X10 != wxGetApp().GetSettings().GetRunTestsSettings().m_nReset) {
348                         m_pResource=new CTestResource(_T(""),m_ep.PlatformName(), strPort, nBaud);
349                     } else {
350                         m_pResource=new CTestResource(_T(""),m_ep.PlatformName(), strPort, nBaud, wxGetApp().GetSettings().GetRunTestsSettings().m_strReset);
351                     }
352                 }
353             }
354             m_runStatus = ecRunning;
355             m_testsAreComplete = FALSE;
356             
357             wxButton* runButton = (wxButton*) FindWindow(ecID_RUN_TESTS_RUN);
358             runButton->SetLabel(_("&Stop"));
359             
360             m_nNextToSubmit=0;
361             m_output->AddLogMsg(_("Run started"));
362
363             SubmitTests();
364         }
365     }
366 }
367
368 wxString ecRunTestsDialog::TranslatePort(const wxString& port) const
369 {
370 #ifdef __WXGTK__
371     wxString name(port.Left(3));
372     if (name.CmpNoCase(wxT("COM")) == 0)
373     {
374         wxString strNum(port.Mid(3));
375         if (strNum.IsEmpty())
376             return port;
377         int num = atoi(strNum);
378         wxString newPort;
379         newPort.Printf(wxT("/dev/ttyS%d"), num-1);
380         return newPort;
381     }
382     else
383 #endif
384         return port;
385 }
386
387 void ecRunTestsDialog::SubmitTests()
388 {
389     int iTest;
390     int nResources=wxGetApp().GetSettings().GetRunTestsSettings().m_bRemote ? wxMax(1,CTestResource::GetMatchCount (m_ep)):1;
391     if(nResources>CeCosTest::InstanceCount){
392         if (m_nNextToSubmit >= m_executables->SelectedTestCount()){
393             m_runStatus = ecStopped;
394
395             wxButton* runButton = (wxButton*) FindWindow(ecID_RUN_TESTS_RUN);
396             runButton->SetLabel(_("&Run"));
397             m_output->AddLogMsg(_("Run complete"));
398
399             delete m_pResource;
400             m_pResource=0;
401             return;
402         }
403         ecRunTestsInfo *pInfo=new ecRunTestsInfo;
404         pInfo->pTest=new CeCosTest(m_ep, m_executables->SelectedTest(m_nNextToSubmit++));
405         pInfo->pSheet=this;
406         if(wxGetApp().GetSettings().GetRunTestsSettings().m_bRemote){
407             CeCosThreadUtils::RunThread(RunRemoteFunc,pInfo, (CeCosThreadUtils::CallbackProc*) RunCallback,_T("RunRemoteFunc"));
408         } else {
409             bool bRun=false;
410             switch((ResetType)wxGetApp().GetSettings().GetRunTestsSettings().m_nReset){
411             case RESET_NONE:
412                 bRun=true;
413                 break;
414             case RESET_X10:
415                 {
416                     // Resetting can take a while, so spawn a thread
417                     bRun=false;
418                     ecResetThread* thread = new ecResetThread(pInfo);
419                     if (thread->Create() != wxTHREAD_NO_ERROR)
420                     {
421                         // Thread will be deleted automatically when it has finished running
422                         thread->Run();
423                     }
424                     else
425                         delete thread;
426
427                     break;
428                 }
429             case RESET_MANUAL:
430                 {
431                     bRun=(wxOK == wxMessageBox(_("Press OK when target is reset - cancel to abort run"),_("Reset board"), wxOK|wxCANCEL));
432                     if(!bRun)
433                     {
434                         m_nNextToSubmit = m_executables->SelectedTestCount();
435                         RunCallback(pInfo);
436                     }
437                     break;
438                 }
439             }
440             if(bRun){
441                 if (1 < m_nNextToSubmit)
442                       m_output->AddLogMsg(_("Run continuing"));
443                 CeCosThreadUtils::RunThread(RunLocalFunc, pInfo, (CeCosThreadUtils::CallbackProc*) RunCallback,_T("RunLocalFunc"));
444             }
445         }
446     }
447 }
448
449 // thread execution starts here
450 void *ecResetThread::Entry()
451 {
452     wxString str;
453     String str1;
454     bool bOk=false;
455     CResetAttributes::ResetResult n=m_info->pSheet->m_pResource->Reset(str1);
456     str = str1;
457     if(CResetAttributes::RESET_OK!=n){
458         str += wxT(">>> Could not reset target\n");
459     }
460     str += wxT('\n');
461
462     m_info->pSheet->OutputToBuffer(str);
463
464     if(bOk){
465         // we're already in a thread, so we can call the function directly
466         m_info->pTest->RunLocal();
467     }
468     ecRunTestsDialog::RunCallback(m_info);
469
470     return NULL;
471 }
472
473 // called when the thread exits - whether it terminates normally or is
474 // stopped with Delete() (but not when it is Kill()ed!)
475 void ecResetThread::OnExit()
476 {
477 }
478
479 void CALLBACK ecRunTestsDialog::RunLocalFunc(void *pParam)
480 {
481   ((ecRunTestsInfo *)pParam)->pTest->RunLocal();
482 }
483
484 void CALLBACK ecRunTestsDialog::RunRemoteFunc(void *pParam)
485 {
486   ((ecRunTestsInfo *)pParam)->pTest->RunRemote(NULL);
487 }
488
489 void ecRunTestsDialog::RunCallback(void *pParam)
490 {
491     ecRunTestsInfo *pInfo=(ecRunTestsInfo *)pParam;
492     ecRunTestsDialog *pSheet=pInfo->pSheet;
493     if (m_runTestsDialog) // Will be NULL if dialog has been closed & deleted
494     {
495         CeCosTest *pTest=pInfo->pTest;
496
497         pInfo->pSheet->m_CS.Enter();
498
499         pSheet->m_summary->AddResult(pTest);
500         delete pTest;
501
502         // OnIdle will check this variable and reset the status and button label
503         pSheet->m_testsAreComplete = TRUE;
504
505         pInfo->pSheet->m_CS.Leave();
506     }
507     delete pInfo;
508 }
509
510 void ecRunTestsDialog::OnIdle(wxIdleEvent& event)
511 {
512     FlushBuffer();
513
514     if (m_testsAreComplete)
515     {
516         m_testsAreComplete = FALSE;
517         SubmitTests();
518     }
519
520     event.Skip();
521 }
522
523 void CALLBACK ecRunTestsDialog::TestOutputCallback(void *pParam,LPCTSTR psz)
524 {
525     ecRunTestsDialog* pWnd = (ecRunTestsDialog*)pParam;
526     if (ecRunTestsDialog::m_runTestsDialog)
527     {
528         pWnd->OutputToBuffer(psz);
529     }
530 }
531
532 // Write to the output buffer for OnIdle to pick up
533 void ecRunTestsDialog::OutputToBuffer(const wxString& str)
534 {
535     wxCriticalSection ct;
536     ct.Enter();
537
538     if (m_outputBufferPresent)
539         m_outputBuffer += str;
540     else
541         m_outputBuffer = str;
542     m_outputBufferPresent = TRUE;
543
544     ct.Leave();
545 }
546
547 // Write any remaining text
548 void ecRunTestsDialog::FlushBuffer()
549 {
550     if (m_outputBufferPresent)
551     {
552         m_output->AddText(m_outputBuffer);
553         m_outputBuffer = wxEmptyString;
554         m_outputBufferPresent = FALSE;
555     }
556 }
557
558 #if 0
559 void ecRunTestsDialog::OnHelp(wxCommandEvent& event)
560 {
561     int sel = m_notebook->GetSelection();
562
563     wxASSERT_MSG( (sel != -1), wxT("A notebook tab should always be selected."));
564
565     wxWindow* page = (wxWindow*) m_notebook->GetPage(sel);
566
567     wxString helpTopic;
568     if (page == m_displayOptions)
569     {
570         helpTopic = wxT("Display options dialog");
571     }
572
573     if (!helpTopic.IsEmpty())
574     {
575         wxGetApp().GetHelpController().KeywordSearch(helpTopic);
576     }
577 }
578 #endif
579
580 // This sets the text for the selected page, but doesn't help
581 // when trying to click on a tab: we would expect the appropriate help
582 // for that tab. We would need to look at the tabs to do this, from within OnContextHelp -
583 // probably not worth it.
584 void ecRunTestsDialog::OnPageChange(wxNotebookEvent& event)
585 {
586     event.Skip();
587 #if 0
588     int sel = m_notebook->GetSelection();
589     if (sel < 0)
590         return;
591
592     wxWindow* page = m_notebook->GetPage(sel);
593     if (page)
594     {
595         wxString helpText;
596
597         if (page == m_displayOptions)
598             helpText = _("The display options dialog allows you to change display-related options.");
599         else if (page == m_viewerOptions)
600             helpText = _("The viewer options dialog allows you to configure viewers.");
601         else if (page == m_pathOptions)
602             helpText = _("The path options dialog allows you to change tool paths.");
603         else if (page == m_conflictResolutionOptions)
604             helpText = _("The conflict resolution options dialog allows you to change options related to conflict resolution.");
605         m_notebook->SetHelpText(helpText);
606     }
607 #endif
608 }
609
610 bool ecRunTestsDialog::TransferDataToWindow()
611 {
612     // In this case there is no data to be transferred
613     m_executables->TransferDataToWindow();
614     m_output->TransferDataToWindow();
615     m_summary->TransferDataToWindow();
616     return TRUE;
617 }
618
619 bool ecRunTestsDialog::TransferDataFromWindow()
620 {
621     // In this case there is no data to be transferred
622     m_executables->TransferDataFromWindow();
623     m_output->TransferDataFromWindow();
624     m_summary->TransferDataFromWindow();
625     return TRUE;
626 }
627
628 void ecRunTestsDialog::OnSize(wxSizeEvent& event)
629 {
630     event.Skip();
631
632     wxRefreshControls(this);
633 }
634
635 // Add the test to the dialog
636 void ecRunTestsDialog::Populate(const wxString& test, bool select)
637 {
638     wxCheckListBox* checkListBox = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
639
640     wxASSERT( checkListBox );
641
642     checkListBox->Append(test);
643     if (select)
644         checkListBox->Check(checkListBox->Number() - 1, TRUE);
645 }
646
647
648 /* Executables dialog
649  */
650
651 IMPLEMENT_CLASS(ecRunTestsExecutablesDialog, wxPanel)
652
653 BEGIN_EVENT_TABLE(ecRunTestsExecutablesDialog, wxPanel)
654     EVT_BUTTON(ecID_RUN_TESTS_CHECK_ALL, ecRunTestsExecutablesDialog::OnCheckAll)
655     EVT_BUTTON(ecID_RUN_TESTS_UNCHECK_ALL, ecRunTestsExecutablesDialog::OnUncheckAll)
656     EVT_BUTTON(ecID_RUN_TESTS_ADD, ecRunTestsExecutablesDialog::OnAdd)
657     EVT_BUTTON(ecID_RUN_TESTS_ADD_FOLDER, ecRunTestsExecutablesDialog::OnAddFromFolder)
658     EVT_BUTTON(ecID_RUN_TESTS_REMOVE, ecRunTestsExecutablesDialog::OnRemove)
659
660     EVT_UPDATE_UI(ecID_RUN_TESTS_CHECK_ALL, ecRunTestsExecutablesDialog::OnUpdateCheckAll)
661     EVT_UPDATE_UI(ecID_RUN_TESTS_UNCHECK_ALL, ecRunTestsExecutablesDialog::OnUpdateUncheckAll)
662
663 END_EVENT_TABLE()
664
665 ecRunTestsExecutablesDialog::ecRunTestsExecutablesDialog(wxWindow* parent):
666     wxPanel(parent, ecID_RUN_TESTS_EXECUTABLES)
667 {
668     CreateControls(this);    
669
670     SetHelpText(_("The executables dialog allows you to select tests to be run."));
671 }
672
673 void ecRunTestsExecutablesDialog::CreateControls( wxPanel *parent)
674 {
675     // Create the foreign control
676     wxCheckListBox* listBox = new wxCheckListBox(parent, ecID_RUN_TESTS_TEST_LIST, wxDefaultPosition, wxSize(100, 100),
677         0, NULL, wxSUNKEN_BORDER|wxLB_EXTENDED);
678
679     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
680
681     wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
682
683     wxButton *item2 = new wxButton( parent, ecID_RUN_TESTS_CHECK_ALL, "C&heck All", wxDefaultPosition, wxDefaultSize, 0 );
684     item1->Add( item2, 0, wxALIGN_CENTRE|wxALL, 5 );
685
686     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
687
688     wxButton *item3 = new wxButton( parent, ecID_RUN_TESTS_UNCHECK_ALL, "&Uncheck All", wxDefaultPosition, wxDefaultSize, 0 );
689     item1->Add( item3, 0, wxALIGN_CENTRE|wxALL, 5 );
690
691     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
692
693     wxButton *item4 = new wxButton( parent, ecID_RUN_TESTS_ADD, "&Add...", wxDefaultPosition, wxDefaultSize, 0 );
694     item1->Add( item4, 0, wxALIGN_CENTRE|wxALL, 5 );
695
696     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
697
698     wxButton *item5 = new wxButton( parent, ecID_RUN_TESTS_ADD_FOLDER, "Add from &Folder...", wxDefaultPosition, wxDefaultSize, 0 );
699     item1->Add( item5, 0, wxALIGN_CENTRE|wxALL, 5 );
700
701     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
702
703     wxButton *item6 = new wxButton( parent, ecID_RUN_TESTS_REMOVE, "&Remove", wxDefaultPosition, wxDefaultSize, 0 );
704     item1->Add( item6, 0, wxALIGN_CENTRE|wxALL, 5 );
705
706     item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
707
708     wxWindow *item7 = parent->FindWindow( ecID_RUN_TESTS_TEST_LIST );
709     wxASSERT( item7 );
710     item0->Add( item7, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
711
712     // Add context-sensitive help
713     FindWindow(ecID_RUN_TESTS_TEST_LIST)->SetHelpText(_("Displays the set of tests that can be executed. Each test can be selected for execution by checking the adjacent box."));
714     FindWindow(ecID_RUN_TESTS_CHECK_ALL)->SetHelpText(_("Selects all tests for execution."));
715     FindWindow(ecID_RUN_TESTS_UNCHECK_ALL)->SetHelpText(_("Clears the selection of tests."));
716     FindWindow(ecID_RUN_TESTS_ADD)->SetHelpText(_("Adds a test to the set that can be executed."));
717     FindWindow(ecID_RUN_TESTS_ADD_FOLDER)->SetHelpText(_("Adds one or more tests to the set that can be executed, from a folder."));
718     FindWindow(ecID_RUN_TESTS_REMOVE)->SetHelpText(_("Removes a test from the set that can executed."));
719
720     parent->SetAutoLayout( TRUE );
721     parent->SetSizer( item0 );
722 }
723
724 void ecRunTestsExecutablesDialog::OnCheckAll(wxCommandEvent& event)
725 {
726     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
727     if (!checkList)
728         return;
729
730     int i;
731     int n = checkList->Number();
732     for (i = 0; i < n; i++)
733         checkList->Check(i, TRUE);
734 }
735
736 void ecRunTestsExecutablesDialog::OnUncheckAll(wxCommandEvent& event)
737 {
738     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
739     if (!checkList)
740         return;
741
742     int i;
743     int n = checkList->Number();
744     for (i = 0; i < n; i++)
745         checkList->Check(i, FALSE);
746 }
747
748 void ecRunTestsExecutablesDialog::OnAdd(wxCommandEvent& event)
749 {
750     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
751     if (!checkList)
752         return;
753
754 //#ifdef __WXMSW__
755 //    wxString wildcard(wxT("Executables (*.exe)|*.exe"));
756 //#else
757     wxString wildcard(wxT("Executables (*)|*"));
758 //#endif
759
760     wxFileDialog dialog(this, _("Choose one or more executables to add"), wxGetCwd(), wxEmptyString,
761         wildcard, wxMULTIPLE|wxOPEN);
762
763     if (dialog.ShowModal() == wxID_OK)
764     {
765         wxArrayString paths;
766         dialog.GetPaths(paths);
767
768         bool err = FALSE;
769
770         unsigned int i;
771         int n = paths.Count();
772         for (i = 0; i < n; i++)
773         {
774             // TODO: check that it's the right kind of file
775             if (-1 == checkList->FindString(paths[i]))
776             {
777                 checkList->Append(paths[i]);
778                 checkList->Check(checkList->Number()-1, TRUE);
779             }
780             else
781                 err = TRUE;
782         }
783         if (err)
784             wxMessageBox(_("One or more of the files was already present"),
785                 wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK, this);
786     }
787 }
788
789 void ecRunTestsExecutablesDialog::OnAddFromFolder(wxCommandEvent& event)
790 {
791     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
792     if (!checkList)
793         return;
794
795     // In the MFC tool, a modified version of the folder dialog was used but
796     // we can't do that in general in wxWindows; so instead we ask the questions
797     // before we show the folder dialog.
798     // We won't bother allowing the user to change the extension: on Windows it's .exe,
799     // on Unix it's anything.
800 //#ifdef __WXMSW__
801 //    wxString filespec(wxT("*.exe"));
802 //#else
803     wxString filespec(wxT("*"));
804 //#endif
805
806     wxString msg;
807     msg.Printf(_("Would you like to add from subfolders, or just the folder you specify?\nChoose Yes to add from subfolders."));
808     int ans = wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO|wxCANCEL, this);
809     if (ans == wxCANCEL)
810         return;
811
812     bool recurse = (ans == wxYES);
813
814     wxDirDialog dialog(this, _("Choose a folder to add tests from"), wxGetCwd());
815     if (dialog.ShowModal() == wxID_OK)
816     {
817         wxString folder(dialog.GetPath());
818
819         if (!wxDirExists(folder))
820         {
821             wxMessageBox(_("Sorry, this folder does not exist."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK, this);
822             return;
823         }
824
825         wxBusyCursor busy;
826         AddFromFolder(folder, recurse, filespec);
827     }
828 }
829
830 void ecRunTestsExecutablesDialog::AddFromFolder(const wxString& folder, bool recurse, const wxString& wildcard)
831 {
832     wxString filename;
833     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
834
835     {
836         wxDir dir;
837         if (!dir.Open(folder))
838             return;
839         
840         
841         bool success = dir.GetFirst(& filename, wildcard, wxDIR_FILES);
842         while (success)
843         {
844             wxString path = folder + wxString(wxFILE_SEP_PATH) + filename;
845             
846             if (-1 == checkList->FindString(path))
847             {
848                 checkList->Append(path);
849                 checkList->Check(checkList->Number()-1, TRUE);
850             }       
851             
852             success = dir.GetNext(& filename);
853         }
854     }
855     
856     // Recurse down the subfolders
857     if (recurse)
858     {
859         wxArrayString subfolders;
860
861         {
862             wxDir dir2;
863             if (!dir2.Open(folder))
864                 return;
865             
866             bool success = dir2.GetFirst(& filename, wxT("*"), wxDIR_DIRS);
867             while (success)
868             {
869                 wxString path = folder + wxString(wxFILE_SEP_PATH) + filename;
870                 subfolders.Add(path);            
871                 
872                 success = dir2.GetNext(& filename);
873             }
874         }
875
876         unsigned int i;
877         for (i = 0; i < subfolders.Count(); i ++)
878         {
879             AddFromFolder(subfolders[i], recurse, wildcard);
880         }
881     }
882 }
883
884 void ecRunTestsExecutablesDialog::OnRemove(wxCommandEvent& event)
885 {
886     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
887     if (!checkList)
888         return;
889
890     bool cont = FALSE;
891     do
892     {
893         // Delete the selections one at a time since
894         // the indexes change when you delete one
895
896         wxArrayInt ar;
897         if (checkList->GetSelections(ar) > 0)
898         {
899             checkList->Delete(ar[0]);
900             cont = TRUE;
901         }
902         else
903             cont = FALSE;
904
905     } while (cont);
906
907 }
908
909 void ecRunTestsExecutablesDialog::OnUpdateCheckAll(wxUpdateUIEvent& event)
910 {
911     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
912     if (!checkList)
913         return;
914
915     // If there were no unchecked items, we can disable the check all button
916     event.Enable( checkList->Number() != SelectedTestCount() );
917 }
918
919 void ecRunTestsExecutablesDialog::OnUpdateUncheckAll(wxUpdateUIEvent& event)
920 {
921     event.Enable( SelectedTestCount() > 0 );
922 }
923
924 int ecRunTestsExecutablesDialog::SelectedTestCount()
925 {
926     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
927     if (!checkList)
928         return 0;
929
930     int selCount = 0;
931     int i;
932     int n = checkList->Number();
933     for (i = 0; i < n; i++)
934     {
935         if (checkList->IsChecked(i))
936         {
937             selCount ++;
938         }
939     }
940     return selCount;
941 }
942
943 wxString ecRunTestsExecutablesDialog::SelectedTest(int nIndex)
944 {
945     wxString str;
946     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
947     if (!checkList)
948         return str;
949
950     int i;
951     for (i=0; i < checkList->Number(); i++)
952     {
953         if (checkList->IsChecked(i))
954         {
955             if(0==nIndex--)
956             {
957                 str = checkList->GetString(i);
958                 break;
959             }
960         }
961     }
962     return str;
963 }
964
965 /* Output dialog
966  */
967
968 IMPLEMENT_CLASS(ecRunTestsOutputDialog, wxPanel)
969
970 ecRunTestsOutputDialog::ecRunTestsOutputDialog(wxWindow* parent):
971     wxPanel(parent, ecID_RUN_TESTS_OUTPUT)
972 {
973     CreateControls(this);    
974
975     SetHelpText(_("The output dialog displays the run output."));
976 }
977
978 void ecRunTestsOutputDialog::CreateControls( wxPanel *parent)
979 {
980     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
981
982     wxTextCtrl *item1 = new wxTextCtrl( parent, ecID_RUN_TESTS_OUTPUT_TEXT, "", wxDefaultPosition, wxSize(80,40), wxTE_MULTILINE );
983     item0->Add( item1, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
984
985     // Add context-sensitive help
986     FindWindow(ecID_RUN_TESTS_OUTPUT_TEXT)->SetHelpText(_("Displays the output of test execution."));
987
988     parent->SetAutoLayout( TRUE );
989     parent->SetSizer( item0 );
990 }
991
992 void ecRunTestsOutputDialog::AddText(const wxString& msg)
993 {
994     wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow(ecID_RUN_TESTS_OUTPUT_TEXT);
995     wxASSERT (textCtrl != NULL);
996
997     textCtrl->SetInsertionPointEnd();
998     textCtrl->AppendText(msg);    
999 }
1000
1001 void ecRunTestsOutputDialog::AddLogMsg(const wxString& msg)
1002 {
1003     wxString msg2(msg);
1004
1005     if ((msg == wxEmptyString) || (msg.Last() != wxT('\n')))
1006         msg2 += wxT("\n");
1007
1008     AddText(msg2);
1009 }
1010
1011 /* Summary dialog
1012  */
1013
1014 IMPLEMENT_CLASS(ecRunTestsSummaryDialog, wxPanel)
1015
1016 BEGIN_EVENT_TABLE(ecRunTestsSummaryDialog, wxPanel)
1017     EVT_LIST_COL_CLICK(ecID_RUN_TESTS_SUMMARY_LIST, ecRunTestsSummaryDialog::OnColClick)
1018 END_EVENT_TABLE()
1019
1020 wxListCtrl* ecRunTestsSummaryDialog::m_listCtrl = NULL;
1021
1022 ecRunTestsSummaryDialog::ecRunTestsSummaryDialog(wxWindow* parent):
1023     wxPanel(parent, ecID_RUN_TESTS_SUMMARY)
1024 {
1025     CreateControls(this);    
1026
1027     SetHelpText(_("The summary dialog shows a summary of the results of each run."));
1028 }
1029
1030 void ecRunTestsSummaryDialog::CreateControls( wxPanel *parent)
1031 {
1032     m_listCtrl = new wxListCtrl(parent, ecID_RUN_TESTS_SUMMARY_LIST, wxDefaultPosition, wxSize(100, 100), wxSUNKEN_BORDER|wxLC_REPORT);
1033     m_listCtrl->InsertColumn(0, "Time", wxLIST_FORMAT_LEFT, 60);
1034     m_listCtrl->InsertColumn(1, "Host", wxLIST_FORMAT_LEFT, 60);
1035     m_listCtrl->InsertColumn(2, "Platform", wxLIST_FORMAT_LEFT, 60);
1036     m_listCtrl->InsertColumn(3, "Executable", wxLIST_FORMAT_LEFT, 60);
1037     m_listCtrl->InsertColumn(4, "Status", wxLIST_FORMAT_LEFT, 60);
1038     m_listCtrl->InsertColumn(5, "Size", wxLIST_FORMAT_LEFT, 60);
1039     m_listCtrl->InsertColumn(6, "Download", wxLIST_FORMAT_LEFT, 60);
1040     m_listCtrl->InsertColumn(7, "Elapsed", wxLIST_FORMAT_LEFT, 60);
1041     m_listCtrl->InsertColumn(8, "Execution", wxLIST_FORMAT_LEFT, 60);
1042
1043     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
1044
1045     wxWindow *item1 = parent->FindWindow( ecID_RUN_TESTS_SUMMARY_LIST );
1046     wxASSERT( item1 );
1047     item0->Add( item1, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1048
1049     parent->SetAutoLayout( TRUE );
1050     parent->SetSizer( item0 );
1051
1052     // Add context-sensitive help
1053     FindWindow(ecID_RUN_TESTS_SUMMARY_LIST)->SetHelpText(_("Displays a summary of test execution."));
1054 }
1055
1056 void ecRunTestsSummaryDialog::AddResult (CeCosTest *pTest)
1057 {
1058     const wxString strResult(pTest->ResultString(FALSE));
1059     int nLength=strResult.Length();
1060     wxString arstr[8];
1061     wxString strTime,strDate;
1062     int i;
1063
1064     // 1999-05-28 10:29:28 nan:0 TX39-jmr3904-sim tx39-jmr3904sim-libc10-signal2.exe Fail 0k/1108k D=0.0/0.0 Total=9.3 E=0.6/300.0 
1065     wxStringTokenizer tok(strResult, wxT(" "));
1066     strDate = tok.GetNextToken();
1067     strTime = tok.GetNextToken();
1068
1069     strDate += wxT(" ");
1070     strDate += strTime;
1071
1072     for (i = 0; i < 8; i++)
1073         arstr[i] = tok.GetNextToken();
1074
1075     // Remove characters before '=' in time fields
1076     for ( i = 5 ; i < 8 ; i ++ )
1077     {
1078         wxString str = arstr[i].AfterFirst(wxT('-')) ;
1079         arstr[i] = str.IsEmpty() ? arstr[i] : str;
1080     }
1081
1082     int nItem = m_listCtrl->GetItemCount() ;
1083     int nIndex = m_listCtrl->InsertItem (nItem, strDate);
1084     m_listCtrl->SetItemData(nItem,nItem);// to support sorting
1085     for (i = 0; i < 8; i++)
1086     {
1087         m_listCtrl->SetItem(nIndex, i+1, arstr[i]);
1088     }  
1089
1090 #if 0
1091     // OLD CODE
1092     int i;
1093     // TRACE(_T("%s\n"),strResult);
1094     // 1999-05-28 10:29:28 nan:0 TX39-jmr3904-sim tx39-jmr3904sim-libc10-signal2.exe Fail 0k/1108k D=0.0/0.0 Total=9.3 E=0.6/300.0 
1095     _stscanf(strResult,_T("%s %s %s %s %s %s %s %s %s %s"),
1096         strDate.GetBuffer(1+nLength),
1097         strTime.GetBuffer(1+nLength),
1098         arstr[0].GetBuffer(1+nLength),
1099         arstr[1].GetBuffer(1+nLength),
1100         arstr[2].GetBuffer(1+nLength),
1101         arstr[3].GetBuffer(1+nLength),
1102         arstr[4].GetBuffer(1+nLength),
1103         arstr[5].GetBuffer(1+nLength),
1104         arstr[6].GetBuffer(1+nLength),
1105         arstr[7].GetBuffer(1+nLength));
1106
1107     // Remove before '=' in time fields
1108     for(i=5;i<8;i++){
1109         TCHAR *pch=_tcschr(arstr[i],_TCHAR('='));
1110         if(pch){
1111             arstr[i]=pch+1;
1112         }
1113     }
1114     
1115     strDate.ReleaseBuffer();
1116     strTime.ReleaseBuffer();
1117     strDate+=_TCHAR(' ');
1118     strDate+=strTime;
1119     int nItem=m_List.GetItemCount();
1120     m_List.InsertItem(nItem,strDate);
1121     m_List.SetItemData(nItem,nItem);// to support sorting
1122     for(i=0;i<8;i++){
1123         m_List.SetItemText(nItem,1+i,arstr[i]);
1124         arstr[i].ReleaseBuffer();
1125     }
1126 #endif
1127 }
1128
1129 // Sort function.
1130 // The function is passed the client data of the two items,
1131 // plus another general client data value which in this case
1132 // we use for the column index.
1133 int CALLBACK ecRunTestsSummaryDialog::SummarySortFunc(long data1, long data2, long col)
1134 {
1135     wxString str1 = wxListCtrlGetItemTextColumn(* m_listCtrl, data1, col);
1136     wxString str2 = wxListCtrlGetItemTextColumn(* m_listCtrl, data2, col);
1137
1138     int ret = str1.CmpNoCase(str2);
1139     return ret;
1140 }
1141
1142 void ecRunTestsSummaryDialog::OnColClick(wxListEvent& event)
1143 {
1144     m_listCtrl->SortItems((wxListCtrlCompare) SummarySortFunc,(long) event.m_col);
1145
1146     // The item data contains the index in the list control, so this needs
1147     // to be reset after sorting.
1148     int i;
1149     for (i = m_listCtrl->GetItemCount()-1;i>=0;--i)
1150     {
1151         m_listCtrl->SetItemData(i,i);
1152     }
1153 }