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