wxgraph.h

00001 /*************************************************************************************
00002  * MechSys - A C++ library to simulate (Continuum) Mechanical Systems                *
00003  * Copyright (C) 2005 Dorival de Moraes Pedroso <dorival.pedroso at gmail.com>       *
00004  * Copyright (C) 2005 Raul Dario Durand Farfan  <raul.durand at gmail.com>           *
00005  *                                                                                   *
00006  * This file is part of MechSys.                                                     *
00007  *                                                                                   *
00008  * MechSys is free software; you can redistribute it and/or modify it under the      *
00009  * terms of the GNU General Public License as published by the Free Software         *
00010  * Foundation; either version 2 of the License, or (at your option) any later        *
00011  * version.                                                                          *
00012  *                                                                                   *
00013  * MechSys is distributed in the hope that it will be useful, but WITHOUT ANY        *
00014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A   *
00015  * PARTICULAR PURPOSE. See the GNU General Public License for more details.          *
00016  *                                                                                   *
00017  * You should have received a copy of the GNU General Public License along with      *
00018  * MechSys; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, *
00019  * Fifth Floor, Boston, MA 02110-1301, USA                                           *
00020  *************************************************************************************/
00021 
00022 #ifndef MECHSYS_WXGRAPH_H
00023 #define MECHSYS_WXGRAPH_H
00024 
00025 #include <sstream>
00026 #include <iomanip>
00027 #include <wx/frame.h>
00028 #include <wx/dcbuffer.h>
00029 
00030 #ifdef HAVE_CONFIG_H
00031   #include "config.h"
00032 #else
00033   #ifndef REAL
00034     #define REAL double
00035   #endif
00036 #endif
00037 
00038 #include "util/array.h"
00039 #include "util/lineparser.h"
00040 
00041 #include "gui/wxcurve.h"
00042 #include "gui/wxruler.h"
00043 #include "gui/wxgrid.h"
00044 
00045 class WxGraph : public wxWindow
00046 {
00047 public:
00048     // Constructor
00049      WxGraph (wxFrame * Parent, wxSize Size=wxDefaultSize);
00050      WxGraph (wxFrame * Parent, String const & BgPenColor, String const & BgColor, wxSize Size=wxDefaultSize);
00051     ~WxGraph ();
00052 
00053     // Methods
00054     void RePaint();
00055 
00056     // Events
00057     void OnPaint           (wxPaintEvent & Event);
00058     void OnEraseBackground (wxEraseEvent & Event);
00059     void OnSize            (wxSizeEvent  & Event);
00060 
00061     // Config Methods
00062     WxGraph & EqualScales(bool Val=false) { _td.EqScales=Val; return (*this); }
00063 
00064     // Methods
00065     WxCurve & AddCurve    (Array<REAL> const & X, Array<REAL> const & Y);
00066     WxCurve & AddCurve    (REAL const * X, REAL const * Y, int Size);
00067     WxCurve & AddCurve    (REAL x_min, REAL x_max, REAL y_min, REAL y_max, int nDiv, REAL DelPctX=0.1, REAL DelPctY=0.1);
00068     WxCurve & ResetCurve  (int i, REAL const * X, REAL const * Y, int Size);
00069     WxCurve & ResetCurve  (int i, Array<REAL> const & X, Array<REAL> const & Y);
00070     WxCurve & ResetCurve  (int i, REAL x_min, REAL x_max, REAL y_min, REAL y_max, int nDiv, REAL DelPctX=0.1, REAL DelPctY=0.1);
00071     WxCurve & SetContour  (int i, int nLevels, REAL const * Levels);
00072     WxCurve & EnableCurve (int i, bool Enabled);
00073     WxRuler & XRuler      ()      { return _x_ruler;      }
00074     WxRuler & YRuler      ()      { return _y_ruler;      }
00075     WxRuler & X2Ruler     ()      { return _x2_ruler;     }
00076     WxRuler & Y2Ruler     ()      { return _y2_ruler;     }
00077     WxCurve & GetCurve    (int i) { return (*_curves[i]); }
00078     WxGrid  & Grid        ()      { return _grid;         }
00079     void      DelCurve    (size_t i) { if (i<_curves.size()) { delete _curves[i]; _curves.erase(_curves.begin()+i); } }
00080 
00081 private:
00082     // Event table
00083     DECLARE_EVENT_TABLE()
00084     // Data
00085     WxTransformData _td;
00086     Array<WxCurve*> _curves;
00087     wxPen           _bg_pen;
00088     wxBrush         _bg_brush;
00089     // Scales
00090     WxRuler         _x_ruler;  // bottom
00091     WxRuler         _y_ruler;  // left
00092     WxRuler         _x2_ruler; // top
00093     WxRuler         _y2_ruler; // right
00094     // Grid
00095     WxGrid          _grid;
00096 
00097     // Methods
00098     void _bounding_box     ();
00099     void _paint_background (wxDC & DC);
00100     void _draw_graph       (wxDC & DC);
00101     void _calc_size        ();
00102 }; // class SWindow
00103 
00104 
00106 
00107 
00108 inline WxGraph::WxGraph(wxFrame * Parent, wxSize Size) // {{{
00109     : wxWindow (Parent, wxID_ANY, wxDefaultPosition, Size, wxFULL_REPAINT_ON_RESIZE),
00110       _bg_pen   (_T("blue"),/*width*/1,wxSOLID),
00111       _bg_brush (static_cast<wxColour>(GetBackgroundColour()), wxSOLID)
00112 {
00113     // TransformData
00114     _td.EqScales = false;
00115     
00116     // Rulers
00117     _x_ruler .Position(WxRuler::POS_BOTTOM);
00118     _y_ruler .Position(WxRuler::POS_LEFT  );
00119     _x2_ruler.Position(WxRuler::POS_TOP   );
00120     _y2_ruler.Position(WxRuler::POS_RIGHT );
00121 } // }}}
00122 
00123 inline WxGraph::WxGraph(wxFrame * Parent, String const & BgPenColor, String const & BgColor, wxSize Size) // {{{
00124     : wxWindow (Parent, wxID_ANY, wxDefaultPosition, Size, wxFULL_REPAINT_ON_RESIZE),
00125       _bg_pen   (BgPenColor,/*width*/1,wxSOLID),
00126       _bg_brush (BgColor,wxSOLID)
00127 {
00128     // TransformData
00129     _td.EqScales = false;
00130 
00131     // Rulers
00132     _x_ruler .Position(WxRuler::POS_BOTTOM);
00133     _y_ruler .Position(WxRuler::POS_LEFT  );
00134     _x2_ruler.Position(WxRuler::POS_TOP   );
00135     _y2_ruler.Position(WxRuler::POS_RIGHT );
00136 } // }}}
00137 
00138 inline WxGraph::~WxGraph() // {{{
00139 {
00140     for (size_t i=0; i<_curves.size(); ++i)
00141         delete _curves[i];
00142 } // }}}
00143 
00144 inline void WxGraph::RePaint() // {{{
00145 {
00146     _calc_size();
00147     this->Refresh();
00148     this->Update();
00149 } // }}}
00150 
00151 inline void WxGraph::OnPaint(wxPaintEvent & Event) // {{{
00152 {
00153     // Device context
00154     wxBufferedPaintDC dc(this);
00155     PrepareDC(dc);
00156 
00157     // Background
00158     _paint_background(dc);
00159 
00160     // Paint
00161     _draw_graph(dc);
00162 } // }}}
00163 
00164 inline void WxGraph::OnEraseBackground(wxEraseEvent & Event) // {{{
00165 {
00166     // Empty implementation to prevent flicker
00167 } // }}}
00168 
00169 inline void WxGraph::OnSize(wxSizeEvent & Event) // {{{
00170 {
00171     _calc_size();
00172 } // }}}
00173 
00174 inline WxCurve & WxGraph::AddCurve(Array<REAL> const & X, Array<REAL> const & Y) // {{{
00175 {
00176     WxCurve * C = new WxCurve (X,Y);
00177     _curves.push_back(C);
00178     _bounding_box();
00179     return (*C);
00180 } // }}}
00181 
00182 inline WxCurve & WxGraph::AddCurve(REAL const * X, REAL const * Y, int Size) // {{{
00183 {
00184     WxCurve * C = new WxCurve (X,Y,Size);
00185     _curves.push_back(C);
00186     _bounding_box();
00187     return (*C);
00188 } // }}}
00189 
00190 inline WxCurve & WxGraph::AddCurve(REAL x_min, REAL x_max, REAL y_min, REAL y_max, int nDiv, REAL DelPctX, REAL DelPctY) // {{{
00191 {
00192     WxCurve * C = new WxCurve (x_min,x_max, y_min,y_max, nDiv, DelPctX, DelPctY);
00193     _curves.push_back(C);
00194     _bounding_box();
00195     return (*C);
00196 } // }}}
00197 
00198 inline WxCurve & WxGraph::ResetCurve(int i, REAL const * X, REAL const * Y, int Size) // {{{
00199 {
00200     // TODO: check range
00201     _curves[i]->ResetData(X, Y, Size);
00202     _bounding_box();
00203 
00204     // Send event to (re)paint the graph
00205     RePaint();
00206 
00207     // Return
00208     return (*_curves[i]);
00209 } // }}}
00210 
00211 inline WxCurve & WxGraph::ResetCurve(int i, Array<REAL> const & X, Array<REAL> const & Y) // {{{
00212 {
00213     // TODO: check range
00214     _curves[i]->ResetData(X, Y);
00215     _bounding_box();
00216 
00217     // Send event to (re)paint the graph
00218     RePaint();
00219 
00220     // Return
00221     return (*_curves[i]);
00222 } // }}}
00223 
00224 inline WxCurve & WxGraph::ResetCurve(int i, REAL x_min, REAL x_max, REAL y_min, REAL y_max, int nDiv, REAL DelPctX, REAL DelPctY) // {{{
00225 {
00226     // TODO: check range
00227     _curves[i]->ResetData(x_min, x_max, y_min, y_max, nDiv, DelPctX, DelPctY);
00228     _bounding_box();
00229 
00230     // Send event to (re)paint the graph
00231     RePaint();
00232 
00233     // Return
00234     return (*_curves[i]);
00235 } // }}}
00236 
00237 inline WxCurve & WxGraph::SetContour(int i, int nLevels, REAL const * Levels) // {{{
00238 {
00239     _curves[i]->SetContour(nLevels, Levels);
00240     _bounding_box();
00241 
00242     // Send event to (re)paint the graph
00243     RePaint();
00244 
00245     // Return
00246     return (*_curves[i]);
00247 } // }}}
00248 
00249 inline WxCurve & WxGraph::EnableCurve(int i, bool Enabled) // {{{
00250 {
00251     // TODO: check range
00252     _curves[i]->Enable(Enabled);
00253 
00254     // Return
00255     return (*_curves[i]);
00256 } // }}}
00257 
00258 inline void WxGraph::_bounding_box() // {{{
00259 {
00260     if (_curves.size()==0) return;
00261 
00262     _curves[0]->GetRange(_td.xMin, _td.xMax,  _td.yMin, _td.yMax);
00263 
00264     for (size_t i=1; i<_curves.size(); ++i)
00265     {
00266         REAL min_x;  REAL max_x;
00267         REAL min_y;  REAL max_y;
00268         _curves[i]->GetRange(min_x, max_x,  min_y, max_y);
00269         if (min_x<_td.xMin) _td.xMin=min_x;
00270         if (max_x>_td.xMax) _td.xMax=max_x;
00271         if (min_y<_td.yMin) _td.yMin=min_y;
00272         if (max_y>_td.yMax) _td.yMax=max_y;
00273     }
00274 
00275     _td.xRange = _td.xMax - _td.xMin;
00276     _td.yRange = _td.yMax - _td.yMin;
00277 } // }}}
00278 
00279 inline void WxGraph::_paint_background(wxDC & DC) // {{{
00280 {
00281     DC.SetBrush(_bg_brush);
00282     DC.SetPen  (_bg_pen);
00283     wxRect win_rect(wxPoint(0,0), GetClientSize());
00284     DC.DrawRectangle(win_rect);
00285 } // }}}
00286 
00287 inline void WxGraph::_draw_graph(wxDC & DC) // {{{
00288 {
00289     if (_curves.size()>0)
00290     {
00291         // Grid
00292         _grid.Draw(DC);
00293 
00294         // Rulers
00295         _x_ruler .Draw(DC);
00296         _y_ruler .Draw(DC);
00297         _x2_ruler.Draw(DC);
00298         _y2_ruler.Draw(DC);
00299 
00300         // Curves
00301         for (size_t i=0; i<_curves.size(); ++i)
00302         {
00303             _curves[i]->DrawLine  (DC);
00304             _curves[i]->DrawPoints(DC);
00305         }
00306     }
00307 } // }}}
00308 
00309 inline void WxGraph::_calc_size() // {{{
00310 {
00311     // Client (canvas) area
00312     _td.CanvasRect.x = 0;
00313     _td.CanvasRect.y = 0;
00314     GetClientSize(&_td.CanvasRect.width, &_td.CanvasRect.height);
00315 
00316     // Area - rulers
00317     if (_x_ruler .IsActive()) _td.CanvasRect.height -= _x_ruler .Thick();                                                // bottom ruler
00318     if (_y_ruler .IsActive()) { _td.CanvasRect.x     = _y_ruler .Thick();  _td.CanvasRect.width  -= _y_ruler .Thick(); } // left ruler
00319     if (_x2_ruler.IsActive()) { _td.CanvasRect.y     = _x2_ruler.Thick();  _td.CanvasRect.height -= _x2_ruler.Thick(); } // top ruler
00320     if (_y2_ruler.IsActive()) _td.CanvasRect.width  -= _y2_ruler.Thick();                                                // right ruler
00321 
00322     // Calculate scale factors
00323     WxCalcScaleFactor(_td);
00324 
00325     // Set rulers
00326     _x_ruler .UpdateSize(_td);
00327     _y_ruler .UpdateSize(_td);
00328     _x2_ruler.UpdateSize(_td);
00329     _y2_ruler.UpdateSize(_td);
00330     
00331     // Set curves
00332     for (size_t i=0; i<_curves.size(); ++i)
00333         _curves[i]->UpdateSize(_td);
00334 
00335     // Grid
00336     _grid.UpdateSize(_td);
00337     
00338 } // }}}
00339 
00340 BEGIN_EVENT_TABLE(WxGraph, wxWindow) // {{{
00341     EVT_PAINT            ( WxGraph::OnPaint           )
00342     EVT_ERASE_BACKGROUND ( WxGraph::OnEraseBackground )
00343     EVT_SIZE             ( WxGraph::OnSize            )
00344 END_EVENT_TABLE() // }}}
00345 
00346 #endif // MECHSYS_WXGRAPH_H
00347 
00348 // vim:fdm=marker

Generated on Wed Jan 24 15:56:26 2007 for MechSys by  doxygen 1.4.7