r329: *** empty log message ***
[ctsim.git] / src / views.cpp
index 8c53e4ced61bf734570a557db7ee14d1fd75f7ff..0a8f4c8b7472f9c4c9850ea9c01bf130d39efcb4 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2000 Kevin Rosenberg
 **
-**  $Id: views.cpp,v 1.40 2000/12/29 15:45:06 kevin Exp $
+**  $Id: views.cpp,v 1.45 2001/01/02 06:29:23 kevin Exp $
 **
 **  This program is free software; you can redistribute it and/or modify
 **  it under the terms of the GNU General Public License (version 2) as
@@ -87,7 +87,6 @@ void
 ImageFileCanvas::DrawRubberBandCursor (wxDC& dc, int x, int y)\r
 {\r
   const ImageFile& rIF = m_pView->GetDocument()->getImageFile();\r
-  ImageFileArrayConst v = rIF.getArray();\r
   int nx = rIF.nx();\r
   int ny = rIF.ny();\r
   \r
@@ -130,7 +129,16 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
   if (event.RightIsDown()) {\r
     if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {\r
       std::ostringstream os;\r
-      os << "Image value (" << pt.x << "," << yPt << ") = " << v[pt.x][yPt] << "\n";\r
+      os << "Image value (" << pt.x << "," << yPt << ") = " << v[pt.x][yPt];\r
+      if (rIF.isComplex()) {\r
+        double dImag = rIF.getImaginaryArray()[pt.x][yPt];\r
+        if (dImag < 0)\r
+          os << " - " << -dImag;\r
+        else\r
+          os << " + " << dImag;\r
+        os << "i\n";\r
+      } else\r
+        os << "\n";\r
       *theApp->getLog() << os.str().c_str();\r
     } else\r
       *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << yPt << ")\n";\r
@@ -157,27 +165,42 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
 
 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
 
-BEGIN_EVENT_TABLE(ImageFileView, wxView)
+BEGIN_EVENT_TABLE(ImageFileView, wxView)\r
+EVT_MENU(IFMENU_FILE_EXPORT, ImageFileView::OnExport)
 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
 EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)\r
 EVT_MENU(IFMENU_COMPARE_IMAGES, ImageFileView::OnCompare)\r
 EVT_MENU(IFMENU_COMPARE_ROW, ImageFileView::OnCompareRow)\r
 EVT_MENU(IFMENU_COMPARE_COL, ImageFileView::OnCompareCol)\r
-EVT_MENU(IFMENU_PROCESS_INVERTVALUES, ImageFileView::OnInvertValues)\r
-EVT_MENU(IFMENU_PROCESS_SQUARE, ImageFileView::OnSquare)\r
-EVT_MENU(IFMENU_PROCESS_SQRT, ImageFileView::OnSquareRoot)\r
-EVT_MENU(IFMENU_PROCESS_LOG, ImageFileView::OnLog)\r
-EVT_MENU(IFMENU_PROCESS_EXP, ImageFileView::OnExp)\r
-EVT_MENU(IFMENU_PROCESS_FFT_MAGNITUDE, ImageFileView::OnFFTMagnitude)\r
-EVT_MENU(IFMENU_PROCESS_FFT_PHASE, ImageFileView::OnFFTPhase)\r
+EVT_MENU(IFMENU_FILTER_INVERTVALUES, ImageFileView::OnInvertValues)\r
+EVT_MENU(IFMENU_FILTER_SQUARE, ImageFileView::OnSquare)\r
+EVT_MENU(IFMENU_FILTER_SQRT, ImageFileView::OnSquareRoot)\r
+EVT_MENU(IFMENU_FILTER_LOG, ImageFileView::OnLog)\r
+EVT_MENU(IFMENU_FILTER_EXP, ImageFileView::OnExp)\r
+EVT_MENU(IFMENU_FILTER_FOURIER, ImageFileView::OnFourier)\r
+EVT_MENU(IFMENU_FILTER_INVERSE_FOURIER, ImageFileView::OnInverseFourier)\r
+EVT_MENU(IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, ImageFileView::OnShuffleFourierToNaturalOrder)\r
+EVT_MENU(IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, ImageFileView::OnShuffleNaturalToFourierOrder)\r
+EVT_MENU(IFMENU_IMAGE_ADD, ImageFileView::OnAdd)\r
+EVT_MENU(IFMENU_IMAGE_SUBTRACT, ImageFileView::OnSubtract)\r
+EVT_MENU(IFMENU_IMAGE_MULTIPLY, ImageFileView::OnMultiply)\r
+EVT_MENU(IFMENU_IMAGE_DIVIDE, ImageFileView::OnDivide)\r
+EVT_MENU(IFMENU_IMAGE_SCALESIZE, ImageFileView::OnScaleSize)\r
+#ifdef HAVE_FFTW\r
+EVT_MENU(IFMENU_FILTER_FFT, ImageFileView::OnFFT)\r
+EVT_MENU(IFMENU_FILTER_IFFT, ImageFileView::OnIFFT)\r
+#endif\r
+EVT_MENU(IFMENU_FILTER_MAGNITUDE, ImageFileView::OnMagnitude)\r
+EVT_MENU(IFMENU_FILTER_PHASE, ImageFileView::OnPhase)\r
 EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow)\r
 EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol)\r
 END_EVENT_TABLE()
 
 ImageFileView::ImageFileView(void) 
 : wxView(), m_canvas(NULL), m_frame(NULL), m_bMinSpecified(false), m_bMaxSpecified(false)
-{
+{\r
+  m_iDefaultExportFormatID = ImageFile::FORMAT_PNG;\r
 }
 
 ImageFileView::~ImageFileView(void)
@@ -187,15 +210,30 @@ ImageFileView::~ImageFileView(void)
 void
 ImageFileView::OnProperties (wxCommandEvent& event)
 {
-  double min, max, mean, mode, median, stddev;
   const ImageFile& rIF = GetDocument()->getImageFile();
   if (rIF.nx() == 0 || rIF.ny() == 0)
     *theApp->getLog() << "Properties: empty imagefile\n";
   else {
     const std::string& rFilename = rIF.getFilename();
-    rIF.statistics (min, max, mean, mode, median, stddev);
     std::ostringstream os;
-    os << "file: " << rFilename << "\nmin: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";
+    double min, max, mean, mode, median, stddev;\r
+    rIF.statistics (rIF.getArray(), min, max, mean, mode, median, stddev);\r
+    os << "Filename: " << rFilename << "\n";\r
+    os << "Size: (" << rIF.nx() << "," << rIF.ny() << ")\n";\r
+    os << "Data type: ";\r
+    if (rIF.isComplex())\r
+      os << "Complex\n";\r
+    else\r
+      os << "Real\n";\r
+    os << "\nMinimum: "<<min<<"\nMaximum: "<<max<<"\nMean: "<<mean<<"\nMedian: "<<median<<"\nMode: "<<mode<<"\nStandard Deviation: "<<stddev << "\n";
+    if (rIF.isComplex()) {\r
+      rIF.statistics (rIF.getImaginaryArray(), min, max, mean, mode, median, stddev);\r
+      os << "\nImaginary: min: "<<min<<"\nmax: "<<max<<"\nmean: "<<mean<<"\nmedian: "<<median<<"\nmode: "<<mode<<"\nstddev: "<<stddev << "\n";\r
+    }\r
+    if (rIF.nLabels() > 0) {\r
+      os << "\n";\r
+      rIF.printLabelsBrief (os);\r
+    }\r
     *theApp->getLog() << os.str().c_str();
     wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Imagefile Properties", wxOK | wxICON_INFORMATION);
     dialogMsg.ShowModal();
@@ -267,7 +305,7 @@ ImageFileView::OnCompare (wxCommandEvent& event)
       rIF.statistics (min, max, mean, mode, median, stddev);\r
       os << rIF.getFilename() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
       rCompareIF.statistics (min, max, mean, mode, median, stddev);\r
-      os << rCompareIF.getFilename() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
+      os << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": minimum=" << min << ", maximum=" << max << ", mean=" << mean << ", mode=" << mode << ", median=" << median << ", stddev=" << stddev << "\n";\r
       os << "\n";\r
       double d, r, e;\r
       rIF.comparativeStatistics (rCompareIF, d, r, e);\r
@@ -287,6 +325,15 @@ ImageFileView::OnCompare (wxCommandEvent& event)
           return;\r
         }\r
         \r
+        wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+        differenceImage.labelsCopy (rIF, s.c_str());\r
+        s = pCompareDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+        differenceImage.labelsCopy (rCompareIF, s.c_str());\r
+        std::ostringstream osLabel;\r
+        osLabel << "Compare image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() \r
+          << " and " << pCompareDoc->GetFirstView()->GetFrame()->GetTitle().c_str() << ": "\r
+          << os.str().c_str();\r
+        differenceImage.labelAdd (os.str().c_str());\r
         if (theApp->getSetModifyNewDocs())\r
           pDifferenceDoc->Modify(true);\r
         pDifferenceDoc->UpdateAllViews(this);\r
@@ -302,6 +349,7 @@ ImageFileView::OnInvertValues (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.invertPixelValues (rIF);\r
+  rIF.labelAdd ("Invert Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -312,6 +360,7 @@ ImageFileView::OnSquare (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.square (rIF);\r
+  rIF.labelAdd ("Square Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -322,6 +371,7 @@ ImageFileView::OnSquareRoot (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.sqrt (rIF);\r
+  rIF.labelAdd ("Square-root Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -332,6 +382,7 @@ ImageFileView::OnLog (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.log (rIF);\r
+  rIF.labelAdd ("Logrithm base-e Pixel Values");\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
@@ -342,31 +393,286 @@ ImageFileView::OnExp (wxCommandEvent& event)
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
   rIF.exp (rIF);\r
+  rIF.labelAdd ("Exponent base-e Pixel Values");\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+}\r
+\r
+void\r
+ImageFileView::OnAdd (wxCommandEvent& event)\r
+{\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Add", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
+        if (! pNewDoc) {\r
+          sys_error (ERR_SEVERE, "Unable to create image file");\r
+          return;\r
+        }\r
+      ImageFile& newImage = pNewDoc->getImageFile();  \r
+      newImage.setArraySize (rIF.nx(), rIF.ny());\r
+      rIF.addImages (rRHSIF, newImage);\r
+      std::ostringstream os;\r
+      os << "Add image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " \r
+        << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rIF, s.c_str());\r
+      s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rRHSIF, s.c_str());\r
+      newImage.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        pNewDoc->Modify(TRUE);\r
+      pNewDoc->UpdateAllViews(this);\r
+      pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnSubtract (wxCommandEvent& event)\r
+{\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Subtract", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
+        if (! pNewDoc) {\r
+          sys_error (ERR_SEVERE, "Unable to create image file");\r
+          return;\r
+        }\r
+      ImageFile& newImage = pNewDoc->getImageFile();  \r
+      newImage.setArraySize (rIF.nx(), rIF.ny());\r
+      rIF.subtractImages (rRHSIF, newImage);\r
+      std::ostringstream os;\r
+      os << "Subtract image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " \r
+        << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rIF, s.c_str());\r
+      s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rRHSIF, s.c_str());\r
+      newImage.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        pNewDoc->Modify(TRUE);\r
+      pNewDoc->UpdateAllViews(this);\r
+      pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnMultiply (wxCommandEvent& event)\r
+{\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Multiply", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
+        if (! pNewDoc) {\r
+          sys_error (ERR_SEVERE, "Unable to create image file");\r
+          return;\r
+        }\r
+      ImageFile& newImage = pNewDoc->getImageFile();  \r
+      newImage.setArraySize (rIF.nx(), rIF.ny());\r
+      rIF.multiplyImages (rRHSIF, newImage);\r
+      std::ostringstream os;\r
+      os << "Multiply image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " and " \r
+        << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rIF, s.c_str());\r
+      s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rRHSIF, s.c_str());\r
+      newImage.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        pNewDoc->Modify(TRUE);\r
+      pNewDoc->UpdateAllViews(this);\r
+      pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnDivide (wxCommandEvent& event)\r
+{\r
+  std::vector<ImageFileDocument*> vecIF;\r
+  theApp->getCompatibleImages (GetDocument(), vecIF);\r
+  \r
+  if (vecIF.size() == 0) {\r
+    wxMessageBox ("There are no compatible image files open for comparision", "No comparison images");\r
+  } else {\r
+    DialogGetComparisonImage dialogGetCompare (m_frame, "Get Image to Divide", vecIF, false);\r
+    \r
+    if (dialogGetCompare.ShowModal() == wxID_OK) {\r
+      ImageFile& rIF = GetDocument()->getImageFile();\r
+      ImageFileDocument* pRHSDoc = dialogGetCompare.getImageFileDocument();\r
+      const ImageFile& rRHSIF = pRHSDoc->getImageFile();\r
+      ImageFileDocument* pNewDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
+        if (! pNewDoc) {\r
+          sys_error (ERR_SEVERE, "Unable to create image file");\r
+          return;\r
+        }\r
+      ImageFile& newImage = pNewDoc->getImageFile();  \r
+      newImage.setArraySize (rIF.nx(), rIF.ny());\r
+      rIF.divideImages (rRHSIF, newImage);\r
+      std::ostringstream os;\r
+      os << "Divide image " << GetDocument()->GetFirstView()->GetFrame()->GetTitle().c_str() << " by " \r
+        << pRHSDoc->GetFirstView()->GetFrame()->GetTitle().c_str();\r
+      wxString s = GetDocument()->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rIF, s.c_str());\r
+      s = pRHSDoc->GetFirstView()->GetFrame()->GetTitle() + ": ";\r
+      newImage.labelsCopy (rRHSIF, s.c_str());\r
+      newImage.labelAdd (os.str().c_str());\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      if (theApp->getSetModifyNewDocs())\r
+        pNewDoc->Modify(TRUE);\r
+      pNewDoc->UpdateAllViews(this);\r
+      pNewDoc->GetFirstView()->OnUpdate (this, NULL);\r
+    }\r
+  }\r
+}\r
+\r
+\r
+#ifdef HAVE_FFTW\r
+void\r
+ImageFileView::OnFFT (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  wxProgressDialog dlgProgress (wxString("FFT"), wxString("FFT Progress"), 1, m_frame, wxPD_APP_MODAL);\r
+  rIF.fft (rIF);\r
+  rIF.labelAdd ("FFT Image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+}\r
+\r
+void\r
+ImageFileView::OnIFFT (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  wxProgressDialog dlgProgress (wxString("IFFT"), wxString("IFFT Progress"), 1, m_frame, wxPD_APP_MODAL);\r
+  rIF.ifft (rIF);\r
+  rIF.labelAdd ("IFFT Image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
 }\r
+#endif\r
 \r
 void\r
-ImageFileView::OnFFTMagnitude (wxCommandEvent& event)\r
+ImageFileView::OnFourier (wxCommandEvent& event)\r
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
-  rIF.FFTMagnitude (rIF);\r
+  wxProgressDialog dlgProgress (wxString("Fourier"), wxString("Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);\r
+  rIF.fourier (rIF);\r
+  rIF.labelAdd ("Fourier Image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+}\r
+void\r
+ImageFileView::OnInverseFourier (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  wxProgressDialog dlgProgress (wxString("Inverse Fourier"), wxString("Inverse Fourier Progress"), 1, m_frame, wxPD_APP_MODAL);\r
+  rIF.inverseFourier (rIF);\r
+  rIF.labelAdd ("Inverse Fourier Image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
 }\r
 \r
 void\r
-ImageFileView::OnFFTPhase (wxCommandEvent& event)\r
+ImageFileView::OnShuffleNaturalToFourierOrder (wxCommandEvent& event)\r
 {\r
   ImageFile& rIF = GetDocument()->getImageFile();\r
-  rIF.FFTPhase (rIF);\r
+  Fourier::shuffleNaturalToFourierOrder (rIF);\r
+  rIF.labelAdd ("Shuffle Natural To Fourier Order");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
   if (theApp->getSetModifyNewDocs())\r
     GetDocument()->Modify(TRUE);\r
   GetDocument()->UpdateAllViews(this);\r
 }\r
 \r
+void\r
+ImageFileView::OnShuffleFourierToNaturalOrder (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  Fourier::shuffleFourierToNaturalOrder (rIF);\r
+  rIF.labelAdd ("Shuffle Fourier To Natural Order");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+}\r
+\r
+void\r
+ImageFileView::OnMagnitude (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  if (rIF.isComplex()) {\r
+    rIF.magnitude (rIF);\r
+    rIF.labelAdd ("Magnitude of complex-image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnPhase (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  if (rIF.isComplex()) {\r
+    rIF.phase (rIF);\r
+    rIF.labelAdd ("Phase of complex-image");\r
+  m_bMinSpecified = false;\r
+  m_bMaxSpecified = false;\r
+  if (theApp->getSetModifyNewDocs())\r
+    GetDocument()->Modify(TRUE);\r
+  GetDocument()->UpdateAllViews(this);\r
+  }\r
+}\r
+\r
 \r
 ImageFileCanvas* 
 ImageFileView::CreateCanvas (wxView *view, wxFrame *parent)
@@ -391,14 +697,16 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   
   wxMenu *file_menu = new wxMenu;
   
-  file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
+  file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");\r
+  file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
   file_menu->Append(wxID_OPEN, "&Open...");
   file_menu->Append(wxID_SAVE, "&Save");
   file_menu->Append(wxID_SAVEAS, "Save &As...");
   file_menu->Append(wxID_CLOSE, "&Close");
   
-  file_menu->AppendSeparator();
+  file_menu->AppendSeparator();\r
   file_menu->Append(IFMENU_FILE_PROPERTIES, "P&roperties");
+  file_menu->Append(IFMENU_FILE_EXPORT, "&Export...");\r
   
   file_menu->AppendSeparator();
   file_menu->Append(wxID_PRINT, "&Print...");
@@ -409,14 +717,35 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...");
   view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...");
   \r
-  wxMenu* process_menu = new wxMenu;\r
-  process_menu->Append (IFMENU_PROCESS_INVERTVALUES, "&Invert Values");\r
-  process_menu->Append (IFMENU_PROCESS_SQUARE, "&Square");\r
-  process_menu->Append (IFMENU_PROCESS_SQRT, "Square &Root");\r
-  process_menu->Append (IFMENU_PROCESS_LOG, "&Log");\r
-  process_menu->Append (IFMENU_PROCESS_EXP, "&Exp");\r
-  process_menu->Append (IFMENU_PROCESS_FFT_MAGNITUDE, "&FFT Magnitude");\r
-  process_menu->Append (IFMENU_PROCESS_FFT_PHASE, "FFT &Phase");\r
+  wxMenu* filter_menu = new wxMenu;\r
+  filter_menu->Append (IFMENU_FILTER_INVERTVALUES, "&Invert Values");\r
+  filter_menu->Append (IFMENU_FILTER_SQUARE, "&Square");\r
+  filter_menu->Append (IFMENU_FILTER_SQRT, "Square &Root");\r
+  filter_menu->Append (IFMENU_FILTER_LOG, "&Log");\r
+  filter_menu->Append (IFMENU_FILTER_EXP, "&Exp");\r
+  filter_menu->AppendSeparator();\r
+#ifdef HAVE_FFTW\r
+  filter_menu->Append (IFMENU_FILTER_FFT, "&FFT");\r
+  filter_menu->Append (IFMENU_FILTER_IFFT, "&IFFT");\r
+  filter_menu->Append (IFMENU_FILTER_FOURIER, "F&ourier");\r
+  filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "Inverse Fo&urier");\r
+#else\r
+  filter_menu->Append (IFMENU_FILTER_FOURIER, "&Fourier");\r
+  filter_menu->Append (IFMENU_FILTER_INVERSE_FOURIER, "&Inverse Fourier");\r
+#endif\r
+  filter_menu->Append (IFMENU_FILTER_SHUFFLEFOURIERTONATURALORDER, "S&huffle Fourier to Natural Order");\r
+  filter_menu->Append (IFMENU_FILTER_SHUFFLENATURALTOFOURIERORDER, "Shu&ffle Natural to Fourier Order");\r
+  filter_menu->Append (IFMENU_FILTER_MAGNITUDE, "&Magnitude");\r
+  filter_menu->Append (IFMENU_FILTER_PHASE, "&Phase");\r
+  \r
+  wxMenu* image_menu = new wxMenu;\r
+  filter_menu->AppendSeparator();\r
+  image_menu->Append (IFMENU_IMAGE_ADD, "&Add...");\r
+  image_menu->Append (IFMENU_IMAGE_SUBTRACT, "&Subtract...");\r
+  image_menu->Append (IFMENU_IMAGE_MULTIPLY, "&Multiply...");\r
+  image_menu->Append (IFMENU_IMAGE_DIVIDE, "&Divide...");\r
+  image_menu->AppendSeparator();\r
+  image_menu->Append (IFMENU_IMAGE_SCALESIZE, "S&cale Size...");\r
 \r
   wxMenu *plot_menu = new wxMenu;\r
   plot_menu->Append (IFMENU_PLOT_ROW, "Plot &Row");\r
@@ -434,7 +763,8 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   
   menu_bar->Append(file_menu, "&File");
   menu_bar->Append(view_menu, "&View");\r
-  menu_bar->Append(process_menu, "&Process");\r
+  menu_bar->Append(image_menu, "&Image");\r
+  menu_bar->Append(filter_menu, "Fi&lter");\r
   menu_bar->Append(plot_menu, "P&lot");\r
   menu_bar->Append(compare_menu, "&Compare");
   menu_bar->Append(help_menu, "&Help");
@@ -448,7 +778,7 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
 
 
 bool 
-ImageFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
+ImageFileView::OnCreate (wxDocument *doc, long WXUNUSED(flags) )
 {
   m_frame = CreateChildFrame(doc, this);
   SetFrame (m_frame);
@@ -551,6 +881,80 @@ ImageFileView::OnClose (bool deleteWindow)
   return true;
 }
 \r
+void\r
+ImageFileView::OnExport (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();\r
+  ImageFileArrayConst v = rIF.getArray();\r
+  int nx = rIF.nx();\r
+  int ny = rIF.ny();\r
+  if (v != NULL && nx != 0 && ny != 0) {\r
+    if (! m_bMinSpecified || ! m_bMaxSpecified) {\r
+      double min, max;\r
+      rIF.getMinMax (min, max);\r
+      if (! m_bMinSpecified)\r
+        m_dMinPixel = min;\r
+      if (! m_bMaxSpecified)\r
+        m_dMaxPixel = max;\r
+    }\r
+\r
+    DialogExportParameters dialogExport (m_frame, m_iDefaultExportFormatID);\r
+    if (dialogExport.ShowModal() == wxID_OK) {\r
+      wxString strFormatName (dialogExport.getFormatName ());\r
+      m_iDefaultExportFormatID = ImageFile::convertFormatNameToID (strFormatName.c_str());\r
+\r
+      wxString strExt;\r
+      wxString strWildcard;\r
+      if (m_iDefaultExportFormatID == ImageFile::FORMAT_PGM || m_iDefaultExportFormatID == ImageFile::FORMAT_PGMASCII) {\r
+        strExt = ".pgm";\r
+        strWildcard = "PGM Files (*.pgm)|*.pgm";\r
+      }\r
+#ifdef HAVE_PNG\r
+      else if (m_iDefaultExportFormatID == ImageFile::FORMAT_PNG || m_iDefaultExportFormatID == ImageFile::FORMAT_PNG16) {\r
+        strExt = ".png";\r
+        strWildcard = "PNG Files (*.png)|*.png";\r
+      }\r
+#endif\r
+\r
+      const wxString& strFilename = wxFileSelector (wxString("Export Filename"), wxString(""), \r
+        wxString(""), strExt, strWildcard, wxOVERWRITE_PROMPT | wxHIDE_READONLY | wxSAVE);\r
+      if (strFilename) {\r
+        rIF.exportImage (strFormatName.c_str(), strFilename.c_str(), 1, 1, m_dMinPixel, m_dMaxPixel);\r
+        *theApp->getLog() << "Exported file " << strFilename << "\n";\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+void\r
+ImageFileView::OnScaleSize (wxCommandEvent& event)\r
+{\r
+  ImageFile& rIF = GetDocument()->getImageFile();\r
+  unsigned int iOldNX = rIF.nx();\r
+  unsigned int iOldNY = rIF.ny();\r
+\r
+  DialogGetXYSize dialogGetXYSize (m_frame, "Set New X & Y Dimensions", iOldNX, iOldNY);\r
+  if (dialogGetXYSize.ShowModal() == wxID_OK) {\r
+    unsigned int iNewNX = dialogGetXYSize.getXSize();\r
+    unsigned int iNewNY = dialogGetXYSize.getYSize();\r
+    std::ostringstream os;\r
+    os << "Scale Size from (" << iOldNX << "," << iOldNY << ") to (" << iNewNX << "," << iNewNY << ")";\r
+    ImageFileDocument* pScaledDoc = dynamic_cast<ImageFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.if", wxDOC_SILENT));\r
+    if (! pScaledDoc) {\r
+      sys_error (ERR_SEVERE, "Unable to create image file");\r
+      return;\r
+    }\r
+    ImageFile& rScaledIF = pScaledDoc->getImageFile();\r
+    rScaledIF.setArraySize (iNewNX, iNewNY);\r
+    rScaledIF.labelAdd (os.str().c_str());\r
+    rIF.scaleImage (rScaledIF);\r
+    *theApp->getLog() << os.str().c_str() << "\n";\r
+    if (theApp->getSetModifyNewDocs())\r
+      pScaledDoc->Modify(TRUE);\r
+    pScaledDoc->UpdateAllViews (this);\r
+    pScaledDoc->GetFirstView()->OnUpdate (this, NULL);\r
+  }\r
+}\r
 \r
 void\r
 ImageFileView::OnPlotRow (wxCommandEvent& event)\r
@@ -802,7 +1206,7 @@ PhantomCanvas::PhantomCanvas (PhantomView* v, wxFrame *frame, const wxPoint& pos
 }
 
 void 
-PhantomCanvas::OnDraw(wxDC& dc)
+PhantomCanvas::OnDraw (wxDC& dc)
 {
   if (m_pView)
     m_pView->OnDraw(& dc);
@@ -842,12 +1246,14 @@ PhantomView::OnProperties (wxCommandEvent& event)
   const int idPhantom = GetDocument()->getPhantomID();
   const wxString& namePhantom = GetDocument()->getPhantomName();
   std::ostringstream os;
-  os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")\n";
-  *theApp->getLog() << os.str().c_str();
+  os << "Phantom " << namePhantom.c_str() << " (" << idPhantom << ")" << "\n";\r
+  const Phantom& rPhantom = GetDocument()->getPhantom();\r
+  rPhantom.printDefinitions (os);
 #if DEBUG
-  const Phantom& rPhantom = GetDocument()->getPhantom();
-  rPhantom.print();
+  rPhantom.print (os);
 #endif
+  *theApp->getLog() << os.str().c_str() << "\n";\r
+  wxMessageBox (os.str().c_str(), "Phantom Properties");\r
 }
 
 
@@ -946,7 +1352,7 @@ PhantomView::OnRasterize (wxCommandEvent& event)
   if (retVal == wxID_OK) {
     int xSize = dialogRaster.getXSize();
     int ySize = dialogRaster.getYSize();
-    int nSamples = dialogRaster.getNSamples();
+    int nSamples = dialogRaster.getNSamples();\r
     if (nSamples < 1)
       nSamples = 1;
     if (xSize > 0 && ySize > 0) {
@@ -959,7 +1365,8 @@ PhantomView::OnRasterize (wxCommandEvent& event)
       ImageFile& imageFile = pRasterDoc->getImageFile();
       
       imageFile.setArraySize (xSize, ySize);
-      wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), imageFile.nx() + 1, m_frame, wxPD_CAN_ABORT);
+      wxProgressDialog dlgProgress (wxString("Rasterize"), wxString("Rasterization Progress"), imageFile.nx() + 1, m_frame, wxPD_CAN_ABORT);\r
+      Timer timer;
       for (unsigned int i = 0; i < imageFile.nx(); i++) {
         rPhantom.convertToImagefile (imageFile, nSamples, Trace::TRACE_NONE, i, 1, true);
         if (! dlgProgress.Update(i+1)) {
@@ -969,16 +1376,17 @@ PhantomView::OnRasterize (wxCommandEvent& event)
       }
       if (theApp->getSetModifyNewDocs())\r
         pRasterDoc->Modify(true);
-      pRasterDoc->UpdateAllViews(this);
+      pRasterDoc->UpdateAllViews(this);\r
+      std::ostringstream os;\r
+      os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << xSize << ", YSize=" << ySize << ", nSamples=" << nSamples;\r
+      *theApp->getLog() << os.str().c_str() << "\n";\r
+      imageFile.labelAdd (os.str().c_str(), timer.timerEnd());
       ImageFileView* rasterView = dynamic_cast<ImageFileView*>(pRasterDoc->GetFirstView());\r
       if (rasterView) {\r
         rasterView->getFrame()->SetFocus();\r
         rasterView->OnUpdate (rasterView, NULL);\r
       }\r
       
-      std::ostringstream os;
-      os << "Rasterize Phantom " << rPhantom.name() << ": XSize=" << xSize << ", YSize=" << ySize << ", nSamples=" << nSamples << "\n";
-      *theApp->getLog() << os.str().c_str();
     }\r
   }
 }
@@ -1007,7 +1415,9 @@ PhantomView::CreateChildFrame(wxDocument *doc, wxView *view)
   wxMenu *file_menu = new wxMenu;
   
   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
-  file_menu->Append(wxID_OPEN, "&Open...");
+  file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
+  file_menu->Append(wxID_OPEN, "&Open...");\r
+  file_menu->Append(wxID_SAVEAS, "Save &As...");\r
   file_menu->Append(wxID_CLOSE, "&Close");
   
   file_menu->AppendSeparator();
@@ -1204,24 +1614,9 @@ ProjectionFileView::OnReconstruct (wxCommandEvent& event)
         wxMessageBox ("Sorry!\nCurrently, frequency-based filtering with direct filter generation is not support for geometries other than parallel.\nAborting command.", "Not Supported", wxOK | wxICON_WARNING, m_frame);
         return;
       }
-#if 0
-      SGPDriver* pSGPDriver = NULL;
-      SGP* pSGP = NULL;
-      wxMemoryDC* pDCPlot = NULL;
-      wxBitmap bitmap;
-      if (m_iDefaultTrace >= Trace::TRACE_PLOT) {
-        bitmap.Create (500, 500);
-        pDCPlot = new wxMemoryDC;
-        pDCPlot->SelectObject (bitmap);
-        pSGPDriver = new SGPDriver (dynamic_cast<wxDC*>pDCPlot, 500, 500);
-        pSGP = new SGP (*pSGPDriver);
-      }
-      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, pSGP);
-      delete pSGP;
-#else
+\r
       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);
-#endif
-      \r
+\r
       Timer timerRecon;
       if (m_iDefaultTrace > Trace::TRACE_CONSOLE) {
         ReconstructDialog* pDlgReconstruct = new ReconstructDialog (*pReconstruct, rProj, imageFile, m_iDefaultTrace, m_frame);
@@ -1266,7 +1661,7 @@ ProjectionFileView::OnReconstruct (wxCommandEvent& event)
       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();
       *theApp->getLog() << os.str().c_str() << "\n";
       imageFile.labelAdd (rProj.getLabel());
-      imageFile.labelAdd (Array2dFileLabel::L_HISTORY, os.str().c_str(), timerRecon.timerEnd());
+      imageFile.labelAdd (os.str().c_str(), timerRecon.timerEnd());
     }
   }
 }
@@ -1296,6 +1691,7 @@ ProjectionFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   wxMenu *file_menu = new wxMenu;
   
   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
+  file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
   file_menu->Append(wxID_OPEN, "&Open...");
   file_menu->Append(wxID_SAVE, "&Save");
   file_menu->Append(wxID_SAVEAS, "Save &As...");
@@ -1475,9 +1871,10 @@ PlotFileView::~PlotFileView(void)
 void
 PlotFileView::OnProperties (wxCommandEvent& event)
 {
-  const PlotFile& rProj = GetDocument()->getPlotFile();
+  const PlotFile& rPlot = GetDocument()->getPlotFile();
   std::ostringstream os;\r
-  os << "Columns: " << rProj.getNumColumns() << ", Records: " << rProj.getNumRecords() << "\n";
+  os << "Columns: " << rPlot.getNumColumns() << ", Records: " << rPlot.getNumRecords() << "\n";\r
+  rPlot.printHeaders (os);
   *theApp->getLog() << os.str().c_str();
   wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION);
   dialogMsg.ShowModal();
@@ -1509,9 +1906,10 @@ void
 PlotFileView::OnScaleMinMax (wxCommandEvent& event)\r
 {\r
   const PlotFile& rPlotFile = GetDocument()->getPlotFile();\r
-  double min, max;\r
-  \r
-  if (! m_bMinSpecified && ! m_bMaxSpecified) {\r
+  double min;\r
+  double max;\r
+\r
+  if (! m_bMinSpecified || ! m_bMaxSpecified) {\r
     if (! rPlotFile.getMinMax (1, min, max)) {\r
       *theApp->getLog() << "Error: unable to find Min/Max\n";\r
       return;\r
@@ -1558,6 +1956,7 @@ PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
   wxMenu *file_menu = new wxMenu;
   
   file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
+  file_menu->Append(MAINMENU_FILE_CREATE_FILTER, "Create &Filter...");\r
   file_menu->Append(wxID_OPEN, "&Open...");
   file_menu->Append(wxID_SAVE, "&Save");
   file_menu->Append(wxID_SAVEAS, "Save &As...");
@@ -1642,7 +2041,6 @@ PlotFileView::OnDraw (wxDC* dc)
 void 
 PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
 {
-  if (m_canvas) {
     const PlotFile& rPlotFile = GetDocument()->getPlotFile();\r
     const int iNColumns = rPlotFile.getNumColumns();\r
     const int iNRecords = rPlotFile.getNumRecords();\r
@@ -1652,7 +2050,7 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
         delete m_pEZPlot;\r
       m_pEZPlot = new EZPlot;\r
       \r
-      for (int iEzset = 0; iEzset < rPlotFile.getNumEzsetCommands(); iEzset++)\r
+      for (unsigned int iEzset = 0; iEzset < rPlotFile.getNumEzsetCommands(); iEzset++)\r
         m_pEZPlot->ezset (rPlotFile.getEzsetCommand (iEzset));\r
       \r
       if (m_bMinSpecified) {\r
@@ -1682,9 +2080,9 @@ PlotFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
       delete pdXaxis;\r
       delete pdY;\r
     }\r
-    \r
-    m_canvas->Refresh();\r
-  }
+\r
+    if (m_canvas)\r
+      m_canvas->Refresh();\r
 }
 
 bool