1 /*****************************************************************************
5 ** Purpose: View & Canvas routines for CTSim program
6 ** Programmer: Kevin Rosenberg
7 ** Date Started: July 2000
9 ** This is part of the CTSim program
10 ** Copyright (C) 1983-2000 Kevin Rosenberg
12 ** $Id: views.cpp,v 1.69 2001/01/20 17:43:41 kevin Exp $
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.
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.
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 ******************************************************************************/
28 // For compilers that support precompilation, includes "wx/wx.h".
29 #include "wx/wxprec.h"
39 #if !wxUSE_DOC_VIEW_ARCHITECTURE
40 #error You must set wxUSE_DOC_VIEW_ARCHITECTURE to 1 in setup.h!
44 #include "wx/progdlg.h"
51 #include "dlgprojections.h"
52 #include "dlgreconstruct.h"
53 #include "backprojectors.h"
54 #include "reconstruct.h"
57 #if defined(MSVC) || HAVE_SSTREAM
60 #include <sstream_subst>
66 BEGIN_EVENT_TABLE(ImageFileCanvas, wxScrolledWindow)
67 EVT_MOUSE_EVENTS(ImageFileCanvas::OnMouseEvent)
71 ImageFileCanvas::ImageFileCanvas (ImageFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
72 : wxScrolledWindow(frame, -1, pos, size, style)
79 ImageFileCanvas::~ImageFileCanvas()
82 wxMenu* pMenu = m_pView->getFileMenu();
83 theApp->getDocManager()->FileHistoryRemoveMenu (pMenu);
88 ImageFileCanvas::OnDraw(wxDC& dc)
91 m_pView->OnDraw(& dc);
95 ImageFileCanvas::DrawRubberBandCursor (wxDC& dc, int x, int y)
97 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
101 int yPt = ny - y - 1;
102 dc.SetLogicalFunction (wxINVERT);
103 dc.SetPen (*wxGREEN_PEN);
104 dc.DrawLine (0, yPt, nx, yPt);
105 dc.DrawLine (x, 0, x, ny);
106 dc.SetLogicalFunction (wxCOPY);
110 ImageFileCanvas::GetCurrentCursor (int& x, int& y)
115 if (m_xCursor >= 0 && m_yCursor >= 0)
122 ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
130 wxPoint pt(event.GetLogicalPosition(dc));
132 const ImageFileDocument* pIFDoc = m_pView->GetDocument();
135 const ImageFile& rIF = pIFDoc->getImageFile();
136 ImageFileArrayConst v = rIF.getArray();
139 const int yPt = ny - 1 - pt.y;
140 if (event.RightIsDown()) {
141 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
142 std::ostringstream os;
143 os << "Image value (" << pt.x << "," << yPt << ") = " << v[pt.x][yPt];
144 if (rIF.isComplex()) {
145 double dImag = rIF.getImaginaryArray()[pt.x][yPt];
147 os << " - " << -dImag;
149 os << " + " << dImag;
153 *theApp->getLog() << os.str().c_str();
155 *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";
157 else if (event.LeftIsDown() || event.LeftUp() || event.RightUp()) {
158 if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
159 if (m_xCursor >= 0 && m_yCursor >= 0) {
160 DrawRubberBandCursor (dc, m_xCursor, m_yCursor);
162 DrawRubberBandCursor (dc, pt.x, yPt);
166 *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";
168 if (event.LeftUp()) {
169 std::ostringstream os;
170 os << "Selected column " << pt.x << " , row " << yPt << "\n";
171 *theApp->getLog() << os.str().c_str();
176 ImageFileCanvas::GetBestSize() const
181 const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
182 return wxSize (rIF.nx(), rIF.ny());
188 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
190 BEGIN_EVENT_TABLE(ImageFileView, wxView)
191 EVT_MENU(IFMENU_FILE_EXPORT, ImageFileView::OnExport)
192 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
193 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
194 EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)
195 EVT_MENU(IFMENU_VIEW_SCALE_FULL, ImageFileView::OnScaleFull)
196 EVT_MENU(IFMENU_COMPARE_IMAGES, ImageFileView::OnCompare)
197 EVT_MENU(IFMENU_COMPARE_ROW, ImageFileView::OnCompareRow)
198 EVT_MENU(IFMENU_COMPARE_COL, ImageFileView::OnCompareCol)
199 EVT_MENU(IFMENU_FILTER_INVERTVALUES, ImageFileView::OnInvertValues)
200 EVT_MENU(IFMENU_FILTER_SQUARE, ImageFileView::OnSquare)
201 EVT_MENU(IFMENU_FILTER_SQRT, ImageFileView::OnSquareRoot)
202 EVT_MENU(IFMENU_FILTER_LOG, ImageFileView::OnLog)
203 EVT_MENU(IFMENU_FILTER_EXP, ImageFileView::OnExp)
204 EVT_MENU(IFMENU_FILTER_FOURIER, ImageFileView::OnFourier)
205 EVT_MENU(IFMENU_FILTER_INVERSE_FOURIER, ImageFileView::OnInverseFourier)
206 EVT_MENU(IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, ImageFileView::OnShuffleFourierToNaturalOrder)
207 EVT_MENU(IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, ImageFileView::OnShuffleNaturalToFourierOrder)
208 EVT_MENU(IFMENU_IMAGE_ADD, ImageFileView::OnAdd)
209 EVT_MENU(IFMENU_IMAGE_SUBTRACT, ImageFileView::OnSubtract)
210 EVT_MENU(IFMENU_IMAGE_MULTIPLY, ImageFileView::OnMultiply)
211 EVT_MENU(IFMENU_IMAGE_DIVIDE, ImageFileView::OnDivide)
212 EVT_MENU(IFMENU_IMAGE_SCALESIZE, ImageFileView::OnScaleSize)
214 EVT_MENU(IFMENU_FILTER_FFT, ImageFileView::OnFFT)
215 EVT_MENU(IFMENU_FILTER_IFFT, ImageFileView::OnIFFT)
216 EVT_MENU(IFMENU_FILTER_FFT_ROWS, ImageFileView::OnFFTRows)
217 EVT_MENU(IFMENU_FILTER_IFFT_ROWS, ImageFileView::OnIFFTRows)
218 EVT_MENU(IFMENU_FILTER_FFT_COLS, ImageFileView::OnFFTCols)
219 EVT_MENU(IFMENU_FILTER_IFFT_COLS, ImageFileView::OnIFFTCols)
221 EVT_MENU(IFMENU_FILTER_MAGNITUDE, ImageFileView::OnMagnitude)
222 EVT_MENU(IFMENU_FILTER_PHASE, ImageFileView::OnPhase)
223 EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow)
224 EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol)
226 EVT_MENU(IFMENU_PLOT_FFT_ROW, ImageFileView::OnPlotFFTRow)
227 EVT_MENU(IFMENU_PLOT_FFT_COL, ImageFileView::OnPlotFFTCol)
229 EVT_MENU(IFMENU_PLOT_HISTOGRAM, ImageFileView::OnPlotHistogram)
232 ImageFileView::ImageFileView(void)
233 : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false), m_pFileMenu(0)
235 m_iDefaultExportFormatID = ImageFile::FORMAT_PNG;
238 ImageFileView::~ImageFileView(void)
243 ImageFileView::OnProperties (wxCommandEvent& event)
245 const ImageFile& rIF = GetDocument()->getImageFile();
246 if (rIF.nx() == 0 || rIF.ny() == 0)
247 *theApp->getLog() << "Properties: empty imagefile\n";
249 const std::string& rFilename = rIF.getFilename();
250 std::ostringstream os;
251 double min, max, mean, mode, median, stddev;
252 rIF.statistics (rIF.getArray(), min, max, mean, mode, median, stddev);
253 os << "Filename: " << rFilename << "\n";
254 os << "Size: (" << rIF.nx() << "," << rIF.ny() << ")\n";
260 os << "\nMinimum: "<<min<<"\nMaximum: "<<max<<"\nMean: "<<mean<<"\nMedian: "<<median<<"\nMode: "<<mode<<"\nStandard Deviation: "<<stddev << "\n";
261 if (rIF.isComplex()) {
262 rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev);
263 os << "\nImaginary: min: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";
265 if (rIF.nLabels() > 0) {
267 rIF.printLabelsBrief (os);
269 *theApp->getLog() << os.str().c_str();
270 wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Imagefile Properties", wxOK | wxICON_INFORMATION);
271 dialogMsg.ShowModal();
276 ImageFileView::OnScaleAuto (wxCommandEvent& event)
278 const ImageFile& rIF = GetDocument()->getImageFile();
279 double min, max, mean, mode, median, stddev;
280 rIF.statistics(min, max, mean, mode, median, stddev);
281 DialogAutoScaleParameters dialogAutoScale (getFrameForChild(), mean, mode, median, stddev, m_dAutoScaleFactor);
282 int iRetVal = dialogAutoScale.ShowModal();
283 if (iRetVal == wxID_OK) {
284 m_bMinSpecified = true;
285 m_bMaxSpecified = true;
287 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
290 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
291 OnUpdate (this, NULL);
297 ImageFileView::OnScaleMinMax (wxCommandEvent& event)
299 const ImageFile& rIF = GetDocument()->getImageFile();
301 if (! m_bMinSpecified && ! m_bMaxSpecified)
302 rIF.getMinMax (min, max);
309 DialogGetMinMax dialogMinMax (getFrameForChild(), "Set Image Minimum & Maximum", min, max);
310 int retVal = dialogMinMax.ShowModal();
311 if (retVal == wxID_OK) {
312 m_bMinSpecified = true;
313 m_bMaxSpecified = true;
314 m_dMinPixel = dialogMinMax.getMinimum();
315 m_dMaxPixel = dialogMinMax.getMaximum();
316 OnUpdate (this, NULL);
321 ImageFileView::OnScaleFull (wxCommandEvent& event)
323 if (m_bMinSpecified || m_bMaxSpecified) {
324 m_bMinSpecified = false;
325 m_bMaxSpecified = false;
326 OnUpdate (this, NULL);
331 ImageFileView::OnCompare (wxCommandEvent& event)
333 std::vector<ImageFileDocument*> vecIF;
334 theApp->getCompatibleImages (GetDocument(), vecIF);
336 if (vecIF.size() == 0) {
337 wxMessageBox("There are no compatible image files open for comparision", "No comparison images");
339 DialogGetComparisonImage dialogGetCompare(getFrameForChild(), "Get Comparison Image", vecIF, true);
341 if (dialogGetCompare.ShowModal() == wxID_OK) {
342 const ImageFile& rIF = GetDocument()->getImageFile();
343 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
344 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
345 std::ostringstream os;
346 double min, max, mean, mode, median, stddev;
347 rIF.statistics (min, max, mean, mode, median, stddev);
348 os << GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
349 rCompareIF.statistics (min, max, mean, mode, median, stddev);
350 os << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";
353 rIF.comparativeStatistics (rCompareIF, d, r, e);
354 os << "Comparative Statistics: d=" << d << ", r=" << r << ", e=" << e << "\n";
355 *theApp->getLog() << os.str().c_str();
356 if (dialogGetCompare.getMakeDifferenceImage()) {
357 ImageFileDocument* pDifferenceDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
358 if (! pDifferenceDoc) {
359 sys_error (ERR_SEVERE, "Unable to create image file");
362 ImageFile& differenceImage = pDifferenceDoc->getImageFile();
364 differenceImage.setArraySize (rIF.nx(), rIF.ny());
365 if (! rIF.subtractImages (rCompareIF, differenceImage)) {
366 pDifferenceDoc->DeleteAllViews();
370 wxString s = GetFrame()->GetTitle() + ": ";
371 differenceImage.labelsCopy (rIF, s.c_str());
372 s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
373 differenceImage.labelsCopy (rCompareIF, s.c_str());
374 std::ostringstream osLabel;
375 osLabel << "Compare image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str()
376 << " and " << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": "
378 differenceImage.labelAdd (os.str().c_str());
379 if (theApp->getSetModifyNewDocs())
380 pDifferenceDoc->Modify(true);
381 pDifferenceDoc->UpdateAllViews(this);
382 pDifferenceDoc->GetFirstView()->OnUpdate (this, NULL);
384 wxMessageBox(os.str().c_str(), "Image Comparison");
390 ImageFileView::OnInvertValues (wxCommandEvent& event)
392 ImageFile& rIF = GetDocument()->getImageFile();
393 rIF.invertPixelValues (rIF);
394 rIF.labelAdd ("Invert Pixel Values");
395 if (theApp->getSetModifyNewDocs())
396 GetDocument()->Modify(TRUE);
397 GetDocument()->UpdateAllViews(this);
401 ImageFileView::OnSquare (wxCommandEvent& event)
403 ImageFile& rIF = GetDocument()->getImageFile();
405 rIF.labelAdd ("Square Pixel Values");
406 if (theApp->getSetModifyNewDocs())
407 GetDocument()->Modify(TRUE);
408 GetDocument()->UpdateAllViews(this);
412 ImageFileView::OnSquareRoot (wxCommandEvent& event)
414 ImageFile& rIF = GetDocument()->getImageFile();
416 rIF.labelAdd ("Square-root Pixel Values");
417 if (theApp->getSetModifyNewDocs())
418 GetDocument()->Modify(TRUE);
419 GetDocument()->UpdateAllViews(this);
423 ImageFileView::OnLog (wxCommandEvent& event)
425 ImageFile& rIF = GetDocument()->getImageFile();
427 rIF.labelAdd ("Logrithm base-e Pixel Values");
428 if (theApp->getSetModifyNewDocs())
429 GetDocument()->Modify(TRUE);
430 GetDocument()->UpdateAllViews(this);
434 ImageFileView::OnExp (wxCommandEvent& event)
436 ImageFile& rIF = GetDocument()->getImageFile();
438 rIF.labelAdd ("Exponent base-e Pixel Values");
439 if (theApp->getSetModifyNewDocs())
440 GetDocument()->Modify(TRUE);
441 GetDocument()->UpdateAllViews(this);
445 ImageFileView::OnAdd (wxCommandEvent& event)
447 std::vector<ImageFileDocument*> vecIF;
448 theApp->getCompatibleImages (GetDocument(), vecIF);
450 if (vecIF.size() == 0) {
451 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
453 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Add", vecIF, false);
455 if (dialogGetCompare.ShowModal() == wxID_OK) {
456 ImageFile& rIF = GetDocument()->getImageFile();
457 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
458 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
459 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
461 sys_error (ERR_SEVERE, "Unable to create image file");
464 ImageFile& newImage = pNewDoc->getImageFile();
465 newImage.setArraySize (rIF.nx(), rIF.ny());
466 rIF.addImages (rRHSIF, newImage);
467 std::ostringstream os;
468 os << "Add image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
469 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
470 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
471 newImage.labelsCopy (rIF, s.c_str());
472 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
473 newImage.labelsCopy (rRHSIF, s.c_str());
474 newImage.labelAdd (os.str().c_str());
475 *theApp->getLog() << os.str().c_str() << "\n";
476 if (theApp->getSetModifyNewDocs())
477 pNewDoc->Modify(TRUE);
478 pNewDoc->UpdateAllViews(this);
479 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
485 ImageFileView::OnSubtract (wxCommandEvent& event)
487 std::vector<ImageFileDocument*> vecIF;
488 theApp->getCompatibleImages (GetDocument(), vecIF);
490 if (vecIF.size() == 0) {
491 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
493 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Subtract", vecIF, false);
495 if (dialogGetCompare.ShowModal() == wxID_OK) {
496 ImageFile& rIF = GetDocument()->getImageFile();
497 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
498 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
499 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
501 sys_error (ERR_SEVERE, "Unable to create image file");
504 ImageFile& newImage = pNewDoc->getImageFile();
505 newImage.setArraySize (rIF.nx(), rIF.ny());
506 rIF.subtractImages (rRHSIF, newImage);
507 std::ostringstream os;
508 os << "Subtract image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
509 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
510 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
511 newImage.labelsCopy (rIF, s.c_str());
512 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
513 newImage.labelsCopy (rRHSIF, s.c_str());
514 newImage.labelAdd (os.str().c_str());
515 *theApp->getLog() << os.str().c_str() << "\n";
516 if (theApp->getSetModifyNewDocs())
517 pNewDoc->Modify(TRUE);
518 pNewDoc->UpdateAllViews(this);
519 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
525 ImageFileView::OnMultiply (wxCommandEvent& event)
527 std::vector<ImageFileDocument*> vecIF;
528 theApp->getCompatibleImages (GetDocument(), vecIF);
530 if (vecIF.size() == 0) {
531 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
533 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Multiply", vecIF, false);
535 if (dialogGetCompare.ShowModal() == wxID_OK) {
536 ImageFile& rIF = GetDocument()->getImageFile();
537 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
538 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
539 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
541 sys_error (ERR_SEVERE, "Unable to create image file");
544 ImageFile& newImage = pNewDoc->getImageFile();
545 newImage.setArraySize (rIF.nx(), rIF.ny());
546 rIF.multiplyImages (rRHSIF, newImage);
547 std::ostringstream os;
548 os << "Multiply image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
549 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
550 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
551 newImage.labelsCopy (rIF, s.c_str());
552 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
553 newImage.labelsCopy (rRHSIF, s.c_str());
554 newImage.labelAdd (os.str().c_str());
555 *theApp->getLog() << os.str().c_str() << "\n";
556 if (theApp->getSetModifyNewDocs())
557 pNewDoc->Modify(TRUE);
558 pNewDoc->UpdateAllViews(this);
559 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
565 ImageFileView::OnDivide (wxCommandEvent& event)
567 std::vector<ImageFileDocument*> vecIF;
568 theApp->getCompatibleImages (GetDocument(), vecIF);
570 if (vecIF.size() == 0) {
571 wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");
573 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Image to Divide", vecIF, false);
575 if (dialogGetCompare.ShowModal() == wxID_OK) {
576 ImageFile& rIF = GetDocument()->getImageFile();
577 ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();
578 const ImageFile& rRHSIF = pRHSDoc->getImageFile();
579 ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
581 sys_error (ERR_SEVERE, "Unable to create image file");
584 ImageFile& newImage = pNewDoc->getImageFile();
585 newImage.setArraySize (rIF.nx(), rIF.ny());
586 rIF.divideImages (rRHSIF, newImage);
587 std::ostringstream os;
588 os << "Divide image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " by "
589 << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
590 wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";
591 newImage.labelsCopy (rIF, s.c_str());
592 s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";
593 newImage.labelsCopy (rRHSIF, s.c_str());
594 newImage.labelAdd (os.str().c_str());
595 *theApp->getLog() << os.str().c_str() << "\n";
596 if (theApp->getSetModifyNewDocs())
597 pNewDoc->Modify(TRUE);
598 pNewDoc->UpdateAllViews(this);
599 pNewDoc->GetFirstView()->OnUpdate (this, NULL);
607 ImageFileView::OnFFT (wxCommandEvent& event)
609 ImageFile& rIF = GetDocument()->getImageFile();
611 rIF.labelAdd ("FFT Image");
612 m_bMinSpecified = false;
613 m_bMaxSpecified = false;
614 if (theApp->getSetModifyNewDocs())
615 GetDocument()->Modify(TRUE);
616 GetDocument()->UpdateAllViews(this);
620 ImageFileView::OnIFFT (wxCommandEvent& event)
622 ImageFile& rIF = GetDocument()->getImageFile();
624 rIF.labelAdd ("IFFT Image");
625 m_bMinSpecified = false;
626 m_bMaxSpecified = false;
627 if (theApp->getSetModifyNewDocs())
628 GetDocument()->Modify(TRUE);
629 GetDocument()->UpdateAllViews(this);
633 ImageFileView::OnFFTRows (wxCommandEvent& event)
635 ImageFile& rIF = GetDocument()->getImageFile();
637 rIF.labelAdd ("FFT Rows");
638 m_bMinSpecified = false;
639 m_bMaxSpecified = false;
640 if (theApp->getSetModifyNewDocs())
641 GetDocument()->Modify(TRUE);
642 GetDocument()->UpdateAllViews(this);
646 ImageFileView::OnIFFTRows (wxCommandEvent& event)
648 ImageFile& rIF = GetDocument()->getImageFile();
650 rIF.labelAdd ("IFFT Rows");
651 m_bMinSpecified = false;
652 m_bMaxSpecified = false;
653 if (theApp->getSetModifyNewDocs())
654 GetDocument()->Modify(TRUE);
655 GetDocument()->UpdateAllViews(this);
659 ImageFileView::OnFFTCols (wxCommandEvent& event)
661 ImageFile& rIF = GetDocument()->getImageFile();
663 rIF.labelAdd ("FFT Columns");
664 m_bMinSpecified = false;
665 m_bMaxSpecified = false;
666 if (theApp->getSetModifyNewDocs())
667 GetDocument()->Modify(TRUE);
668 GetDocument()->UpdateAllViews(this);
672 ImageFileView::OnIFFTCols (wxCommandEvent& event)
674 ImageFile& rIF = GetDocument()->getImageFile();
676 rIF.labelAdd ("IFFT Columns");
677 m_bMinSpecified = false;
678 m_bMaxSpecified = false;
679 if (theApp->getSetModifyNewDocs())
680 GetDocument()->Modify(TRUE);
681 GetDocument()->UpdateAllViews(this);
686 ImageFileView::OnFourier (wxCommandEvent& event)
688 ImageFile& rIF = GetDocument()->getImageFile();
689 wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
691 rIF.labelAdd ("Fourier Image");
692 m_bMinSpecified = false;
693 m_bMaxSpecified = false;
694 if (theApp->getSetModifyNewDocs())
695 GetDocument()->Modify(TRUE);
696 GetDocument()->UpdateAllViews(this);
700 ImageFileView::OnInverseFourier (wxCommandEvent& event)
702 ImageFile& rIF = GetDocument()->getImageFile();
703 wxProgressDialog dlgProgress (wxString("Inverse Fourier"), wxString("Inverse Fourier Progress"), 1, getFrameForChild(), wxPD_APP_MODAL);
704 rIF.inverseFourier (rIF);
705 rIF.labelAdd ("Inverse Fourier Image");
706 m_bMinSpecified = false;
707 m_bMaxSpecified = false;
708 if (theApp->getSetModifyNewDocs())
709 GetDocument()->Modify(TRUE);
710 GetDocument()->UpdateAllViews(this);
714 ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)
716 ImageFile& rIF = GetDocument()->getImageFile();
717 Fourier::shuffleNaturalToFourierOrder (rIF);
718 rIF.labelAdd ("Shuffle Natural To Fourier Order");
719 m_bMinSpecified = false;
720 m_bMaxSpecified = false;
721 if (theApp->getSetModifyNewDocs())
722 GetDocument()->Modify(TRUE);
723 GetDocument()->UpdateAllViews(this);
727 ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)
729 ImageFile& rIF = GetDocument()->getImageFile();
730 Fourier::shuffleFourierToNaturalOrder (rIF);
731 rIF.labelAdd ("Shuffle Fourier To Natural Order");
732 m_bMinSpecified = false;
733 m_bMaxSpecified = false;
734 if (theApp->getSetModifyNewDocs())
735 GetDocument()->Modify(TRUE);
736 GetDocument()->UpdateAllViews(this);
740 ImageFileView::OnMagnitude (wxCommandEvent& event)
742 ImageFile& rIF = GetDocument()->getImageFile();
743 if (rIF.isComplex()) {
745 rIF.labelAdd ("Magnitude of complex-image");
746 m_bMinSpecified = false;
747 m_bMaxSpecified = false;
748 if (theApp->getSetModifyNewDocs())
749 GetDocument()->Modify(TRUE);
750 GetDocument()->UpdateAllViews(this);
755 ImageFileView::OnPhase (wxCommandEvent& event)
757 ImageFile& rIF = GetDocument()->getImageFile();
758 if (rIF.isComplex()) {
760 rIF.labelAdd ("Phase of complex-image");
761 m_bMinSpecified = false;
762 m_bMaxSpecified = false;
763 if (theApp->getSetModifyNewDocs())
764 GetDocument()->Modify(TRUE);
765 GetDocument()->UpdateAllViews(this);
771 ImageFileView::CreateCanvas (wxView *view, wxFrame *parent)
773 ImageFileCanvas* pCanvas;
775 parent->GetClientSize(&width, &height);
777 pCanvas = new ImageFileCanvas (dynamic_cast<ImageFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
779 pCanvas->SetScrollbars(20, 20, 50, 50);
780 pCanvas->SetBackgroundColour(*wxWHITE);
787 ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
790 wxDocMDIChildFrame* subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "ImageFile Frame", wxPoint(-1, -1), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
792 wxDocChildFrame* subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, "ImageFile Frame", wxPoint(-1, -1), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
794 theApp->setIconForFrame (subframe);
796 wxMenu *m_pFileMenu = new wxMenu;
798 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
799 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
800 m_pFileMenu->Append(wxID_OPEN, "&Open...\tCtrl-O");
801 m_pFileMenu->Append(wxID_SAVE, "&Save\tCtrl-S");
802 m_pFileMenu->Append(wxID_SAVEAS, "Save &As...");
803 m_pFileMenu->Append(wxID_CLOSE, "&Close\tCtrl-W");
805 m_pFileMenu->AppendSeparator();
806 m_pFileMenu->Append(IFMENU_FILE_PROPERTIES, "P&roperties");
807 m_pFileMenu->Append(IFMENU_FILE_EXPORT, "&Export...");
809 m_pFileMenu->AppendSeparator();
810 m_pFileMenu->Append(wxID_PRINT, "&Print...");
811 m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
812 m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
814 m_pFileMenu->AppendSeparator();
815 m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit");
817 theApp->getDocManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
818 theApp->getDocManager()->FileHistoryUseMenu(m_pFileMenu);
820 wxMenu *view_menu = new wxMenu;
821 view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale S&et...\tCtrl-E");
822 view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...\tCtrl-A");
823 view_menu->Append(IFMENU_VIEW_SCALE_FULL, "Display F&ull Scale\tCtrl-U");
825 wxMenu* filter_menu = new wxMenu;
826 filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "&Invert Values");
827 filter_menu->Append (IFMENU_FILTER_SQUARE, "&Square");
828 filter_menu->Append (IFMENU_FILTER_SQRT, "Square &Root");
829 filter_menu->Append (IFMENU_FILTER_LOG, "&Log");
830 filter_menu->Append (IFMENU_FILTER_EXP, "&Exp");
831 filter_menu->AppendSeparator();
833 filter_menu->Append (IFMENU_FILTER_FFT, "2D &FFT");
834 filter_menu->Append (IFMENU_FILTER_IFFT, "2D &IFFT");
835 filter_menu->Append (IFMENU_FILTER_FFT_ROWS, "FFT Rows");
836 filter_menu->Append (IFMENU_FILTER_IFFT_ROWS, "IFFT Rows");
837 filter_menu->Append (IFMENU_FILTER_FFT_COLS, "FFT Columns");
838 filter_menu->Append (IFMENU_FILTER_IFFT_COLS, "IFFT Columns");
839 filter_menu->Append (IFMENU_FILTER_FOURIER, "F&ourier");
840 filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "Inverse Fo&urier");
842 filter_menu->Append (IFMENU_FILTER_FOURIER, "&Fourier");
843 filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "&Inverse Fourier");
845 filter_menu->Append (IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, "S&huffle Fourier to Natural Order");
846 filter_menu->Append (IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, "Shu&ffle Natural to Fourier Order");
847 filter_menu->Append (IFMENU_FILTER_MAGNITUDE, "&Magnitude");
848 filter_menu->Append (IFMENU_FILTER_PHASE, "&Phase");
850 wxMenu* image_menu = new wxMenu;
851 image_menu->Append (IFMENU_IMAGE_ADD, "&Add...");
852 image_menu->Append (IFMENU_IMAGE_SUBTRACT, "&Subtract...");
853 image_menu->Append (IFMENU_IMAGE_MULTIPLY, "&Multiply...");
854 image_menu->Append (IFMENU_IMAGE_DIVIDE, "&Divide...");
855 image_menu->AppendSeparator();
856 image_menu->Append (IFMENU_IMAGE_SCALESIZE, "S&cale Size...");
858 wxMenu *analyze_menu = new wxMenu;
859 analyze_menu->Append (IFMENU_PLOT_ROW, "Plot &Row");
860 analyze_menu->Append (IFMENU_PLOT_COL, "Plot &Column");
861 analyze_menu->Append (IFMENU_PLOT_HISTOGRAM, "Plot &Histogram");
862 analyze_menu->AppendSeparator();
863 analyze_menu->Append (IFMENU_PLOT_FFT_ROW, "Plot FFT Row");
864 analyze_menu->Append (IFMENU_PLOT_FFT_COL, "Plot FFT Column");
865 analyze_menu->AppendSeparator();
866 analyze_menu->Append (IFMENU_COMPARE_IMAGES, "Compare &Images...");
867 analyze_menu->Append (IFMENU_COMPARE_ROW, "Compare &Row");
868 analyze_menu->Append (IFMENU_COMPARE_COL, "Compare &Column");
870 wxMenu *help_menu = new wxMenu;
871 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
872 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
873 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
875 wxMenuBar *menu_bar = new wxMenuBar;
877 menu_bar->Append(m_pFileMenu, "&File");
878 menu_bar->Append(view_menu, "&View");
879 menu_bar->Append(image_menu, "&Image");
880 menu_bar->Append(filter_menu, "Fi<er");
881 menu_bar->Append(analyze_menu, "&Analyze");
882 menu_bar->Append(help_menu, "&Help");
884 subframe->SetMenuBar(menu_bar);
886 subframe->Centre(wxBOTH);
888 wxAcceleratorEntry accelEntries[10];
889 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
890 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
891 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('W'), wxID_CLOSE);
892 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
893 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
894 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
895 accelEntries[6].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
896 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('A'), IFMENU_VIEW_SCALE_AUTO);
897 accelEntries[8].Set (wxACCEL_CTRL, static_cast<int>('U'), IFMENU_VIEW_SCALE_FULL);
898 accelEntries[9].Set (wxACCEL_CTRL, static_cast<int>('E'), IFMENU_VIEW_SCALE_MINMAX);
899 wxAcceleratorTable accelTable (10, accelEntries);
900 subframe->SetAcceleratorTable (accelTable);
907 ImageFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
909 m_frame = CreateChildFrame(doc, this);
912 m_bMinSpecified = false;
913 m_bMaxSpecified = false;
914 m_dAutoScaleFactor = 1.;
917 m_frame->GetClientSize (&width, &height);
918 m_frame->SetTitle("ImageFileView");
919 m_canvas = CreateCanvas (this, m_frame);
921 int x, y; // X requires a forced resize
922 m_frame->GetSize(&x, &y);
923 m_frame->SetSize(-1, -1, x, y);
932 ImageFileView::OnDraw (wxDC* dc)
934 wxSize sizeWindow = m_frame->GetClientSize();
935 wxSize sizeBest = m_canvas->GetBestSize();
936 if (sizeWindow.x > sizeBest.x || sizeWindow.y > sizeBest.y)
937 m_frame->SetClientSize (sizeBest);
940 dc->DrawBitmap(m_bitmap, 0, 0, false);
942 int xCursor, yCursor;
943 if (m_canvas->GetCurrentCursor (xCursor, yCursor))
944 m_canvas->DrawRubberBandCursor (*dc, xCursor, yCursor);
949 ImageFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
951 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
952 ImageFileArrayConst v = rIF.getArray();
955 if (v != NULL && nx != 0 && ny != 0) {
956 if (! m_bMinSpecified || ! m_bMaxSpecified) {
958 rIF.getMinMax (min, max);
959 if (! m_bMinSpecified)
961 if (! m_bMaxSpecified)
964 double scaleWidth = m_dMaxPixel - m_dMinPixel;
966 unsigned char* imageData = new unsigned char [nx * ny * 3];
967 for (int ix = 0; ix < nx; ix++) {
968 for (int iy = 0; iy < ny; iy++) {
969 double scaleValue = ((v[ix][iy] - m_dMinPixel) / scaleWidth) * 255;
970 int intensity = static_cast<int>(scaleValue + 0.5);
971 intensity = clamp (intensity, 0, 255);
972 int baseAddr = ((ny - 1 - iy) * nx + ix) * 3;
973 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
976 wxImage image (nx, ny, imageData, true);
977 m_bitmap = image.ConvertToBitmap();
981 ySize = clamp (ySize, 0, 800);
982 m_frame->SetClientSize (xSize, ySize);
983 m_canvas->SetScrollbars(20, 20, nx/20, ny/20);
984 m_canvas->SetBackgroundColour(*wxWHITE);
992 ImageFileView::OnClose (bool deleteWindow)
994 if (!GetDocument()->Close())
997 // m_canvas->Clear();
998 // m_canvas->setView(NULL);
1000 wxString s(theApp->GetAppName());
1002 m_frame->SetTitle(s);
1015 ImageFileView::OnExport (wxCommandEvent& event)
1017 ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1018 ImageFileArrayConst v = rIF.getArray();
1021 if (v != NULL && nx != 0 && ny != 0) {
1022 if (! m_bMinSpecified || ! m_bMaxSpecified) {
1024 rIF.getMinMax (min, max);
1025 if (! m_bMinSpecified)
1027 if (! m_bMaxSpecified)
1031 DialogExportParameters dialogExport (getFrameForChild(), m_iDefaultExportFormatID);
1032 if (dialogExport.ShowModal() == wxID_OK) {
1033 wxString strFormatName (dialogExport.getFormatName ());
1034 m_iDefaultExportFormatID = ImageFile::convertFormatNameToID (strFormatName.c_str());
1037 wxString strWildcard;
1038 if (m_iDefaultExportFormatID == ImageFile::FORMAT_PGM || m_iDefaultExportFormatID == ImageFile::FORMAT_PGMASCII) {
1040 strWildcard = "PGM Files (*.pgm)|*.pgm";
1043 else if (m_iDefaultExportFormatID == ImageFile::FORMAT_PNG || m_iDefaultExportFormatID == ImageFile::FORMAT_PNG16) {
1045 strWildcard = "PNG Files (*.png)|*.png";
1049 const wxString& strFilename = wxFileSelector (wxString("Export Filename"), wxString(""),
1050 wxString(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxHIDE_READONLY | wxSAVE);
1052 rIF.exportImage (strFormatName.c_str(), strFilename.c_str(), 1, 1, m_dMinPixel, m_dMaxPixel);
1053 *theApp->getLog() << "Exported file " << strFilename << "\n";
1060 ImageFileView::OnScaleSize (wxCommandEvent& event)
1062 ImageFile& rIF = GetDocument()->getImageFile();
1063 unsigned int iOldNX = rIF.nx();
1064 unsigned int iOldNY = rIF.ny();
1066 DialogGetXYSize dialogGetXYSize (getFrameForChild(), "Set New X & Y Dimensions", iOldNX, iOldNY);
1067 if (dialogGetXYSize.ShowModal() == wxID_OK) {
1068 unsigned int iNewNX = dialogGetXYSize.getXSize();
1069 unsigned int iNewNY = dialogGetXYSize.getYSize();
1070 std::ostringstream os;
1071 os << "Scale Size from (" << iOldNX << "," << iOldNY << ") to (" << iNewNX << "," << iNewNY << ")";
1072 ImageFileDocument* pScaledDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
1074 sys_error (ERR_SEVERE, "Unable to create image file");
1077 ImageFile& rScaledIF = pScaledDoc->getImageFile();
1078 rScaledIF.setArraySize (iNewNX, iNewNY);
1079 rScaledIF.labelsCopy (rIF);
1080 rScaledIF.labelAdd (os.str().c_str());
1081 rIF.scaleImage (rScaledIF);
1082 *theApp->getLog() << os.str().c_str() << "\n";
1083 if (theApp->getSetModifyNewDocs())
1084 pScaledDoc->Modify(TRUE);
1085 pScaledDoc->UpdateAllViews (this);
1086 pScaledDoc->GetFirstView()->OnUpdate (this, NULL);
1091 ImageFileView::OnPlotRow (wxCommandEvent& event)
1093 int xCursor, yCursor;
1094 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1095 wxMessageBox ("No row selected. Please use left mouse button on image to select column","Error");
1099 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1100 ImageFileArrayConst v = rIF.getArray();
1101 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1105 if (v != NULL && yCursor < ny) {
1106 double* pX = new double [nx];
1107 double* pYReal = new double [nx];
1108 double *pYImag = NULL;
1109 double *pYMag = NULL;
1110 if (rIF.isComplex()) {
1111 pYImag = new double [nx];
1112 pYMag = new double [nx];
1114 for (int i = 0; i < nx; i++) {
1116 pYReal[i] = v[i][yCursor];
1117 if (rIF.isComplex()) {
1118 pYImag[i] = vImag[i][yCursor];
1119 pYMag[i] = ::sqrt (v[i][yCursor] * v[i][yCursor] + vImag[i][yCursor] * vImag[i][yCursor]);
1122 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1124 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1126 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1127 std::ostringstream os;
1128 os << "Row " << yCursor;
1129 std::string title("title ");
1131 rPlotFile.addEzsetCommand (title.c_str());
1132 rPlotFile.addEzsetCommand ("xlabel Column");
1133 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1134 rPlotFile.addEzsetCommand ("lxfrac 0");
1135 rPlotFile.addEzsetCommand ("box");
1136 rPlotFile.addEzsetCommand ("grid");
1137 rPlotFile.addEzsetCommand ("curve 1");
1138 rPlotFile.addEzsetCommand ("color 1");
1139 if (rIF.isComplex()) {
1140 rPlotFile.addEzsetCommand ("dash 1");
1141 rPlotFile.addEzsetCommand ("curve 2");
1142 rPlotFile.addEzsetCommand ("color 4");
1143 rPlotFile.addEzsetCommand ("dash 3");
1144 rPlotFile.addEzsetCommand ("curve 3");
1145 rPlotFile.addEzsetCommand ("color 0");
1146 rPlotFile.addEzsetCommand ("solid");
1147 rPlotFile.setCurveSize (4, nx);
1149 rPlotFile.setCurveSize (2, nx);
1150 rPlotFile.addColumn (0, pX);
1151 rPlotFile.addColumn (1, pYReal);
1152 if (rIF.isComplex()) {
1153 rPlotFile.addColumn (2, pYImag);
1154 rPlotFile.addColumn (3, pYMag);
1156 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1157 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1158 os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1159 *theApp->getLog() << os.str().c_str() << "\n";
1160 rPlotFile.addDescription (os.str().c_str());
1164 if (rIF.isComplex()) {
1168 if (theApp->getSetModifyNewDocs())
1169 pPlotDoc->Modify(true);
1170 pPlotDoc->UpdateAllViews();
1175 ImageFileView::OnPlotCol (wxCommandEvent& event)
1177 int xCursor, yCursor;
1178 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1179 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1183 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1184 ImageFileArrayConst v = rIF.getArray();
1185 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1189 if (v != NULL && xCursor < nx) {
1190 double* pX = new double [ny];
1191 double* pYReal = new double [ny];
1192 double* pYImag = NULL;
1193 double* pYMag = NULL;
1194 if (rIF.isComplex()) {
1195 pYImag = new double [ny];
1196 pYMag = new double [ny];
1198 for (int i = 0; i < ny; i++) {
1200 pYReal[i] = v[xCursor][i];
1201 if (rIF.isComplex()) {
1202 pYImag[i] = vImag[xCursor][i];
1203 pYMag[i] = ::sqrt (v[xCursor][i] * v[xCursor][i] + vImag[xCursor][i] * vImag[xCursor][i]);
1206 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1208 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1210 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1211 std::ostringstream os;
1212 os << "Column " << xCursor;
1213 std::string title("title ");
1215 rPlotFile.addEzsetCommand (title.c_str());
1216 rPlotFile.addEzsetCommand ("xlabel Row");
1217 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1218 rPlotFile.addEzsetCommand ("lxfrac 0");
1219 rPlotFile.addEzsetCommand ("box");
1220 rPlotFile.addEzsetCommand ("grid");
1221 rPlotFile.addEzsetCommand ("curve 1");
1222 rPlotFile.addEzsetCommand ("color 1");
1223 if (rIF.isComplex()) {
1224 rPlotFile.addEzsetCommand ("dash 1");
1225 rPlotFile.addEzsetCommand ("curve 2");
1226 rPlotFile.addEzsetCommand ("color 4");
1227 rPlotFile.addEzsetCommand ("dash 3");
1228 rPlotFile.addEzsetCommand ("curve 3");
1229 rPlotFile.addEzsetCommand ("color 0");
1230 rPlotFile.addEzsetCommand ("solid");
1231 rPlotFile.setCurveSize (4, ny);
1233 rPlotFile.setCurveSize (2, ny);
1234 rPlotFile.addColumn (0, pX);
1235 rPlotFile.addColumn (1, pYReal);
1236 if (rIF.isComplex()) {
1237 rPlotFile.addColumn (2, pYImag);
1238 rPlotFile.addColumn (3, pYMag);
1240 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++)
1241 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1242 os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1243 *theApp->getLog() << os.str().c_str() << "\n";
1244 rPlotFile.addDescription (os.str().c_str());
1248 if (rIF.isComplex()) {
1252 if (theApp->getSetModifyNewDocs())
1253 pPlotDoc->Modify(true);
1254 pPlotDoc->UpdateAllViews();
1260 ImageFileView::OnPlotFFTRow (wxCommandEvent& event)
1262 int xCursor, yCursor;
1263 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1264 wxMessageBox ("No row selected. Please use left mouse button on image to select column","Error");
1268 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1269 ImageFileArrayConst v = rIF.getArray();
1270 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1274 if (v != NULL && yCursor < ny) {
1275 fftw_complex* pcIn = new fftw_complex [nx];
1278 for (i = 0; i < nx; i++) {
1279 pcIn[i].re = v[i][yCursor];
1280 if (rIF.isComplex())
1281 pcIn[i].im = vImag[i][yCursor];
1286 fftw_plan plan = fftw_create_plan (nx, FFTW_FORWARD, FFTW_IN_PLACE);
1287 fftw_one (plan, pcIn, NULL);
1288 fftw_destroy_plan (plan);
1290 double* pX = new double [nx];
1291 double* pYReal = new double [nx];
1292 double* pYImag = new double [nx];
1293 double* pYMag = new double [nx];
1294 for (i = 0; i < nx; i++) {
1296 pYReal[i] = pcIn[i].re;
1297 pYImag[i] = pcIn[i].im;
1298 pYMag[i] = ::sqrt (pcIn[i].re * pcIn[i].re + pcIn[i].im * pcIn[i].im);
1300 Fourier::shuffleFourierToNaturalOrder (pYReal, nx);
1301 Fourier::shuffleFourierToNaturalOrder (pYImag, nx);
1302 Fourier::shuffleFourierToNaturalOrder (pYMag, nx);
1304 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1306 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1308 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1309 std::ostringstream os;
1310 os << "Row " << yCursor;
1311 std::string title("title ");
1313 rPlotFile.addEzsetCommand (title.c_str());
1314 rPlotFile.addEzsetCommand ("xlabel Column");
1315 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1316 rPlotFile.addEzsetCommand ("lxfrac 0");
1317 rPlotFile.addEzsetCommand ("curve 1");
1318 rPlotFile.addEzsetCommand ("color 1");
1319 rPlotFile.addEzsetCommand ("dash 1");
1320 rPlotFile.addEzsetCommand ("curve 2");
1321 rPlotFile.addEzsetCommand ("color 4");
1322 rPlotFile.addEzsetCommand ("dash 3");
1323 rPlotFile.addEzsetCommand ("curve 3");
1324 rPlotFile.addEzsetCommand ("color 0");
1325 rPlotFile.addEzsetCommand ("solid");
1326 rPlotFile.addEzsetCommand ("box");
1327 rPlotFile.addEzsetCommand ("grid");
1328 rPlotFile.setCurveSize (4, nx);
1329 rPlotFile.addColumn (0, pX);
1330 rPlotFile.addColumn (1, pYReal);
1331 rPlotFile.addColumn (2, pYImag);
1332 rPlotFile.addColumn (3, pYMag);
1333 for (int iL = 0; iL < rIF.nLabels(); iL++)
1334 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1335 os << " FFT Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1336 *theApp->getLog() << os.str().c_str() << "\n";
1337 rPlotFile.addDescription (os.str().c_str());
1345 if (theApp->getSetModifyNewDocs())
1346 pPlotDoc->Modify(true);
1347 pPlotDoc->UpdateAllViews();
1352 ImageFileView::OnPlotFFTCol (wxCommandEvent& event)
1354 int xCursor, yCursor;
1355 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1356 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1360 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1361 ImageFileArrayConst v = rIF.getArray();
1362 ImageFileArrayConst vImag = rIF.getImaginaryArray();
1366 if (v != NULL && xCursor < nx) {
1367 fftw_complex* pcIn = new fftw_complex [ny];
1368 double *pdTemp = new double [ny];
1371 for (i = 0; i < ny; i++)
1372 pdTemp[i] = v[xCursor][i];
1373 Fourier::shuffleNaturalToFourierOrder (pdTemp, ny);
1374 for (i = 0; i < ny; i++)
1375 pcIn[i].re = pdTemp[i];
1377 for (i = 0; i < ny; i++) {
1378 if (rIF.isComplex())
1379 pdTemp[i] = vImag[xCursor][i];
1383 Fourier::shuffleNaturalToFourierOrder (pdTemp, ny);
1384 for (i = 0; i < ny; i++)
1385 pcIn[i].im = pdTemp[i];
1387 fftw_plan plan = fftw_create_plan (ny, FFTW_BACKWARD, FFTW_IN_PLACE);
1388 fftw_one (plan, pcIn, NULL);
1389 fftw_destroy_plan (plan);
1391 double* pX = new double [ny];
1392 double* pYReal = new double [ny];
1393 double* pYImag = new double [ny];
1394 double* pYMag = new double [ny];
1395 for (i = 0; i < ny; i++) {
1397 pYReal[i] = pcIn[i].re;
1398 pYImag[i] = pcIn[i].im;
1399 pYMag[i] = ::sqrt (pcIn[i].re * pcIn[i].re + pcIn[i].im * pcIn[i].im);
1402 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1404 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1406 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1407 std::ostringstream os;
1408 os << "Column " << xCursor;
1409 std::string title("title ");
1411 rPlotFile.addEzsetCommand (title.c_str());
1412 rPlotFile.addEzsetCommand ("xlabel Column");
1413 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1414 rPlotFile.addEzsetCommand ("lxfrac 0");
1415 rPlotFile.addEzsetCommand ("curve 1");
1416 rPlotFile.addEzsetCommand ("color 1");
1417 rPlotFile.addEzsetCommand ("dash 1");
1418 rPlotFile.addEzsetCommand ("curve 2");
1419 rPlotFile.addEzsetCommand ("color 4");
1420 rPlotFile.addEzsetCommand ("dash 3");
1421 rPlotFile.addEzsetCommand ("curve 3");
1422 rPlotFile.addEzsetCommand ("color 0");
1423 rPlotFile.addEzsetCommand ("solid");
1424 rPlotFile.addEzsetCommand ("box");
1425 rPlotFile.addEzsetCommand ("grid");
1426 rPlotFile.setCurveSize (4, ny);
1427 rPlotFile.addColumn (0, pX);
1428 rPlotFile.addColumn (1, pYReal);
1429 rPlotFile.addColumn (2, pYImag);
1430 rPlotFile.addColumn (3, pYMag);
1431 for (int iL = 0; iL < rIF.nLabels(); iL++)
1432 rPlotFile.addDescription (rIF.labelGet(iL).getLabelString().c_str());
1433 os << " FFT Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1434 *theApp->getLog() << os.str().c_str() << "\n";
1435 rPlotFile.addDescription (os.str().c_str());
1444 if (theApp->getSetModifyNewDocs())
1445 pPlotDoc->Modify(true);
1446 pPlotDoc->UpdateAllViews();
1452 ImageFileView::OnCompareCol (wxCommandEvent& event)
1454 int xCursor, yCursor;
1455 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1456 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1460 std::vector<ImageFileDocument*> vecIFDoc;
1461 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
1462 if (vecIFDoc.size() == 0) {
1463 wxMessageBox ("No compatible images for Column Comparison", "Error");
1466 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Comparison Image", vecIFDoc, false);
1468 if (dialogGetCompare.ShowModal() == wxID_OK) {
1469 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
1470 const ImageFile& rIF = GetDocument()->getImageFile();
1471 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
1473 ImageFileArrayConst v1 = rIF.getArray();
1474 ImageFileArrayConst v2 = rCompareIF.getArray();
1478 if (v1 != NULL && xCursor < nx) {
1479 double* pX = new double [ny];
1480 double* pY1 = new double [ny];
1481 double* pY2 = new double [ny];
1482 for (int i = 0; i < ny; i++) {
1484 pY1[i] = v1[xCursor][i];
1485 pY2[i] = v2[xCursor][i];
1487 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1489 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1491 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1492 std::ostringstream os;
1493 os << "Column " << xCursor << " Comparison";
1494 std::string title("title ");
1496 rPlotFile.addEzsetCommand (title.c_str());
1497 rPlotFile.addEzsetCommand ("xlabel Row");
1498 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1499 rPlotFile.addEzsetCommand ("lxfrac 0");
1500 rPlotFile.addEzsetCommand ("curve 1");
1501 rPlotFile.addEzsetCommand ("color 2");
1502 rPlotFile.addEzsetCommand ("curve 2");
1503 rPlotFile.addEzsetCommand ("color 4");
1504 rPlotFile.addEzsetCommand ("dash 5");
1505 rPlotFile.addEzsetCommand ("box");
1506 rPlotFile.addEzsetCommand ("grid");
1507 rPlotFile.setCurveSize (3, ny);
1508 rPlotFile.addColumn (0, pX);
1509 rPlotFile.addColumn (1, pY1);
1510 rPlotFile.addColumn (2, pY2);
1513 for (iL = 0; iL < rIF.nLabels(); iL++) {
1514 std::string s = GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1516 s += rIF.labelGet(iL).getLabelString();
1517 rPlotFile.addDescription (s.c_str());
1519 for (iL = 0; iL < rCompareIF.nLabels(); iL++) {
1520 std::string s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1522 s += rCompareIF.labelGet(iL).getLabelString();
1523 rPlotFile.addDescription (s.c_str());
1525 os << " Between " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
1526 << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1527 *theApp->getLog() << os.str().c_str() << "\n";
1528 rPlotFile.addDescription (os.str().c_str());
1533 if (theApp->getSetModifyNewDocs())
1534 pPlotDoc->Modify(true);
1535 pPlotDoc->UpdateAllViews();
1541 ImageFileView::OnCompareRow (wxCommandEvent& event)
1543 int xCursor, yCursor;
1544 if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {
1545 wxMessageBox ("No column selected. Please use left mouse button on image to select column","Error");
1549 std::vector<ImageFileDocument*> vecIFDoc;
1550 theApp->getCompatibleImages (GetDocument(), vecIFDoc);
1552 if (vecIFDoc.size() == 0) {
1553 wxMessageBox ("No compatible images for Row Comparison", "Error");
1557 DialogGetComparisonImage dialogGetCompare (getFrameForChild(), "Get Comparison Image", vecIFDoc, false);
1559 if (dialogGetCompare.ShowModal() == wxID_OK) {
1560 ImageFileDocument* pCompareDoc = dialogGetCompare.getImageFileDocument();
1561 const ImageFile& rIF = GetDocument()->getImageFile();
1562 const ImageFile& rCompareIF = pCompareDoc->getImageFile();
1564 ImageFileArrayConst v1 = rIF.getArray();
1565 ImageFileArrayConst v2 = rCompareIF.getArray();
1569 if (v1 != NULL && yCursor < ny) {
1570 double* pX = new double [nx];
1571 double* pY1 = new double [nx];
1572 double* pY2 = new double [nx];
1573 for (int i = 0; i < nx; i++) {
1575 pY1[i] = v1[i][yCursor];
1576 pY2[i] = v2[i][yCursor];
1578 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1580 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1582 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1583 std::ostringstream os;
1584 os << "Row " << yCursor << " Comparison";
1585 std::string title("title ");
1587 rPlotFile.addEzsetCommand (title.c_str());
1588 rPlotFile.addEzsetCommand ("xlabel Column");
1589 rPlotFile.addEzsetCommand ("ylabel Pixel Value");
1590 rPlotFile.addEzsetCommand ("lxfrac 0");
1591 rPlotFile.addEzsetCommand ("curve 1");
1592 rPlotFile.addEzsetCommand ("color 2");
1593 rPlotFile.addEzsetCommand ("curve 2");
1594 rPlotFile.addEzsetCommand ("color 4");
1595 rPlotFile.addEzsetCommand ("dash 5");
1596 rPlotFile.addEzsetCommand ("box");
1597 rPlotFile.addEzsetCommand ("grid");
1598 rPlotFile.setCurveSize (3, nx);
1599 rPlotFile.addColumn (0, pX);
1600 rPlotFile.addColumn (1, pY1);
1601 rPlotFile.addColumn (2, pY2);
1603 for (iL = 0; iL < rIF.nLabels(); iL++) {
1604 std::string s = GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1606 s += rIF.labelGet(iL).getLabelString();
1607 rPlotFile.addDescription (s.c_str());
1609 for (iL = 0; iL < rCompareIF.nLabels(); iL++) {
1610 std::string s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1612 s += rCompareIF.labelGet(iL).getLabelString();
1613 rPlotFile.addDescription (s.c_str());
1615 os << " Between " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and "
1616 << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str();
1617 *theApp->getLog() << os.str().c_str() << "\n";
1618 rPlotFile.addDescription (os.str().c_str());
1623 if (theApp->getSetModifyNewDocs())
1624 pPlotDoc->Modify(true);
1625 pPlotDoc->UpdateAllViews();
1630 static int NUMBER_HISTOGRAM_BINS = 256;
1633 ImageFileView::OnPlotHistogram (wxCommandEvent& event)
1635 const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();
1636 ImageFileArrayConst v = rIF.getArray();
1640 if (v != NULL && nx > 0 && ny > 0) {
1641 PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));
1643 sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");
1647 double* pX = new double [NUMBER_HISTOGRAM_BINS];
1648 double* pY = new double [NUMBER_HISTOGRAM_BINS];
1650 rIF.getMinMax (dMin, dMax);
1651 double dBinWidth = (dMax - dMin) / NUMBER_HISTOGRAM_BINS;
1653 for (int i = 0; i < NUMBER_HISTOGRAM_BINS; i++) {
1654 pX[i] = dMin + (i + 0.5) * dBinWidth;
1657 for (int ix = 0; ix < nx; ix++)
1658 for (int iy = 0; iy < ny; iy++) {
1659 int iBin = nearest<int> ((v[ix][iy] - dMin) / dBinWidth);
1660 if (iBin >= 0 && iBin < NUMBER_HISTOGRAM_BINS)
1664 PlotFile& rPlotFile = pPlotDoc->getPlotFile();
1665 std::ostringstream os;
1667 std::string title("title ");
1669 rPlotFile.addEzsetCommand (title.c_str());
1670 rPlotFile.addEzsetCommand ("xlabel Pixel Value");
1671 rPlotFile.addEzsetCommand ("ylabel Count");
1672 rPlotFile.addEzsetCommand ("box");
1673 rPlotFile.addEzsetCommand ("grid");
1674 rPlotFile.setCurveSize (2, NUMBER_HISTOGRAM_BINS);
1675 rPlotFile.addColumn (0, pX);
1676 rPlotFile.addColumn (1, pY);
1677 for (unsigned int iL = 0; iL < rIF.nLabels(); iL++) {
1678 std::string s = GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1680 s += rIF.labelGet(iL).getLabelString();
1681 rPlotFile.addDescription (s.c_str());
1683 os << " Plot of " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str();
1684 *theApp->getLog() << os.str().c_str() << "\n";
1685 rPlotFile.addDescription (os.str().c_str());
1688 if (theApp->getSetModifyNewDocs())
1689 pPlotDoc->Modify(true);
1690 pPlotDoc->UpdateAllViews();
1697 PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
1698 : wxScrolledWindow(frame, -1, pos, size, style)
1703 PhantomCanvas::~PhantomCanvas ()
1706 wxMenu* pMenu = m_pView->getFileMenu();
1707 theApp->getDocManager()->FileHistoryRemoveMenu (pMenu);
1712 PhantomCanvas::OnDraw (wxDC& dc)
1715 m_pView->OnDraw(& dc);
1721 IMPLEMENT_DYNAMIC_CLASS(PhantomView, wxView)
1723 BEGIN_EVENT_TABLE(PhantomView, wxView)
1724 EVT_MENU(PHMMENU_FILE_PROPERTIES, PhantomView::OnProperties)
1725 EVT_MENU(PHMMENU_PROCESS_RASTERIZE, PhantomView::OnRasterize)
1726 EVT_MENU(PHMMENU_PROCESS_PROJECTIONS, PhantomView::OnProjections)
1729 PhantomView::PhantomView(void)
1730 : wxView(), m_canvas(NULL), m_frame(NULL), m_pFileMenu(0)
1732 m_iDefaultNDet = 367;
1733 m_iDefaultNView = 320;
1734 m_iDefaultNSample = 2;
1735 m_dDefaultRotation = 1;
1736 m_dDefaultFocalLength = 2;
1737 m_dDefaultFieldOfView = 1;
1738 m_iDefaultGeometry = Scanner::GEOMETRY_PARALLEL;
1739 m_iDefaultTrace = Trace::TRACE_NONE;
1741 m_iDefaultRasterNX = 256;
1742 m_iDefaultRasterNY = 256;
1743 m_iDefaultRasterNSamples = 2;
1746 PhantomView::~PhantomView()
1751 PhantomView::OnProperties (wxCommandEvent& event)
1753 const int idPhantom = GetDocument()->getPhantomID();
1754 const wxString& namePhantom = GetDocument()->getPhantomName();
1755 std::ostringstream os;
1756 os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")" << "\n";
1757 const Phantom& rPhantom = GetDocument()->getPhantom();
1758 rPhantom.printDefinitions (os);
1760 rPhantom.print (os);
1762 *theApp->getLog() << os.str().c_str() << "\n";
1763 wxMessageBox (os.str().c_str(), "Phantom Properties");
1768 PhantomView::OnProjections (wxCommandEvent& event)
1770 DialogGetProjectionParameters dialogProjection (getFrameForChild(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView, m_iDefaultGeometry, m_iDefaultTrace);
1771 int retVal = dialogProjection.ShowModal();
1772 if (retVal == wxID_OK) {
1773 m_iDefaultNDet = dialogProjection.getNDet();
1774 m_iDefaultNView = dialogProjection.getNView();
1775 m_iDefaultNSample = dialogProjection.getNSamples();
1776 m_iDefaultTrace = dialogProjection.getTrace();
1777 m_dDefaultRotation = dialogProjection.getRotAngle();
1778 m_dDefaultFocalLength = dialogProjection.getFocalLengthRatio();
1779 m_dDefaultFieldOfView = dialogProjection.getFieldOfViewRatio();
1780 wxString sGeometry = dialogProjection.getGeometry();
1781 m_iDefaultGeometry = Scanner::convertGeometryNameToID (sGeometry.c_str());
1783 if (m_iDefaultNDet > 0 && m_iDefaultNView > 0 && sGeometry != "") {
1784 const Phantom& rPhantom = GetDocument()->getPhantom();
1785 ProjectionFileDocument* pProjectionDoc = dynamic_cast<ProjectionFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.pj", wxDOC_SILENT));
1786 if (! pProjectionDoc) {
1787 sys_error (ERR_SEVERE, "Unable to create projection document");
1790 Projections& rProj = pProjectionDoc->getProjections();
1791 Scanner theScanner (rPhantom, sGeometry.c_str(), m_iDefaultNDet, m_iDefaultNView, m_iDefaultNSample, m_dDefaultRotation, m_dDefaultFocalLength, m_dDefaultFieldOfView);
1792 if (theScanner.fail()) {
1793 *theApp->getLog() << "Failed making scanner: " << theScanner.failMessage().c_str() << "\n";
1796 rProj.initFromScanner (theScanner);
1797 m_dDefaultRotation /= PI; // convert back to PI units
1800 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
1801 ProjectionsDialog dialogProjections (theScanner, rProj, rPhantom, m_iDefaultTrace, dynamic_cast<wxWindow*>(getFrameForChild()));
1802 for (int iView = 0; iView < rProj.nView(); iView++) {
1805 if (dialogProjections.isCancelled() || ! dialogProjections.projectView (iView)) {
1806 pProjectionDoc->DeleteAllViews();
1811 while (dialogProjections.isPaused()) {
1817 wxProgressDialog dlgProgress (wxString("Projection"), wxString("Projection Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT);
1818 for (int i = 0; i < rProj.nView(); i++) {
1819 theScanner.collectProjections (rProj, rPhantom, i, 1, true, m_iDefaultTrace);
1820 if (! dlgProgress.Update (i+1)) {
1821 pProjectionDoc->DeleteAllViews();
1827 std::ostringstream os;
1828 os << "Projections for " << rPhantom.name() << ": nDet=" << m_iDefaultNDet << ", nView=" << m_iDefaultNView << ", nSamples=" << m_iDefaultNSample << ", RotAngle=" << m_dDefaultRotation << ", FocalLengthRatio=" << m_dDefaultFocalLength << ", FieldOfViewRatio=" << m_dDefaultFieldOfView << ", Geometry=" << sGeometry.c_str();
1829 rProj.setCalcTime (timer.timerEnd());
1830 rProj.setRemark (os.str());
1831 *theApp->getLog() << os.str().c_str() << "\n";
1835 ProjectionFileView* projView = dynamic_cast<ProjectionFileView*>(pProjectionDoc->GetFirstView());
1837 projView->getFrame()->SetFocus();
1838 projView->OnUpdate (projView, NULL);
1840 if (wxView* pView = pProjectionDoc->GetFirstView()) {
1841 if (wxFrame* pFrame = pView->GetFrame()) {
1845 theApp->getDocManager()->ActivateView (pView, true, false);
1848 if (theApp->getSetModifyNewDocs())
1849 pProjectionDoc->Modify(true);
1850 pProjectionDoc->UpdateAllViews(this);
1857 PhantomView::OnRasterize (wxCommandEvent& event)
1859 DialogGetRasterParameters dialogRaster (getFrameForChild(), m_iDefaultRasterNX, m_iDefaultRasterNY, m_iDefaultRasterNSamples);
1860 int retVal = dialogRaster.ShowModal();
1861 if (retVal == wxID_OK) {
1862 m_iDefaultRasterNX = dialogRaster.getXSize();
1863 m_iDefaultRasterNY = dialogRaster.getYSize();
1864 m_iDefaultRasterNSamples = dialogRaster.getNSamples();
1865 if (m_iDefaultRasterNSamples < 1)
1866 m_iDefaultRasterNSamples = 1;
1867 if (m_iDefaultRasterNX > 0 && m_iDefaultRasterNY > 0) {
1868 const Phantom& rPhantom = GetDocument()->getPhantom();
1869 ImageFileDocument* pRasterDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
1871 sys_error (ERR_SEVERE, "Unable to create image file");
1874 ImageFile& imageFile = pRasterDoc->getImageFile();
1876 imageFile.setArraySize (m_iDefaultRasterNX, m_iDefaultRasterNX);
1877 wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), imageFile.nx() + 1, getFrameForChild(), wxPD_CAN_ABORT);
1879 for (unsigned int i = 0; i < imageFile.nx(); i++) {
1880 rPhantom.convertToImagefile (imageFile, m_iDefaultRasterNSamples, Trace::TRACE_NONE, i, 1, true);
1881 if (! dlgProgress.Update(i+1)) {
1882 pRasterDoc->DeleteAllViews();
1886 if (theApp->getSetModifyNewDocs())
1887 pRasterDoc->Modify(true);
1888 pRasterDoc->UpdateAllViews(this);
1889 std::ostringstream os;
1890 os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << m_iDefaultRasterNX << ", YSize="
1891 << m_iDefaultRasterNY << ", nSamples=" << m_iDefaultRasterNSamples;
1892 *theApp->getLog() << os.str().c_str() << "\n";
1893 imageFile.labelAdd (os.str().c_str(), timer.timerEnd());
1894 ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pRasterDoc->GetFirstView());
1896 rasterView->getFrame()->SetFocus();
1897 rasterView->OnUpdate (rasterView, NULL);
1906 PhantomView::CreateCanvas (wxView *view, wxFrame *parent)
1908 PhantomCanvas* pCanvas;
1910 parent->GetClientSize(&width, &height);
1912 pCanvas = new PhantomCanvas (dynamic_cast<PhantomView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
1914 pCanvas->SetBackgroundColour(*wxWHITE);
1921 PhantomView::CreateChildFrame(wxDocument *doc, wxView *view)
1924 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "Phantom Frame", wxPoint(10, 10), wxSize(256, 256), wxDEFAULT_FRAME_STYLE);
1926 wxDocChildFrame *subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, "Phantom Frame", wxPoint(10, 10), wxSize(256, 256), wxDEFAULT_FRAME_STYLE);
1928 theApp->setIconForFrame (subframe);
1930 wxMenu *m_pFileMenu = new wxMenu;
1932 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
1933 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
1934 m_pFileMenu->Append(wxID_OPEN, "&Open...\tCtrl-O");
1935 m_pFileMenu->Append(wxID_SAVEAS, "Save &As...");
1936 m_pFileMenu->Append(wxID_CLOSE, "&Close");
1938 m_pFileMenu->AppendSeparator();
1939 m_pFileMenu->Append(PHMMENU_FILE_PROPERTIES, "P&roperties");
1941 m_pFileMenu->AppendSeparator();
1942 m_pFileMenu->Append(wxID_PRINT, "&Print...");
1943 m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
1944 m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
1946 m_pFileMenu->AppendSeparator();
1947 m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit");
1949 theApp->getDocManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
1950 theApp->getDocManager()->FileHistoryUseMenu(m_pFileMenu);
1952 wxMenu *process_menu = new wxMenu;
1953 process_menu->Append(PHMMENU_PROCESS_RASTERIZE, "&Rasterize...\tCtrl-R");
1954 process_menu->Append(PHMMENU_PROCESS_PROJECTIONS, "&Projections...\tCtrl-J");
1956 wxMenu *help_menu = new wxMenu;
1957 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
1958 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
1959 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
1961 wxMenuBar *menu_bar = new wxMenuBar;
1963 menu_bar->Append(m_pFileMenu, "&File");
1964 menu_bar->Append(process_menu, "&Process");
1965 menu_bar->Append(help_menu, "&Help");
1967 subframe->SetMenuBar(menu_bar);
1968 subframe->Centre(wxBOTH);
1970 wxAcceleratorEntry accelEntries[8];
1971 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
1972 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
1973 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
1974 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
1975 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
1976 accelEntries[5].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
1977 accelEntries[6].Set (wxACCEL_CTRL, static_cast<int>('J'), PHMMENU_PROCESS_PROJECTIONS);
1978 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('R'), PHMMENU_PROCESS_RASTERIZE);
1979 wxAcceleratorTable accelTable (8, accelEntries);
1980 subframe->SetAcceleratorTable (accelTable);
1987 PhantomView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
1989 m_frame = CreateChildFrame(doc, this);
1993 m_frame->GetClientSize(&width, &height);
1994 m_frame->SetTitle("PhantomView");
1995 m_canvas = CreateCanvas (this, m_frame);
1998 int x, y; // X requires a forced resize
1999 m_frame->GetSize(&x, &y);
2000 m_frame->SetSize(-1, -1, x, y);
2003 m_frame->Show(true);
2010 PhantomView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2013 m_canvas->Refresh();
2017 PhantomView::OnClose (bool deleteWindow)
2019 if (!GetDocument()->Close())
2022 // m_canvas->Clear();
2023 // m_canvas->setView(NULL);
2025 wxString s(wxTheApp->GetAppName());
2027 m_frame->SetTitle(s);
2039 PhantomView::OnDraw (wxDC* dc)
2042 m_canvas->GetClientSize (&xsize, &ysize);
2043 SGPDriver driver (dc, xsize, ysize);
2045 const Phantom& rPhantom = GetDocument()->getPhantom();
2046 sgp.setColor (C_RED);
2047 rPhantom.show (sgp);
2052 ProjectionFileCanvas::ProjectionFileCanvas (ProjectionFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
2053 : wxScrolledWindow(frame, -1, pos, size, style)
2058 ProjectionFileCanvas::~ProjectionFileCanvas ()
2061 wxMenu* pMenu = m_pView->getFileMenu();
2062 theApp->getDocManager()->FileHistoryRemoveMenu (pMenu);
2067 ProjectionFileCanvas::OnDraw(wxDC& dc)
2070 m_pView->OnDraw(& dc);
2074 ProjectionFileCanvas::GetBestSize () const
2078 Projections& rProj = m_pView->GetDocument()->getProjections();
2079 best.Set (rProj.nDet(), rProj.nView());
2086 // ProjectionFileView
2088 IMPLEMENT_DYNAMIC_CLASS(ProjectionFileView, wxView)
2090 BEGIN_EVENT_TABLE(ProjectionFileView, wxView)
2091 EVT_MENU(PJMENU_FILE_PROPERTIES, ProjectionFileView::OnProperties)
2092 EVT_MENU(PJMENU_RECONSTRUCT_FBP, ProjectionFileView::OnReconstructFBP)
2093 EVT_MENU(PJMENU_CONVERT_POLAR, ProjectionFileView::OnConvertPolar)
2094 EVT_MENU(PJMENU_CONVERT_FFT_POLAR, ProjectionFileView::OnConvertFFTPolar)
2097 ProjectionFileView::ProjectionFileView(void)
2098 : wxView(), m_canvas(NULL), m_frame(NULL), m_pFileMenu(0)
2102 m_iDefaultFilter = SignalFilter::FILTER_ABS_BANDLIMIT;
2103 m_dDefaultFilterParam = 1.;
2105 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_RFFTW;
2106 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_INVERSE_FOURIER;
2108 m_iDefaultFilterMethod = ProcessSignal::FILTER_METHOD_CONVOLUTION;
2109 m_iDefaultFilterGeneration = ProcessSignal::FILTER_GENERATION_DIRECT;
2111 m_iDefaultZeropad = 1;
2112 m_iDefaultBackprojector = Backprojector::BPROJ_IDIFF3;
2113 m_iDefaultInterpolation = Backprojector::INTERP_LINEAR;
2114 m_iDefaultInterpParam = 1;
2115 m_iDefaultTrace = Trace::TRACE_NONE;
2117 m_iDefaultPolarNX = 256;
2118 m_iDefaultPolarNY = 256;
2119 m_iDefaultPolarInterpolation = Projections::POLAR_INTERP_BILINEAR;
2120 m_iDefaultPolarZeropad = 1;
2123 ProjectionFileView::~ProjectionFileView(void)
2128 ProjectionFileView::OnProperties (wxCommandEvent& event)
2130 const Projections& rProj = GetDocument()->getProjections();
2131 std::ostringstream os;
2132 rProj.printScanInfo(os);
2133 *theApp->getLog() << os.str().c_str();
2134 wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Projection File Properties", wxOK | wxICON_INFORMATION);
2135 dialogMsg.ShowModal();
2140 ProjectionFileView::OnConvertPolar (wxCommandEvent& event)
2142 Projections& rProj = GetDocument()->getProjections();
2143 DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), "Convert Polar", m_iDefaultPolarNX, m_iDefaultPolarNY,
2144 m_iDefaultPolarInterpolation, -1);
2145 if (dialogPolar.ShowModal() == wxID_OK) {
2146 wxString strInterpolation (dialogPolar.getInterpolationName());
2147 m_iDefaultPolarNX = dialogPolar.getXSize();
2148 m_iDefaultPolarNY = dialogPolar.getYSize();
2149 ImageFileDocument* pPolarDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
2150 ImageFile& rIF = pPolarDoc->getImageFile();
2152 sys_error (ERR_SEVERE, "Unable to create image file");
2155 rIF.setArraySize (m_iDefaultPolarNX, m_iDefaultPolarNY);
2156 m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.c_str());
2157 rProj.convertPolar (rIF, m_iDefaultPolarInterpolation);
2158 rIF.labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2159 std::ostringstream os;
2160 os << "Convert projection file " << GetFrame()->GetTitle().c_str() << " to polar image: xSize="
2161 << m_iDefaultPolarNX << ", ySize=" << m_iDefaultPolarNY << ", interpolation="
2162 << strInterpolation.c_str();
2163 *theApp->getLog() << os.str().c_str() << "\n";
2164 rIF.labelAdd (os.str().c_str());
2165 if (theApp->getSetModifyNewDocs())
2166 pPolarDoc->Modify(true);
2167 pPolarDoc->UpdateAllViews();
2168 pPolarDoc->GetFirstView()->OnUpdate (this, NULL);
2173 ProjectionFileView::OnConvertFFTPolar (wxCommandEvent& event)
2175 Projections& rProj = GetDocument()->getProjections();
2176 DialogGetConvertPolarParameters dialogPolar (getFrameForChild(), "Convert to FFT Polar", m_iDefaultPolarNX, m_iDefaultPolarNY,
2177 m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad);
2178 if (dialogPolar.ShowModal() == wxID_OK) {
2179 wxString strInterpolation (dialogPolar.getInterpolationName());
2180 m_iDefaultPolarNX = dialogPolar.getXSize();
2181 m_iDefaultPolarNY = dialogPolar.getYSize();
2182 m_iDefaultPolarZeropad = dialogPolar.getZeropad();
2183 ImageFileDocument* pPolarDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
2184 ImageFile& rIF = pPolarDoc->getImageFile();
2186 sys_error (ERR_SEVERE, "Unable to create image file");
2189 rIF.setArraySize (m_iDefaultPolarNX, m_iDefaultPolarNY);
2190 m_iDefaultPolarInterpolation = Projections::convertInterpNameToID (strInterpolation.c_str());
2191 rProj.convertFFTPolar (rIF, m_iDefaultPolarInterpolation, m_iDefaultPolarZeropad);
2192 rIF.labelAdd (rProj.getLabel().getLabelString().c_str(), rProj.calcTime());
2193 std::ostringstream os;
2194 os << "Convert projection file " << GetFrame()->GetTitle().c_str() << " to FFT polar image: xSize="
2195 << m_iDefaultPolarNX << ", ySize=" << m_iDefaultPolarNY << ", interpolation="
2196 << strInterpolation.c_str() << ", zeropad=" << m_iDefaultPolarZeropad;
2197 *theApp->getLog() << os.str().c_str() << "\n";
2198 rIF.labelAdd (os.str().c_str());
2199 if (theApp->getSetModifyNewDocs())
2200 pPolarDoc->Modify(true);
2201 pPolarDoc->UpdateAllViews();
2202 pPolarDoc->GetFirstView()->OnUpdate (this, NULL);
2206 ProjectionFileView::OnReconstructFourier (wxCommandEvent& event)
2208 wxMessageBox ("Fourier Reconstruction is not yet supported", "Unimplemented function");
2212 ProjectionFileView::OnReconstructFBP (wxCommandEvent& event)
2214 DialogGetReconstructionParameters dialogReconstruction (getFrameForChild(), m_iDefaultNX, m_iDefaultNY, m_iDefaultFilter, m_dDefaultFilterParam, m_iDefaultFilterMethod, m_iDefaultFilterGeneration, m_iDefaultZeropad, m_iDefaultInterpolation, m_iDefaultInterpParam, m_iDefaultBackprojector, m_iDefaultTrace);
2216 int retVal = dialogReconstruction.ShowModal();
2217 if (retVal == wxID_OK) {
2218 m_iDefaultNX = dialogReconstruction.getXSize();
2219 m_iDefaultNY = dialogReconstruction.getYSize();
2220 wxString optFilterName = dialogReconstruction.getFilterName();
2221 m_iDefaultFilter = SignalFilter::convertFilterNameToID (optFilterName.c_str());
2222 m_dDefaultFilterParam = dialogReconstruction.getFilterParam();
2223 wxString optFilterMethodName = dialogReconstruction.getFilterMethodName();
2224 m_iDefaultFilterMethod = ProcessSignal::convertFilterMethodNameToID(optFilterMethodName.c_str());
2225 m_iDefaultZeropad = dialogReconstruction.getZeropad();
2226 wxString optFilterGenerationName = dialogReconstruction.getFilterGenerationName();
2227 m_iDefaultFilterGeneration = ProcessSignal::convertFilterGenerationNameToID (optFilterGenerationName.c_str());
2228 wxString optInterpName = dialogReconstruction.getInterpName();
2229 m_iDefaultInterpolation = Backprojector::convertInterpNameToID (optInterpName.c_str());
2230 m_iDefaultInterpParam = dialogReconstruction.getInterpParam();
2231 wxString optBackprojectName = dialogReconstruction.getBackprojectName();
2232 m_iDefaultBackprojector = Backprojector::convertBackprojectNameToID (optBackprojectName.c_str());
2233 m_iDefaultTrace = dialogReconstruction.getTrace();
2234 if (m_iDefaultNX > 0 && m_iDefaultNY > 0) {
2235 ImageFileDocument* pReconDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));
2237 sys_error (ERR_SEVERE, "Unable to create image file");
2240 ImageFile& imageFile = pReconDoc->getImageFile();
2241 const Projections& rProj = GetDocument()->getProjections();
2242 imageFile.setArraySize (m_iDefaultNX, m_iDefaultNY);
2244 Reconstructor* pReconstruct = new Reconstructor (rProj, imageFile, optFilterName.c_str(), m_dDefaultFilterParam, optFilterMethodName.c_str(), m_iDefaultZeropad, optFilterGenerationName.c_str(), optInterpName.c_str(), m_iDefaultInterpParam, optBackprojectName.c_str(), m_iDefaultTrace);
2247 if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
2248 ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstruct, rProj, imageFile, m_iDefaultTrace, getFrameForChild());
2249 for (int iView = 0; iView < rProj.nView(); iView++) {
2252 if (pDlgReconstruct->isCancelled() || ! pDlgReconstruct->reconstructView (iView)) {
2253 delete pDlgReconstruct;
2254 delete pReconstruct;
2255 pReconDoc->DeleteAllViews();
2260 while (pDlgReconstruct->isPaused()) {
2265 delete pDlgReconstruct;
2267 wxProgressDialog dlgProgress (wxString("Reconstruction"), wxString("Reconstruction Progress"), rProj.nView() + 1, getFrameForChild(), wxPD_CAN_ABORT);
2268 for (int i = 0; i < rProj.nView(); i++) {
2269 pReconstruct->reconstructView (i, 1);
2270 if (! dlgProgress.Update(i + 1)) {
2271 delete pReconstruct;
2272 pReconDoc->DeleteAllViews();
2277 delete pReconstruct;
2278 if (theApp->getSetModifyNewDocs())
2279 pReconDoc->Modify(true);
2280 pReconDoc->UpdateAllViews(this);
2281 ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pReconDoc->GetFirstView());
2283 rasterView->getFrame()->SetFocus();
2284 rasterView->OnUpdate (rasterView, NULL);
2286 std::ostringstream os;
2287 os << "Reconstruct " << rProj.getFilename() << ": xSize=" << m_iDefaultNX << ", ySize=" << m_iDefaultNY << ", Filter=" << optFilterName.c_str() << ", FilterParam=" << m_dDefaultFilterParam << ", FilterMethod=" << optFilterMethodName.c_str() << ", FilterGeneration=" << optFilterGenerationName.c_str() << ", Zeropad=" << m_iDefaultZeropad << ", Interpolation=" << optInterpName.c_str() << ", InterpolationParam=" << m_iDefaultInterpParam << ", Backprojection=" << optBackprojectName.c_str();
2288 *theApp->getLog() << os.str().c_str() << "\n";
2289 imageFile.labelAdd (rProj.getLabel());
2290 imageFile.labelAdd (os.str().c_str(), timerRecon.timerEnd());
2296 ProjectionFileCanvas*
2297 ProjectionFileView::CreateCanvas (wxView *view, wxFrame *parent)
2299 ProjectionFileCanvas* pCanvas;
2301 parent->GetClientSize(&width, &height);
2303 pCanvas = new ProjectionFileCanvas (dynamic_cast<ProjectionFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
2305 pCanvas->SetScrollbars(20, 20, 50, 50);
2306 pCanvas->SetBackgroundColour(*wxWHITE);
2313 ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
2316 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "Projection Frame", wxPoint(10, 10), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
2318 wxDocChildFrame *subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, "Projection Frame", wxPoint(10, 10), wxSize(0, 0), wxDEFAULT_FRAME_STYLE);
2320 theApp->setIconForFrame (subframe);
2322 wxMenu *m_pFileMenu = new wxMenu;
2324 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
2325 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
2326 m_pFileMenu->Append(wxID_OPEN, "&Open...\tCtrl-O");
2327 m_pFileMenu->Append(wxID_SAVE, "&Save\tCtrl-S");
2328 m_pFileMenu->Append(wxID_SAVEAS, "Save &As...");
2329 m_pFileMenu->Append(wxID_CLOSE, "&Close\tCtrl-W");
2331 m_pFileMenu->AppendSeparator();
2332 m_pFileMenu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
2334 m_pFileMenu->AppendSeparator();
2335 m_pFileMenu->Append(wxID_PRINT, "&Print...");
2336 m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
2337 m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
2339 m_pFileMenu->AppendSeparator();
2340 m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit");
2343 wxMenu *convert_menu = new wxMenu;
2344 convert_menu->Append (PJMENU_CONVERT_POLAR, "&Polar Image...\tCtrl-L");
2345 convert_menu->Append (PJMENU_CONVERT_FFT_POLAR, "&FFT->Polar Image...\tCtrl-I");
2347 wxMenu *reconstruct_menu = new wxMenu;
2348 reconstruct_menu->Append (PJMENU_RECONSTRUCT_FBP, "&Filtered Backprojection...\tCtrl-R");
2349 reconstruct_menu->Append (PJMENU_RECONSTRUCT_FOURIER, "&Fourier...\tCtrl-E");
2351 wxMenu *help_menu = new wxMenu;
2352 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
2353 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
2354 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
2356 wxMenuBar *menu_bar = new wxMenuBar;
2358 menu_bar->Append (m_pFileMenu, "&File");
2359 menu_bar->Append (convert_menu, "&Convert");
2360 menu_bar->Append (reconstruct_menu, "&Reconstruct");
2361 menu_bar->Append (help_menu, "&Help");
2363 subframe->SetMenuBar(menu_bar);
2364 subframe->Centre(wxBOTH);
2366 wxAcceleratorEntry accelEntries[11];
2367 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
2368 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
2369 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('W'), wxID_CLOSE);
2370 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
2371 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
2372 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
2373 accelEntries[6].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
2374 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('L'), PJMENU_CONVERT_POLAR);
2375 accelEntries[8].Set (wxACCEL_CTRL, static_cast<int>('I'), PJMENU_CONVERT_FFT_POLAR);
2376 accelEntries[9].Set (wxACCEL_CTRL, static_cast<int>('R'), PJMENU_RECONSTRUCT_FBP);
2377 accelEntries[10].Set (wxACCEL_CTRL, static_cast<int>('E'), PJMENU_RECONSTRUCT_FOURIER);
2378 wxAcceleratorTable accelTable (11, accelEntries);
2379 subframe->SetAcceleratorTable (accelTable);
2386 ProjectionFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
2388 m_frame = CreateChildFrame(doc, this);
2392 m_frame->GetClientSize(&width, &height);
2393 m_frame->SetTitle("ProjectionFileView");
2394 m_canvas = CreateCanvas(this, m_frame);
2397 int x, y; // X requires a forced resize
2398 m_frame->GetSize(&x, &y);
2399 m_frame->SetSize(-1, -1, x, y);
2402 m_frame->Show(true);
2409 ProjectionFileView::OnDraw (wxDC* dc)
2411 wxSize clientSize = m_frame->GetClientSize();
2412 wxSize bestSize = m_canvas->GetBestSize();
2414 if (clientSize.x > bestSize.x || clientSize.y > bestSize.y)
2415 m_frame->SetClientSize (bestSize);
2418 dc->DrawBitmap (m_bitmap, 0, 0, false);
2423 ProjectionFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2425 const Projections& rProj = GetDocument()->getProjections();
2426 const int nDet = rProj.nDet();
2427 const int nView = rProj.nView();
2428 if (nDet != 0 && nView != 0) {
2429 const DetectorArray& detarray = rProj.getDetectorArray(0);
2430 const DetectorValue* detval = detarray.detValues();
2431 double min = detval[0];
2432 double max = detval[0];
2433 for (int iy = 0; iy < nView; iy++) {
2434 const DetectorArray& detarray = rProj.getDetectorArray(iy);
2435 const DetectorValue* detval = detarray.detValues();
2436 for (int ix = 0; ix < nDet; ix++) {
2437 if (min > detval[ix])
2439 else if (max < detval[ix])
2444 unsigned char* imageData = new unsigned char [nDet * nView * 3];
2445 double scale = (max - min) / 255;
2446 for (int iy2 = 0; iy2 < nView; iy2++) {
2447 const DetectorArray& detarray = rProj.getDetectorArray (iy2);
2448 const DetectorValue* detval = detarray.detValues();
2449 for (int ix = 0; ix < nDet; ix++) {
2450 int intensity = static_cast<int>(((detval[ix] - min) / scale) + 0.5);
2451 intensity = clamp(intensity, 0, 255);
2452 int baseAddr = (iy2 * nDet + ix) * 3;
2453 imageData[baseAddr] = imageData[baseAddr+1] = imageData[baseAddr+2] = intensity;
2456 wxImage image (nDet, nView, imageData, true);
2457 m_bitmap = image.ConvertToBitmap();
2461 xSize = clamp (xSize, 0, 800);
2462 ySize = clamp (ySize, 0, 800);
2463 m_frame->SetClientSize (xSize, ySize);
2464 m_canvas->SetScrollbars (20, 20, nDet/20, nView/20);
2468 m_canvas->Refresh();
2472 ProjectionFileView::OnClose (bool deleteWindow)
2474 if (!GetDocument()->Close())
2477 // m_canvas->Clear();
2478 // m_canvas->setView(NULL);
2480 wxString s(wxTheApp->GetAppName());
2482 m_frame->SetTitle(s);
2497 PlotFileCanvas::PlotFileCanvas (PlotFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
2498 : wxScrolledWindow(frame, -1, pos, size, style)
2503 PlotFileCanvas::~PlotFileCanvas ()
2506 wxMenu* pMenu = m_pView->getFileMenu();
2507 theApp->getDocManager()->FileHistoryRemoveMenu (pMenu);
2512 PlotFileCanvas::OnDraw(wxDC& dc)
2515 m_pView->OnDraw(& dc);
2521 IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView)
2523 BEGIN_EVENT_TABLE(PlotFileView, wxView)
2524 EVT_MENU(PJMENU_FILE_PROPERTIES, PlotFileView::OnProperties)
2525 EVT_MENU(PLOTMENU_VIEW_SCALE_MINMAX, PlotFileView::OnScaleMinMax)
2526 EVT_MENU(PLOTMENU_VIEW_SCALE_AUTO, PlotFileView::OnScaleAuto)
2527 EVT_MENU(PLOTMENU_VIEW_SCALE_FULL, PlotFileView::OnScaleFull)
2530 PlotFileView::PlotFileView(void)
2531 : wxView(), m_canvas(NULL), m_frame(NULL), m_pEZPlot(NULL), m_pFileMenu(0)
2533 m_bMinSpecified = false;
2534 m_bMaxSpecified = false;
2537 PlotFileView::~PlotFileView(void)
2544 PlotFileView::OnProperties (wxCommandEvent& event)
2546 const PlotFile& rPlot = GetDocument()->getPlotFile();
2547 std::ostringstream os;
2548 os << "Columns: " << rPlot.getNumColumns() << ", Records: " << rPlot.getNumRecords() << "\n";
2549 rPlot.printHeadersBrief (os);
2550 *theApp->getLog() << os.str().c_str();
2551 wxMessageDialog dialogMsg (getFrameForChild(), os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION);
2552 dialogMsg.ShowModal();
2557 PlotFileView::OnScaleAuto (wxCommandEvent& event)
2559 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2560 double min, max, mean, mode, median, stddev;
2561 rPlotFile.statistics (1, min, max, mean, mode, median, stddev);
2562 DialogAutoScaleParameters dialogAutoScale (getFrameForChild(), mean, mode, median, stddev, m_dAutoScaleFactor);
2563 int iRetVal = dialogAutoScale.ShowModal();
2564 if (iRetVal == wxID_OK) {
2565 m_bMinSpecified = true;
2566 m_bMaxSpecified = true;
2568 if (dialogAutoScale.getMinMax (&dMin, &dMax)) {
2571 m_dAutoScaleFactor = dialogAutoScale.getAutoScaleFactor();
2572 OnUpdate (this, NULL);
2578 PlotFileView::OnScaleMinMax (wxCommandEvent& event)
2580 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2584 if (! m_bMinSpecified || ! m_bMaxSpecified) {
2585 if (! rPlotFile.getMinMax (1, min, max)) {
2586 *theApp->getLog() << "Error: unable to find Min/Max\n";
2591 if (m_bMinSpecified)
2593 if (m_bMaxSpecified)
2596 DialogGetMinMax dialogMinMax (getFrameForChild(), "Set Y-axis Minimum & Maximum", min, max);
2597 int retVal = dialogMinMax.ShowModal();
2598 if (retVal == wxID_OK) {
2599 m_bMinSpecified = true;
2600 m_bMaxSpecified = true;
2601 m_dMinPixel = dialogMinMax.getMinimum();
2602 m_dMaxPixel = dialogMinMax.getMaximum();
2603 OnUpdate (this, NULL);
2608 PlotFileView::OnScaleFull (wxCommandEvent& event)
2610 if (m_bMinSpecified || m_bMaxSpecified) {
2611 m_bMinSpecified = false;
2612 m_bMaxSpecified = false;
2613 OnUpdate (this, NULL);
2619 PlotFileView::CreateCanvas (wxView *view, wxFrame *parent)
2621 PlotFileCanvas* pCanvas;
2623 parent->GetClientSize(&width, &height);
2625 pCanvas = new PlotFileCanvas (dynamic_cast<PlotFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
2627 pCanvas->SetBackgroundColour(*wxWHITE);
2634 PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
2637 wxDocMDIChildFrame *subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "Plot Frame", wxPoint(10, 10), wxSize(500, 300), wxDEFAULT_FRAME_STYLE);
2639 wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Plot Frame", wxPoint(10, 10), wxSize(500, 300), wxDEFAULT_FRAME_STYLE);
2641 theApp->setIconForFrame (subframe);
2643 wxMenu *m_pFileMenu = new wxMenu;
2645 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
2646 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
2647 m_pFileMenu->Append(wxID_OPEN, "&Open...\tCtrl-O");
2648 m_pFileMenu->Append(wxID_SAVE, "&Save\tCtrl-S");
2649 m_pFileMenu->Append(wxID_SAVEAS, "Save &As...");
2650 m_pFileMenu->Append(wxID_CLOSE, "&Close\tCtrl-W");
2652 m_pFileMenu->AppendSeparator();
2653 m_pFileMenu->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
2655 m_pFileMenu->AppendSeparator();
2656 m_pFileMenu->Append(wxID_PRINT, "&Print...");
2657 m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
2658 m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
2660 m_pFileMenu->AppendSeparator();
2661 m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit");
2663 theApp->getDocManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
2664 theApp->getDocManager()->FileHistoryUseMenu(m_pFileMenu);
2666 wxMenu *view_menu = new wxMenu;
2667 view_menu->Append(PLOTMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...\tCtrl-E");
2668 view_menu->Append(PLOTMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...\tCtrl-A");
2669 view_menu->Append(PLOTMENU_VIEW_SCALE_FULL, "Display &Full Scale\tCtrl-U");
2671 wxMenu *help_menu = new wxMenu;
2672 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
2673 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
2674 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
2676 wxMenuBar *menu_bar = new wxMenuBar;
2678 menu_bar->Append(m_pFileMenu, "&File");
2679 menu_bar->Append(view_menu, "&View");
2680 menu_bar->Append(help_menu, "&Help");
2682 subframe->SetMenuBar(menu_bar);
2683 subframe->Centre(wxBOTH);
2685 wxAcceleratorEntry accelEntries[10];
2686 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
2687 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
2688 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('W'), wxID_CLOSE);
2689 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
2690 accelEntries[4].Set (wxACCEL_CTRL, static_cast<int>('P'), MAINMENU_FILE_CREATE_PHANTOM);
2691 accelEntries[5].Set (wxACCEL_CTRL, static_cast<int>('F'), MAINMENU_FILE_CREATE_FILTER);
2692 accelEntries[6].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
2693 accelEntries[7].Set (wxACCEL_CTRL, static_cast<int>('E'), PLOTMENU_VIEW_SCALE_MINMAX);
2694 accelEntries[8].Set (wxACCEL_CTRL, static_cast<int>('A'), PLOTMENU_VIEW_SCALE_AUTO);
2695 accelEntries[9].Set (wxACCEL_CTRL, static_cast<int>('U'), PLOTMENU_VIEW_SCALE_FULL);
2696 wxAcceleratorTable accelTable (10, accelEntries);
2697 subframe->SetAcceleratorTable (accelTable);
2704 PlotFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
2706 m_frame = CreateChildFrame(doc, this);
2709 m_bMinSpecified = false;
2710 m_bMaxSpecified = false;
2711 m_dAutoScaleFactor = 1.;
2714 m_frame->GetClientSize(&width, &height);
2715 m_frame->SetTitle ("Plot File");
2716 m_canvas = CreateCanvas (this, m_frame);
2719 int x, y; // X requires a forced resize
2720 m_frame->GetSize(&x, &y);
2721 m_frame->SetSize(-1, -1, x, y);
2724 m_frame->Show(true);
2731 PlotFileView::OnDraw (wxDC* dc)
2733 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2734 const int iNColumns = rPlotFile.getNumColumns();
2735 const int iNRecords = rPlotFile.getNumRecords();
2737 if (iNColumns > 0 && iNRecords > 0) {
2739 m_canvas->GetClientSize (&xsize, &ysize);
2740 SGPDriver driver (dc, xsize, ysize);
2743 m_pEZPlot->plot (&sgp);
2749 PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2751 const PlotFile& rPlotFile = GetDocument()->getPlotFile();
2752 const int iNColumns = rPlotFile.getNumColumns();
2753 const int iNRecords = rPlotFile.getNumRecords();
2755 if (iNColumns > 0 && iNRecords > 0) {
2758 m_pEZPlot = new EZPlot;
2760 for (unsigned int iEzset = 0; iEzset < rPlotFile.getNumEzsetCommands(); iEzset++)
2761 m_pEZPlot->ezset (rPlotFile.getEzsetCommand (iEzset));
2763 if (m_bMinSpecified) {
2764 std::ostringstream os;
2765 os << "ymin " << m_dMinPixel;
2766 m_pEZPlot->ezset (os.str());
2769 if (m_bMaxSpecified) {
2770 std::ostringstream os;
2771 os << "ymax " << m_dMaxPixel;
2772 m_pEZPlot->ezset (os.str());
2775 m_pEZPlot->ezset("box");
2776 m_pEZPlot->ezset("grid");
2778 double* pdXaxis = new double [iNRecords];
2779 rPlotFile.getColumn (0, pdXaxis);
2781 double* pdY = new double [iNRecords];
2782 for (int iCol = 1; iCol < iNColumns; iCol++) {
2783 rPlotFile.getColumn (iCol, pdY);
2784 m_pEZPlot->addCurve (pdXaxis, pdY, iNRecords);
2792 m_canvas->Refresh();
2796 PlotFileView::OnClose (bool deleteWindow)
2798 if (!GetDocument()->Close())
2801 // m_canvas->Clear();
2802 // m_canvas->setView (NULL);
2804 wxString s(wxTheApp->GetAppName());
2806 m_frame->SetTitle(s);
2819 ////////////////////////////////////////////////////////////////
2822 IMPLEMENT_DYNAMIC_CLASS(TextEditView, wxView)
2824 TextEditView::~TextEditView()
2827 theApp->getDocManager()->FileHistoryRemoveMenu (m_pFileMenu);
2830 bool TextEditView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
2832 m_pFrame = CreateChildFrame(doc, this);
2833 SetFrame (m_pFrame);
2836 m_pFrame->GetClientSize(&width, &height);
2837 m_pFrame->SetTitle("TextEdit");
2838 m_pCanvas = new TextEditCanvas (this, m_pFrame, wxPoint(0, 0), wxSize(width, height), wxTE_MULTILINE | wxTE_READONLY);
2839 m_pFrame->SetTitle("Log");
2842 // X seems to require a forced resize
2844 frame->GetSize(&x, &y);
2845 frame->SetSize(-1, -1, x, y);
2848 m_pFrame->Show (true);
2854 // Handled by wxTextWindow
2855 void TextEditView::OnDraw(wxDC *WXUNUSED(dc) )
2859 void TextEditView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
2864 TextEditView::OnClose (bool deleteWindow)
2868 if (!GetDocument()->Close())
2882 TextEditView::CreateChildFrame (wxDocument *doc, wxView *view)
2885 wxDocMDIChildFrame* subframe = new wxDocMDIChildFrame (doc, view, theApp->getMainFrame(), -1, "TextEdit Frame", wxPoint(-1, -1), wxSize(300, 150), wxDEFAULT_FRAME_STYLE);
2887 wxDocChildFrame* subframe = new wxDocChildFrame (doc, view, theApp->getMainFrame(), -1, "TextEdit Frame", wxPoint(-1, -1), wxSize(300, 150), wxDEFAULT_FRAME_STYLE);
2889 theApp->setIconForFrame (subframe);
2891 wxMenu *m_pFileMenu = new wxMenu;
2893 m_pFileMenu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...\tCtrl-P");
2894 m_pFileMenu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...\tCtrl-F");
2895 m_pFileMenu->Append(wxID_OPEN, "&Open...\tCtrl-O");
2896 m_pFileMenu->Append(wxID_SAVE, "&Save\tCtrl-S");
2897 m_pFileMenu->Append(wxID_SAVEAS, "Save &As...");
2898 // m_pFileMenu->Append(wxID_CLOSE, "&Close\tCtrl-W");
2900 m_pFileMenu->AppendSeparator();
2901 m_pFileMenu->Append(wxID_PRINT, "&Print...");
2902 m_pFileMenu->Append(wxID_PRINT_SETUP, "Print &Setup...");
2903 m_pFileMenu->Append(wxID_PREVIEW, "Print Pre&view");
2905 m_pFileMenu->AppendSeparator();
2906 m_pFileMenu->Append(MAINMENU_FILE_EXIT, "E&xit");
2908 theApp->getDocManager()->FileHistoryAddFilesToMenu(m_pFileMenu);
2909 theApp->getDocManager()->FileHistoryUseMenu(m_pFileMenu);
2911 wxMenu *help_menu = new wxMenu;
2912 help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents\tF1");
2913 help_menu->Append(MAINMENU_HELP_TOPICS, "&Topics\tCtrl-H");
2914 help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
2916 wxMenuBar *menu_bar = new wxMenuBar;
2918 menu_bar->Append(m_pFileMenu, "&File");
2919 menu_bar->Append(help_menu, "&Help");
2921 subframe->SetMenuBar(menu_bar);
2922 subframe->Centre(wxBOTH);
2924 wxAcceleratorEntry accelEntries[5];
2925 accelEntries[0].Set (wxACCEL_CTRL, static_cast<int>('O'), wxID_OPEN);
2926 accelEntries[1].Set (wxACCEL_CTRL, static_cast<int>('S'), wxID_SAVE);
2927 accelEntries[2].Set (wxACCEL_CTRL, static_cast<int>('W'), wxID_CLOSE);
2928 accelEntries[3].Set (wxACCEL_CTRL, static_cast<int>('H'), MAINMENU_HELP_TOPICS);
2929 accelEntries[4].Set (wxACCEL_NORMAL, WXK_F1, MAINMENU_HELP_CONTENTS);
2930 wxAcceleratorTable accelTable (5, accelEntries);
2931 subframe->SetAcceleratorTable (accelTable);
2937 // Define a constructor for my text subwindow
2938 TextEditCanvas::TextEditCanvas (TextEditView* v, wxFrame* frame, const wxPoint& pos, const wxSize& size, long style)
2939 : wxTextCtrl (frame, -1, "", pos, size, style), m_pView(v)
2943 TextEditCanvas::~TextEditCanvas ()
2946 wxMenu* pMenu = m_pView->getFileMenu();
2947 theApp->getDocManager()->FileHistoryRemoveMenu (pMenu);