+CTSimApp::OnExit()
+{
+ closeConfig();
+
+#ifdef HAVE_DMALLOC
+ dmalloc_shutdown();
+#endif
+ return 0;
+}
+
+void
+CTSimApp::openConfig()
+{
+#ifdef MSVC
+ m_pConfig = new wxConfig("ctsim", "Kevin Rosenberg", "", "", wxCONFIG_USE_LOCAL_FILE);
+#else
+ m_pConfig = new wxConfig("ctsim", "Kevin Rosenberg", ".ctsim", "", wxCONFIG_USE_LOCAL_FILE);
+#endif
+
+ wxConfigBase::Set(m_pConfig);
+ m_pConfig->Read ("AdvancedOptions", &m_bAdvancedOptions);
+ m_pConfig->Read ("SetModifyNewDocs", &m_bSetModifyNewDocs);
+ m_pConfig->Read ("VerboseLogging", &m_bVerboseLogging);
+ m_pConfig->Read ("StartupTips", &m_bShowStartupTips);
+ m_pConfig->Read ("CurrentTip", &m_iCurrentTip);
+ m_pConfig->Read ("UseBackgroundTasks", &m_bUseBackgroundTasks);
+}
+
+void
+CTSimApp::closeConfig()
+{
+ m_pConfig->Write ("AdvancedOptions", m_bAdvancedOptions);
+ m_pConfig->Write ("SetModifyNewDocs", m_bSetModifyNewDocs);
+ m_pConfig->Write ("VerboseLogging", m_bVerboseLogging);
+ m_pConfig->Write ("StartupTips", m_bShowStartupTips);
+ m_pConfig->Write ("CurrentTip", m_iCurrentTip);
+ m_pConfig->Write ("UseBackgroundTasks", m_bUseBackgroundTasks);
+
+ delete m_pConfig;
+}
+
+
+wxString
+CTSimApp::getUntitledFilename()
+{
+ static int untitledNumber = 1;
+
+ wxString filename ("Untitled");
+ filename << untitledNumber++;
+
+ return (filename);
+}
+
+
+// Top-level window for CTSim
+
+#if CTSIM_MDI
+IMPLEMENT_CLASS(MainFrame, wxMDIParentFrame)
+
+BEGIN_EVENT_TABLE(MainFrame, wxMDIParentFrame)
+#else
+IMPLEMENT_CLASS(MainFrame, wxDocParentFrame)
+
+BEGIN_EVENT_TABLE(MainFrame, wxDocParentFrame)
+#endif
+
+EVT_MENU(MAINMENU_FILE_PREFERENCES, MainFrame::OnPreferences)
+EVT_MENU(MAINMENU_HELP_ABOUT, MainFrame::OnAbout)
+EVT_MENU(MAINMENU_HELP_CONTENTS, MainFrame::OnHelpContents)
+EVT_MENU(MAINMENU_HELP_TIPS, MainFrame::OnHelpTips)
+EVT_MENU(MAINMENU_IMPORT, MainFrame::OnImport)
+EVT_MENU(IDH_QUICKSTART, MainFrame::OnHelpButton)
+EVT_MENU(MAINMENU_LOG_EVENT, MainFrame::OnLogEvent)
+EVT_MENU(NEW_IMAGEFILE_EVENT, MainFrame::OnNewImageFile)
+EVT_MENU(NEW_PROJECTIONFILE_EVENT, MainFrame::OnNewProjectionFile)
+EVT_BUTTON(IDH_DLG_RASTERIZE, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_PROJECTIONS, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_RECONSTRUCTION, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_FILTER, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_MINMAX, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_EXPORT, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_PHANTOM, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_COMPARISON, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_PREFERENCES, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_POLAR, MainFrame::OnHelpButton)
+EVT_BUTTON(IDH_DLG_AUTOSCALE, MainFrame::OnHelpButton)
+
+EVT_SIZE(MainFrame::OnSize)
+
+#if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
+EVT_MENU(MAINMENU_HELP_SECONDARY, MainFrame::OnHelpSecondary)
+#endif
+EVT_MENU(MAINMENU_FILE_CREATE_PHANTOM, MainFrame::OnCreatePhantom)
+EVT_MENU(MAINMENU_FILE_CREATE_FILTER, MainFrame::OnCreateFilter)
+EVT_MENU(MAINMENU_FILE_EXIT, MainFrame::OnExit)
+EVT_MENU_RANGE(wxID_FILE1, wxID_FILE9, MainFrame::OnMRUFile)
+EVT_MENU(MAINMENU_WINDOW_BASE, MainFrame::OnWindowMenu0)
+EVT_MENU(MAINMENU_WINDOW_BASE+1, MainFrame::OnWindowMenu1)
+EVT_MENU(MAINMENU_WINDOW_BASE+2, MainFrame::OnWindowMenu2)
+EVT_MENU(MAINMENU_WINDOW_BASE+3, MainFrame::OnWindowMenu3)
+EVT_MENU(MAINMENU_WINDOW_BASE+4, MainFrame::OnWindowMenu4)
+EVT_MENU(MAINMENU_WINDOW_BASE+5, MainFrame::OnWindowMenu5)
+EVT_MENU(MAINMENU_WINDOW_BASE+6, MainFrame::OnWindowMenu6)
+EVT_MENU(MAINMENU_WINDOW_BASE+7, MainFrame::OnWindowMenu7)
+EVT_MENU(MAINMENU_WINDOW_BASE+8, MainFrame::OnWindowMenu8)
+EVT_MENU(MAINMENU_WINDOW_BASE+9, MainFrame::OnWindowMenu9)
+EVT_MENU(MAINMENU_WINDOW_BASE+10, MainFrame::OnWindowMenu10)
+EVT_MENU(MAINMENU_WINDOW_BASE+11, MainFrame::OnWindowMenu11)
+EVT_MENU(MAINMENU_WINDOW_BASE+12, MainFrame::OnWindowMenu12)
+EVT_MENU(MAINMENU_WINDOW_BASE+13, MainFrame::OnWindowMenu13)
+EVT_MENU(MAINMENU_WINDOW_BASE+14, MainFrame::OnWindowMenu14)
+EVT_MENU(MAINMENU_WINDOW_BASE+15, MainFrame::OnWindowMenu15)
+EVT_MENU(MAINMENU_WINDOW_BASE+16, MainFrame::OnWindowMenu16)
+EVT_MENU(MAINMENU_WINDOW_BASE+17, MainFrame::OnWindowMenu17)
+EVT_MENU(MAINMENU_WINDOW_BASE+18, MainFrame::OnWindowMenu18)
+EVT_MENU(MAINMENU_WINDOW_BASE+19, MainFrame::OnWindowMenu19)
+EVT_UPDATE_UI_RANGE(MAINMENU_WINDOW_BASE, MAINMENU_WINDOW_BASE+20, MainFrame::OnUpdateUI)
+END_EVENT_TABLE()
+
+
+
+#if CTSIM_MDI
+MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
+: wxDocMDIParentFrame(manager, NULL, id, title, pos, size, type, "MainFrame")
+#else
+MainFrame::MainFrame(wxDocManager *manager, wxFrame *frame, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, const long type)
+: wxDocParentFrame(manager, frame, id, title, pos, size, type, "MainFrame")
+#endif
+{
+ m_bShuttingDown = false;
+
+ //// Make a menubar
+ wxMenu *file_menu = new wxMenu;
+
+ file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
+ file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
+ file_menu->Append(wxID_OPEN, "&Open...\tCtrl-O");
+
+ file_menu->AppendSeparator();
+ file_menu->Append (MAINMENU_IMPORT, "&Import...\tCtrl-M");
+ file_menu->Append (MAINMENU_FILE_PREFERENCES, "Prefere&nces...");
+ file_menu->Append(MAINMENU_FILE_EXIT, "E&xit");
+
+ // history of files visited
+ theApp->getDocManager()->FileHistoryAddFilesToMenu(file_menu);
+ theApp->getDocManager()->FileHistoryUseMenu(file_menu);
+
+#ifndef CTSIM_MDI
+ m_pWindowMenu = new wxMenu;
+ m_pWindowMenu->UpdateUI (this);
+#endif
+
+ wxMenu* help_menu = new wxMenu;
+ help_menu->Append (MAINMENU_HELP_CONTENTS, "&Contents\tF1");
+ help_menu->Append (MAINMENU_HELP_TIPS, "&Tips");
+ help_menu->Append (IDH_QUICKSTART, "&Quick Start");
+#if defined(CTSIM_WINHELP) && (defined(DEBUG) || defined(_DEBUG))
+ help_menu->Append (MAINMENU_HELP_SECONDARY, "&Secondary Help");
+#endif
+ help_menu->Append (MAINMENU_HELP_ABOUT, "&About");
+
+ wxMenuBar* menu_bar = new wxMenuBar;
+
+ menu_bar->Append(file_menu, "&File");
+#ifndef CTSIM_MDI
+ menu_bar->Append(m_pWindowMenu, "&Window");
+#endif
+ menu_bar->Append(help_menu, "&Help");
+
+ SetMenuBar(menu_bar);
+
+
+#ifndef CTSIM_MDI
+ int i;
+ for (i = 0; i < MAX_WINDOW_MENUITEMS; i++) {
+ m_apWindowMenuItems[i] = new wxMenuItem (m_pWindowMenu, MAINMENU_WINDOW_BASE+i, wxString("[EMPTY]"));
+ m_pWindowMenu->Append (m_apWindowMenuItems[i]);
+ m_pWindowMenu->Enable (MAINMENU_WINDOW_BASE+i, false);
+ }
+#endif
+
+ m_iDefaultPhantomID = Phantom::PHM_HERMAN;
+ m_iDefaultFilterID = SignalFilter::FILTER_BANDLIMIT;
+ m_iDefaultFilterDomainID = SignalFilter::DOMAIN_FREQUENCY;
+ m_iDefaultFilterXSize = 256;
+ m_iDefaultFilterYSize = 256;
+ m_dDefaultFilterParam = 1.;
+ m_dDefaultFilterBandwidth = 1.;
+ m_dDefaultFilterInputScale = 1.;
+ m_dDefaultFilterOutputScale = 1.;
+ m_iDefaultImportFormat = ImageFile::IMPORT_FORMAT_PNG;
+
+ wxAcceleratorEntry accelEntries[15];
+ accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
+ accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
+ accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
+ accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('M'), MAINMENU_IMPORT);
+ accelEntries[4].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
+#ifndef CTSIM_MDI
+ for (i = 0; i < 10; i++)
+ accelEntries[i+5].Set (wxACCEL_CTRL, static_cast<int>('0'+i), MAINMENU_WINDOW_BASE+i);
+ wxAcceleratorTable accelTable (15, accelEntries);
+#else
+ wxAcceleratorTable accelTable (5, accelEntries);
+#endif
+
+ SetAcceleratorTable (accelTable);
+}
+
+MainFrame::~MainFrame()
+{
+ m_bShuttingDown = true; // Currently used so that Log Window will close
+#if 0
+ // delete all non-modified documents
+ wxList& rListDocs = theApp->getDocManager()->GetDocuments();
+ for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) {
+ wxDocument* pDoc = dynamic_cast<wxDocument*>(pNode->GetData());
+ if (pDoc && ! pDoc->IsModified()) {
+ theApp->getDocManager()->RemoveDocument(pDoc);
+ delete pDoc;
+ }
+ }
+#endif
+ ::wxYield();
+ if (theApp->getConfig())
+ theApp->getDocManager()->FileHistorySave (*theApp->getConfig());
+ ::wxYield();
+ delete theApp->getDocManager();
+
+}
+
+void
+MainFrame::OnSize (wxSizeEvent& event)
+{
+#ifdef CTSIM_MDI
+ if (theApp->getLogDoc()) {
+ int xSize, ySize;
+ GetClientSize(&xSize, &ySize);
+ int yLogSize = ySize / 4;
+ theApp->getLogDoc()->getView()->getFrame()->SetSize (0, ySize - yLogSize, xSize, yLogSize);
+ theApp->getLogDoc()->getView()->getFrame()->Show (true);
+ }
+#endif
+
+#if CTSIM_MDI
+ wxDocMDIParentFrame::OnSize (event);
+#else
+ wxDocParentFrame::OnSize (event);
+#endif
+}
+
+void
+MainFrame::OnCreatePhantom(wxCommandEvent& event)
+{
+ DialogGetPhantom dialogPhantom (this, m_iDefaultPhantomID);
+ int dialogReturn = dialogPhantom.ShowModal();
+ if (dialogReturn == wxID_OK) {
+ wxString selection (dialogPhantom.getPhantom());
+ if (theApp->getVerboseLogging())
+ *theApp->getLog() << "Selected phantom " << selection.c_str() << "\n";
+ wxString filename = selection + ".phm";
+ m_iDefaultPhantomID = Phantom::convertNameToPhantomID (selection.c_str());
+ theApp->getDocManager()->CreateDocument (filename, wxDOC_SILENT);
+ }
+
+}
+
+void
+MainFrame::OnCreateFilter (wxCommandEvent& WXUNUSED(event))
+{
+ DialogGetFilterParameters dialogFilter (this, m_iDefaultFilterXSize, m_iDefaultFilterYSize, m_iDefaultFilterID, m_dDefaultFilterParam, m_dDefaultFilterBandwidth, m_iDefaultFilterDomainID, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
+ int dialogReturn = dialogFilter.ShowModal();
+ if (dialogReturn == wxID_OK) {
+ wxString strFilter (dialogFilter.getFilterName());
+ wxString strDomain (dialogFilter.getDomainName());
+ m_iDefaultFilterID = SignalFilter::convertFilterNameToID (strFilter.c_str());
+ m_iDefaultFilterDomainID = SignalFilter::convertDomainNameToID (strDomain.c_str());
+ m_iDefaultFilterXSize = dialogFilter.getXSize();
+ m_iDefaultFilterYSize = dialogFilter.getYSize();
+ m_dDefaultFilterBandwidth = dialogFilter.getBandwidth();
+ m_dDefaultFilterParam= dialogFilter.getFilterParam();
+ m_dDefaultFilterInputScale = dialogFilter.getInputScale();
+ m_dDefaultFilterOutputScale = dialogFilter.getOutputScale();
+ std::ostringstream os;
+ os << "Generate Filter=" << strFilter.c_str()
+ << ", size=(" << static_cast<int>(m_iDefaultFilterXSize) << "," << static_cast<int>(m_iDefaultFilterYSize)
+ << "), domain=" << strDomain.c_str() << ", filterParam=" << m_dDefaultFilterParam << ", bandwidth=" << m_dDefaultFilterBandwidth
+ << ", inputScale=" << m_dDefaultFilterInputScale << ", outputScale=" << m_dDefaultFilterOutputScale;
+ *theApp->getLog() << os.str().c_str() << "\n";
+ wxString filename = "untitled.if";
+ ImageFileDocument* pFilterDoc = theApp->newImageDoc();
+ pFilterDoc->setBadFileOpen();
+ if (! pFilterDoc) {
+ sys_error (ERR_SEVERE, "Unable to create filter image");
+ return;
+ }
+ ImageFile& rIF = pFilterDoc->getImageFile();
+ rIF.setArraySize (m_iDefaultFilterXSize, m_iDefaultFilterYSize);
+ rIF.filterResponse (strDomain.c_str(), m_dDefaultFilterBandwidth, strFilter.c_str(), m_dDefaultFilterParam, m_dDefaultFilterInputScale, m_dDefaultFilterOutputScale);
+ rIF.labelAdd (os.str().c_str());
+ if (theApp->getAskDeleteNewDocs())
+ pFilterDoc->Modify (true);
+ pFilterDoc->UpdateAllViews();
+ pFilterDoc->GetFirstView()->OnUpdate (NULL, NULL);
+ pFilterDoc->getView()->getFrame()->SetClientSize(m_iDefaultFilterXSize, m_iDefaultFilterYSize);
+ pFilterDoc->getView()->getFrame()->Show(true);
+ }
+}
+
+void
+CTSimApp::getCompatibleImages (const ImageFileDocument* pIFDoc, std::vector<ImageFileDocument*>& vecIF)
+{
+ const ImageFile& rIF = pIFDoc->getImageFile();
+ unsigned int nx = rIF.nx();
+ unsigned int ny = rIF.ny();
+ wxList& rListDocs = m_docManager->GetDocuments();
+ for (wxNode* pNode = rListDocs.GetFirst(); pNode != NULL; pNode = pNode->GetNext()) {
+ wxDocument* pDoc = reinterpret_cast<wxDocument*>(pNode->GetData());
+ ImageFileDocument* pIFCompareDoc = dynamic_cast<ImageFileDocument*>(pDoc);
+ if (pIFCompareDoc && (pIFDoc != pIFCompareDoc)) {
+ const ImageFile& rCompareIF = pIFCompareDoc->getImageFile();
+ if (rCompareIF.nx() == nx && rCompareIF.ny() == ny)
+ vecIF.push_back (pIFCompareDoc);
+ }
+ }
+}
+
+
+void
+MainFrame::OnNewImageFile (wxCommandEvent& event)
+{
+ ImageFile* pImageFile = reinterpret_cast<ImageFile*>(event.GetClientData());
+
+ ImageFileDocument* pImageDoc = theApp->newImageDoc();
+ if (! pImageDoc) {
+ sys_error (ERR_SEVERE, "Unable to create image file");
+ return;
+ }
+ pImageDoc->setImageFile (pImageFile);
+ pImageDoc->UpdateAllViews (NULL);
+ if (ImageFileView* imageView = pImageDoc->getView()) {
+ imageView->OnUpdate (imageView, NULL);
+ imageView->getFrame()->SetFocus();
+ imageView->getFrame()->Show(true);
+ }
+ if (theApp->getAskDeleteNewDocs())
+ pImageDoc->Modify (true);
+
+}
+
+void
+MainFrame::OnNewProjectionFile (wxCommandEvent& event)
+{
+ Projections* pProjections = reinterpret_cast<Projections*>(event.GetClientData());
+ ProjectionFileDocument* pProjDoc = theApp->newProjectionDoc();
+ if (! pProjDoc) {
+ sys_error (ERR_SEVERE, "Unable to create projection file");
+ return;
+ }
+ pProjDoc->setProjections (pProjections);
+ pProjDoc->UpdateAllViews (NULL);
+ if (ProjectionFileView* projView = pProjDoc->getView()) {
+ projView->OnUpdate (projView, NULL);
+ projView->getFrame()->SetFocus();
+ projView->getFrame()->Show(true);
+ }
+
+ if (theApp->getAskDeleteNewDocs())
+ pProjDoc->Modify (true);
+}
+
+void
+MainFrame::OnLogEvent (wxCommandEvent& event)
+{
+ *theApp->getLog() << event.GetString();
+}
+
+void
+MainFrame::OnHelpTips (wxCommandEvent& event)
+{
+ theApp->ShowTips();
+}
+
+void
+MainFrame::OnHelpContents (wxCommandEvent& event)
+{
+ showHelp (event.GetId());
+}
+
+void
+MainFrame::OnHelpButton (wxCommandEvent& event)