r520: no 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-2000 Kevin Rosenberg
11 **
12 **  $Id: ctsim.cpp,v 1.74 2001/02/11 04:56:38 kevin Exp $
13 **
14 **  This program is free software; you can redistribute it and/or modify
15 **  it under the terms of the GNU General Public License (version 2) as
16 **  published by the Free Software Foundation.
17 **
18 **  This program is distributed in the hope that it will be useful,
19 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 **  GNU General Public License for more details.
22 **
23 **  You should have received a copy of the GNU General Public License
24 **  along with this program; if not, write to the Free Software
25 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 ******************************************************************************/
27
28 #ifdef MSVC
29 #define strdup _strdup
30 #endif
31
32 // For compilers that support precompilation, includes "wx/wx.h".
33 #include "wx/wxprec.h"
34
35 #ifdef __BORLANDC__
36 #pragma hdrstop
37 #endif
38
39 #ifndef WX_PRECOMP
40 #include "wx/wx.h"
41 #endif
42
43 #include "wx/image.h"
44 #include "wx/filesys.h"
45 #include "wx/fs_zip.h"
46 #include "wx/msw/helpchm.h"
47
48 #if !wxUSE_DOC_VIEW_ARCHITECTURE
49 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
50 #endif
51
52
53 #include "ct.h"
54 #include "ctsim.h"
55 #include "ctsim-map.h"
56 #include "docs.h"
57 #include "views.h"
58 #include "dialogs.h"
59
60 #if defined(HAVE_CONFIG_H)
61 #include "config.h"
62 #endif
63
64 #if defined(HAVE_GETOPT_H) || defined(HAVE_GETOPT_LONG)
65 #ifdef MSVC
66 #define __STDC__ 1
67 #endif
68 #include "getopt.h"
69 #ifdef MSVC
70 #undef __STDC__
71 #endif
72 #endif
73
74 static const char* rcsindent = "$Id: ctsim.cpp,v 1.74 2001/02/11 04:56:38 kevin Exp $";
75
76 struct option CTSimApp::ctsimOptions[] = 
77 {
78         {"help", 0, 0, O_HELP},
79         {"version", 0, 0, O_VERSION},
80         {0, 0, 0, 0}
81 };
82
83 IMPLEMENT_APP(CTSimApp)
84
85 CTSimApp::CTSimApp()
86 : m_docManager(NULL), m_pFrame(NULL), m_pLog(0), m_pLogDoc(0), m_bAdvancedOptions(false)
87 {
88         theApp = this;
89 }
90
91 #ifdef HAVE_SYS_TIME_H
92 #include <sys/time.h>
93 #endif
94
95 #ifdef HAVE_SYS_RESOURCE_H
96 #include <sys/resource.h>
97 #endif
98
99 bool
100 CTSimApp::OnInit()
101 {
102 #ifdef HAVE_SETPRIORITY
103         setpriority (PRIO_PROCESS, 0, 15);  // set to low scheduling priority
104 #endif
105         
106         m_pConfig = new wxConfig("ctsim", _T(""), ".ctsim", "", wxCONFIG_USE_LOCAL_FILE);
107         wxConfigBase::Set(m_pConfig);
108         
109         g_bRunningWXWindows = true;
110         // process options
111         while (1) {
112                 int c = getopt_long (argc, argv, "", ctsimOptions, NULL);
113                 if (c == -1)
114                         break;
115                 
116                 switch (c) {
117                 case O_VERSION:
118                         std::cout << rcsindent << std::endl;
119 #ifdef CTSIMVERSION
120                         std::cout << "Version: CTSIMVERSION" << std::endl;
121 #elif defined(VERSION)
122                         std::cout << "Version: VERSION" << std::endl;
123 #endif
124                         exit(0);
125                 case O_HELP:
126                 case '?':
127                         usage (argv[0]);
128                         exit (0);
129                 default:
130                         usage (argv[0]);
131                         exit (1);
132                 }
133         }
134         
135         m_docManager = new wxDocManager (wxDEFAULT_DOCMAN_FLAGS, true);
136         
137         m_pDocTemplImage = new wxDocTemplate (m_docManager, "ImageFile", "*.if", "", "if", "ImageFile", "ImageView", CLASSINFO(ImageFileDocument), CLASSINFO(ImageFileView));
138         m_pDocTemplProjection = new wxDocTemplate (m_docManager, "ProjectionFile", "*.pj", "", "pj", "ProjectionFile", "ProjectionView", CLASSINFO(ProjectionFileDocument), CLASSINFO(ProjectionFileView));
139         m_pDocTemplPhantom = new wxDocTemplate (m_docManager, "PhantomFile", "*.phm", "", "phm", "PhantomFile", "PhantomView", CLASSINFO(PhantomFileDocument), CLASSINFO(PhantomFileView));
140         m_pDocTemplPlot = new wxDocTemplate (m_docManager, "PlotFile", "*.plt", "", "plt", "PlotFile", "PlotView", CLASSINFO(PlotFileDocument), CLASSINFO(PlotFileView));
141         m_pDocTemplText = new wxDocTemplate (m_docManager, "TextFile", "*.txt", "", "txt", "TextFile", "TextView", CLASSINFO(TextFileDocument), CLASSINFO(TextFileView), wxTEMPLATE_INVISIBLE);
142 #if wxUSE_GLCANVAS
143         m_pDocTemplGraph3d = new wxDocTemplate (m_docManager, "Graph3dFile", "*.g3d", "", "g3d", "Graph3dFile", "Graph3dView", CLASSINFO(Graph3dFileDocument), CLASSINFO(Graph3dFileView), wxTEMPLATE_INVISIBLE);
144 #endif
145
146 #if wxUSE_GIF
147         wxImage::AddHandler(new wxGIFHandler);     // Required for images in the online documentation
148 #endif
149         
150 #if wxUSE_STREAMS && wxUSE_ZIPSTREAM && wxUSE_ZLIB
151         wxFileSystem::AddHandler(new wxZipFSHandler);     // Required for advanced HTML help
152 #endif
153         
154         // Create the main frame window
155         int xDisplay, yDisplay;
156         ::wxDisplaySize (&xDisplay, &yDisplay);
157         m_pFrame = new MainFrame(m_docManager, (wxFrame *) NULL, -1, "CTSim", wxPoint(0, 0), 
158                 wxSize(nearest<int>(xDisplay * .75), nearest<int>(yDisplay * .755)), wxDEFAULT_FRAME_STYLE);
159         
160         setIconForFrame (m_pFrame);
161         m_pFrame->Centre(wxBOTH);
162         m_pFrame->Show(true);  
163         SetTopWindow (m_pFrame);
164         
165         if (m_pConfig)
166                 m_docManager->FileHistoryLoad(*m_pConfig);
167         
168 #ifdef CTSIM_MDI
169         m_pLogDoc = newTextDoc();
170         if (m_pLogDoc) {
171                 m_pLog = m_pLogDoc->getTextCtrl();
172                 m_pLogDoc->SetDocumentName("Log.txt");
173                 m_pLogDoc->SetFilename("Log.txt");
174                 m_pLogDoc->getView()->getFrame()->SetTitle("Log");
175                 int xSize, ySize;
176                 m_pFrame->GetClientSize(&xSize, &ySize);
177                 int yLogSize = ySize / 4;
178                 m_pLogDoc->getView()->getFrame()->SetSize (0, ySize - yLogSize, xSize, yLogSize);
179                 m_pLogDoc->getView()->getFrame()->Show (true);
180         } else
181 #else
182                 m_pLog = new wxTextCtrl (m_pFrame, -1, "Log Window\n", wxPoint(0, 0), wxSize(0,0), wxTE_MULTILINE | wxTE_READONLY);
183 #endif
184         wxLog::SetActiveTarget (new wxLogTextCtrl(m_pLog));
185
186 #ifdef CTSIM_WINHELP
187         if (! m_pFrame->getWinHelpController().Initialize("ctsim"))
188                 *m_pLog << "Cannot initialize the Windows Help system" << "\n";
189 #endif
190         wxString helpDir;
191         if (! m_pConfig->Read("HelpDir", &helpDir))
192                 helpDir = ::wxGetCwd();
193         if (! m_pFrame->getHtmlHelpController().Initialize(helpDir + "/ctsim") &&
194                 ! m_pFrame->getHtmlHelpController().Initialize("/usr/local/man/ctsim"))
195                 *m_pLog << "Cannot initialize the HTML Help system" << "\n";
196         else {
197             if (::wxDirExists ("/tmp"))
198                 m_pFrame->getHtmlHelpController().SetTempDir(_T("/tmp"));
199             m_pFrame->getHtmlHelpController().UseConfig (m_pConfig);
200         }
201
202         for (int i = optind + 1; i <= argc; i++) {
203                 wxString filename = argv [i - 1];
204                 m_docManager->CreateDocument (filename, wxDOC_SILENT);
205         }
206         
207         return true;
208 }
209
210
211 #include "./ctsim.xpm"
212 void
213 CTSimApp::setIconForFrame(wxFrame* pFrame)
214 {
215         wxIcon iconApp (ctsim16_xpm);
216         
217         if (iconApp.Ok())
218                 pFrame->SetIcon (iconApp);
219 }
220
221 void
222 CTSimApp::usage(const char* program)
223 {
224         std::cout << "usage: " << fileBasename(program) << " [files-to-open...] [OPTIONS]\n";
225         std::cout << "Computed Tomography Simulator (Graphical Shell)\n";
226         std::cout << "\n";
227         std::cout << "  --version Display version\n";
228         std::cout << "  --help    Display this help message\n";
229 }
230
231 int
232 CTSimApp::OnExit()
233 {
234         delete m_pConfig;
235
236 #ifdef HAVE_DMALLOC
237         dmalloc_shutdown();
238 #endif
239         return 0;
240 }
241
242 wxString
243 CTSimApp::getUntitledFilename()
244 {
245         static int untitledNumber = 1;
246         
247         wxString filename ("Untitled");
248         filename << untitledNumber++;
249         
250         return (filename);
251 }
252
253
254 // Top-level window for CTSim
255
256 #if CTSIM_MDI
257 IMPLEMENT_CLASS(MainFrame, wxMDIParentFrame)
258
259 BEGIN_EVENT_TABLE(MainFrame, wxMDIParentFrame)
260 #else
261 IMPLEMENT_CLASS(MainFrame, wxDocParentFrame)
262
263 BEGIN_EVENT_TABLE(MainFrame, wxDocParentFrame)
264 #endif
265
266 EVT_MENU(MAINMENU_FILE_PREFERENCES, MainFrame::OnPreferences)
267 EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout)
268 EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents)
269 EVT_MENU(MAINMENU_HELP_TOPICS, MainFrame::OnHelpTopics)
270 EVT_SIZE(MainFrame::OnSize)
271
272 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
273 EVT_MENU(MAINMENU_HELP_SECONDARY, MainFrame::OnHelpSecondary)
274 #endif
275 EVT_MENU(MAINMENU_FILE_CREATE_PHANTOM, MainFrame::OnCreatePhantom)
276 EVT_MENU(MAINMENU_FILE_CREATE_FILTER, MainFrame::OnCreateFilter)
277 EVT_MENU(MAINMENU_FILE_EXIT, MainFrame::OnExit)
278 EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MainFrame::OnMRUFile)
279 EVT_MENU(MAINMENU_WINDOW_BASE, MainFrame::OnWindowMenu0)
280 EVT_MENU(MAINMENU_WINDOW_BASE+1, MainFrame::OnWindowMenu1)
281 EVT_MENU(MAINMENU_WINDOW_BASE+2, MainFrame::OnWindowMenu2)
282 EVT_MENU(MAINMENU_WINDOW_BASE+3, MainFrame::OnWindowMenu3)
283 EVT_MENU(MAINMENU_WINDOW_BASE+4, MainFrame::OnWindowMenu4)
284 EVT_MENU(MAINMENU_WINDOW_BASE+5, MainFrame::OnWindowMenu5)
285 EVT_MENU(MAINMENU_WINDOW_BASE+6, MainFrame::OnWindowMenu6)
286 EVT_MENU(MAINMENU_WINDOW_BASE+7, MainFrame::OnWindowMenu7)
287 EVT_MENU(MAINMENU_WINDOW_BASE+8, MainFrame::OnWindowMenu8)
288 EVT_MENU(MAINMENU_WINDOW_BASE+9, MainFrame::OnWindowMenu9)
289 EVT_MENU(MAINMENU_WINDOW_BASE+10, MainFrame::OnWindowMenu10)
290 EVT_MENU(MAINMENU_WINDOW_BASE+11, MainFrame::OnWindowMenu11)
291 EVT_MENU(MAINMENU_WINDOW_BASE+12, MainFrame::OnWindowMenu12)
292 EVT_MENU(MAINMENU_WINDOW_BASE+13, MainFrame::OnWindowMenu13)
293 EVT_MENU(MAINMENU_WINDOW_BASE+14, MainFrame::OnWindowMenu14)
294 EVT_MENU(MAINMENU_WINDOW_BASE+15, MainFrame::OnWindowMenu15)
295 EVT_MENU(MAINMENU_WINDOW_BASE+16, MainFrame::OnWindowMenu16)
296 EVT_MENU(MAINMENU_WINDOW_BASE+17, MainFrame::OnWindowMenu17)
297 EVT_MENU(MAINMENU_WINDOW_BASE+18, MainFrame::OnWindowMenu18)
298 EVT_MENU(MAINMENU_WINDOW_BASE+19, MainFrame::OnWindowMenu19)
299 EVT_UPDATE_UI_RANGE(MAINMENU_WINDOW_BASE, MAINMENU_WINDOW_BASE+20, MainFrame::OnUpdateUI)
300 END_EVENT_TABLE()
301
302
303
304 #if CTSIM_MDI
305 MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
306 : wxDocMDIParentFrame(manager, NULL, id, title, pos, size, type, "MainFrame")
307 #else
308 MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
309 : wxDocParentFrame(manager, frame, id, title, pos, size, type, "MainFrame")
310 #endif
311 {
312   m_bShuttingDown = false;
313
314         //// Make a menubar
315         wxMenu *file_menu = new wxMenu;
316         
317         file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
318         file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
319         file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O");
320         
321         file_menu->AppendSeparator();
322   file_menu->Append (MAINMENU_FILE_PREFERENCES, "Pr&eferences...");
323         file_menu->Append(MAINMENU_FILE_EXIT, "E&xit");
324         
325         //  history of files visited
326         theApp->getDocManager()->FileHistoryAddFilesToMenu(file_menu);
327         theApp->getDocManager()->FileHistoryUseMenu(file_menu);
328         
329 #ifndef CTSIM_MDI
330         m_pWindowMenu = new wxMenu;
331         m_pWindowMenu->UpdateUI (this);
332 #endif
333         
334         wxMenu* help_menu = new wxMenu;
335         help_menu->Append (MAINMENU_HELP_CONTENTS, "&Contents\tF1");
336         help_menu->Append (MAINMENU_HELP_TOPICS, "&Topics\tCtrl-T");
337 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
338         help_menu->Append (MAINMENU_HELP_SECONDARY, "&Secondary Help");
339 #endif
340         help_menu->Append (MAINMENU_HELP_ABOUT, "&About");
341         
342         wxMenuBar* menu_bar = new wxMenuBar;
343         
344         menu_bar->Append(file_menu, "&File");
345 #ifndef CTSIM_MDI
346         menu_bar->Append(m_pWindowMenu, "&Window");
347 #endif
348         menu_bar->Append(help_menu, "&Help");
349         
350         SetMenuBar(menu_bar);
351         
352 #ifndef CTSIM_MDI
353         int i;
354         for (i = 0; i < MAX_WINDOW_MENUITEMS; i++) {
355                 m_apWindowMenuItems[i] = new wxMenuItem (m_pWindowMenu, MAINMENU_WINDOW_BASE+i, wxString("[EMPTY]"));
356                 m_pWindowMenu->Append (m_apWindowMenuItems[i]);
357                 m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false);
358         }
359 #endif
360         
361         m_iDefaultPhantomID = Phantom::PHM_HERMAN;
362         m_iDefaultFilterID = SignalFilter::FILTER_BANDLIMIT;
363         m_iDefaultFilterDomainID = SignalFilter::DOMAIN_FREQUENCY;
364         m_iDefaultFilterXSize = 256;
365         m_iDefaultFilterYSize = 256;
366         m_dDefaultFilterParam = 1.;
367         m_dDefaultFilterBandwidth = 1.;
368         m_dDefaultFilterInputScale = 1.;
369         m_dDefaultFilterOutputScale = 1.;
370         
371         wxAcceleratorEntry accelEntries[15];
372         accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
373         accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
374         accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
375         accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
376 #ifndef CTSIM_MDI
377         accelEntries[4].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
378         for (i = 0; i < 10; i++)
379                 accelEntries[i+4].Set (wxACCEL_CTRL, static_cast<int>('0'+i), MAINMENU_WINDOW_BASE+i);
380         wxAcceleratorTable accelTable (15, accelEntries);
381 #else
382         wxAcceleratorTable accelTable (4, accelEntries);
383 #endif
384         
385         SetAcceleratorTable (accelTable);
386 }
387
388 MainFrame::~MainFrame()
389 {
390   m_bShuttingDown = true; // Currently used so that Log Window will close
391 #if 0
392   // delete all non-modified documents
393         wxList& rListDocs = theApp->getDocManager()->GetDocuments();
394         for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) {
395                 wxDocument* pDoc = dynamic_cast<wxDocument*>(pNode->GetData());
396     if (pDoc && ! pDoc->IsModified()) {
397       theApp->getDocManager()->RemoveDocument(pDoc);
398       delete pDoc;
399     }
400         }
401 #endif
402   ::wxYield();
403         if (theApp->getConfig())
404                 theApp->getDocManager()->FileHistorySave (*theApp->getConfig());
405   ::wxYield();
406         delete theApp->getDocManager(); 
407
408 }
409
410 void
411 MainFrame::OnSize (wxSizeEvent& event)
412 {
413 #ifdef CTSIM_MDI
414     if (theApp->getLogDoc()) {
415         int xSize, ySize;       
416                 GetClientSize(&xSize, &ySize);
417                 int yLogSize = ySize / 4;
418                   theApp->getLogDoc()->getView()->getFrame()->SetSize (0, ySize - yLogSize, xSize, yLogSize);
419                   theApp->getLogDoc()->getView()->getFrame()->Show (true);
420     }
421 #endif
422         
423 #if CTSIM_MDI
424         wxDocMDIParentFrame::OnSize (event);
425 #else
426         wxDocParentFrame::OnSize (event);
427 #endif
428 }
429
430 void 
431 MainFrame::OnCreatePhantom(wxCommandEvent& event)
432 {
433         DialogGetPhantom dialogPhantom (this, m_iDefaultPhantomID);
434         int dialogReturn = dialogPhantom.ShowModal();
435         if (dialogReturn == wxID_OK) {
436                 wxString selection (dialogPhantom.getPhantom());
437                 *theApp->getLog() << "Selected phantom " << selection.c_str() << "\n";
438                 wxString filename = selection + ".phm";
439                 m_iDefaultPhantomID = Phantom::convertNameToPhantomID (selection.c_str());
440                 theApp->getDocManager()->CreateDocument (filename, wxDOC_SILENT);
441         }
442         
443 }
444
445 void 
446 MainFrame::OnCreateFilter (wxCommandEvent& WXUNUSED(event))
447 {
448         DialogGetFilterParameters dialogFilter (this, m_iDefaultFilterXSize, m_iDefaultFilterYSize, m_iDefaultFilterID, m_dDefaultFilterParam, m_dDefaultFilterBandwidth, m_iDefaultFilterDomainID, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
449         int dialogReturn = dialogFilter.ShowModal();
450         if (dialogReturn == wxID_OK) {
451                 wxString strFilter (dialogFilter.getFilterName());
452                 wxString strDomain (dialogFilter.getDomainName());
453                 m_iDefaultFilterID = SignalFilter::convertFilterNameToID (strFilter.c_str());
454                 m_iDefaultFilterDomainID = SignalFilter::convertDomainNameToID (strDomain.c_str());
455                 m_iDefaultFilterXSize = dialogFilter.getXSize();
456                 m_iDefaultFilterYSize = dialogFilter.getYSize();
457                 m_dDefaultFilterBandwidth = dialogFilter.getBandwidth();
458                 m_dDefaultFilterParam= dialogFilter.getFilterParam();
459                 m_dDefaultFilterInputScale = dialogFilter.getInputScale();
460                 m_dDefaultFilterOutputScale = dialogFilter.getOutputScale();
461                 std::ostringstream os;
462                 os << "Generate Filter=" << strFilter.c_str() 
463                         << ", size=(" << static_cast<int>(m_iDefaultFilterXSize) << "," << static_cast<int>(m_iDefaultFilterYSize) 
464                         << "), domain=" << strDomain.c_str() << ", filterParam=" << m_dDefaultFilterParam << ", bandwidth=" << m_dDefaultFilterBandwidth 
465                         << ", inputScale=" << m_dDefaultFilterInputScale << ", outputScale=" << m_dDefaultFilterOutputScale;
466                 *theApp->getLog() << os.str().c_str() << "\n";
467                 wxString filename = "untitled.if";
468                 ImageFileDocument* pFilterDoc = theApp->newImageDoc();
469     pFilterDoc->setBadFileOpen();
470                 if (! pFilterDoc) {
471                         sys_error (ERR_SEVERE, "Unable to create filter image");
472                         return;
473                 }
474                 ImageFile& rIF = pFilterDoc->getImageFile();
475                 rIF.setArraySize (m_iDefaultFilterXSize, m_iDefaultFilterYSize);
476                 rIF.filterResponse (strDomain.c_str(), m_dDefaultFilterBandwidth, strFilter.c_str(), m_dDefaultFilterParam, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
477                 rIF.labelAdd (os.str().c_str());
478     pFilterDoc->Modify (true);
479                 pFilterDoc->UpdateAllViews();
480                 pFilterDoc->GetFirstView()->OnUpdate (NULL, NULL);
481                 pFilterDoc->getView()->getFrame()->SetClientSize(m_iDefaultFilterXSize, m_iDefaultFilterYSize);
482                 pFilterDoc->getView()->getFrame()->Show(true);
483         }
484 }
485
486 void
487 CTSimApp::getCompatibleImages (const ImageFileDocument* pIFDoc, std::vector<ImageFileDocument*>& vecIF)
488 {
489         const ImageFile& rIF = pIFDoc->getImageFile();
490         unsigned int nx = rIF.nx();
491         unsigned int ny = rIF.ny();
492         wxList& rListDocs = m_docManager->GetDocuments();
493         for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) {
494                 wxDocument* pDoc = reinterpret_cast<wxDocument*>(pNode->GetData());
495                 ImageFileDocument* pIFCompareDoc = dynamic_cast<ImageFileDocument*>(pDoc);
496                 if (pIFCompareDoc && (pIFDoc != pIFCompareDoc)) {
497                         const ImageFile& rCompareIF = pIFCompareDoc->getImageFile();
498                         if (rCompareIF.nx() == nx && rCompareIF.ny() == ny)
499                                 vecIF.push_back (pIFCompareDoc);
500                 }
501         }
502 }
503
504 void 
505 MainFrame::OnHelpTopics (wxCommandEvent& event)
506 {
507         showHelp (event.GetId());
508 }
509
510 void 
511 MainFrame::OnHelpContents (wxCommandEvent& event)
512 {
513         showHelp (event.GetId());
514 }
515
516 #if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
517 void
518 MainFrame::OnHelpSecondary (wxCommandEvent& event)
519 {
520         m_htmlHelp.DisplayContents();
521 }
522 #endif
523
524 void
525 MainFrame::showHelp (int commandID)
526 {
527         switch (commandID) {
528                 
529         case MAINMENU_HELP_CONTENTS:
530 #ifdef CTSIM_WINHELP
531                 m_winHelp.DisplayContents ();
532 #else
533                 m_htmlHelp.DisplayContents ();
534 #endif
535                 break;
536                 
537         case MAINMENU_HELP_TOPICS:
538 #ifdef CTSIM_WINHELP
539                 m_winHelp.DisplaySection (introduction);
540 #else
541                 m_htmlHelp.DisplayIndex();
542 #endif
543                 break;
544                 
545         default:
546                 *theApp->getLog() << "Unknown help command # " << commandID << "\n";
547                 break;
548         }
549 }
550
551 void 
552 MainFrame::OnExit (wxCommandEvent& WXUNUSED(event) )
553 {
554         Close(true);
555 }
556
557 void
558 MainFrame::OnUpdateUI (wxUpdateUIEvent& rEvent)
559 {
560 #ifndef CTSIM_MDI
561         int iPos = 0;
562         wxList& rListDocs = theApp->getDocManager()->GetDocuments();
563         wxNode* pNode = rListDocs.GetFirst();
564         while (iPos < MAX_WINDOW_MENUITEMS && pNode != NULL) {
565                 wxDocument* pDoc = static_cast<wxDocument*>(pNode->GetData());
566                 wxString strFilename = pDoc->GetFilename();
567                 if (iPos < 10) {
568                         strFilename += "\tCtrl-";
569                         strFilename += static_cast<char>('0' + iPos);
570                 }
571                 static_cast<wxMenuItemBase*>(m_apWindowMenuItems[iPos])->SetName (strFilename);
572                 m_apWindowMenuData[iPos] = pDoc;
573                 m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+iPos, true);
574                 iPos++;
575                 pNode = pNode->GetNext();
576         }
577         for (int i = iPos; i < MAX_WINDOW_MENUITEMS; i++) {
578                 m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false);
579                 static_cast<wxMenuItemBase*>(m_apWindowMenuItems[i])->SetName (wxString("[EMPTY]"));
580                 m_apWindowMenuData[i] = NULL;
581         }
582 #endif  
583 }
584
585 #ifdef CTSIM_CUSTOM_MRU
586 void 
587 MainFrame::OnMRUFile (wxCommandEvent& event)
588 {
589         wxString fileName (theApp->getDocManager()->GetHistoryFile(event.GetId() - wxID_FILE1));
590         if (fileName != "")
591                 theApp->getDocManager()->CreateDocument(fileName, wxDOC_SILENT);
592 }
593 #endif
594
595 void 
596 MainFrame::DoWindowMenu (int iMenuPosition, wxCommandEvent& event)
597 {
598         if (wxDocument* pDoc = m_apWindowMenuData [iMenuPosition]) {
599                 wxString strFilename = pDoc->GetFilename();
600                 const wxView* pView = pDoc->GetFirstView();
601                 if (pView) {
602                         wxFrame* pFrame = pView->GetFrame();
603                         pFrame->SetFocus();
604                         pFrame->Raise();
605                 }
606         }
607 }
608
609 void MainFrame::OnWindowMenu0 (wxCommandEvent& event)
610 { DoWindowMenu (0, event); }
611
612 void MainFrame::OnWindowMenu1 (wxCommandEvent& event)
613 { DoWindowMenu (1, event); }
614
615 void MainFrame::OnWindowMenu2 (wxCommandEvent& event)
616 { DoWindowMenu (2, event); }
617
618 void MainFrame::OnWindowMenu3 (wxCommandEvent& event)
619 { DoWindowMenu (3, event); }
620
621 void MainFrame::OnWindowMenu4 (wxCommandEvent& event)
622 { DoWindowMenu (4, event); }
623
624 void MainFrame::OnWindowMenu5 (wxCommandEvent& event)
625 { DoWindowMenu (5, event); }
626
627 void MainFrame::OnWindowMenu6 (wxCommandEvent& event)
628 { DoWindowMenu (6, event); }
629
630 void MainFrame::OnWindowMenu7 (wxCommandEvent& event)
631 { DoWindowMenu (7, event); }
632
633 void MainFrame::OnWindowMenu8 (wxCommandEvent& event)
634 { DoWindowMenu (8, event); }
635
636 void MainFrame::OnWindowMenu9 (wxCommandEvent& event)
637 { DoWindowMenu (9, event); }
638
639 void MainFrame::OnWindowMenu10 (wxCommandEvent& event)
640 { DoWindowMenu (10, event); }
641
642 void MainFrame::OnWindowMenu11 (wxCommandEvent& event)
643 { DoWindowMenu (11, event); }
644
645 void MainFrame::OnWindowMenu12 (wxCommandEvent& event)
646 { DoWindowMenu (12, event); }
647
648 void MainFrame::OnWindowMenu13 (wxCommandEvent& event)
649 { DoWindowMenu (13, event); }
650
651 void MainFrame::OnWindowMenu14 (wxCommandEvent& event)
652 { DoWindowMenu (14, event); }
653
654 void MainFrame::OnWindowMenu15 (wxCommandEvent& event)
655 { DoWindowMenu (15, event); }
656
657 void MainFrame::OnWindowMenu16 (wxCommandEvent& event)
658 { DoWindowMenu (16, event); }
659
660 void MainFrame::OnWindowMenu17 (wxCommandEvent& event)
661 { DoWindowMenu (17, event); }
662
663 void MainFrame::OnWindowMenu18 (wxCommandEvent& event)
664 { DoWindowMenu (18, event); }
665
666 void MainFrame::OnWindowMenu19 (wxCommandEvent& event)
667 { DoWindowMenu (19, event); }
668
669
670 class BitmapControl : public wxPanel
671 {
672 private:  
673         DECLARE_DYNAMIC_CLASS (BitmapControl)
674                 DECLARE_EVENT_TABLE ()
675                 wxBitmap* m_pBitmap;
676         
677 public:
678         BitmapControl (wxBitmap* pBitmap, wxWindow *parent, wxWindowID id = -1,
679                 const wxPoint& pos = wxDefaultPosition,
680                 const wxSize& size = wxDefaultSize,
681                 long style = wxSTATIC_BORDER,
682                 const wxValidator& validator = wxDefaultValidator,
683                 const wxString& name = "BitmapCtrl");
684         
685         
686         virtual ~BitmapControl();
687         
688         virtual wxSize GetBestSize() const;
689         
690         wxBitmap* getBitmap() 
691         { return m_pBitmap; }
692         
693         void OnPaint(wxPaintEvent& event);
694 };
695
696
697 BEGIN_EVENT_TABLE(BitmapControl, wxPanel)
698 EVT_PAINT(BitmapControl::OnPaint)
699 END_EVENT_TABLE()
700
701 IMPLEMENT_CLASS(BitmapControl, wxPanel)
702
703
704 BitmapControl::BitmapControl (wxBitmap* pBitmap, wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, 
705                               long style, const wxValidator& validator, const wxString& name)
706                               : m_pBitmap(pBitmap)
707 {
708         Create(parent, id, pos, size, style, name);
709         
710         SetSize (GetBestSize());
711 }
712
713 wxSize
714 BitmapControl::GetBestSize () const
715 {
716         if (m_pBitmap)
717                 return wxSize (m_pBitmap->GetWidth(), m_pBitmap->GetHeight());
718         else
719                 return wxSize(0,0);
720 }
721
722 BitmapControl::~BitmapControl()
723 {}
724
725 void
726 BitmapControl::OnPaint (wxPaintEvent& event)
727 {
728         wxPaintDC dc(this);
729         if (m_pBitmap)
730                 dc.DrawBitmap (*m_pBitmap, 0, 0);
731 }
732
733
734 class BitmapDialog : public wxDialog {
735 private:
736         BitmapControl* m_pBitmapCtrl;
737         
738 public:
739         BitmapDialog (wxBitmap* pBitmap, char const* pszTitle);
740         virtual ~BitmapDialog();
741 };
742
743 BitmapDialog::BitmapDialog (wxBitmap* pBitmap, char const* pszTitle)
744 : wxDialog(theApp->getMainFrame(), -1, wxString(pszTitle), wxDefaultPosition, wxDefaultSize, wxDIALOG_MODAL | wxDEFAULT_DIALOG_STYLE)
745 {
746         wxBoxSizer* pTopSizer = new wxBoxSizer (wxVERTICAL);
747         
748         pTopSizer->Add (new BitmapControl (pBitmap, this), 0, wxALIGN_CENTER | wxALL, 5);
749         
750         wxBoxSizer* pButtonSizer = new wxBoxSizer (wxHORIZONTAL);
751         wxButton* pButtonOk = new wxButton (this, wxID_OK, "Ok");
752         pButtonSizer->Add (pButtonOk, 0, wxEXPAND | wxALL, 10);
753         
754         pTopSizer->Add (pButtonSizer, 0, wxALIGN_CENTER);
755         
756         SetAutoLayout (true);
757         SetSizer (pTopSizer);
758         pTopSizer->Fit (this);
759         pTopSizer->SetSizeHints (this);
760 }
761
762 BitmapDialog::~BitmapDialog()
763 {}
764
765
766 void 
767 MainFrame::OnPreferences (wxCommandEvent& WXUNUSED(event) )
768 {
769   theApp->setAdvancedOptions (! theApp->getAdvancedOptions());
770 }
771
772
773 #include "./splash.xpm"
774 void 
775 MainFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
776 {
777         wxBitmap bmp (splash);
778         if (bmp.Ok()) {
779                 BitmapDialog dlg (&bmp, "About CTSim");
780                 dlg.Show(true);
781         } else {
782                 wxString msg = "CTSim\nThe Open Source Computed Tomography Simulator\n";
783 #ifdef CTSIMVERSION
784                 msg += "Version ";
785                 msg += CTSIMVERSION;
786                 msg += "\n\n";
787 #elif defined(VERSION)
788                 msg << "Version: " <<  VERSION << "\n\n";
789 #endif
790                 msg += "Author: Kevin Rosenberg <kevin@rosenberg.net>\nUsage: ctsim [files-to-open..] [--help]";
791                 
792                 wxMessageBox(msg, "About CTSim", wxOK | wxICON_INFORMATION, this);
793         }
794 }
795
796
797 ProjectionFileDocument*
798 CTSimApp::newProjectionDoc()
799 {
800         ProjectionFileDocument* newDoc = dynamic_cast<ProjectionFileDocument*>(m_pDocTemplProjection->CreateDocument (""));
801         if (newDoc) {
802                 ProjectionFileView* pView = newDoc->getView();
803                 if (pView) {
804                         wxFrame* pFrame = pView->getFrame();
805                         if (pFrame) {
806                                 pFrame->SetSize (0,0);
807                                 pFrame->Show (false);
808                         }
809                 }
810     newDoc->SetDocumentName (m_pDocTemplProjection->GetDocumentName());
811     newDoc->SetDocumentTemplate (m_pDocTemplProjection);
812     newDoc->OnNewDocument();
813         }
814         
815         return newDoc;
816 }
817
818 ImageFileDocument*
819 CTSimApp::newImageDoc()
820 {
821         ImageFileDocument* newDoc = dynamic_cast<ImageFileDocument*>(m_pDocTemplImage->CreateDocument (""));
822         if (newDoc) {
823                 ImageFileView* pView = newDoc->getView();
824                 if (pView) {
825                         wxFrame* pFrame = pView->getFrame();
826                         if (pFrame) {
827                                 pFrame->SetSize (0,0);
828                                 pFrame->Show (false);
829                         }
830                 }
831     newDoc->SetDocumentName (m_pDocTemplImage->GetDocumentName());
832     newDoc->SetDocumentTemplate (m_pDocTemplImage);
833     newDoc->OnNewDocument();
834         }
835         
836         return newDoc;
837 }
838
839 PlotFileDocument*
840 CTSimApp::newPlotDoc()
841 {
842         PlotFileDocument* newDoc = dynamic_cast<PlotFileDocument*>(m_pDocTemplPlot->CreateDocument (""));
843         if (newDoc) {
844                 PlotFileView* pView = newDoc->getView();
845                 if (pView) {
846                         wxFrame* pFrame = pView->getFrame();
847                         if (pFrame) {
848                                 wxSize size;
849                                 m_pFrame->GetClientSize (&size.x, &size.y);
850                                 pFrame->SetSize (size.x / 2, size.y / 2);
851                                 pFrame->Show (false);
852                         }
853                 }
854     newDoc->SetDocumentName (m_pDocTemplPlot->GetDocumentName());
855     newDoc->SetDocumentTemplate (m_pDocTemplPlot);
856     newDoc->OnNewDocument();
857         }
858         
859         return newDoc;
860 }
861
862
863 TextFileDocument*
864 CTSimApp::newTextDoc()
865 {
866         wxString strFilename (getUntitledFilename());
867         strFilename += ".txt";
868         
869         TextFileDocument* newDoc = dynamic_cast<TextFileDocument*>(m_pDocTemplText->CreateDocument (""));
870         if (newDoc) {
871                 TextFileView* pView = newDoc->getView();
872                 if (pView) {
873                         wxFrame* pFrame = pView->getFrame();
874                         if (pFrame) {
875                                 wxSize size;
876                                 m_pFrame->GetClientSize (&size.x, &size.y);;
877                                 pFrame->SetSize (size.x / 2, size.y / 2);
878                                 pFrame->Show (false);
879                         }
880                 }
881     newDoc->SetDocumentName (m_pDocTemplText->GetDocumentName());
882     newDoc->SetDocumentTemplate (m_pDocTemplText);
883     newDoc->OnNewDocument();
884         }
885         
886         return newDoc;
887 }
888
889
890 PhantomFileDocument*
891 CTSimApp::newPhantomDoc()
892 {
893         PhantomFileDocument* newDoc = dynamic_cast<PhantomFileDocument*>(m_pDocTemplPhantom->CreateDocument (""));
894         if (newDoc) {
895                 PhantomFileView* pView = newDoc->getView();
896                 if (pView) {
897                         wxFrame* pFrame = pView->getFrame();
898                         if (pFrame)
899                                 pFrame->SetSize (0,0);
900                 }
901     newDoc->SetDocumentName (m_pDocTemplPhantom->GetDocumentName());
902     newDoc->SetDocumentTemplate (m_pDocTemplPhantom);
903     newDoc->OnNewDocument();
904         }
905         
906         return newDoc;
907 }
908
909 #if wxUSE_GLCANVAS
910
911 Graph3dFileDocument*
912 CTSimApp::newGraph3dDoc()
913 {
914         Graph3dFileDocument* newDoc = dynamic_cast<Graph3dFileDocument*>(m_pDocTemplGraph3d->CreateDocument (""));
915         if (newDoc) {
916                 Graph3dFileView* pView = newDoc->getView();
917                 if (pView) {
918                         wxFrame* pFrame = pView->getFrame();
919                         if (pFrame)
920                                 pFrame->SetSize (0,0);
921                 }
922     newDoc->SetDocumentName (m_pDocTemplGraph3d->GetDocumentName());
923     newDoc->SetDocumentTemplate (m_pDocTemplGraph3d);
924     newDoc->OnNewDocument();
925         }
926         
927         return newDoc;
928 }
929 #endif