Advertisement
acheong87

wx.cpp

Mar 3rd, 2014
396
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.42 KB | None | 0 0
  1. /***************************************************************************
  2.  * wx.cpp is part of Math Graphic Library                              *
  3.  * Copyright (C) 2007-2014 Alexey Balakin <[email protected]>       *
  4.  *                                                                         *
  5.  *   This program is free software; you can redistribute it and/or modify  *
  6.  *   it under the terms of the GNU Library General Public License as       *
  7.  *   published by the Free Software Foundation; either version 3 of the    *
  8.  *   License, or (at your option) any later version.                       *
  9.  *                                                                         *
  10.  *   This program is distributed in the hope that it will be useful,       *
  11.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  12.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  13.  *   GNU General Public License for more details.                          *
  14.  *                                                                         *
  15.  *   You should have received a copy of the GNU Library General Public     *
  16.  *   License along with this program; if not, write to the                 *
  17.  *   Free Software Foundation, Inc.,                                       *
  18.  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  19.  ***************************************************************************/
  20. //-----------------------------------------------------------------------------
  21. #include <wx/dcclient.h>
  22. #include <wx/msgdlg.h>
  23. #include <wx/clipbrd.h>
  24. #include <wx/dataobj.h>
  25. #include <wx/menu.h>
  26. #include <wx/scrolwin.h>
  27.  
  28. #include "mgl2/canvas_wnd.h"
  29. #include "mgl2/wx.h"
  30. //-----------------------------------------------------------------------------
  31. class MGL_EXPORT mglCanvasWX : public mglCanvasWnd
  32. {
  33. friend class wxMathGL;
  34. public:
  35.     int sshow;          ///< Current state of animation switch (toggle button)
  36.     wxMathGL *WMGL;     ///< Control which draw graphics
  37.     wxWindow *Wnd;      ///< Pointer to window
  38.  
  39.     mglCanvasWX();
  40.     virtual ~mglCanvasWX();
  41.  
  42.     /// Create a window for plotting. Now implemeted only for GLUT.
  43.     void Window(int argc, char **argv, int (*draw)(mglBase *gr, void *p), const char *title,
  44.                 void *par=NULL, void (*reload)(void *p)=NULL, bool maximize=false);
  45.     /// Switch on/off transparency (do not overwrite switches in user drawing function)
  46.     void ToggleAlpha();
  47.     /// Switch on/off lighting (do not overwrite switches in user drawing function)
  48.     void ToggleLight();
  49.     void ToggleRotate();    ///< Switch on/off rotation by mouse
  50.     void ToggleZoom();      ///< Switch on/off zooming by mouse
  51.     void ToggleNo();        ///< Switch off all zooming and rotation
  52.     void Update();          ///< Update picture by calling user drawing function
  53.     void Adjust();          ///< Adjust size of bitmap to window size
  54.     void GotoFrame(int d);  ///< Show arbitrary frame (use relative step)
  55.     void Animation();   ///< Run animation (I'm too lasy to change it)
  56.  
  57. protected:
  58.     wxScrolledWindow *scroll;   ///< Scrolling area
  59.     wxMenu *popup;          ///< Popup menu
  60. //  wxSpinCtrl *tet, *phi;  ///< Spin box for angles // TODO
  61.  
  62.     void MakeMenu();        ///< Create menu, toolbar and popup menu
  63. };
  64. //-----------------------------------------------------------------------------
  65. const wxString ScriptName(L"default");
  66. enum
  67. {
  68.     TIMER_ID=1000,
  69.     LAST_ID
  70. };
  71. BEGIN_EVENT_TABLE(wxMathGL, wxWindow)
  72.     EVT_TIMER   (TIMER_ID,  wxMathGL::OnNextSlide)
  73.     EVT_PAINT   (wxMathGL::OnPaint)
  74.     EVT_SIZE    (wxMathGL::OnSize)
  75.     EVT_LEFT_DOWN   (wxMathGL::OnMouseLeftDown)
  76.     EVT_RIGHT_DOWN  (wxMathGL::OnMouseDown)
  77.     EVT_MIDDLE_DOWN (wxMathGL::OnMouseDown)
  78.     EVT_LEFT_UP     (wxMathGL::OnMouseLeftUp)
  79.     EVT_RIGHT_UP    (wxMathGL::OnMouseRightUp)
  80.     EVT_MOTION      (wxMathGL::OnMouseMove)
  81. END_EVENT_TABLE()
  82. //-----------------------------------------------------------------------------
  83. //
  84. //      class wxMathGL
  85. //
  86. //-----------------------------------------------------------------------------
  87. wxMathGL::wxMathGL(wxWindow *parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style, const wxString& name) : wxWindow(parent,id,pos,size,style,name)
  88. {
  89.     AutoResize = false; draw_par = 0;   draw_func = 0;
  90.     gr = new mglCanvas; popup = 0;
  91.     phi = tet = per = 0;
  92.     x1 = y1 = 0;    x2 = y2 = 1;
  93.     alpha = light = zoom = rotate = false;
  94. //  SetSize(600, 400);
  95.     timer = new wxTimer(this,TIMER_ID);
  96. }
  97. //-----------------------------------------------------------------------------
  98. wxMathGL::~wxMathGL()   {   if(mgl_use_graph(gr,-1)<1)  mgl_delete_graph(gr);   }
  99. //-----------------------------------------------------------------------------
  100. double wxMathGL::GetRatio() {   return double(mgl_get_width(gr))/mgl_get_height(gr);    };
  101. //-----------------------------------------------------------------------------
  102. void wxMathGL::SetGraph(HMGL GR)
  103. {
  104.     mglCanvas *gg = dynamic_cast<mglCanvas *>(GR);
  105.     if(!gg) return;
  106.     if(mgl_use_graph(gr,-1)<1)  mgl_delete_graph(gr);
  107.     gr=gg;  mgl_use_graph(gg,1);
  108. }
  109. //-----------------------------------------------------------------------------
  110. void wxMathGL::OnPaint(wxPaintEvent& event)
  111. {
  112.     wxPaintDC dc(this);
  113.     dc.DrawBitmap(pic,0,0);
  114. //  if(zoom)    dc.DrawRectangle(x0,y0,xe-x0,ye-y0);
  115.     if(mgl_get_flag(gr,MGL_SHOW_POS) && !MousePos.IsEmpty())
  116.         dc.DrawText(MousePos,0,12);
  117.     // TODO: add grid drawing here (from Qt)
  118.     // TODO: add active points drawing here (from Qt)
  119. }
  120. //-----------------------------------------------------------------------------
  121. void wxMathGL::OnSize(wxSizeEvent& event)
  122. {
  123.     wxSize ev = event.GetSize();
  124.     if(mgl_get_width(gr)==ev.GetWidth() && mgl_get_height(gr)==ev.GetHeight())
  125.         return;
  126.     if(AutoResize && ev.GetWidth()>0 && ev.GetHeight()>0)
  127.     {   mgl_set_size(gr, ev.GetWidth(), ev.GetHeight());    Update();   }
  128.     else    SetSize(mgl_get_width(gr), mgl_get_height(gr));
  129. }
  130. //-----------------------------------------------------------------------------
  131. void wxMathGL::OnNextSlide(wxTimerEvent& evt)   {   NextSlide();    }
  132. //-----------------------------------------------------------------------------
  133. void wxMathGL::SetPer(int p)
  134. {   if(100*per!=p && p>=0 && p<100) {   per = 0.01*p;   Repaint();  }   }
  135. //-----------------------------------------------------------------------------
  136. void wxMathGL::SetPhi(int p)
  137. {   if(phi!=p)  {   phi = p;    Repaint();  }   }
  138. //-----------------------------------------------------------------------------
  139. void wxMathGL::SetTet(int t)
  140. {   if(tet!=t)  {   tet = t;    Repaint();  }   }
  141. //-----------------------------------------------------------------------------
  142. void wxMathGL::SetAlpha(bool a)
  143. {   if(alpha!=a)    {   alpha = a;  Update();   }   }
  144. //-----------------------------------------------------------------------------
  145. void wxMathGL::SetLight(bool l)
  146. {   if(light!=l)    {   light = l;  Update();   }   }
  147. //-----------------------------------------------------------------------------
  148. void wxMathGL::SetZoom(bool z)
  149. {   if(zoom!=z) {   zoom=z; rotate=false;   Repaint();  }   }
  150. //-----------------------------------------------------------------------------
  151. void wxMathGL::SetRotate(bool r)
  152. {   if(rotate!=r)   {   zoom=false; rotate=r;   Repaint();  }   }
  153. //-----------------------------------------------------------------------------
  154. void wxMathGL::ShiftDown()
  155. {   mreal d=(y2-y1)/3;  y1+=d;  y2+=d;  Repaint();  }
  156. //-----------------------------------------------------------------------------
  157. void wxMathGL::ShiftUp()
  158. {   mreal d=(y2-y1)/3;  y1-=d;  y2-=d;  Repaint();  }
  159. //-----------------------------------------------------------------------------
  160. void wxMathGL::ShiftRight()
  161. {   mreal d=(x2-x1)/3;  x1-=d;  x2-=d;  Repaint();  }
  162. //-----------------------------------------------------------------------------
  163. void wxMathGL::ShiftLeft()
  164. {   mreal d=(x2-x1)/3;  x1+=d;  x2+=d;  Repaint();  }
  165. //-----------------------------------------------------------------------------
  166. void wxMathGL::Restore()
  167. {
  168.     SetPhi(0);  SetTet(0);  SetPer(0);
  169.     x1=y1=0;    x2=y2=1;    zoom=rotate=false;
  170.     Repaint();
  171. }
  172. //-----------------------------------------------------------------------------
  173. void wxMathGL::ZoomIn()
  174. {
  175.     mreal d;
  176.     d = (y2-y1)/4;  y1 += d;    y2 -= d;
  177.     d = (x2-x1)/4;  x1 += d;    x2 -= d;
  178.     Repaint();
  179. }
  180. //-----------------------------------------------------------------------------
  181. void wxMathGL::ZoomOut()
  182. {
  183.     mreal d;
  184.     d = (y2-y1)/2;  y1 -= d;    y2 += d;
  185.     d = (x2-x1)/2;  x1 -= d;    x2 += d;
  186.     Repaint();
  187. }
  188. //-----------------------------------------------------------------------------
  189. void wxMathGL::Update()
  190. {
  191.     if(draw_func || draw_cl)
  192.     {
  193.         if(mgl_get_flag(gr,MGL_CLF_ON_UPD)) mgl_set_def_param(gr);
  194.         mgl_reset_frames(gr);
  195.         mgl_set_alpha(gr,alpha);    mgl_set_light(gr,light);
  196.         if(draw_func)   draw_func(gr, draw_par);    // drawing itself
  197.         else    if(draw_cl) {   mglGraph g(gr); draw_cl->Draw(&g);  }
  198.         const char *buf = mgl_get_mess(gr);
  199.         if(*buf)
  200.         {
  201.             wxMessageDialog dlg(this, wxString(buf,wxConvLocal), appName, wxOK);
  202.             dlg.ShowModal();
  203.         }
  204.     }
  205.     MousePos.Empty();   Repaint();
  206. }
  207. //-----------------------------------------------------------------------------
  208. wxBitmap MGL_EXPORT ConvertFromGraph(HMGL gr)
  209. {
  210.     const unsigned char *bb = mgl_get_rgb(gr);
  211.     int w=mgl_get_width(gr), h=mgl_get_height(gr);
  212.     unsigned char *tmp = (unsigned char *)malloc(3*w*h);
  213.     memcpy(tmp,bb,3*w*h);
  214.     wxImage img(w, h);  img.SetData(tmp);
  215.     return wxBitmap(img);
  216. }
  217. //-----------------------------------------------------------------------------
  218. void wxMathGL::Repaint()
  219. {
  220.     mgl_zoom(gr,x1,y1,x2,y2);   mgl_view(gr,phi,0,tet); mgl_perspective(gr, per);
  221.     pic = ConvertFromGraph(gr);
  222.     wxSize sz=GetSize();
  223.     if(pic.GetWidth()!=sz.GetWidth() || pic.GetHeight()!=sz.GetHeight())
  224.         SetSize(pic.GetWidth(), pic.GetHeight());
  225.     Refresh();
  226. }
  227. //-----------------------------------------------------------------------------
  228. void wxMathGL::OnMouseLeftDown(wxMouseEvent &ev)
  229. {
  230.     long x=ev.GetX(), y=ev.GetY();
  231.     if(!zoom && !rotate)
  232.     {
  233.         mglPoint p = gr->CalcXYZ(x, y);
  234.         MousePos.Printf(wxT("x=%g, y=%g, z=%g"),p.x,p.y,p.z);
  235.         Refresh();
  236. //      emit mouseClick(p.x,p.y,p.z);
  237.     }
  238.     xe=x0=x;    ye=y0=y;    ev.Skip();
  239. }
  240. //-----------------------------------------------------------------------------
  241. void wxMathGL::OnMouseDown(wxMouseEvent &ev)
  242. {   xe=x0=ev.GetX();    ye=y0=ev.GetY();    ev.Skip();  }
  243. //-----------------------------------------------------------------------------
  244. void wxMathGL::OnMouseLeftUp(wxMouseEvent &ev)
  245. {
  246.     if(zoom)
  247.     {
  248.         int w1=GetSize().GetWidth(),h1=GetSize().GetHeight();
  249.         mreal _x1,_x2,_y1,_y2;
  250.         _x1 = x1+(x2-x1)*(x0-GetPosition().x)/mreal(w1);
  251.         _y1 = y2-(y2-y1)*(ye-GetPosition().y)/mreal(h1);
  252.         _x2 = x1+(x2-x1)*(xe-GetPosition().x)/mreal(w1);
  253.         _y2 = y2-(y2-y1)*(y0-GetPosition().y)/mreal(h1);
  254.         x1=_x1;     x2=_x2;     y1=_y1;     y2=_y2;
  255.         if(x1>x2)   {   _x1=x1; x1=x2;  x2=_x1; }
  256.         if(y1>y2)   {   _x1=y1; y1=y2;  y2=_x1; }
  257.         x0 = xe;    y0 = ye;
  258.         Update();
  259.     }
  260. }
  261. //-----------------------------------------------------------------------------
  262. void wxMathGL::OnMouseRightUp(wxMouseEvent &ev)
  263. {   if(popup && !rotate)    PopupMenu(popup, ev.GetPosition()); }
  264. //-----------------------------------------------------------------------------
  265. void wxMathGL::OnMouseMove(wxMouseEvent &ev)
  266. {
  267.     long w=GetSize().GetWidth(), h=GetSize().GetHeight();
  268.     xe=ev.GetX();   ye=ev.GetY();
  269.     if(rotate)
  270.     {
  271.         if(ev.ButtonDown(wxMOUSE_BTN_LEFT)) // rotate
  272.         {
  273.             mreal ff = 240/sqrt(mreal(w*h));
  274.             phi += int((x0-xe)*ff);
  275.             tet += int((y0-ye)*ff);
  276.             if(phi>180) phi-=360;       if(phi<-180)    phi+=360;
  277.             if(tet>180) tet-=360;       if(tet<-180)    tet+=360;
  278. //          Update();
  279.         }
  280.         if(ev.ButtonDown(wxMOUSE_BTN_RIGHT))    // zoom and perspective
  281.         {
  282.             mreal ff = 2.*(y0-ye)/w, gg = 0.5*(xe-x0)/h;
  283.             mreal cx = (x1+x2)/2, cy = (y1+y2)/2;
  284.             x1 = cx+(x1-cx)*exp(-ff);   x2 = cx+(x2-cx)*exp(-ff);
  285.             y1 = cy+(y1-cy)*exp(-ff);   y2 = cy+(y2-cy)*exp(-ff);
  286.             per = per + gg;
  287.             if(per<0)   per = 0;    if(per>=1)  per = 0.9999;
  288. //          Update();
  289.         }
  290.         if(ev.ButtonDown(wxMOUSE_BTN_MIDDLE))   // shift
  291.         {
  292.             mreal ff = 1./sqrt(mreal(w*h));
  293.             mreal dx = (x0-xe)*ff*(x2-x1), dy = (y0-ye)*ff*(y2-y1);
  294.             x1 += dx;   x2 += dx;   y1 -= dy;   y2 -= dy;
  295.         }
  296.         x0 = xe;    y0 = ye;
  297.         Update();
  298.     }
  299. //  if(zoom)    Update();
  300.     if(zoom)    Refresh(0);
  301. }
  302. //-----------------------------------------------------------------------------
  303. wxString mglSetExtension(wxString &fname, const char *ext)
  304. {
  305.     wxString oname;
  306.     if(fname.Right(4)!=wxChar('.')+wxString(ext,*wxConvCurrent))
  307.         oname = fname+wxChar('.')+wxString(ext,*wxConvCurrent);
  308.     return oname;
  309. }
  310. //-----------------------------------------------------------------------------
  311. // NOTE: this is replacement for wxString::char_str() which is for v.2.8 or later
  312. const char *mglw_str(const wxString &str)
  313. {
  314.     static char *buf=0;
  315.     if(buf) delete []buf;
  316.     long i, n=str.Len();
  317.     buf = new char[n+1];    buf[n]=0;
  318.     for(i=0;i<n;i++)    buf[i] = str.GetChar(i);
  319.     return buf;
  320. }
  321. //-----------------------------------------------------------------------------
  322. void wxMathGL::ExportPNG(wxString fname)
  323. {
  324.     if(fname.IsEmpty()) fname = ScriptName;
  325.     if(fname.IsEmpty()) wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
  326.     else    mgl_write_png(gr,mglw_str(mglSetExtension(fname,"png")), mglw_str(appName));
  327. }
  328. //-----------------------------------------------------------------------------
  329. void wxMathGL::ExportPNGs(wxString fname)
  330. {
  331.     if(fname.IsEmpty()) fname = ScriptName;
  332.     if(fname.IsEmpty()) wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
  333.     else    mgl_write_png_solid(gr,mglw_str(mglSetExtension(fname,"png")), mglw_str(appName));
  334. }
  335. //-----------------------------------------------------------------------------
  336. void wxMathGL::ExportJPG(wxString fname)
  337. {
  338.     if(fname.IsEmpty()) fname = ScriptName;
  339.     if(fname.IsEmpty()) wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
  340.     else    mgl_write_jpg(gr,mglw_str(mglSetExtension(fname,"jpg")), mglw_str(appName));
  341. }
  342. //-----------------------------------------------------------------------------
  343. void wxMathGL::ExportBPS(wxString fname)
  344. {
  345.     if(fname.IsEmpty()) fname = ScriptName;
  346.     if(fname.IsEmpty()) wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
  347.     else
  348.     {
  349.         setlocale(LC_ALL, "C");
  350.         mgl_write_bps(gr,mglw_str(mglSetExtension(fname,"eps")), mglw_str(appName));
  351.         setlocale(LC_ALL, "");
  352.     }
  353. }
  354. //-----------------------------------------------------------------------------
  355. void wxMathGL::ExportEPS(wxString fname)
  356. {
  357.     if(fname.IsEmpty()) fname = ScriptName;
  358.     if(fname.IsEmpty()) wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
  359.     else
  360.     {
  361.         setlocale(LC_ALL, "C");
  362.         mgl_write_eps(gr,mglw_str(mglSetExtension(fname,"eps")), mglw_str(appName));
  363.         setlocale(LC_ALL, "");
  364.     }
  365. }
  366. //-----------------------------------------------------------------------------
  367. void wxMathGL::ExportSVG(wxString fname)
  368. {
  369.     if(fname.IsEmpty()) fname = ScriptName;
  370.     if(fname.IsEmpty()) wxMessageBox(appName, wxT("No filename."),wxOK|wxICON_ERROR ,this);
  371.     else
  372.     {
  373.         setlocale(LC_ALL, "C");
  374.         mgl_write_svg(gr,mglw_str(mglSetExtension(fname,"eps")), mglw_str(appName));
  375.         setlocale(LC_ALL, "");
  376.     }
  377. }
  378. //-----------------------------------------------------------------------------
  379. void wxMathGL::Copy()
  380. {
  381.     if (wxTheClipboard->Open())
  382.     {
  383.         wxTheClipboard->SetData( new wxBitmapDataObject(pic) );
  384.         wxTheClipboard->Close();
  385.     }
  386. }
  387. //-----------------------------------------------------------------------------
  388. void wxMathGL::SetSize(int w, int h)
  389. {   mgl_set_size(gr,w,h);   wxWindow::SetSize(w, h);    Update();   };
  390. //-----------------------------------------------------------------------------
  391. void wxMathGL::Adjust()
  392. {
  393.     wxSize sz=GetSize();
  394.     mgl_set_size(gr,sz.GetWidth(),sz.GetHeight());
  395.     Repaint();
  396. }
  397. //-----------------------------------------------------------------------------
  398. void wxMathGL::NextSlide()
  399. {
  400.     mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
  401.     if(g && g->GetNumFig()>1)   g->NextFrame();
  402. }
  403. //-----------------------------------------------------------------------------
  404. void wxMathGL::PrevSlide()
  405. {
  406.     mglCanvasWnd *g = dynamic_cast<mglCanvasWnd *>(gr);
  407.     if(g && g->GetNumFig()>1)   g->PrevFrame();
  408. }
  409. //-----------------------------------------------------------------------------
  410. void wxMathGL::Animation(bool st)
  411. {
  412.     if(st)  timer->Start(int(mgl_wnd_get_delay(gr)*1000));
  413.     else    timer->Stop();
  414. }
  415. //-----------------------------------------------------------------------------
  416. void wxMathGL::About()
  417. {
  418.     wxString s = wxT("MathGL v. 2.") + wxString::Format(wxT("%g"),MGL_VER2) +
  419.         wxT("\n(c) Alexey Balakin, 2007\nhttp://mathgl.sourceforge.net/");
  420.     wxMessageBox(s, wxT("MathGL - about"), wxOK|wxICON_INFORMATION, this);
  421. }
  422. //-----------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement