r427: Changes for MDI support
[ctsim.git] / src / ctsim.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   Name:          ctsim.cpp
5 **   Purpose:       Top-level routines of CTSim program
6 **   Programmer:    Kevin Rosenberg
7 **   Date Started:  July 2000
8 **
9 **  This is part of the CTSim program
10 **  Copyright (C) 1983-2000 Kevin Rosenberg
11 **
12 **  $Id: ctsim.cpp,v 1.39 2001/01/20 08:10:33 kevin Exp $
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28 #ifdef MSVC
29 #define strdup _strdup
30 #endif
31
32 // For compilers that support precompilation, includes "wx/wx.h".
33 #include "wx/wxprec.h"
34
35 #ifdef __BORLANDC__
36 #pragma hdrstop
37 #endif
38
39 #ifndef WX_PRECOMP
40 #include "wx/wx.h"
41 #endif
42
43 #include "wx/image.h"
44 #include "wx/filesys.h"
45 #include "wx/fs_zip.h"
46
47 #if !wxUSE_DOC_VIEW_ARCHITECTURE
48 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
49 #endif
50
51
52 #include "ct.h"
53 #include "ctsim.h"
54 #include "ctsim-map.h"
55 #include "docs.h"
56 #include "views.h"
57 #include "dialogs.h"
58
59 #if defined(HAVE_CONFIG_H)
60 #include "config.h"
61 #endif
62
63 #if defined(HAVE_GETOPT_H) || defined(HAVE_GETOPT_LONG)
64 #ifdef MSVC
65 #define __STDC__ 1
66 #endif
67 #include "getopt.h"
68 #ifdef MSVC
69 #undef __STDC__
70 #endif
71 #endif
72
73 static const char* rcsindent = "$Id: ctsim.cpp,v 1.39 2001/01/20 08:10:33 kevin Exp $";
74
75 struct option CTSimApp::ctsimOptions[] = 
76 {
77   {"help", 0, 0, O_HELP},
78   {"version", 0, 0, O_VERSION},
79   {0, 0, 0, 0}
80 };
81
82 IMPLEMENT_APP(CTSimApp)
83
84 CTSimApp::CTSimApp()
85 : m_docManager(NULL), m_pFrame(NULL)
86 {
87   theApp = this;
88 }
89
90 #ifdef HAVE_SYS_TIME_H
91 #include <sys/time.h>
92 #endif
93
94 #ifdef HAVE_SYS_RESOURCE_H
95 #include <sys/resource.h>
96 #endif
97
98 bool
99 CTSimApp::OnInit()
100 {
101 #ifdef HAVE_SETPRIORITY
102   setpriority (PRIO_PROCESS, 0, 15);  // set to low scheduling priority
103 #endif
104   
105   g_bRunningWXWindows = true;
106   // process options
107   while (1) {
108     int c = getopt_long (argc, argv, "", ctsimOptions, NULL);
109     if (c == -1)
110       break;
111     
112     switch (c) {
113     case O_VERSION:
114       std::cout << rcsindent << std::endl;
115 #ifdef CTSIMVERSION
116       std::cout << "Version: CTSIMVERSION" << std::endl;
117 #elif defined(VERSION)
118       std::cout << "Version: VERSION" << std::endl;
119 #endif
120       exit(0);
121     case O_HELP:
122     case '?':
123       usage (argv[0]);
124       exit (0);
125     default:
126       usage (argv[0]);
127       exit (1);
128     }
129   }
130   
131   m_docManager = new wxDocManager (wxDEFAULT_DOCMAN_FLAGS, true);
132   
133   new wxDocTemplate (m_docManager, "ImageFile", "*.if", "", "if", "ImageFile doc", "ImageFile View", CLASSINFO(ImageFileDocument), CLASSINFO(ImageFileView));
134   new wxDocTemplate (m_docManager, "ProjectionFile", "*.pj", "", "pj", "ProjectionFile doc", "ProjectionFile View", CLASSINFO(ProjectionFileDocument), CLASSINFO(ProjectionFileView));
135   new wxDocTemplate (m_docManager, "PhantomFile", "*.phm", "", "phm", "Phantom doc", "Phantom View", CLASSINFO(PhantomDocument), CLASSINFO(PhantomView));
136   new wxDocTemplate (m_docManager, "PlotFile", "*.plt", "", "plt", "Plot doc", "Plot View", CLASSINFO(PlotFileDocument), CLASSINFO(PlotFileView));
137   
138 #if wxUSE_GIF
139   wxImage::AddHandler(new wxGIFHandler);     // Required for images in the online documentation
140 #endif
141   
142 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
143   wxFileSystem::AddHandler(new wxZipFSHandler);     // Required for advanced HTML help
144 #endif
145   
146   // Create the main frame window
147   m_pFrame = new MainFrame(m_docManager, (wxFrame *) NULL, -1, "CTSim", wxPoint(0, 0), wxSize(500, 400), wxDEFAULT_FRAME_STYLE);
148   
149   SetTopWindow (m_pFrame);
150   m_pFrame->Centre(wxBOTH);
151   
152   m_pFrame->Show(true);
153   
154   for (int i = optind + 1; i <= argc; i++) {
155     wxString filename = argv [i - 1];
156     m_docManager->CreateDocument (filename, wxDOC_SILENT);
157   }
158   
159   setIconForFrame (m_pFrame);
160   
161 #ifdef CTSIM_WINHELP
162   if (! m_pFrame->getWinHelpController().Initialize("ctsim"))
163     ::wxMessageBox ("Cannot initialize the help system", "Error");
164 #endif
165   if (! m_pFrame->getHtmlHelpController().Initialize(::wxGetCwd() + "/ctsim"))
166     ::wxMessageBox ("Cannot initialize the help system", "Error");
167   
168   return true;
169 }
170
171
172 #include "./ctsim.xpm"
173 void
174 CTSimApp::setIconForFrame(wxFrame* pFrame)
175 {
176   wxIcon iconApp (ctsim16_xpm);
177   
178   if (iconApp.Ok())
179     pFrame->SetIcon (iconApp);
180 }
181
182 void
183 CTSimApp::usage(const char* program)
184 {
185   std::cout << "usage: " << fileBasename(program) << " [files-to-open...] [OPTIONS]\n";
186   std::cout << "Computed Tomography Simulator (Graphical Shell)\n";
187   std::cout << "\n";
188   std::cout << "  --version Display version\n";
189   std::cout << "  --help    Display this help message\n";
190 }
191
192 int
193 CTSimApp::OnExit()
194 {
195   delete m_docManager;
196 #ifdef HAVE_DMALLOC
197   dmalloc_shutdown();
198 #endif
199   return 0;
200 }
201
202 wxString
203 CTSimApp::getUntitledFilename()
204 {
205   static int untitledNumber = 1;
206   
207   wxString filename ("Untitled");
208   filename << untitledNumber++;
209   
210   return (filename);
211 }
212
213
214 // Top-level window for CTSim
215
216 #if CTSIM_MDI
217 IMPLEMENT_CLASS(MainFrame, wxMDIParentFrame)
218
219 BEGIN_EVENT_TABLE(MainFrame, wxMDIParentFrame)
220 #else
221 IMPLEMENT_CLASS(MainFrame, wxDocParentFrame)
222
223 BEGIN_EVENT_TABLE(MainFrame, wxDocParentFrame)
224 #endif
225
226 EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout)
227 EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents)
228 EVT_MENU(MAINMENU_HELP_TOPICS, MainFrame::OnHelpTopics)
229 EVT_SIZE(MainFrame::OnSize)
230
231 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
232 EVT_MENU(MAINMENU_HELP_SECONDARY, MainFrame::OnHelpSecondary)
233 #endif
234 EVT_MENU(MAINMENU_FILE_CREATE_PHANTOM, MainFrame::OnCreatePhantom)
235 EVT_MENU(MAINMENU_FILE_CREATE_FILTER, MainFrame::OnCreateFilter)
236 EVT_MENU(MAINMENU_FILE_EXIT, MainFrame::OnExit)
237 EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MainFrame::OnMRUFile)
238 EVT_MENU(MAINMENU_WINDOW_BASE, MainFrame::OnWindowMenu0)
239 EVT_MENU(MAINMENU_WINDOW_BASE+1, MainFrame::OnWindowMenu1)
240 EVT_MENU(MAINMENU_WINDOW_BASE+2, MainFrame::OnWindowMenu2)
241 EVT_MENU(MAINMENU_WINDOW_BASE+3, MainFrame::OnWindowMenu3)
242 EVT_MENU(MAINMENU_WINDOW_BASE+4, MainFrame::OnWindowMenu4)
243 EVT_MENU(MAINMENU_WINDOW_BASE+5, MainFrame::OnWindowMenu5)
244 EVT_MENU(MAINMENU_WINDOW_BASE+6, MainFrame::OnWindowMenu6)
245 EVT_MENU(MAINMENU_WINDOW_BASE+7, MainFrame::OnWindowMenu7)
246 EVT_MENU(MAINMENU_WINDOW_BASE+8, MainFrame::OnWindowMenu8)
247 EVT_MENU(MAINMENU_WINDOW_BASE+9, MainFrame::OnWindowMenu9)
248 EVT_MENU(MAINMENU_WINDOW_BASE+10, MainFrame::OnWindowMenu10)
249 EVT_MENU(MAINMENU_WINDOW_BASE+11, MainFrame::OnWindowMenu11)
250 EVT_MENU(MAINMENU_WINDOW_BASE+12, MainFrame::OnWindowMenu12)
251 EVT_MENU(MAINMENU_WINDOW_BASE+13, MainFrame::OnWindowMenu13)
252 EVT_MENU(MAINMENU_WINDOW_BASE+14, MainFrame::OnWindowMenu14)
253 EVT_MENU(MAINMENU_WINDOW_BASE+15, MainFrame::OnWindowMenu15)
254 EVT_MENU(MAINMENU_WINDOW_BASE+16, MainFrame::OnWindowMenu16)
255 EVT_MENU(MAINMENU_WINDOW_BASE+17, MainFrame::OnWindowMenu17)
256 EVT_MENU(MAINMENU_WINDOW_BASE+18, MainFrame::OnWindowMenu18)
257 EVT_MENU(MAINMENU_WINDOW_BASE+19, MainFrame::OnWindowMenu19)
258 EVT_UPDATE_UI_RANGE(MAINMENU_WINDOW_BASE, MAINMENU_WINDOW_BASE+20, MainFrame::OnUpdateUI)
259 END_EVENT_TABLE()
260
261
262
263 #if CTSIM_MDI
264 MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
265 : wxMDIParentFrame(NULL,  id, title, pos, size, type), m_pLog(NULL)
266 #else
267 MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
268 : wxDocParentFrame(manager, frame, id, title, pos, size, type), m_pLog(NULL)
269 #endif
270 {
271 #if 0
272 //#if CTSIM_MDI
273   m_pLog = new wxLogWindow (this, "Log");
274   //std::cout = new ostream (m_pLog->GetTextCtrl());
275   wxLog::SetActiveTarget(m_pLog);
276 #else
277   m_pLog = new wxTextCtrl (this, -1, "Log Window\n", wxPoint(0, 0), wxSize(0,0), wxTE_MULTILINE | wxTE_READONLY);
278   wxLog::SetActiveTarget (new wxLogTextCtrl(m_pLog));
279 #endif
280
281   //// Make a menubar
282   wxMenu *file_menu = new wxMenu;
283   
284   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
285   file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
286   file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O");
287   
288   file_menu->AppendSeparator();
289   file_menu->Append(MAINMENU_FILE_EXIT, "E&xit");
290   
291   //  history of files visited
292   theApp->getDocManager()->FileHistoryUseMenu(file_menu);
293
294 #ifndef CTSIM_MDI
295   m_pWindowMenu = new wxMenu;
296   m_pWindowMenu->UpdateUI (this);
297 #endif
298
299   wxMenu* help_menu = new wxMenu;
300   help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
301   help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-T");
302 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
303   help_menu->Append(MAINMENU_HELP_SECONDARY, "&Secondary Help");
304 #endif
305   help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
306   
307   wxMenuBar* menu_bar = new wxMenuBar;
308   
309   menu_bar->Append(file_menu, "&File");
310 #ifndef CTSIM_MDI
311   menu_bar->Append(m_pWindowMenu, "&Window");
312 #endif
313   menu_bar->Append(help_menu, "&Help");
314   
315   SetMenuBar(menu_bar);
316   
317 #ifndef CTSIM_MDI
318   for (int i = 0; i < MAX_WINDOW_MENUITEMS; i++) {
319     m_apWindowMenuItems[i] = new wxMenuItem (m_pWindowMenu, MAINMENU_WINDOW_BASE+i, wxString("<Empty>"));
320     m_pWindowMenu->Append (m_apWindowMenuItems[i]);
321     m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false);
322   }
323 #endif
324
325   m_iDefaultPhantomID = Phantom::PHM_HERMAN;
326   m_iDefaultFilterID = SignalFilter::FILTER_BANDLIMIT;
327   m_iDefaultFilterDomainID = SignalFilter::DOMAIN_FREQUENCY;
328   m_iDefaultFilterXSize = 256;
329   m_iDefaultFilterYSize = 256;
330   m_dDefaultFilterParam = 1.;
331   m_dDefaultFilterBandwidth = 1.;
332   m_dDefaultFilterInputScale = 1.;
333   m_dDefaultFilterOutputScale = 1.;
334   
335   wxAcceleratorEntry accelEntries[15];
336   accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
337   accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
338   accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
339   accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
340 #ifndef CTSIM_MDI
341   accelEntries[4].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
342   for (i = 0; i < 10; i++)
343     accelEntries[i+4].Set (wxACCEL_CTRL, static_cast<int>('0'+i), MAINMENU_WINDOW_BASE+i);
344   wxAcceleratorTable accelTable (15, accelEntries);
345 #else
346   wxAcceleratorTable accelTable (4, accelEntries);
347 #endif
348
349   SetAcceleratorTable (accelTable);
350 }
351
352 void
353 MainFrame::OnSize (wxSizeEvent& event)
354 {
355   wxSize sizeClient = GetClientSize();
356   wxSize sizeLog = sizeClient;
357   if (sizeClient.y < 100) {
358     sizeLog.y = 0;
359     sizeLog.x = 0;
360   } else {
361     sizeLog.x = sizeClient.x;
362     sizeLog.y = 100;
363   }
364   sizeClient.x -= sizeLog.x;
365   sizeClient.y -= sizeLog.y;
366 //  m_pLog->SetSize (0, sizeClient.y, sizeLog.x, sizeLog.y);
367 //  GetClientWindow()->SetSize (0, 0, sizeClient.x, sizeClient.y);
368 //    GetClientWindow()->Refresh();
369   wxMDIParentFrame::OnSize (event);
370 }
371
372 void 
373 MainFrame::OnCreatePhantom(wxCommandEvent& event)
374 {
375   DialogGetPhantom dialogPhantom (this, m_iDefaultPhantomID);
376   int dialogReturn = dialogPhantom.ShowModal();
377   if (dialogReturn == wxID_OK) {
378     wxString selection (dialogPhantom.getPhantom());
379     *theApp->getLog() << "Selected phantom " << selection.c_str() << "\n";
380     wxString filename = selection + ".phm";
381     m_iDefaultPhantomID = Phantom::convertNameToPhantomID (selection.c_str());
382     theApp->getDocManager()->CreateDocument(filename, wxDOC_SILENT);
383   }
384   
385 }
386
387 void 
388 MainFrame::OnCreateFilter (wxCommandEvent& WXUNUSED(event))
389 {
390   DialogGetFilterParameters dialogFilter (this, m_iDefaultFilterXSize, m_iDefaultFilterYSize, m_iDefaultFilterID, m_dDefaultFilterParam, m_dDefaultFilterBandwidth, m_iDefaultFilterDomainID, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
391   int dialogReturn = dialogFilter.ShowModal();
392   if (dialogReturn == wxID_OK) {
393     wxString strFilter (dialogFilter.getFilterName());
394     wxString strDomain (dialogFilter.getDomainName());
395     m_iDefaultFilterID = SignalFilter::convertFilterNameToID (strFilter.c_str());
396     m_iDefaultFilterDomainID = SignalFilter::convertDomainNameToID (strDomain.c_str());
397     m_iDefaultFilterXSize = dialogFilter.getXSize();
398     m_iDefaultFilterYSize = dialogFilter.getYSize();
399     m_dDefaultFilterBandwidth = dialogFilter.getBandwidth();
400     m_dDefaultFilterParam= dialogFilter.getFilterParam();
401     m_dDefaultFilterInputScale = dialogFilter.getInputScale();
402     m_dDefaultFilterOutputScale = dialogFilter.getOutputScale();
403     std::ostringstream os;
404     os << "Generate Filter=" << strFilter.c_str() 
405       << ", size=(" << static_cast<int>(m_iDefaultFilterXSize) << "," << static_cast<int>(m_iDefaultFilterYSize) 
406       << "), domain=" << strDomain.c_str() << ", filterParam=" << m_dDefaultFilterParam << ", bandwidth=" << m_dDefaultFilterBandwidth 
407       << ", inputScale=" << m_dDefaultFilterInputScale << ", outputScale=" << m_dDefaultFilterOutputScale;
408     *theApp->getLog() << os.str().c_str() << "\n";
409     wxString filename = "untitled.if";
410     ImageFileDocument* pFilterDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument ("untitled.if", wxDOC_SILENT));
411     if (! pFilterDoc) {
412       sys_error (ERR_SEVERE, "Unable to create filter image");
413       return;
414     }
415     ImageFile& rIF = pFilterDoc->getImageFile();
416     rIF.setArraySize (m_iDefaultFilterXSize, m_iDefaultFilterYSize);
417     rIF.filterResponse (strDomain.c_str(), m_dDefaultFilterBandwidth, strFilter.c_str(), m_dDefaultFilterParam, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
418     rIF.labelAdd (os.str().c_str());
419     if (theApp->getSetModifyNewDocs())
420       pFilterDoc->Modify (true);
421     pFilterDoc->UpdateAllViews();
422     pFilterDoc->GetFirstView()->OnUpdate (NULL, NULL);
423   }
424 }
425
426 void
427 CTSimApp::getCompatibleImages (const ImageFileDocument* pIFDoc, std::vector<ImageFileDocument*>& vecIF)
428 {
429   const ImageFile& rIF = pIFDoc->getImageFile();
430   unsigned int nx = rIF.nx();
431   unsigned int ny = rIF.ny();
432   wxList& rListDocs = m_docManager->GetDocuments();
433   for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) {
434     wxDocument* pDoc = reinterpret_cast<wxDocument*>(pNode->GetData());
435     ImageFileDocument* pIFCompareDoc = dynamic_cast<ImageFileDocument*>(pDoc);
436     if (pIFCompareDoc && (pIFDoc != pIFCompareDoc)) {
437       const ImageFile& rCompareIF = pIFCompareDoc->getImageFile();
438       if (rCompareIF.nx() == nx && rCompareIF.ny() == ny)
439         vecIF.push_back (pIFCompareDoc);
440     }
441   }
442 }
443
444 void 
445 MainFrame::OnHelpTopics (wxCommandEvent& event)
446 {
447   showHelp (event.GetId());
448 }
449
450 void 
451 MainFrame::OnHelpContents (wxCommandEvent& event)
452 {
453   showHelp (event.GetId());
454 }
455
456 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
457 void
458 MainFrame::OnHelpSecondary (wxCommandEvent& event)
459 {
460     m_htmlHelp.DisplayContents();
461 }
462 #endif
463
464 void
465 MainFrame::showHelp (int commandID)
466 {
467 #ifdef CTSIM_WINHELP
468   m_winHelp.LoadFile();
469 #else
470   m_htmlHelp.LoadFile();
471 #endif
472   
473   switch (commandID) {
474
475   case MAINMENU_HELP_CONTENTS:
476 #ifdef CTSIM_WINHELP
477     m_winHelp.DisplayContents ();
478 #else
479     m_htmlHelp.DisplayContents ();
480 #endif
481     break;
482
483   case MAINMENU_HELP_TOPICS:
484 #ifdef CTSIM_WINHELP
485     m_winHelp.DisplaySection (introduction);
486 #else
487     m_htmlHelp.DisplayIndex();
488 #endif
489     break;
490
491   default:
492     *getLog() << "Unknown help command # " << commandID << "\n";
493     break;
494   }
495 }
496
497 void 
498 MainFrame::OnExit (wxCommandEvent& WXUNUSED(event) )
499 {
500   Close(true);
501 }
502
503 void
504 MainFrame::OnUpdateUI (wxUpdateUIEvent& rEvent)
505 {
506   int iPos = 0;
507   wxList& rListDocs = theApp->getDocManager()->GetDocuments();
508   wxNode* pNode = rListDocs.GetFirst();
509   while (iPos < MAX_WINDOW_MENUITEMS && pNode != NULL) {
510     wxDocument* pDoc = static_cast<wxDocument*>(pNode->GetData());
511     wxString strFilename = pDoc->GetFilename();
512     if (iPos < 10) {
513       strFilename += "\tCtrl-";
514       strFilename += static_cast<char>('0' + iPos);
515     }
516     static_cast<wxMenuItemBase*>(m_apWindowMenuItems[iPos])->SetName (strFilename);
517     m_apWindowMenuData[iPos] = pDoc;
518     m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+iPos, true);
519     iPos++;
520     pNode = pNode->GetNext();
521   }
522   for (int i = iPos; i < MAX_WINDOW_MENUITEMS; i++) {
523     m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false);
524     static_cast<wxMenuItemBase*>(m_apWindowMenuItems[i])->SetName (wxString("<Empty>"));
525     m_apWindowMenuData[i] = NULL;
526   }
527   
528 }
529
530 void MainFrame::OnMRUFile(wxCommandEvent& event)
531 {
532    wxString fileName (theApp->getDocManager()->GetHistoryFile(event.GetSelection()));
533    if (fileName != "")
534      theApp->getDocManager()->CreateDocument(fileName, wxDOC_SILENT);
535 }
536
537 void 
538 MainFrame::DoWindowMenu (int iMenuPosition, wxCommandEvent& event)
539 {
540   if (wxDocument* pDoc = m_apWindowMenuData [iMenuPosition]) {
541     wxString strFilename = pDoc->GetFilename();
542     const wxView* pView = pDoc->GetFirstView();
543     if (pView) {
544       wxFrame* pFrame = pView->GetFrame();
545       pFrame->SetFocus();
546       pFrame->Raise();
547     }
548   }
549 }
550
551 void MainFrame::OnWindowMenu0 (wxCommandEvent& event)
552 { DoWindowMenu (0, event); }
553
554 void MainFrame::OnWindowMenu1 (wxCommandEvent& event)
555 { DoWindowMenu (1, event); }
556
557 void MainFrame::OnWindowMenu2 (wxCommandEvent& event)
558 { DoWindowMenu (2, event); }
559
560 void MainFrame::OnWindowMenu3 (wxCommandEvent& event)
561 { DoWindowMenu (3, event); }
562
563 void MainFrame::OnWindowMenu4 (wxCommandEvent& event)
564 { DoWindowMenu (4, event); }
565
566 void MainFrame::OnWindowMenu5 (wxCommandEvent& event)
567 { DoWindowMenu (5, event); }
568
569 void MainFrame::OnWindowMenu6 (wxCommandEvent& event)
570 { DoWindowMenu (6, event); }
571
572 void MainFrame::OnWindowMenu7 (wxCommandEvent& event)
573 { DoWindowMenu (7, event); }
574
575 void MainFrame::OnWindowMenu8 (wxCommandEvent& event)
576 { DoWindowMenu (8, event); }
577
578 void MainFrame::OnWindowMenu9 (wxCommandEvent& event)
579 { DoWindowMenu (9, event); }
580
581 void MainFrame::OnWindowMenu10 (wxCommandEvent& event)
582 { DoWindowMenu (10, event); }
583
584 void MainFrame::OnWindowMenu11 (wxCommandEvent& event)
585 { DoWindowMenu (11, event); }
586
587 void MainFrame::OnWindowMenu12 (wxCommandEvent& event)
588 { DoWindowMenu (12, event); }
589
590 void MainFrame::OnWindowMenu13 (wxCommandEvent& event)
591 { DoWindowMenu (13, event); }
592
593 void MainFrame::OnWindowMenu14 (wxCommandEvent& event)
594 { DoWindowMenu (14, event); }
595
596 void MainFrame::OnWindowMenu15 (wxCommandEvent& event)
597 { DoWindowMenu (15, event); }
598
599 void MainFrame::OnWindowMenu16 (wxCommandEvent& event)
600 { DoWindowMenu (16, event); }
601
602 void MainFrame::OnWindowMenu17 (wxCommandEvent& event)
603 { DoWindowMenu (17, event); }
604
605 void MainFrame::OnWindowMenu18 (wxCommandEvent& event)
606 { DoWindowMenu (18, event); }
607
608 void MainFrame::OnWindowMenu19 (wxCommandEvent& event)
609 { DoWindowMenu (19, event); }
610
611
612 class BitmapControl : public wxPanel
613 {
614 private:  
615   DECLARE_DYNAMIC_CLASS (BitmapControl)
616     DECLARE_EVENT_TABLE ()
617     wxBitmap* m_pBitmap;
618   
619 public:
620   BitmapControl (wxBitmap* pBitmap, wxWindow *parent, wxWindowID id = -1,
621     const wxPoint& pos = wxDefaultPosition,
622     const wxSize& size = wxDefaultSize,
623     long style = wxSTATIC_BORDER,
624     const wxValidator& validator = wxDefaultValidator,
625     const wxString& name = "BitmapCtrl");
626   
627   
628   virtual ~BitmapControl();
629   
630   virtual wxSize GetBestSize() const;
631   
632   wxBitmap* getBitmap() 
633   { return m_pBitmap; }
634   
635   void OnPaint(wxPaintEvent& event);
636 };
637
638
639 BEGIN_EVENT_TABLE(BitmapControl, wxPanel)
640 EVT_PAINT(BitmapControl::OnPaint)
641 END_EVENT_TABLE()
642
643 IMPLEMENT_CLASS(BitmapControl, wxPanel)
644
645
646 BitmapControl::BitmapControl (wxBitmap* pBitmap, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, 
647                               long style, const wxValidator& validator, const wxString& name)
648                               : m_pBitmap(pBitmap)
649 {
650   Create(parent, id, pos, size, style, name);
651   
652   SetSize (GetBestSize());
653 }
654
655 wxSize
656 BitmapControl::GetBestSize () const
657 {
658   if (m_pBitmap)
659     return wxSize (m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
660   else
661     return wxSize(0,0);
662 }
663
664 BitmapControl::~BitmapControl()
665 {}
666
667 void
668 BitmapControl::OnPaint (wxPaintEvent& event)
669 {
670   wxPaintDC dc(this);
671   if (m_pBitmap)
672     dc.DrawBitmap (*m_pBitmap, 0, 0);
673 }
674
675
676 class BitmapDialog : public wxDialog {
677 private:
678   BitmapControl* m_pBitmapCtrl;
679   
680 public:
681   BitmapDialog (wxBitmap* pBitmap, char const* pszTitle);
682   virtual ~BitmapDialog();
683 };
684
685 BitmapDialog::BitmapDialog (wxBitmap* pBitmap, char const* pszTitle)
686 : wxDialog(theApp->getMainFrame(), -1, wxString(pszTitle), wxDefaultPosition, wxDefaultSize, wxDIALOG_MODAL | wxDEFAULT_DIALOG_STYLE)
687 {
688   wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL);
689   
690   pTopSizer->Add (new BitmapControl (pBitmap, this), 0, wxALIGN_CENTER | wxALL, 5);
691   
692   wxBoxSizer* pButtonSizer = new wxBoxSizer (wxHORIZONTAL);
693   wxButton* pButtonOk = new wxButton (this, wxID_OK, "Ok");
694   pButtonSizer->Add (pButtonOk, 0, wxEXPAND | wxALL, 10);
695   
696   pTopSizer->Add (pButtonSizer, 0, wxALIGN_CENTER);
697   
698   SetAutoLayout (true);
699   SetSizer (pTopSizer);
700   pTopSizer->Fit (this);
701   pTopSizer->SetSizeHints (this);
702 }
703
704 BitmapDialog::~BitmapDialog()
705 {}
706
707
708 #include "./splash.xpm"
709 void 
710 MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
711 {
712   wxBitmap bmp (splash);
713   if (bmp.Ok()) {
714     BitmapDialog dlg (&bmp, "About CTSim");
715     dlg.Show(true);
716   } else {
717     wxString msg = "CTSim\nThe Open Source Computed Tomography Simulator\n";
718 #ifdef CTSIMVERSION
719     msg += "Version ";
720     msg += CTSIMVERSION;
721     msg += "\n\n";
722 #elif defined(VERSION)
723     msg << "Version: " <<  VERSION << "\n\n";
724 #endif
725     msg += "Author: Kevin Rosenberg <kevin@rosenberg.net>\nUsage: ctsim [files-to-open..] [--help]";
726     
727     wxMessageBox(msg, "About CTSim", wxOK | wxICON_INFORMATION, this);
728   }
729 }
730