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