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