Applied initial patches for wx2.8 compatibility
[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-2001 Kevin Rosenberg
11 **
12 **  $Id$
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 #include "wx/wxprec.h"
33
34 #ifndef WX_PRECOMP
35 #include "wx/wx.h"
36 #endif
37
38 #include "wx/image.h"
39 #include "wx/filesys.h"
40 #include "wx/fs_zip.h"
41 #ifdef __WXMSW__
42 #include "wx/msw/helpchm.h"
43 #endif
44
45 #if !wxUSE_DOC_VIEW_ARCHITECTURE
46 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
47 #endif
48
49 #include "ct.h"
50 #include "ctndicom.h"
51 #include "ctsim.h"
52 #include "docs.h"
53 #include "views.h"
54 #include "dialogs.h"
55 #include "tips.h"
56 #include "backgroundmgr.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$";
73
74 struct option CTSimApp::ctsimOptions[] =
75 {
76   {"help", 0, 0, O_HELP},
77   {"version", 0, 0, O_VERSION},
78   {"print", 0, 0, O_PRINT},
79   {0, 0, 0, 0}
80 };
81
82 IMPLEMENT_APP(CTSimApp)
83
84 CTSimApp::CTSimApp()
85 : m_bAdvancedOptions(false), m_bSetModifyNewDocs(true), 
86   m_bVerboseLogging(false), m_bShowStartupTips(true),
87 m_iCurrentTip(0), m_bUseBackgroundTasks(false),
88 m_docManager(NULL), m_pFrame(NULL), m_pConfig(0), m_pLog(0), m_pLogDoc(0)
89 {
90   theApp = this;
91 }
92
93 #ifdef HAVE_SYS_TIME_H
94 #include <sys/time.h>
95 #endif
96
97 #ifdef HAVE_SYS_RESOURCE_H
98 #include <sys/resource.h>
99 #endif
100
101 bool
102 CTSimApp::OnInit()
103 {
104   wxApp::OnInit();
105
106 #ifdef HAVE_SETPRIORITY
107   setpriority (PRIO_PROCESS, 0, 15);  // set to low scheduling priority
108 #endif
109
110   openConfig();
111
112   g_bRunningWXWindows = true;
113   bool bPrintFiles = false;
114   // process options
115   while (1) {
116 #ifdef __WXMAC__
117     int c = -1;
118 #else
119     char** cargv = new char* [argc];
120     for (int i = 0; i < argc; i++) {
121       const char* p = wxConvUTF8.cWX2MB(argv[i]);
122       cargv[i] = new char [strlen(p)+1];
123       strcpy(cargv[i], p);
124     }
125     int c = getopt_long (argc, cargv, "", ctsimOptions, NULL);
126     for (int i = 0; i < argc; i++) {
127       delete cargv[i];
128     }
129     delete cargv;
130     
131 #endif
132     if (c == -1)
133       break;
134
135     switch (c) {
136     case O_VERSION:
137       std::cout << rcsindent << std::endl;
138 #ifdef VERSION
139       std::cout << "Version: " << VERSION << std::endl;
140 #elif defined(CTSIMVERSION)
141       std::cout << "Version: " << CTSIMVERSION << std::endl;
142 #endif
143       exit(0);
144     case O_HELP:
145     case '?':
146       usage (wxConvCurrent->cWX2MB(argv[0]));
147       exit (0);
148     case O_PRINT:
149       bPrintFiles = true;
150       break;
151     default:
152       usage (wxConvCurrent->cWX2MB(argv[0]));
153       exit (1);
154     }
155   }
156
157   m_docManager = new wxDocManager (wxDEFAULT_DOCMAN_FLAGS, true);
158
159   m_pDocTemplImage = new wxDocTemplate (m_docManager, _T("ImageFile"), _T("*.if"), _T(""), _T("if"), _T("ImageFile"), _T("ImageView"), CLASSINFO(ImageFileDocument), CLASSINFO(ImageFileView));
160   m_pDocTemplProjection = new wxDocTemplate (m_docManager, _T("ProjectionFile"), _T("*.pj"), _T(""), _T("pj"), _T("ProjectionFile"), _T("ProjectionView"), CLASSINFO(ProjectionFileDocument), CLASSINFO(ProjectionFileView));
161   m_pDocTemplPhantom = new wxDocTemplate (m_docManager, _T("PhantomFile"), _T("*.phm"), _T(""), _T("phm"), _T("PhantomFile"), _T("PhantomView"), CLASSINFO(PhantomFileDocument), CLASSINFO(PhantomFileView));
162   m_pDocTemplPlot = new wxDocTemplate (m_docManager, _T("PlotFile"), _T("*.plt"), _T(""), _T("plt"), _T("PlotFile"), _T("PlotView"), CLASSINFO(PlotFileDocument), CLASSINFO(PlotFileView));
163   m_pDocTemplText = new wxDocTemplate (m_docManager, _T("TextFile"), _T("*.txt"), _T(""), _T("txt"), _T("TextFile"), _T("TextView"), CLASSINFO(TextFileDocument), CLASSINFO(TextFileView), wxTEMPLATE_INVISIBLE);
164 #if wxUSE_GLCANVAS
165   m_pDocTemplGraph3d = new wxDocTemplate (m_docManager, _T("Graph3dFile"), _T("*.g3d"), _T(""), _T("g3d"),
166                                           _T("Graph3dFile"), _T("Graph3dView"), CLASSINFO(Graph3dFileDocument), 
167                                           CLASSINFO(Graph3dFileView), wxTEMPLATE_INVISIBLE);
168 #endif
169
170 #if wxUSE_GIF
171   wxImage::AddHandler(new wxGIFHandler);     // Required for images in the online documentation
172 #endif
173
174 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
175   wxFileSystem::AddHandler(new wxZipFSHandler);     // Required for advanced HTML help
176 #endif
177
178   // Create the main frame window
179   int xDisplay, yDisplay;
180   ::wxDisplaySize (&xDisplay, &yDisplay);
181
182   m_pFrame = new MainFrame(m_docManager, (wxFrame *) NULL, -1, _T("CTSim"), wxPoint(0, 0),
183 #ifdef CTSIM_MDI
184     wxSize(nearest<int>(xDisplay * .75), nearest<int>(yDisplay * .75)),
185 #else
186     wxSize(nearest<int>(xDisplay * .6), nearest<int>(yDisplay * .4)),
187 #endif
188     wxDEFAULT_FRAME_STYLE);
189
190   setIconForFrame (m_pFrame);
191   m_pFrame->Centre(wxBOTH);
192   m_pFrame->Show(true);
193   SetTopWindow (m_pFrame);
194
195   if (m_pConfig)
196     m_docManager->FileHistoryLoad(*m_pConfig);
197
198 #ifdef CTSIM_MDI
199   m_pLogDoc = newTextDoc();
200   if (m_pLogDoc) {
201     m_pLog = m_pLogDoc->getTextCtrl();
202     m_pLogDoc->SetDocumentName("Log.txt");
203     m_pLogDoc->SetFilename("Log.txt");
204     m_pLogDoc->getView()->getFrame()->SetTitle("Log");
205     int xSize, ySize;
206     m_pFrame->GetClientSize(&xSize, &ySize);
207     int yLogSize = ySize / 4;
208     m_pLogDoc->getView()->getFrame()->SetSize (0, ySize - yLogSize, xSize, yLogSize);
209     m_pLogDoc->getView()->getFrame()->Show (true);
210   } else
211 #else
212     m_pLog = new wxTextCtrl (m_pFrame, -1, _T("Log Window\n"), wxPoint(0, 0), wxSize(0,0), wxTE_MULTILINE | wxTE_READONLY);
213 #endif
214   wxLog::SetActiveTarget (new wxLogTextCtrl(m_pLog));
215
216   wxString helpDir;
217   if (! m_pConfig->Read(_T("HelpDir"), &helpDir))
218     helpDir = ::wxGetCwd();
219 #ifdef CTSIM_WINHELP
220   if (! m_pFrame->getWinHelpController().Initialize(helpDir + _T("/ctsim")))
221     *m_pLog << _T("Cannot initialize the Windows Help system") << _T("\n");
222 #else
223 #ifdef DATADIR
224   wxString docDir (DATADIR, *wxConvCurrent);
225 #else
226   wxString docDir (::wxGetCwd());
227 #endif
228   wxString docFile = docDir + _T("ctsim.htb");
229   if (! m_pFrame->getHtmlHelpController().AddBook(docFile) &&
230       ! m_pFrame->getHtmlHelpController().AddBook(_T("/usr/share/ctsim/ctsim.htb")) &&
231       ! m_pFrame->getHtmlHelpController().AddBook(_T("/tmp/ctsim.htb")))
232     *m_pLog << _T("Cannot initialize the HTML Help system") << _T("\n");
233   else {
234     if (::wxDirExists (_T("/tmp")))
235       m_pFrame->getHtmlHelpController().SetTempDir(_T("/tmp"));
236     m_pFrame->getHtmlHelpController().UseConfig (m_pConfig);
237   }
238 #endif
239
240   for (int i = optind + 1; i <= argc; i++) {
241     wxString filename = argv [i - 1];
242     wxDocument* pNewDoc = m_docManager->CreateDocument (filename, wxDOC_SILENT);
243     if (bPrintFiles) {
244       wxView* pNewView = pNewDoc->GetFirstView();
245       wxPrintout *printout = pNewView->OnCreatePrintout();
246       if (printout) {
247         wxPrinter printer;
248         printer.Print(pNewView->GetFrame(), printout, TRUE);
249         delete printout;
250       }
251       wxCommandEvent nullEvent;
252       nullEvent.SetId (wxID_CLOSE);
253       m_docManager->OnFileClose (nullEvent);
254     }
255   }
256   if (bPrintFiles) {
257     wxCommandEvent closeEvent;
258     closeEvent.SetInt (MAINMENU_FILE_EXIT);
259     m_pFrame->AddPendingEvent(closeEvent);
260   }
261
262   if (getStartupTips())
263     ShowTips();
264
265 #ifdef HAVE_WXTHREADS
266   m_pBackgroundMgr = new BackgroundManager;
267 #endif
268
269   return true;
270 }
271
272 void
273 CTSimApp::ShowTips()
274 {
275   CTSimTipProvider tipProvider (m_iCurrentTip);
276   setStartupTips (::wxShowTip (m_pFrame, &tipProvider, getStartupTips()));
277   m_iCurrentTip = tipProvider.GetCurrentTip();
278 }
279
280
281 #include "./ctsim.xpm"
282 void
283 CTSimApp::setIconForFrame(wxFrame* pFrame)
284 {
285   wxIcon iconApp (ctsim16_xpm);
286
287   if (iconApp.Ok())
288     pFrame->SetIcon (iconApp);
289 }
290
291 void
292 CTSimApp::usage(const char* program)
293 {
294   std::cout << "usage: " << fileBasename(program) << " [files-to-open...] [OPTIONS]\n";
295   std::cout << "Computed Tomography Simulator (Graphical Shell)\n";
296   std::cout << "\n";
297   std::cout << "  --version Display version\n";
298   std::cout << "  --help    Display this help message\n";
299 }
300
301 int
302 CTSimApp::OnExit()
303 {
304   closeConfig();
305
306 #ifdef HAVE_DMALLOC
307   dmalloc_shutdown();
308 #endif
309   return 0;
310 }
311
312 void
313 CTSimApp::openConfig()
314 {
315 #ifdef MSVC
316   m_pConfig = new wxConfig(_T("ctsim"), _T("Kevin Rosenberg"), _T(""), _T(""), wxCONFIG_USE_LOCAL_FILE);
317 #else
318   m_pConfig = new wxConfig(_T("ctsim"), _T("Kevin Rosenberg"), _T(".ctsim"), _T(""), wxCONFIG_USE_LOCAL_FILE);
319 #endif
320
321   wxConfigBase::Set(m_pConfig);
322   m_pConfig->Read (_T("AdvancedOptions"), &m_bAdvancedOptions);
323   m_pConfig->Read (_T("SetModifyNewDocs"), &m_bSetModifyNewDocs);
324   m_pConfig->Read (_T("VerboseLogging"), &m_bVerboseLogging);
325   m_pConfig->Read (_T("StartupTips"), &m_bShowStartupTips);
326   m_pConfig->Read (_T("CurrentTip"), &m_iCurrentTip);
327   m_pConfig->Read (_T("UseBackgroundTasks"), &m_bUseBackgroundTasks);
328 #ifdef HAVE_FFTW
329   wxString strFftwWisdom;
330   m_pConfig->Read (_T("FftwWisdom"), strFftwWisdom);
331   if (strFftwWisdom.size() > 0)
332     fftw_import_wisdom_from_string (strFftwWisdom.mb_str(wxConvUTF8));
333 #endif
334 }
335
336 void
337 CTSimApp::closeConfig()
338 {
339   m_pConfig->Write (_T("AdvancedOptions"), m_bAdvancedOptions);
340   m_pConfig->Write (_T("SetModifyNewDocs"), m_bSetModifyNewDocs);
341   m_pConfig->Write (_T("VerboseLogging"), m_bVerboseLogging);
342   m_pConfig->Write (_T("StartupTips"), m_bShowStartupTips);
343   m_pConfig->Write (_T("CurrentTip"), m_iCurrentTip);
344   m_pConfig->Write (_T("UseBackgroundTasks"), m_bUseBackgroundTasks);
345 #ifdef HAVE_FFTW
346   const char* const pszWisdom = fftw_export_wisdom_to_string();
347   wxString strFftwWisdom (pszWisdom, *wxConvCurrent);
348   fftw_free ((void*) pszWisdom);
349   m_pConfig->Write (_T("FftwWisdom"), strFftwWisdom);
350 #endif
351
352   delete m_pConfig;
353 }
354
355
356 wxString
357 CTSimApp::getUntitledFilename()
358 {
359   static int untitledNumber = 1;
360
361   wxString filename (_T("Untitled"));
362   filename << untitledNumber++;
363
364   return (filename);
365 }
366
367
368 // Top-level window for CTSim
369
370 #if CTSIM_MDI
371 IMPLEMENT_CLASS(MainFrame, wxMDIParentFrame)
372
373 BEGIN_EVENT_TABLE(MainFrame, wxMDIParentFrame)
374 #else
375 IMPLEMENT_CLASS(MainFrame, wxDocParentFrame)
376
377 BEGIN_EVENT_TABLE(MainFrame, wxDocParentFrame)
378 #endif
379
380 EVT_MENU(MAINMENU_FILE_PREFERENCES, MainFrame::OnPreferences)
381 EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout)
382 EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents)
383 EVT_MENU(MAINMENU_HELP_TIPS, MainFrame::OnHelpTips)
384 EVT_MENU(MAINMENU_IMPORT, MainFrame::OnImport)
385 EVT_MENU(IDH_QUICKSTART, MainFrame::OnHelpButton)
386 EVT_MENU(MAINMENU_LOG_EVENT, MainFrame::OnLogEvent)
387 EVT_MENU(NEW_IMAGEFILE_EVENT, MainFrame::OnNewImageFile)
388 EVT_MENU(NEW_PROJECTIONFILE_EVENT, MainFrame::OnNewProjectionFile)
389 EVT_BUTTON(IDH_DLG_RASTERIZE, MainFrame::OnHelpButton)
390 EVT_BUTTON(IDH_DLG_PROJECTIONS, MainFrame::OnHelpButton)
391 EVT_BUTTON(IDH_DLG_RECONSTRUCTION, MainFrame::OnHelpButton)
392 EVT_BUTTON(IDH_DLG_FILTER, MainFrame::OnHelpButton)
393 EVT_BUTTON(IDH_DLG_MINMAX, MainFrame::OnHelpButton)
394 EVT_BUTTON(IDH_DLG_EXPORT, MainFrame::OnHelpButton)
395 EVT_BUTTON(IDH_DLG_PHANTOM, MainFrame::OnHelpButton)
396 EVT_BUTTON(IDH_DLG_COMPARISON, MainFrame::OnHelpButton)
397 EVT_BUTTON(IDH_DLG_PREFERENCES, MainFrame::OnHelpButton)
398 EVT_BUTTON(IDH_DLG_POLAR, MainFrame::OnHelpButton)
399 EVT_BUTTON(IDH_DLG_AUTOSCALE, MainFrame::OnHelpButton)
400
401 EVT_SIZE(MainFrame::OnSize)
402
403 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
404 EVT_MENU(MAINMENU_HELP_SECONDARY, MainFrame::OnHelpSecondary)
405 #endif
406 EVT_MENU(MAINMENU_FILE_CREATE_PHANTOM, MainFrame::OnCreatePhantom)
407 EVT_MENU(MAINMENU_FILE_CREATE_FILTER, MainFrame::OnCreateFilter)
408 EVT_MENU(MAINMENU_FILE_EXIT, MainFrame::OnExit)
409 EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MainFrame::OnMRUFile)
410 EVT_MENU(MAINMENU_WINDOW_BASE, MainFrame::OnWindowMenu0)
411 EVT_MENU(MAINMENU_WINDOW_BASE+1, MainFrame::OnWindowMenu1)
412 EVT_MENU(MAINMENU_WINDOW_BASE+2, MainFrame::OnWindowMenu2)
413 EVT_MENU(MAINMENU_WINDOW_BASE+3, MainFrame::OnWindowMenu3)
414 EVT_MENU(MAINMENU_WINDOW_BASE+4, MainFrame::OnWindowMenu4)
415 EVT_MENU(MAINMENU_WINDOW_BASE+5, MainFrame::OnWindowMenu5)
416 EVT_MENU(MAINMENU_WINDOW_BASE+6, MainFrame::OnWindowMenu6)
417 EVT_MENU(MAINMENU_WINDOW_BASE+7, MainFrame::OnWindowMenu7)
418 EVT_MENU(MAINMENU_WINDOW_BASE+8, MainFrame::OnWindowMenu8)
419 EVT_MENU(MAINMENU_WINDOW_BASE+9, MainFrame::OnWindowMenu9)
420 EVT_MENU(MAINMENU_WINDOW_BASE+10, MainFrame::OnWindowMenu10)
421 EVT_MENU(MAINMENU_WINDOW_BASE+11, MainFrame::OnWindowMenu11)
422 EVT_MENU(MAINMENU_WINDOW_BASE+12, MainFrame::OnWindowMenu12)
423 EVT_MENU(MAINMENU_WINDOW_BASE+13, MainFrame::OnWindowMenu13)
424 EVT_MENU(MAINMENU_WINDOW_BASE+14, MainFrame::OnWindowMenu14)
425 EVT_MENU(MAINMENU_WINDOW_BASE+15, MainFrame::OnWindowMenu15)
426 EVT_MENU(MAINMENU_WINDOW_BASE+16, MainFrame::OnWindowMenu16)
427 EVT_MENU(MAINMENU_WINDOW_BASE+17, MainFrame::OnWindowMenu17)
428 EVT_MENU(MAINMENU_WINDOW_BASE+18, MainFrame::OnWindowMenu18)
429 EVT_MENU(MAINMENU_WINDOW_BASE+19, MainFrame::OnWindowMenu19)
430 EVT_UPDATE_UI_RANGE(MAINMENU_WINDOW_BASE, MAINMENU_WINDOW_BASE+20, MainFrame::OnUpdateUI)
431 END_EVENT_TABLE()
432
433
434
435 #if CTSIM_MDI
436 MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
437 : wxDocMDIParentFrame(manager, NULL, id, title, pos, size, type, "MainFrame")
438 #else
439 MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
440 : wxDocParentFrame(manager, frame, id, title, pos, size, type, _T("MainFrame"))
441 #endif
442 {
443   m_bShuttingDown = false;
444
445   //// Make a menubar
446   wxMenu *file_menu = new wxMenu;
447
448   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, _T("Cr&eate Phantom...\tCtrl-P"));
449   file_menu->Append(MAINMENU_FILE_CREATE_FILTER, _T("Create &Filter...\tCtrl-F"));
450   file_menu->Append(wxID_OPEN, _T("&Open...\tCtrl-O"));
451
452   file_menu->AppendSeparator();
453   file_menu->Append (MAINMENU_IMPORT, _T("&Import...\tCtrl-M"));
454   file_menu->Append (MAINMENU_FILE_PREFERENCES, _T("Prefere&nces..."));
455   file_menu->Append(MAINMENU_FILE_EXIT, _T("E&xit"));
456
457   //  history of files visited
458   theApp->getDocManager()->FileHistoryAddFilesToMenu(file_menu);
459   theApp->getDocManager()->FileHistoryUseMenu(file_menu);
460
461 #ifndef CTSIM_MDI
462   m_pWindowMenu = new wxMenu;
463   m_pWindowMenu->UpdateUI (this);
464 #endif
465
466   wxMenu* help_menu = new wxMenu;
467   help_menu->Append (MAINMENU_HELP_CONTENTS, _T("&Contents\tF1"));
468   help_menu->Append (MAINMENU_HELP_TIPS, _T("&Tips"));
469   help_menu->Append (IDH_QUICKSTART, _T("&Quick Start"));
470 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
471   help_menu->Append (MAINMENU_HELP_SECONDARY, _T("&Secondary Help"));
472 #endif
473   help_menu->Append (MAINMENU_HELP_ABOUT, _T("&About"));
474
475   wxMenuBar* menu_bar = new wxMenuBar;
476
477   menu_bar->Append(file_menu, _T("&File"));
478 #ifndef CTSIM_MDI
479   menu_bar->Append(m_pWindowMenu, _T("&Window"));
480 #endif
481   menu_bar->Append(help_menu, _T("&Help"));
482
483   SetMenuBar(menu_bar);
484
485
486 #ifndef CTSIM_MDI
487   int i;
488   for (i = 0; i < MAX_WINDOW_MENUITEMS; i++) {
489     m_apWindowMenuItems[i] = new wxMenuItem (m_pWindowMenu, MAINMENU_WINDOW_BASE+i, _T("[EMPTY]"));
490     m_pWindowMenu->Append (m_apWindowMenuItems[i]);
491     m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false);
492   }
493 #endif
494
495   m_iDefaultPhantomID = Phantom::PHM_HERMAN;
496   m_iDefaultFilterID = SignalFilter::FILTER_BANDLIMIT;
497   m_iDefaultFilterDomainID = SignalFilter::DOMAIN_FREQUENCY;
498   m_iDefaultFilterXSize = 256;
499   m_iDefaultFilterYSize = 256;
500   m_dDefaultFilterParam = 1.;
501   m_dDefaultFilterBandwidth = 1.;
502   m_dDefaultFilterInputScale = 1.;
503   m_dDefaultFilterOutputScale = 1.;
504   m_iDefaultImportFormat = ImageFile::IMPORT_FORMAT_PNG;
505
506   wxAcceleratorEntry accelEntries[15];
507   accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
508   accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
509   accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
510   accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('M'), MAINMENU_IMPORT);
511   accelEntries[4].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
512 #ifndef CTSIM_MDI
513   for (i = 0; i < 10; i++)
514     accelEntries[i+5].Set (wxACCEL_CTRL, static_cast<int>('0'+i), MAINMENU_WINDOW_BASE+i);
515   wxAcceleratorTable accelTable (15, accelEntries);
516 #else
517   wxAcceleratorTable accelTable (5, accelEntries);
518 #endif
519
520   SetAcceleratorTable (accelTable);
521 }
522
523 MainFrame::~MainFrame()
524 {
525   m_bShuttingDown = true; // Currently used so that Log Window will close
526 #if 0
527   // delete all non-modified documents
528   wxList& rListDocs = theApp->getDocManager()->GetDocuments();
529   for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) {
530     wxDocument* pDoc = dynamic_cast<wxDocument*>(pNode->GetData());
531     if (pDoc && ! pDoc->IsModified()) {
532       theApp->getDocManager()->RemoveDocument(pDoc);
533       delete pDoc;
534     }
535   }
536 #endif
537   ::wxYield();
538   if (theApp->getConfig())
539     theApp->getDocManager()->FileHistorySave (*theApp->getConfig());
540   ::wxYield();
541   delete theApp->getDocManager();
542
543 }
544
545 void
546 MainFrame::OnSize (wxSizeEvent& event)
547 {
548 #ifdef CTSIM_MDI
549   if (theApp->getLogDoc()) {
550     int xSize, ySize;
551     GetClientSize(&xSize, &ySize);
552     int yLogSize = ySize / 4;
553     theApp->getLogDoc()->getView()->getFrame()->SetSize (0, ySize - yLogSize, xSize, yLogSize);
554     theApp->getLogDoc()->getView()->getFrame()->Show (true);
555   }
556 #endif
557
558 #if CTSIM_MDI
559   wxDocMDIParentFrame::OnSize (event);
560 #else
561   wxDocParentFrame::OnSize (event);
562 #endif
563 }
564
565 void
566 MainFrame::OnCreatePhantom(wxCommandEvent& event)
567 {
568   DialogGetPhantom dialogPhantom (this, m_iDefaultPhantomID);
569   int dialogReturn = dialogPhantom.ShowModal();
570   if (dialogReturn == wxID_OK) {
571     wxString selection (dialogPhantom.getPhantom(), *wxConvCurrent);
572     if (theApp->getVerboseLogging())
573       *theApp->getLog() << _T("Selected phantom ") << selection.c_str() << _T("\n");
574     wxString filename = selection + _T(".phm");
575     m_iDefaultPhantomID = Phantom::convertNameToPhantomID (selection.mb_str(wxConvUTF8));
576     theApp->getDocManager()->CreateDocument (filename, wxDOC_SILENT);
577   }
578
579 }
580
581 void
582 MainFrame::OnCreateFilter (wxCommandEvent& WXUNUSED(event))
583 {
584   DialogGetFilterParameters dialogFilter (this, m_iDefaultFilterXSize, m_iDefaultFilterYSize, m_iDefaultFilterID, m_dDefaultFilterParam, m_dDefaultFilterBandwidth, m_iDefaultFilterDomainID, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
585   int dialogReturn = dialogFilter.ShowModal();
586   if (dialogReturn == wxID_OK) {
587     wxString strFilter (dialogFilter.getFilterName(), *wxConvCurrent);
588     wxString strDomain (dialogFilter.getDomainName(), *wxConvCurrent);
589     m_iDefaultFilterID = SignalFilter::convertFilterNameToID (strFilter.mb_str(wxConvUTF8));
590     m_iDefaultFilterDomainID = SignalFilter::convertDomainNameToID (strDomain.mb_str(wxConvUTF8));
591     m_iDefaultFilterXSize = dialogFilter.getXSize();
592     m_iDefaultFilterYSize = dialogFilter.getYSize();
593     m_dDefaultFilterBandwidth = dialogFilter.getBandwidth();
594     m_dDefaultFilterParam= dialogFilter.getFilterParam();
595     m_dDefaultFilterInputScale = dialogFilter.getInputScale();
596     m_dDefaultFilterOutputScale = dialogFilter.getOutputScale();
597     wxString os;
598     os << _T("Generate Filter=") << strFilter
599        << _T(", size=(") << static_cast<int>(m_iDefaultFilterXSize) << _T(",")
600        << static_cast<int>(m_iDefaultFilterYSize)
601        << _T("), domain=") << strDomain.c_str() << _T(", filterParam=")
602        << m_dDefaultFilterParam << _T(", bandwidth=") <<
603       m_dDefaultFilterBandwidth
604        << _T(", inputScale=") << m_dDefaultFilterInputScale << _T(", outputScale=") << m_dDefaultFilterOutputScale;
605     *theApp->getLog() << os << _T("\n");
606     wxString filename = _T("untitled.if");
607     ImageFileDocument* pFilterDoc = theApp->newImageDoc();
608     pFilterDoc->setBadFileOpen();
609     if (! pFilterDoc) {
610       sys_error (ERR_SEVERE, "Unable to create filter image");
611       return;
612     }
613     ImageFile& rIF = pFilterDoc->getImageFile();
614     rIF.setArraySize (m_iDefaultFilterXSize, m_iDefaultFilterYSize);
615     rIF.filterResponse (strDomain.mb_str(wxConvUTF8), m_dDefaultFilterBandwidth, strFilter.mb_str(wxConvUTF8), m_dDefaultFilterParam, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
616     rIF.labelAdd (os.mb_str(wxConvUTF8));
617     if (theApp->getAskDeleteNewDocs())
618       pFilterDoc->Modify (true);
619     pFilterDoc->UpdateAllViews();
620     pFilterDoc->GetFirstView()->OnUpdate (NULL, NULL);
621     pFilterDoc->getView()->getFrame()->SetClientSize(m_iDefaultFilterXSize, m_iDefaultFilterYSize);
622     pFilterDoc->getView()->getFrame()->Show(true);
623   }
624 }
625
626 void
627 CTSimApp::getCompatibleImages (const ImageFileDocument* pIFDoc, std::vector<ImageFileDocument*>& vecIF)
628 {
629   const ImageFile& rIF = pIFDoc->getImageFile();
630   unsigned int nx = rIF.nx();
631   unsigned int ny = rIF.ny();
632   wxList& rListDocs = m_docManager->GetDocuments();
633   for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) {
634     wxDocument* pDoc = reinterpret_cast<wxDocument*>(pNode->GetData());
635     ImageFileDocument* pIFCompareDoc = dynamic_cast<ImageFileDocument*>(pDoc);
636     if (pIFCompareDoc && (pIFDoc != pIFCompareDoc)) {
637       const ImageFile& rCompareIF = pIFCompareDoc->getImageFile();
638       if (rCompareIF.nx() == nx && rCompareIF.ny() == ny)
639         vecIF.push_back (pIFCompareDoc);
640     }
641   }
642 }
643
644
645 void
646 MainFrame::OnNewImageFile (wxCommandEvent& event)
647 {
648   ImageFile* pImageFile = reinterpret_cast<ImageFile*>(event.GetClientData());
649
650   ImageFileDocument* pImageDoc = theApp->newImageDoc();
651   if (! pImageDoc) {
652     sys_error (ERR_SEVERE, "Unable to create image file");
653     return;
654   }
655   pImageDoc->setImageFile (pImageFile);
656   if (theApp->getAskDeleteNewDocs())
657     pImageDoc->Modify (true);
658 }
659
660 void
661 MainFrame::OnNewProjectionFile (wxCommandEvent& event)
662 {
663   Projections* pProjections = reinterpret_cast<Projections*>(event.GetClientData());
664   ProjectionFileDocument* pProjDoc = theApp->newProjectionDoc();
665   if (! pProjDoc) {
666     sys_error (ERR_SEVERE, "Unable to create projection file");
667     return;
668   }
669   pProjDoc->setProjections (pProjections);
670   if (theApp->getAskDeleteNewDocs())
671     pProjDoc->Modify (true);
672 }
673
674 void
675 MainFrame::OnLogEvent (wxCommandEvent& event)
676 {
677   *theApp->getLog() << event.GetString();
678 }
679
680 void
681 MainFrame::OnHelpTips (wxCommandEvent& event)
682 {
683   theApp->ShowTips();
684 }
685
686 void
687 MainFrame::OnHelpContents (wxCommandEvent& event)
688 {
689   showHelp (event.GetId());
690 }
691
692 void
693 MainFrame::OnHelpButton (wxCommandEvent& event)
694 {
695   showHelp (event.GetId());
696 }
697
698 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
699 void
700 MainFrame::OnHelpSecondary (wxCommandEvent& event)
701 {
702   m_htmlHelp.Display ("Contents");
703 }
704 #endif
705
706 void
707 MainFrame::showHelp (int commandID)
708 {
709   switch (commandID) {
710
711   case MAINMENU_HELP_CONTENTS:
712 #ifdef CTSIM_WINHELP
713     m_winHelp.DisplayContents ();
714 #else
715     m_htmlHelp.Display (_T("Contents"));
716 #endif
717     break;
718
719   default:
720 #ifdef CTSIM_WINHELP
721     m_winHelp.DisplaySection (commandID);
722 #else
723     m_htmlHelp.Display (commandID);
724 #endif
725     break;
726   }
727 }
728
729 void
730 MainFrame::OnExit (wxCommandEvent& WXUNUSED(event) )
731 {
732   Close(true);
733 }
734
735 void
736 MainFrame::OnUpdateUI (wxUpdateUIEvent& rEvent)
737 {
738 #ifndef CTSIM_MDI
739   int iPos = 0;
740   wxList& rListDocs = theApp->getDocManager()->GetDocuments();
741   wxNode* pNode = rListDocs.GetFirst();
742   while (iPos < MAX_WINDOW_MENUITEMS && pNode != NULL) {
743     wxDocument* pDoc = static_cast<wxDocument*>(pNode->GetData());
744     wxString strFilename = pDoc->GetFilename();
745     if (iPos < 10) {
746       strFilename += _T("\tCtrl-");
747       strFilename += static_cast<char>('0' + iPos);
748     }
749     static_cast<wxMenuItemBase*>(m_apWindowMenuItems[iPos])->SetName (strFilename);
750     m_apWindowMenuData[iPos] = pDoc;
751     m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+iPos, true);
752     iPos++;
753     pNode = pNode->GetNext();
754   }
755   for (int i = iPos; i < MAX_WINDOW_MENUITEMS; i++) {
756     m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false);
757     static_cast<wxMenuItemBase*>(m_apWindowMenuItems[i])->SetName (_T("[EMPTY]"));
758     m_apWindowMenuData[i] = NULL;
759   }
760 #endif
761 }
762
763
764 void
765 MainFrame::DoWindowMenu (int iMenuPosition, wxCommandEvent& event)
766 {
767   if (wxDocument* pDoc = m_apWindowMenuData [iMenuPosition]) {
768     wxString strFilename = pDoc->GetFilename();
769     const wxView* pView = pDoc->GetFirstView();
770     if (pView) {
771       wxWindow* pWindow = pView->GetFrame();
772       pWindow->SetFocus();
773       pWindow->Raise();
774     }
775   }
776 }
777
778 void MainFrame::OnWindowMenu0 (wxCommandEvent& event)
779 { DoWindowMenu (0, event); }
780
781 void MainFrame::OnWindowMenu1 (wxCommandEvent& event)
782 { DoWindowMenu (1, event); }
783
784 void MainFrame::OnWindowMenu2 (wxCommandEvent& event)
785 { DoWindowMenu (2, event); }
786
787 void MainFrame::OnWindowMenu3 (wxCommandEvent& event)
788 { DoWindowMenu (3, event); }
789
790 void MainFrame::OnWindowMenu4 (wxCommandEvent& event)
791 { DoWindowMenu (4, event); }
792
793 void MainFrame::OnWindowMenu5 (wxCommandEvent& event)
794 { DoWindowMenu (5, event); }
795
796 void MainFrame::OnWindowMenu6 (wxCommandEvent& event)
797 { DoWindowMenu (6, event); }
798
799 void MainFrame::OnWindowMenu7 (wxCommandEvent& event)
800 { DoWindowMenu (7, event); }
801
802 void MainFrame::OnWindowMenu8 (wxCommandEvent& event)
803 { DoWindowMenu (8, event); }
804
805 void MainFrame::OnWindowMenu9 (wxCommandEvent& event)
806 { DoWindowMenu (9, event); }
807
808 void MainFrame::OnWindowMenu10 (wxCommandEvent& event)
809 { DoWindowMenu (10, event); }
810
811 void MainFrame::OnWindowMenu11 (wxCommandEvent& event)
812 { DoWindowMenu (11, event); }
813
814 void MainFrame::OnWindowMenu12 (wxCommandEvent& event)
815 { DoWindowMenu (12, event); }
816
817 void MainFrame::OnWindowMenu13 (wxCommandEvent& event)
818 { DoWindowMenu (13, event); }
819
820 void MainFrame::OnWindowMenu14 (wxCommandEvent& event)
821 { DoWindowMenu (14, event); }
822
823 void MainFrame::OnWindowMenu15 (wxCommandEvent& event)
824 { DoWindowMenu (15, event); }
825
826 void MainFrame::OnWindowMenu16 (wxCommandEvent& event)
827 { DoWindowMenu (16, event); }
828
829 void MainFrame::OnWindowMenu17 (wxCommandEvent& event)
830 { DoWindowMenu (17, event); }
831
832 void MainFrame::OnWindowMenu18 (wxCommandEvent& event)
833 { DoWindowMenu (18, event); }
834
835 void MainFrame::OnWindowMenu19 (wxCommandEvent& event)
836 { DoWindowMenu (19, event); }
837
838
839 class BitmapControl : public wxPanel
840 {
841 private:
842   DECLARE_DYNAMIC_CLASS (BitmapControl)
843     DECLARE_EVENT_TABLE ()
844     wxBitmap* m_pBitmap;
845
846 public:
847   BitmapControl (wxBitmap* pBitmap, wxWindow *parent, wxWindowID id = -1,
848     const wxPoint& pos = wxDefaultPosition,
849     const wxSize& size = wxDefaultSize,
850     long style = wxSTATIC_BORDER,
851     const wxValidator& validator = wxDefaultValidator,
852                  const wxString& name = _T("BitmapCtrl"));
853
854
855   virtual ~BitmapControl();
856
857   virtual wxSize GetBestSize() const;
858
859   wxBitmap* getBitmap()
860   { return m_pBitmap; }
861
862   void OnPaint(wxPaintEvent& event);
863 };
864
865
866 BEGIN_EVENT_TABLE(BitmapControl, wxPanel)
867 EVT_PAINT(BitmapControl::OnPaint)
868 END_EVENT_TABLE()
869
870 IMPLEMENT_CLASS(BitmapControl, wxPanel)
871
872
873 BitmapControl::BitmapControl (wxBitmap* pBitmap, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size,
874                               long style, const wxValidator& validator, const wxString& name)
875                               : m_pBitmap(pBitmap)
876 {
877   Create(parent, id, pos, size, style, name);
878
879   SetSize (GetBestSize());
880 }
881
882 wxSize
883 BitmapControl::GetBestSize () const
884 {
885   if (m_pBitmap)
886     return wxSize (m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
887   else
888     return wxSize(0,0);
889 }
890
891 BitmapControl::~BitmapControl()
892 {}
893
894 void
895 BitmapControl::OnPaint (wxPaintEvent& event)
896 {
897   wxPaintDC dc(this);
898   if (m_pBitmap)
899     dc.DrawBitmap (*m_pBitmap, 0, 0);
900 }
901
902
903 class BitmapDialog : public wxDialog {
904 private:
905   BitmapControl* m_pBitmapCtrl;
906
907 public:
908   BitmapDialog (wxBitmap* pBitmap, char const* pszTitle);
909   virtual ~BitmapDialog();
910 };
911
912 BitmapDialog::BitmapDialog (wxBitmap* pBitmap, char const* pszTitle)
913   : wxDialog(theApp->getMainFrame(), -1, wxString(pszTitle,*wxConvCurrent), wxDefaultPosition, wxDefaultSize, wxDIALOG_MODAL | wxDEFAULT_DIALOG_STYLE)
914 {
915   wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL);
916
917   pTopSizer->Add (new BitmapControl (pBitmap, this), 0, wxALIGN_CENTER | wxALL, 5);
918
919   wxBoxSizer* pButtonSizer = new wxBoxSizer (wxHORIZONTAL);
920   wxButton* pButtonOk = new wxButton (this, wxID_OK, _T("Ok"));
921   pButtonSizer->Add (pButtonOk, 0, wxEXPAND | wxALL, 10);
922
923   pTopSizer->Add (pButtonSizer, 0, wxALIGN_CENTER);
924
925   SetAutoLayout (true);
926   SetSizer (pTopSizer);
927   pTopSizer->Fit (this);
928   pTopSizer->SetSizeHints (this);
929 }
930
931 BitmapDialog::~BitmapDialog()
932 {}
933
934
935 void
936 MainFrame::OnPreferences (wxCommandEvent& WXUNUSED(event) )
937 {
938   DialogPreferences dlg (this, _T("CTSim Preferences"), theApp->getAdvancedOptions(),
939     theApp->getAskDeleteNewDocs(), theApp->getVerboseLogging(), theApp->getStartupTips(),
940     theApp->getUseBackgroundTasks());
941   if (dlg.ShowModal() == wxID_OK) {
942     theApp->setAdvancedOptions (dlg.getAdvancedOptions());
943     theApp->setAskDeleteNewDocs (dlg.getAskDeleteNewDocs());
944     theApp->setVerboseLogging (dlg.getVerboseLogging());
945     theApp->setStartupTips (dlg.getStartupTips());
946     theApp->setUseBackgroundTasks (dlg.getUseBackgroundTasks());
947   }
948 }
949
950 void
951 MainFrame::OnImport (wxCommandEvent& WXUNUSED(event) )
952 {
953   DialogImportParameters dialogImport (this, m_iDefaultImportFormat);
954   if (dialogImport.ShowModal() != wxID_OK)
955     return;
956
957   wxString strFormatName (dialogImport.getFormatName (), *wxConvCurrent);
958   m_iDefaultImportFormat = ImageFile::convertImportFormatNameToID (strFormatName.mb_str(wxConvUTF8));
959
960   wxString strExt;
961   wxString strWildcard;
962   if (m_iDefaultImportFormat == ImageFile::IMPORT_FORMAT_PPM) {
963     strExt = _T(".ppm");
964     strWildcard = _T("PPM Files (*.ppm)|*.ppm|PGM Files (*.pgm)|*.pgm");
965   }
966 #ifdef HAVE_PNG
967   else if (m_iDefaultImportFormat == ImageFile::IMPORT_FORMAT_PNG) {
968     strExt = _T(".png");
969     strWildcard = _T("PNG Files (*.png)|*.png");
970   }
971 #endif
972 #ifdef HAVE_CTN_DICOM
973   else if (m_iDefaultImportFormat == ImageFile::IMPORT_FORMAT_DICOM) {
974     strExt = _T("*.*");
975     strWildcard = _T("Dicom Files (*.*)|*.*");
976   }
977 #endif
978   else {
979     return;
980   }
981
982 #if WXWIN_COMPATIBILITY_2_4
983   wxString strFilename = wxFileSelector (wxString(wxConvUTF8.cMB2WX("Import Filename")), wxString(wxConvUTF8.cMB2WX("")),
984                                          wxString(wxConvUTF8.cMB2WX("")), strExt, strWildcard, wxHIDE_READONLY | wxOPEN);
985 #else
986   wxString strFilename = wxFileSelector (wxString(wxConvUTF8.cMB2WX("Import Filename")), wxString(wxConvUTF8.cMB2WX("")),
987                                          wxString(wxConvUTF8.cMB2WX("")), strExt, strWildcard, wxOPEN);
988 #endif
989
990   if (! strFilename.IsEmpty()) {
991     if (m_iDefaultImportFormat == ImageFile::IMPORT_FORMAT_PPM || m_iDefaultImportFormat == ImageFile::IMPORT_FORMAT_PNG) {
992       ImageFile* pIF = new ImageFile;
993       if (pIF->importImage (strFormatName.mb_str(wxConvUTF8), strFilename.mb_str(wxConvUTF8))) {
994         ImageFileDocument* pIFDoc = theApp->newImageDoc();
995         pIFDoc->setImageFile(pIF);
996         pIFDoc->getView()->getFrame()->Show(true);
997         std::ostringstream os;
998         os << "Import file " << strFilename.c_str() << " (type " << strFormatName.c_str() << ")";
999         pIF->labelAdd (os.str().c_str());
1000         if (theApp->getAskDeleteNewDocs())
1001           pIFDoc->Modify (true);
1002         pIFDoc->UpdateAllViews();
1003         pIFDoc->GetFirstView()->OnUpdate (NULL, NULL);
1004         pIFDoc->getView()->getFrame()->Show(true);
1005       } else
1006         delete pIF;
1007     }
1008 #ifdef HAVE_CTN_DICOM
1009     else if (m_iDefaultImportFormat == ImageFile::IMPORT_FORMAT_DICOM) {
1010       DicomImporter dicomImport (strFilename.mb_str(wxConvUTF8));
1011       if (dicomImport.fail()) {
1012         ::wxMessageBox (wxConvUTF8.cMB2WX(dicomImport.failMessage().c_str()), _T("Import Error"));
1013       } else if (dicomImport.testImage()) {
1014         ImageFileDocument* pIFDoc = theApp->newImageDoc();
1015         ImageFile* pIF = dicomImport.getImageFile();
1016         pIFDoc->setImageFile (pIF);
1017         std::ostringstream os;
1018         os << "Import file " << strFilename.c_str() << " (type " << strFormatName.c_str() << ")";
1019         pIF->labelAdd (os.str().c_str());
1020         if (theApp->getAskDeleteNewDocs())
1021           pIFDoc->Modify (true);
1022         pIFDoc->UpdateAllViews();
1023         pIFDoc->getView()->setInitialClientSize();
1024         pIFDoc->Activate();
1025       } else if (dicomImport.testProjections()) {
1026         ProjectionFileDocument* pProjDoc = theApp->newProjectionDoc();
1027         Projections* pProj = dicomImport.getProjections();
1028         pProjDoc->setProjections (pProj);
1029         pProjDoc->getView()->getFrame()->Show(true);
1030         std::ostringstream os;
1031         os << "Import projection file " << strFilename.c_str() << " (type " << strFormatName.c_str() << ")";
1032         pProj->setRemark (os.str().c_str());
1033         if (theApp->getAskDeleteNewDocs())
1034           pProjDoc->Modify (true);
1035         pProjDoc->UpdateAllViews();
1036         pProjDoc->getView()->setInitialClientSize();
1037         pProjDoc->Activate();
1038       } else
1039         ::wxMessageBox (_T("Unrecognized DICOM file contents"), _T("Import Error"));
1040     }
1041 #endif
1042     else
1043       sys_error (ERR_WARNING, "Unknown import format type");
1044   }
1045 }
1046
1047 #include "./splash.xpm"
1048 void
1049 MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
1050 {
1051   wxString strOSDesc = ::wxGetOsDescription();
1052   *theApp->getLog() << _T("Operating System: ") << strOSDesc;
1053   *theApp->getLog() << _T(", wxWindows: ") << wxVERSION_STRING;
1054 #ifdef _TIMESTAMP__
1055   *theApp->getLog() << _T(", Build Date: ") << wxConvUTF8.cMB2WX(_TIMESTAMP__);
1056 #endif
1057 #if defined(DEBUG)
1058   *theApp->getLog() << _T(", Debug version");
1059 #else
1060   *theApp->getLog() << _T(", Release version");
1061 #endif
1062 #ifdef VERSION
1063   *theApp->getLog() << _T(" ") <<  wxConvUTF8.cMB2WX(VERSION);
1064 #elif defined(CTSIMVERSION)
1065   *theApp->getLog() << _T(" ") <<  _T(CTSIMVERSION);
1066 #endif
1067     *theApp->getLog() << _T("\n");
1068
1069   wxBitmap bmp (splash);
1070   if (bmp.Ok()) {
1071     BitmapDialog dlg (&bmp, "About CTSim");
1072     dlg.ShowModal();
1073   } else {
1074     wxString msg = _T("CTSim\nThe Open Source Computed Tomography Simulator\n");
1075 #ifdef VERSION
1076     msg << _T("Version: ") <<  wxConvUTF8.cMB2WX(VERSION) << _T("\n\n");
1077 #elif defined(CTSIMVERSION)
1078     msg << _T("Version: ") <<  wxConvUTF8.cMB2WX(CTSIMVERSION) << _T("\n\n");
1079 #endif
1080     msg += _T("Author: Kevin Rosenberg <kevin@rosenberg.net>\nUsage: ctsim [files-to-open..] [--help]");
1081
1082     wxMessageBox(msg, _T("About CTSim"), wxOK | wxICON_INFORMATION, this);
1083     *theApp->getLog() << msg << wxConvUTF8.cMB2WX("\n");
1084   }
1085 }
1086
1087
1088 // Create new documents
1089
1090 ProjectionFileDocument*
1091 CTSimApp::newProjectionDoc()
1092 {
1093   ProjectionFileDocument* newDoc = dynamic_cast<ProjectionFileDocument*>(m_pDocTemplProjection->CreateDocument (_T("")));
1094   if (newDoc) {
1095     newDoc->SetDocumentName (m_pDocTemplProjection->GetDocumentName());
1096     newDoc->SetDocumentTemplate (m_pDocTemplProjection);
1097     newDoc->OnNewDocument();
1098   }
1099
1100   return newDoc;
1101 }
1102
1103 ImageFileDocument*
1104 CTSimApp::newImageDoc()
1105 {
1106   ImageFileDocument* newDoc = dynamic_cast<ImageFileDocument*>(m_pDocTemplImage->CreateDocument (_T("")));
1107   if (newDoc) {
1108     newDoc->SetDocumentName (m_pDocTemplImage->GetDocumentName());
1109     newDoc->SetDocumentTemplate (m_pDocTemplImage);
1110     newDoc->OnNewDocument();
1111   }
1112
1113   return newDoc;
1114 }
1115
1116 PlotFileDocument*
1117 CTSimApp::newPlotDoc()
1118 {
1119   PlotFileDocument* newDoc = dynamic_cast<PlotFileDocument*>(m_pDocTemplPlot->CreateDocument (_T("")));
1120   if (newDoc) {
1121     newDoc->SetDocumentName (m_pDocTemplPlot->GetDocumentName());
1122     newDoc->SetDocumentTemplate (m_pDocTemplPlot);
1123     newDoc->OnNewDocument();
1124   }
1125
1126   return newDoc;
1127 }
1128
1129
1130 TextFileDocument*
1131 CTSimApp::newTextDoc()
1132 {
1133   wxString strFilename (getUntitledFilename());
1134   strFilename += wxString(".txt", *wxConvCurrent);
1135
1136   TextFileDocument* newDoc = dynamic_cast<TextFileDocument*>(m_pDocTemplText->CreateDocument (_T("")));
1137   if (newDoc) {
1138     newDoc->SetDocumentName (m_pDocTemplText->GetDocumentName());
1139     newDoc->SetDocumentTemplate (m_pDocTemplText);
1140     newDoc->OnNewDocument();
1141   }
1142
1143   return newDoc;
1144 }
1145
1146
1147 PhantomFileDocument*
1148 CTSimApp::newPhantomDoc()
1149 {
1150   PhantomFileDocument* newDoc = dynamic_cast<PhantomFileDocument*>(m_pDocTemplPhantom->CreateDocument (_T("")));
1151   if (newDoc) {
1152     newDoc->SetDocumentName (m_pDocTemplPhantom->GetDocumentName());
1153     newDoc->SetDocumentTemplate (m_pDocTemplPhantom);
1154     newDoc->OnNewDocument();
1155   }
1156
1157   return newDoc;
1158 }
1159
1160
1161 #if wxUSE_GLCANVAS
1162 Graph3dFileDocument*
1163 CTSimApp::newGraph3dDoc()
1164 {
1165   Graph3dFileDocument* newDoc = dynamic_cast<Graph3dFileDocument*>(m_pDocTemplGraph3d->CreateDocument (_T("")));
1166   if (newDoc) {
1167     newDoc->SetDocumentName (m_pDocTemplGraph3d->GetDocumentName());
1168     newDoc->SetDocumentTemplate (m_pDocTemplGraph3d);
1169     newDoc->OnNewDocument();
1170   }
1171
1172   return newDoc;
1173 }
1174 #endif