]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - tools/src/tools/configtool/standalone/wxwin/runtestsdlg.cpp
4764958d01f371c97c9d1dcbe2a02cdbb46d0978
[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         // FIXME: test output should not contain CR characters on non-Windows
529         // platforms so need to find the root of this problem
530 #ifndef __WXMSW__
531         wxString output(psz);
532         output.Replace(wxT("\r"), wxEmptyString); // remove CR characters
533         pWnd->OutputToBuffer(output);
534 #else
535         // FIXME ends
536         pWnd->OutputToBuffer(psz);
537 #endif
538     }
539 }
540
541 // Write to the output buffer for OnIdle to pick up
542 void ecRunTestsDialog::OutputToBuffer(const wxString& str)
543 {
544     wxCriticalSection ct;
545     ct.Enter();
546
547     if (m_outputBufferPresent)
548         m_outputBuffer += str;
549     else
550         m_outputBuffer = str;
551     m_outputBufferPresent = TRUE;
552
553     ct.Leave();
554 }
555
556 // Write any remaining text
557 void ecRunTestsDialog::FlushBuffer()
558 {
559     if (m_outputBufferPresent)
560     {
561         m_output->AddText(m_outputBuffer);
562         m_outputBuffer = wxEmptyString;
563         m_outputBufferPresent = FALSE;
564     }
565 }
566
567 #if 0
568 void ecRunTestsDialog::OnHelp(wxCommandEvent& event)
569 {
570     int sel = m_notebook->GetSelection();
571
572     wxASSERT_MSG( (sel != -1), wxT("A notebook tab should always be selected."));
573
574     wxWindow* page = (wxWindow*) m_notebook->GetPage(sel);
575
576     wxString helpTopic;
577     if (page == m_displayOptions)
578     {
579         helpTopic = wxT("Display options dialog");
580     }
581
582     if (!helpTopic.IsEmpty())
583     {
584         wxGetApp().GetHelpController().KeywordSearch(helpTopic);
585     }
586 }
587 #endif
588
589 // This sets the text for the selected page, but doesn't help
590 // when trying to click on a tab: we would expect the appropriate help
591 // for that tab. We would need to look at the tabs to do this, from within OnContextHelp -
592 // probably not worth it.
593 void ecRunTestsDialog::OnPageChange(wxNotebookEvent& event)
594 {
595     event.Skip();
596 #if 0
597     int sel = m_notebook->GetSelection();
598     if (sel < 0)
599         return;
600
601     wxWindow* page = m_notebook->GetPage(sel);
602     if (page)
603     {
604         wxString helpText;
605
606         if (page == m_displayOptions)
607             helpText = _("The display options dialog allows you to change display-related options.");
608         else if (page == m_viewerOptions)
609             helpText = _("The viewer options dialog allows you to configure viewers.");
610         else if (page == m_pathOptions)
611             helpText = _("The path options dialog allows you to change tool paths.");
612         else if (page == m_conflictResolutionOptions)
613             helpText = _("The conflict resolution options dialog allows you to change options related to conflict resolution.");
614         m_notebook->SetHelpText(helpText);
615     }
616 #endif
617 }
618
619 bool ecRunTestsDialog::TransferDataToWindow()
620 {
621     // In this case there is no data to be transferred
622     m_executables->TransferDataToWindow();
623     m_output->TransferDataToWindow();
624     m_summary->TransferDataToWindow();
625     return TRUE;
626 }
627
628 bool ecRunTestsDialog::TransferDataFromWindow()
629 {
630     // In this case there is no data to be transferred
631     m_executables->TransferDataFromWindow();
632     m_output->TransferDataFromWindow();
633     m_summary->TransferDataFromWindow();
634     return TRUE;
635 }
636
637 void ecRunTestsDialog::OnSize(wxSizeEvent& event)
638 {
639     event.Skip();
640
641     wxRefreshControls(this);
642 }
643
644 // Add the test to the dialog
645 void ecRunTestsDialog::Populate(const wxString& test, bool select)
646 {
647     wxCheckListBox* checkListBox = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
648
649     wxASSERT( checkListBox );
650
651     checkListBox->Append(test);
652     if (select)
653         checkListBox->Check(checkListBox->Number() - 1, TRUE);
654 }
655
656
657 /* Executables dialog
658  */
659
660 IMPLEMENT_CLASS(ecRunTestsExecutablesDialog, wxPanel)
661
662 BEGIN_EVENT_TABLE(ecRunTestsExecutablesDialog, wxPanel)
663     EVT_BUTTON(ecID_RUN_TESTS_CHECK_ALL, ecRunTestsExecutablesDialog::OnCheckAll)
664     EVT_BUTTON(ecID_RUN_TESTS_UNCHECK_ALL, ecRunTestsExecutablesDialog::OnUncheckAll)
665     EVT_BUTTON(ecID_RUN_TESTS_ADD, ecRunTestsExecutablesDialog::OnAdd)
666     EVT_BUTTON(ecID_RUN_TESTS_ADD_FOLDER, ecRunTestsExecutablesDialog::OnAddFromFolder)
667     EVT_BUTTON(ecID_RUN_TESTS_REMOVE, ecRunTestsExecutablesDialog::OnRemove)
668
669     EVT_UPDATE_UI(ecID_RUN_TESTS_CHECK_ALL, ecRunTestsExecutablesDialog::OnUpdateCheckAll)
670     EVT_UPDATE_UI(ecID_RUN_TESTS_UNCHECK_ALL, ecRunTestsExecutablesDialog::OnUpdateUncheckAll)
671
672 END_EVENT_TABLE()
673
674 ecRunTestsExecutablesDialog::ecRunTestsExecutablesDialog(wxWindow* parent):
675     wxPanel(parent, ecID_RUN_TESTS_EXECUTABLES)
676 {
677     CreateControls(this);    
678
679     SetHelpText(_("The executables dialog allows you to select tests to be run."));
680 }
681
682 void ecRunTestsExecutablesDialog::CreateControls( wxPanel *parent)
683 {
684     // Create the foreign control
685     wxCheckListBox* listBox = new wxCheckListBox(parent, ecID_RUN_TESTS_TEST_LIST, wxDefaultPosition, wxSize(100, 100),
686         0, NULL, wxSUNKEN_BORDER|wxLB_EXTENDED);
687
688     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
689
690     wxSizer *item1 = new wxBoxSizer( wxHORIZONTAL );
691
692     wxButton *item2 = new wxButton( parent, ecID_RUN_TESTS_CHECK_ALL, "C&heck All", wxDefaultPosition, wxDefaultSize, 0 );
693     item1->Add( item2, 0, wxALIGN_CENTRE|wxALL, 5 );
694
695     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
696
697     wxButton *item3 = new wxButton( parent, ecID_RUN_TESTS_UNCHECK_ALL, "&Uncheck All", wxDefaultPosition, wxDefaultSize, 0 );
698     item1->Add( item3, 0, wxALIGN_CENTRE|wxALL, 5 );
699
700     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
701
702     wxButton *item4 = new wxButton( parent, ecID_RUN_TESTS_ADD, "&Add...", wxDefaultPosition, wxDefaultSize, 0 );
703     item1->Add( item4, 0, wxALIGN_CENTRE|wxALL, 5 );
704
705     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
706
707     wxButton *item5 = new wxButton( parent, ecID_RUN_TESTS_ADD_FOLDER, "Add from &Folder...", wxDefaultPosition, wxDefaultSize, 0 );
708     item1->Add( item5, 0, wxALIGN_CENTRE|wxALL, 5 );
709
710     item1->Add( 2, 2, 1, wxALIGN_CENTRE|wxALL, 0 );
711
712     wxButton *item6 = new wxButton( parent, ecID_RUN_TESTS_REMOVE, "&Remove", wxDefaultPosition, wxDefaultSize, 0 );
713     item1->Add( item6, 0, wxALIGN_CENTRE|wxALL, 5 );
714
715     item0->Add( item1, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
716
717     wxWindow *item7 = parent->FindWindow( ecID_RUN_TESTS_TEST_LIST );
718     wxASSERT( item7 );
719     item0->Add( item7, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
720
721     // Add context-sensitive help
722     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."));
723     FindWindow(ecID_RUN_TESTS_CHECK_ALL)->SetHelpText(_("Selects all tests for execution."));
724     FindWindow(ecID_RUN_TESTS_UNCHECK_ALL)->SetHelpText(_("Clears the selection of tests."));
725     FindWindow(ecID_RUN_TESTS_ADD)->SetHelpText(_("Adds a test to the set that can be executed."));
726     FindWindow(ecID_RUN_TESTS_ADD_FOLDER)->SetHelpText(_("Adds one or more tests to the set that can be executed, from a folder."));
727     FindWindow(ecID_RUN_TESTS_REMOVE)->SetHelpText(_("Removes a test from the set that can executed."));
728
729     parent->SetAutoLayout( TRUE );
730     parent->SetSizer( item0 );
731 }
732
733 void ecRunTestsExecutablesDialog::OnCheckAll(wxCommandEvent& event)
734 {
735     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
736     if (!checkList)
737         return;
738
739     int i;
740     int n = checkList->Number();
741     for (i = 0; i < n; i++)
742         checkList->Check(i, TRUE);
743 }
744
745 void ecRunTestsExecutablesDialog::OnUncheckAll(wxCommandEvent& event)
746 {
747     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
748     if (!checkList)
749         return;
750
751     int i;
752     int n = checkList->Number();
753     for (i = 0; i < n; i++)
754         checkList->Check(i, FALSE);
755 }
756
757 void ecRunTestsExecutablesDialog::OnAdd(wxCommandEvent& event)
758 {
759     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
760     if (!checkList)
761         return;
762
763 //#ifdef __WXMSW__
764 //    wxString wildcard(wxT("Executables (*.exe)|*.exe"));
765 //#else
766     wxString wildcard(wxT("Executables (*)|*"));
767 //#endif
768
769     wxFileDialog dialog(this, _("Choose one or more executables to add"), wxGetCwd(), wxEmptyString,
770         wildcard, wxMULTIPLE|wxOPEN);
771
772     if (dialog.ShowModal() == wxID_OK)
773     {
774         wxArrayString paths;
775         dialog.GetPaths(paths);
776
777         bool err = FALSE;
778
779         unsigned int i;
780         int n = paths.Count();
781         for (i = 0; i < n; i++)
782         {
783             // TODO: check that it's the right kind of file
784             if (-1 == checkList->FindString(paths[i]))
785             {
786                 checkList->Append(paths[i]);
787                 checkList->Check(checkList->Number()-1, TRUE);
788             }
789             else
790                 err = TRUE;
791         }
792         if (err)
793             wxMessageBox(_("One or more of the files was already present"),
794                 wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK, this);
795     }
796 }
797
798 void ecRunTestsExecutablesDialog::OnAddFromFolder(wxCommandEvent& event)
799 {
800     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
801     if (!checkList)
802         return;
803
804     // In the MFC tool, a modified version of the folder dialog was used but
805     // we can't do that in general in wxWindows; so instead we ask the questions
806     // before we show the folder dialog.
807     // We won't bother allowing the user to change the extension: on Windows it's .exe,
808     // on Unix it's anything.
809 //#ifdef __WXMSW__
810 //    wxString filespec(wxT("*.exe"));
811 //#else
812     wxString filespec(wxT("*"));
813 //#endif
814
815     wxString msg;
816     msg.Printf(_("Would you like to add from subfolders, or just the folder you specify?\nChoose Yes to add from subfolders."));
817     int ans = wxMessageBox(msg, wxGetApp().GetSettings().GetAppName(), wxICON_QUESTION|wxYES_NO|wxCANCEL, this);
818     if (ans == wxCANCEL)
819         return;
820
821     bool recurse = (ans == wxYES);
822
823     wxDirDialog dialog(this, _("Choose a folder to add tests from"), wxGetCwd());
824     if (dialog.ShowModal() == wxID_OK)
825     {
826         wxString folder(dialog.GetPath());
827
828         if (!wxDirExists(folder))
829         {
830             wxMessageBox(_("Sorry, this folder does not exist."), wxGetApp().GetSettings().GetAppName(), wxICON_EXCLAMATION|wxOK, this);
831             return;
832         }
833
834         wxBusyCursor busy;
835         AddFromFolder(folder, recurse, filespec);
836     }
837 }
838
839 void ecRunTestsExecutablesDialog::AddFromFolder(const wxString& folder, bool recurse, const wxString& wildcard)
840 {
841     wxString filename;
842     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
843
844     {
845         wxDir dir;
846         if (!dir.Open(folder))
847             return;
848         
849         
850         bool success = dir.GetFirst(& filename, wildcard, wxDIR_FILES);
851         while (success)
852         {
853             wxString path = folder + wxString(wxFILE_SEP_PATH) + filename;
854             
855             if (-1 == checkList->FindString(path))
856             {
857                 checkList->Append(path);
858                 checkList->Check(checkList->Number()-1, TRUE);
859             }       
860             
861             success = dir.GetNext(& filename);
862         }
863     }
864     
865     // Recurse down the subfolders
866     if (recurse)
867     {
868         wxArrayString subfolders;
869
870         {
871             wxDir dir2;
872             if (!dir2.Open(folder))
873                 return;
874             
875             bool success = dir2.GetFirst(& filename, wxT("*"), wxDIR_DIRS);
876             while (success)
877             {
878                 wxString path = folder + wxString(wxFILE_SEP_PATH) + filename;
879                 subfolders.Add(path);            
880                 
881                 success = dir2.GetNext(& filename);
882             }
883         }
884
885         unsigned int i;
886         for (i = 0; i < subfolders.Count(); i ++)
887         {
888             AddFromFolder(subfolders[i], recurse, wildcard);
889         }
890     }
891 }
892
893 void ecRunTestsExecutablesDialog::OnRemove(wxCommandEvent& event)
894 {
895     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
896     if (!checkList)
897         return;
898
899     bool cont = FALSE;
900     do
901     {
902         // Delete the selections one at a time since
903         // the indexes change when you delete one
904
905         wxArrayInt ar;
906         if (checkList->GetSelections(ar) > 0)
907         {
908             checkList->Delete(ar[0]);
909             cont = TRUE;
910         }
911         else
912             cont = FALSE;
913
914     } while (cont);
915
916 }
917
918 void ecRunTestsExecutablesDialog::OnUpdateCheckAll(wxUpdateUIEvent& event)
919 {
920     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
921     if (!checkList)
922         return;
923
924     // If there were no unchecked items, we can disable the check all button
925     event.Enable( checkList->Number() != SelectedTestCount() );
926 }
927
928 void ecRunTestsExecutablesDialog::OnUpdateUncheckAll(wxUpdateUIEvent& event)
929 {
930     event.Enable( SelectedTestCount() > 0 );
931 }
932
933 int ecRunTestsExecutablesDialog::SelectedTestCount()
934 {
935     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
936     if (!checkList)
937         return 0;
938
939     int selCount = 0;
940     int i;
941     int n = checkList->Number();
942     for (i = 0; i < n; i++)
943     {
944         if (checkList->IsChecked(i))
945         {
946             selCount ++;
947         }
948     }
949     return selCount;
950 }
951
952 wxString ecRunTestsExecutablesDialog::SelectedTest(int nIndex)
953 {
954     wxString str;
955     wxCheckListBox* checkList = (wxCheckListBox*) FindWindow(ecID_RUN_TESTS_TEST_LIST);
956     if (!checkList)
957         return str;
958
959     int i;
960     for (i=0; i < checkList->Number(); i++)
961     {
962         if (checkList->IsChecked(i))
963         {
964             if(0==nIndex--)
965             {
966                 str = checkList->GetString(i);
967                 break;
968             }
969         }
970     }
971     return str;
972 }
973
974 /* Output dialog
975  */
976
977 IMPLEMENT_CLASS(ecRunTestsOutputDialog, wxPanel)
978
979 ecRunTestsOutputDialog::ecRunTestsOutputDialog(wxWindow* parent):
980     wxPanel(parent, ecID_RUN_TESTS_OUTPUT)
981 {
982     CreateControls(this);    
983
984     SetHelpText(_("The output dialog displays the run output."));
985 }
986
987 void ecRunTestsOutputDialog::CreateControls( wxPanel *parent)
988 {
989     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
990
991     wxTextCtrl *item1 = new wxTextCtrl( parent, ecID_RUN_TESTS_OUTPUT_TEXT, "", wxDefaultPosition, wxSize(80,40), wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH|wxCLIP_CHILDREN );
992     item0->Add( item1, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
993
994     // Add context-sensitive help
995     FindWindow(ecID_RUN_TESTS_OUTPUT_TEXT)->SetHelpText(_("Displays the output of test execution."));
996
997     parent->SetAutoLayout( TRUE );
998     parent->SetSizer( item0 );
999 }
1000
1001 void ecRunTestsOutputDialog::AddText(const wxString& msg)
1002 {
1003     wxTextCtrl* textCtrl = (wxTextCtrl*) FindWindow(ecID_RUN_TESTS_OUTPUT_TEXT);
1004     wxASSERT (textCtrl != NULL);
1005
1006     textCtrl->SetInsertionPointEnd();
1007     textCtrl->AppendText(msg);    
1008 }
1009
1010 void ecRunTestsOutputDialog::AddLogMsg(const wxString& msg)
1011 {
1012     wxString msg2(msg);
1013
1014     if ((msg == wxEmptyString) || (msg.Last() != wxT('\n')))
1015         msg2 += wxT("\n");
1016
1017     AddText(msg2);
1018 }
1019
1020 /* Summary dialog
1021  */
1022
1023 IMPLEMENT_CLASS(ecRunTestsSummaryDialog, wxPanel)
1024
1025 BEGIN_EVENT_TABLE(ecRunTestsSummaryDialog, wxPanel)
1026     EVT_LIST_COL_CLICK(ecID_RUN_TESTS_SUMMARY_LIST, ecRunTestsSummaryDialog::OnColClick)
1027 END_EVENT_TABLE()
1028
1029 wxListCtrl* ecRunTestsSummaryDialog::m_listCtrl = NULL;
1030
1031 ecRunTestsSummaryDialog::ecRunTestsSummaryDialog(wxWindow* parent):
1032     wxPanel(parent, ecID_RUN_TESTS_SUMMARY)
1033 {
1034     CreateControls(this);    
1035
1036     SetHelpText(_("The summary dialog shows a summary of the results of each run."));
1037 }
1038
1039 void ecRunTestsSummaryDialog::CreateControls( wxPanel *parent)
1040 {
1041     m_listCtrl = new wxListCtrl(parent, ecID_RUN_TESTS_SUMMARY_LIST, wxDefaultPosition, wxSize(100, 100), wxSUNKEN_BORDER|wxLC_REPORT);
1042     m_listCtrl->InsertColumn(0, "Time", wxLIST_FORMAT_LEFT, 60);
1043     m_listCtrl->InsertColumn(1, "Host", wxLIST_FORMAT_LEFT, 60);
1044     m_listCtrl->InsertColumn(2, "Platform", wxLIST_FORMAT_LEFT, 60);
1045     m_listCtrl->InsertColumn(3, "Executable", wxLIST_FORMAT_LEFT, 60);
1046     m_listCtrl->InsertColumn(4, "Status", wxLIST_FORMAT_LEFT, 60);
1047     m_listCtrl->InsertColumn(5, "Size", wxLIST_FORMAT_LEFT, 60);
1048     m_listCtrl->InsertColumn(6, "Download", wxLIST_FORMAT_LEFT, 60);
1049     m_listCtrl->InsertColumn(7, "Elapsed", wxLIST_FORMAT_LEFT, 60);
1050     m_listCtrl->InsertColumn(8, "Execution", wxLIST_FORMAT_LEFT, 60);
1051
1052     wxSizer *item0 = new wxBoxSizer( wxVERTICAL );
1053
1054     wxWindow *item1 = parent->FindWindow( ecID_RUN_TESTS_SUMMARY_LIST );
1055     wxASSERT( item1 );
1056     item0->Add( item1, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5 );
1057
1058     parent->SetAutoLayout( TRUE );
1059     parent->SetSizer( item0 );
1060
1061     // Add context-sensitive help
1062     FindWindow(ecID_RUN_TESTS_SUMMARY_LIST)->SetHelpText(_("Displays a summary of test execution."));
1063 }
1064
1065 void ecRunTestsSummaryDialog::AddResult (CeCosTest *pTest)
1066 {
1067     const wxString strResult(pTest->ResultString(FALSE));
1068     int nLength=strResult.Length();
1069     wxString arstr[8];
1070     wxString strTime,strDate;
1071     int i;
1072
1073     // 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 
1074     wxStringTokenizer tok(strResult, wxT(" "));
1075     strDate = tok.GetNextToken();
1076     strTime = tok.GetNextToken();
1077
1078     strDate += wxT(" ");
1079     strDate += strTime;
1080
1081     for (i = 0; i < 8; i++)
1082         arstr[i] = tok.GetNextToken();
1083
1084     // Remove characters before '=' in time fields
1085     for ( i = 5 ; i < 8 ; i ++ )
1086     {
1087         wxString str = arstr[i].AfterFirst(wxT('-')) ;
1088         arstr[i] = str.IsEmpty() ? arstr[i] : str;
1089     }
1090
1091     int nItem = m_listCtrl->GetItemCount() ;
1092     int nIndex = m_listCtrl->InsertItem (nItem, strDate);
1093     m_listCtrl->SetItemData(nItem,nItem);// to support sorting
1094     for (i = 0; i < 8; i++)
1095     {
1096         m_listCtrl->SetItem(nIndex, i+1, arstr[i]);
1097     }  
1098
1099 #if 0
1100     // OLD CODE
1101     int i;
1102     // TRACE(_T("%s\n"),strResult);
1103     // 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 
1104     _stscanf(strResult,_T("%s %s %s %s %s %s %s %s %s %s"),
1105         strDate.GetBuffer(1+nLength),
1106         strTime.GetBuffer(1+nLength),
1107         arstr[0].GetBuffer(1+nLength),
1108         arstr[1].GetBuffer(1+nLength),
1109         arstr[2].GetBuffer(1+nLength),
1110         arstr[3].GetBuffer(1+nLength),
1111         arstr[4].GetBuffer(1+nLength),
1112         arstr[5].GetBuffer(1+nLength),
1113         arstr[6].GetBuffer(1+nLength),
1114         arstr[7].GetBuffer(1+nLength));
1115
1116     // Remove before '=' in time fields
1117     for(i=5;i<8;i++){
1118         TCHAR *pch=_tcschr(arstr[i],_TCHAR('='));
1119         if(pch){
1120             arstr[i]=pch+1;
1121         }
1122     }
1123     
1124     strDate.ReleaseBuffer();
1125     strTime.ReleaseBuffer();
1126     strDate+=_TCHAR(' ');
1127     strDate+=strTime;
1128     int nItem=m_List.GetItemCount();
1129     m_List.InsertItem(nItem,strDate);
1130     m_List.SetItemData(nItem,nItem);// to support sorting
1131     for(i=0;i<8;i++){
1132         m_List.SetItemText(nItem,1+i,arstr[i]);
1133         arstr[i].ReleaseBuffer();
1134     }
1135 #endif
1136 }
1137
1138 // Sort function.
1139 // The function is passed the client data of the two items,
1140 // plus another general client data value which in this case
1141 // we use for the column index.
1142 int CALLBACK ecRunTestsSummaryDialog::SummarySortFunc(long data1, long data2, long col)
1143 {
1144     wxString str1 = wxListCtrlGetItemTextColumn(* m_listCtrl, data1, col);
1145     wxString str2 = wxListCtrlGetItemTextColumn(* m_listCtrl, data2, col);
1146
1147     int ret = str1.CmpNoCase(str2);
1148     return ret;
1149 }
1150
1151 void ecRunTestsSummaryDialog::OnColClick(wxListEvent& event)
1152 {
1153     m_listCtrl->SortItems((wxListCtrlCompare) SummarySortFunc,(long) event.m_col);
1154
1155     // The item data contains the index in the list control, so this needs
1156     // to be reset after sorting.
1157     int i;
1158     for (i = m_listCtrl->GetItemCount()-1;i>=0;--i)
1159     {
1160         m_listCtrl->SetItemData(i,i);
1161     }
1162 }