r308: plotfile changes
[ctsim.git] / src / views.cpp
index f150237ba69005232ad9ef6f407d9c73b121fc80..d40fd5edd988240a2f38ff43d1fda38b4a95f770 100644 (file)
@@ -9,7 +9,7 @@
 **  This is part of the CTSim program
 **  Copyright (C) 1983-2000 Kevin Rosenberg
 **
-**  $Id: views.cpp,v 1.30 2000/12/18 09:31:26 kevin Exp $
+**  $Id: views.cpp,v 1.33 2000/12/20 14:52:30 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
@@ -71,7 +71,9 @@ END_EVENT_TABLE()
 ImageFileCanvas::ImageFileCanvas (ImageFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
 : wxScrolledWindow(frame, -1, pos, size, style)
 {
-    m_pView = v;
+    m_pView = v;\r
+       m_xCursor = -1;\r
+       m_yCursor = -1;
 }
 
 void 
@@ -79,8 +81,35 @@ ImageFileCanvas::OnDraw(wxDC& dc)
 {
     if (m_pView)
         m_pView->OnDraw(& dc);
+}\r
+\r
+void \r
+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
+       dc.SetLogicalFunction (wxINVERT);\r
+       dc.SetPen (*wxGREEN_PEN);\r
+       dc.DrawLine (0, y, nx, y);\r
+       dc.DrawLine (x, 0, x, ny);\r
+       dc.SetLogicalFunction (wxCOPY);\r
+}\r
+\r
+bool\r
+ImageFileCanvas::GetCurrentCursor (int& x, int& y)\r
+{\r
+       x = m_xCursor;\r
+       y = m_yCursor;\r
+\r
+       if (m_xCursor >= 0 && m_yCursor >= 0)\r
+               return true;\r
+       else\r
+               return false;\r
 }
-
+\r
 void 
 ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
 {
@@ -91,24 +120,41 @@ ImageFileCanvas::OnMouseEvent(wxMouseEvent& event)
     PrepareDC(dc);
     
     wxPoint pt(event.GetLogicalPosition(dc));
-       
-    if (event.LeftIsDown()) {
-               const ImageFile& rIF = m_pView->GetDocument()->getImageFile();
-               ImageFileArrayConst v = rIF.getArray();
-               int nx = rIF.nx();
-               int ny = rIF.ny();
-               
-               if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {
-                       std::ostringstream os;
-                       os << "Image value (" << pt.x << "," << pt.y << ") = " << v[pt.x][ny - 1 - pt.y] << "\n";
-                       *theApp->getLog() << os.str().c_str();
-               } else
-                       *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << pt.y << ")\n";
-               
-    }
+\r
+    if (event.RightIsDown()) {\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
+               if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {\r
+                       std::ostringstream os;\r
+                       os << "Image value (" << pt.x << "," << pt.y << ") = " << v[pt.x][ny - 1 - pt.y] << "\n";\r
+                       *theApp->getLog() << os.str().c_str();\r
+               } else\r
+                       *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << pt.y << ")\n";\r
+    }\r
+    else if (event.LeftIsDown()) {\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
+               if (pt.x >= 0 && pt.x < nx && pt.y >= 0 && pt.y < ny) {\r
+                       if (m_xCursor >= 0 && m_yCursor >= 0) {\r
+                               DrawRubberBandCursor (dc, m_xCursor, m_yCursor);\r
+                       }\r
+                       DrawRubberBandCursor (dc, pt.x, pt.y);\r
+                       m_xCursor = pt.x;\r
+                       m_yCursor = pt.y;\r
+                       std::ostringstream os;\r
+                       os << "Selected column" << pt.x << " and row" << pt.y << "\n";\r
+                       *theApp->getLog() << os.str().c_str();\r
+               } else\r
+                       *theApp->getLog() << "Mouse out of image range (" << pt.x << "," << pt.y << ")\n";\r
+    }\r
 }
 
-
 // ImageFileView
 
 IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
@@ -116,7 +162,9 @@ IMPLEMENT_DYNAMIC_CLASS(ImageFileView, wxView)
 BEGIN_EVENT_TABLE(ImageFileView, wxView)
 EVT_MENU(IFMENU_FILE_PROPERTIES, ImageFileView::OnProperties)
 EVT_MENU(IFMENU_VIEW_SCALE_MINMAX, ImageFileView::OnScaleMinMax)
-EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)
+EVT_MENU(IFMENU_VIEW_SCALE_AUTO, ImageFileView::OnScaleAuto)\r
+EVT_MENU(IFMENU_PLOT_ROW, ImageFileView::OnPlotRow)
+EVT_MENU(IFMENU_PLOT_COL, ImageFileView::OnPlotCol)\r
 END_EVENT_TABLE()
 
 ImageFileView::ImageFileView(void) 
@@ -229,14 +277,19 @@ ImageFileView::CreateChildFrame(wxDocument *doc, wxView *view)
     wxMenu *view_menu = new wxMenu;
     view_menu->Append(IFMENU_VIEW_SCALE_MINMAX, "Display Scale &Set...");
     view_menu->Append(IFMENU_VIEW_SCALE_AUTO, "Display Scale &Auto...");
-    
+    \r
+       wxMenu *plot_menu = new wxMenu;\r
+       plot_menu->Append (IFMENU_PLOT_ROW, "Plot &Row");\r
+       plot_menu->Append (IFMENU_PLOT_COL, "Plot &Column");\r
+
     wxMenu *help_menu = new wxMenu;
     help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
     
     wxMenuBar *menu_bar = new wxMenuBar;
     
     menu_bar->Append(file_menu, "&File");
-    menu_bar->Append(view_menu, "&View");
+    menu_bar->Append(view_menu, "&View");\r
+       menu_bar->Append(plot_menu, "&Plot");
     menu_bar->Append(help_menu, "&Help");
     
     subframe->SetMenuBar(menu_bar);
@@ -277,6 +330,10 @@ ImageFileView::OnDraw (wxDC* dc)
 {
        if (m_bitmap.Ok())
                dc->DrawBitmap(m_bitmap, 0, 0, false);
+\r
+       int xCursor, yCursor;\r
+       if (m_canvas->GetCurrentCursor (xCursor, yCursor))\r
+               m_canvas->DrawRubberBandCursor (*dc, xCursor, yCursor);\r
 }
 
 
@@ -317,7 +374,7 @@ ImageFileView::OnUpdate (wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
                ySize = clamp (ySize, 0, 800);
                m_frame->SetClientSize (xSize, ySize);
                m_canvas->SetScrollbars(20, 20, nx/20, ny/20);
-               m_canvas->SetBackgroundColour(*wxWHITE);
+               m_canvas->SetBackgroundColour(*wxWHITE);\r
     } 
        
     if (m_canvas)
@@ -346,8 +403,97 @@ ImageFileView::OnClose (bool deleteWindow)
     }
     return true;
 }
-
-
+\r
+#include "wx/plot.h"\r
+\r
+void\r
+ImageFileView::OnPlotRow (wxCommandEvent& event)\r
+{\r
+       int xCursor, yCursor;\r
+       if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {\r
+               *theApp->getLog() << "No row selected. Please use left mouse button on image to select row\n";\r
+               return;\r
+       }\r
+\r
+    const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();\r
+    ImageFileArrayConst v = rIF.getArray();\r
+    int nx = rIF.nx();\r
+    int ny = rIF.ny();\r
+\r
+    if (v != NULL && yCursor < ny) {\r
+               double* pX = new double [nx];\r
+               double* pY = new double [nx];\r
+               for (int i = 0; i < nx; i++) {\r
+                       pX[i] = i;\r
+                       pY[i] = v[i][yCursor];\r
+               }\r
+               PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));\r
+               if (! pPlotDoc) {\r
+                       sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");\r
+               } else {\r
+                       PlotFile& rPlot = pPlotDoc->getPlotFile();\r
+                       std::ostringstream title;\r
+                       title << "Row " << yCursor;\r
+                       rPlot.setTitle(title.str());\r
+                       rPlot.setXLabel("Column");\r
+                       rPlot.setYLabel("Pixel Value");\r
+                       rPlot.setCurveSize (2, nx);\r
+                       rPlot.addColumn (0, pX);\r
+                       rPlot.addColumn (1, pY);\r
+               }\r
+               delete pX;\r
+               delete pY;\r
+       }\r
+\r
+}\r
+
+void\r
+ImageFileView::OnPlotCol (wxCommandEvent& event)\r
+{\r
+       int xCursor, yCursor;\r
+       if (! m_canvas->GetCurrentCursor (xCursor, yCursor)) {\r
+               // os << "No column selected. Please use left mouse button on image to select column\n";\r
+               return;\r
+       }\r
+\r
+    const ImageFile& rIF = dynamic_cast<ImageFileDocument*>(GetDocument())->getImageFile();\r
+    ImageFileArrayConst v = rIF.getArray();\r
+    int nx = rIF.nx();\r
+    int ny = rIF.ny();\r
+\r
+    if (v != NULL && xCursor < nx) {\r
+               double* pX = new double [ny];\r
+               double* pY = new double [ny];\r
+               double minVal = v[xCursor][0];\r
+               double maxVal = minVal;\r
+               for (int i = 0; i < ny; i++) {\r
+                       double y = v[xCursor][i];\r
+                       if (minVal < y)\r
+                               minVal = y;\r
+                       else if (maxVal > y)\r
+                               maxVal = y;\r
+                       pX[i] = i;\r
+                       pY[i] = y;\r
+               }\r
+               PlotFileDocument* pPlotDoc = dynamic_cast<PlotFileDocument*>(theApp->getDocManager()->CreateDocument("untitled.plt", wxDOC_SILENT));\r
+               if (! pPlotDoc) {\r
+                       sys_error (ERR_SEVERE, "Internal error: unable to create Plot file");\r
+               } else {\r
+                       PlotFile& rPlot = pPlotDoc->getPlotFile();\r
+                       std::ostringstream title;\r
+                       title << "Column " << xCursor;\r
+                       rPlot.setTitle(title.str());\r
+                       rPlot.setXLabel("Row");\r
+                       rPlot.setYLabel("Pixel Value");\r
+                       rPlot.setCurveSize (2, nx);\r
+                       rPlot.addColumn (0, pX);\r
+                       rPlot.addColumn (1, pY);\r
+               }\r
+               delete pX;\r
+               delete pY;\r
+       }\r
+}\r
+\r
 
 // PhantomCanvas
 
@@ -975,3 +1121,206 @@ ProjectionFileView::OnClose (bool deleteWindow)
     return true;
 }
 
+
+
+// PlotFileCanvas
+PlotFileCanvas::PlotFileCanvas (PlotFileView* v, wxFrame *frame, const wxPoint& pos, const wxSize& size, const long style)
+: wxScrolledWindow(frame, -1, pos, size, style)
+{
+    m_pView = v;
+}
+
+void 
+PlotFileCanvas::OnDraw(wxDC& dc)
+{
+    if (m_pView)
+        m_pView->OnDraw(& dc);
+}
+
+// PlotFileView
+
+IMPLEMENT_DYNAMIC_CLASS(PlotFileView, wxView)
+
+BEGIN_EVENT_TABLE(PlotFileView, wxView)
+EVT_MENU(PJMENU_FILE_PROPERTIES, PlotFileView::OnProperties)
+END_EVENT_TABLE()
+
+PlotFileView::PlotFileView(void) 
+: wxView(), m_canvas(NULL), m_frame(NULL)
+{
+}
+
+PlotFileView::~PlotFileView(void)
+{
+}
+
+void
+PlotFileView::OnProperties (wxCommandEvent& event)
+{
+       const PlotFile& rProj = GetDocument()->getPlotFile();
+       std::ostringstream os;\r
+       os << "Columns: " << rProj.getNumColumns() << ", Records: " << rProj.getNumRecords() << "\n";
+       *theApp->getLog() << os.str().c_str();
+       wxMessageDialog dialogMsg (m_frame, os.str().c_str(), "Plot File Properties", wxOK | wxICON_INFORMATION);
+       dialogMsg.ShowModal();
+}
+
+
+PlotFileCanvas* 
+PlotFileView::CreateCanvas (wxView *view, wxFrame *parent)
+{
+    PlotFileCanvas* pCanvas;
+    int width, height;
+    parent->GetClientSize(&width, &height);
+    
+    pCanvas = new PlotFileCanvas (dynamic_cast<PlotFileView*>(view), parent, wxPoint(0, 0), wxSize(width, height), 0);
+    
+    pCanvas->SetBackgroundColour(*wxWHITE);
+    pCanvas->Clear();
+    
+    return pCanvas;
+}
+
+wxFrame*
+PlotFileView::CreateChildFrame(wxDocument *doc, wxView *view)
+{
+    wxDocChildFrame *subframe = new wxDocChildFrame(doc, view, theApp->getMainFrame(), -1, "Plot Frame", wxPoint(10, 10), wxSize(500, 300), wxDEFAULT_FRAME_STYLE);
+    
+    wxMenu *file_menu = new wxMenu;
+    
+    file_menu->Append(MAINMENU_FILE_CREATE_PHANTOM, "Cr&eate Phantom...");
+    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->Append(PJMENU_FILE_PROPERTIES, "P&roperties");
+       
+    file_menu->AppendSeparator();
+    file_menu->Append(wxID_PRINT, "&Print...");
+    file_menu->Append(wxID_PRINT_SETUP, "Print &Setup...");
+    file_menu->Append(wxID_PREVIEW, "Print Pre&view");
+    
+    wxMenu *help_menu = new wxMenu;
+    help_menu->Append(MAINMENU_HELP_CONTENTS, "&Contents");
+    help_menu->AppendSeparator();
+    help_menu->Append(MAINMENU_HELP_ABOUT, "&About");
+    
+    wxMenuBar *menu_bar = new wxMenuBar;
+    
+    menu_bar->Append(file_menu, "&File");
+    menu_bar->Append(help_menu, "&Help");
+    
+    subframe->SetMenuBar(menu_bar);
+    
+    subframe->Centre(wxBOTH);
+    
+    return subframe;
+}
+
+
+bool 
+PlotFileView::OnCreate(wxDocument *doc, long WXUNUSED(flags) )
+{
+    m_frame = CreateChildFrame(doc, this);
+    SetFrame(m_frame);
+    
+    int width, height;
+    m_frame->GetClientSize(&width, &height);
+    m_frame->SetTitle ("Plot File");
+    m_canvas = CreateCanvas (this, m_frame);
+       
+#ifdef __X__
+    int x, y;  // X requires a forced resize
+    m_frame->GetSize(&x, &y);
+    m_frame->SetSize(-1, -1, x, y);
+#endif
+       
+    m_frame->Show(true);
+    Activate(true);
+    
+    return true;
+}
+
+void 
+PlotFileView::OnDraw (wxDC* dc)
+{
+    const PlotFile& rPlot = GetDocument()->getPlotFile();\r
+    const int iNColumns = rPlot.getNumColumns();\r
+       const int iNRecords = rPlot.getNumRecords();\r
+\r
+       if (iNColumns > 0 && iNRecords > 0) {\r
+               int xsize, ysize;\r
+               m_canvas->GetClientSize (&xsize, &ysize);\r
+               SGPDriver driver (dc, xsize, ysize);\r
+               SGP sgp (driver);\r
+               const PlotFile& rPhantom = GetDocument()->getPlotFile();\r
+               EZPlot plot (sgp);\r
+\r
+               if (! rPlot.getTitle().empty()) {\r
+                       std::string s("title ");\r
+                       s += rPlot.getTitle();\r
+                       plot.ezset (s);\r
+               }\r
+               if (! rPlot.getXLabel().empty()) {\r
+                       std::string s("xlabel ");\r
+                       s += rPlot.getXLabel();\r
+                       plot.ezset (s);\r
+               }\r
+               if (! rPlot.getYLabel().empty()) {\r
+                       std::string s("ylabel ");\r
+                       s += rPlot.getYLabel();\r
+                       plot.ezset (s);\r
+               }\r
+\r
+       plot.ezset("box");\r
+       plot.ezset("grid");\r
+\r
+               double* pdXaxis = new double [iNRecords];\r
+               rPlot.getColumn (0, pdXaxis);\r
+\r
+               double* pdY = new double [iNRecords];\r
+               for (int iCol = 1; iCol < iNColumns; iCol++) {\r
+                       rPlot.getColumn (iCol, pdY);\r
+                       plot.addCurve (pdXaxis, pdY, iNRecords);\r
+               }\r
+\r
+               delete pdXaxis;\r
+               delete pdY;\r
+\r
+               plot.plot();\r
+       }\r
+}
+
+
+void 
+PlotFileView::OnUpdate(wxView *WXUNUSED(sender), wxObject *WXUNUSED(hint) )
+{
+    if (m_canvas)
+      m_canvas->Refresh();
+}
+
+bool 
+PlotFileView::OnClose (bool deleteWindow)
+{
+    if (!GetDocument()->Close())
+        return false;
+       
+    m_canvas->Clear();
+    m_canvas->m_pView = NULL;
+    m_canvas = NULL;
+    wxString s(wxTheApp->GetAppName());
+    if (m_frame)
+      m_frame->SetTitle(s);
+    SetFrame(NULL);
+       
+    Activate(false);
+    
+    if (deleteWindow) {
+      delete m_frame;
+      return true;
+    }
+    return true;
+}
+