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