home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2233.zip / wxOS2-2_3_3.zip / wxWindows-2.3.3 / contrib / src / canvas / canvas.cpp < prev    next >
C/C++ Source or Header  |  2002-05-08  |  81KB  |  2,950 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        canvas.cpp
  3. // Author:      Robert Roebling
  4. // Created:     XX/XX/XX
  5. // Copyright:   2000 (c) Robert Roebling
  6. // Licence:     wxWindows Licence
  7. /////////////////////////////////////////////////////////////////////////////
  8.  
  9. #ifdef __GNUG__
  10.     #pragma implementation "canvas.cpp"
  11. #endif
  12.  
  13. // For compilers that support precompilation, includes "wx/wx.h".
  14. #include "wx/wxprec.h"
  15.  
  16. #ifdef __BORLANDC__
  17.     #pragma hdrstop
  18. #endif
  19.  
  20. #include "wx/canvas/canvas.h"
  21. #include "wx/canvas/polygon.h"
  22. #include "wx/canvas/liner.h"
  23.  
  24. #ifdef __WXGTK__
  25.     #include <gtk/gtk.h>
  26.     #include <gdk/gdkrgb.h>
  27.     #include "wx/gtk/win_gtk.h"
  28. #endif
  29.  
  30. #ifndef wxUSE_FREETYPE
  31.     #define wxUSE_FREETYPE 0
  32. #endif
  33.  
  34. #if wxUSE_FREETYPE
  35.     #include <freetype/freetype.h>
  36. #endif
  37.  
  38. //#define CANVASDEBUG
  39.  
  40. //----------------------------------------------------------------------------
  41. // globals
  42. //----------------------------------------------------------------------------
  43.  
  44. static const double pi = 3.1415926535;
  45.  
  46. #if wxUSE_FREETYPE
  47. FT_Library g_freetypeLibrary;
  48. #endif
  49.  
  50. //----------------------------------------------------------------------------
  51. // wxCanvasObject
  52. //----------------------------------------------------------------------------
  53.  
  54. IMPLEMENT_CLASS(wxCanvasObject, wxEvtHandler)
  55.  
  56. wxCanvasObject::wxCanvasObject()
  57. {
  58.     // the default event handler is just this object
  59.     m_eventHandler=this;
  60.     m_admin = NULL;
  61.     m_isControl = FALSE;
  62.     m_isVector = FALSE;
  63.     m_isImage = FALSE;
  64.     m_visible  = TRUE;
  65.     m_dragmode = wxDRAG_ONTOP;
  66. //  handy when debugging
  67. //  m_dragmode = wxDRAG_RECTANGLE;
  68.     m_dragable = TRUE;
  69. }
  70.  
  71. bool wxCanvasObject::ProcessCanvasObjectEvent(wxEvent& event)
  72. {
  73.     return m_eventHandler->ProcessEvent(event);
  74. }
  75.  
  76. void wxCanvasObject::PushEventHandler(wxEvtHandler *handler)
  77. {
  78.     handler->SetNextHandler(GetEventHandler());
  79.     m_eventHandler=handler;
  80. }
  81.  
  82. wxEvtHandler *wxCanvasObject::PopEventHandler(bool deleteHandler)
  83. {
  84.     wxEvtHandler *handlerA = m_eventHandler;
  85.     if ( handlerA )
  86.     {
  87.         wxEvtHandler *handlerB = handlerA->GetNextHandler();
  88.         handlerA->SetNextHandler((wxEvtHandler *)NULL);
  89.         m_eventHandler=handlerB;
  90.         if ( deleteHandler )
  91.         {
  92.             delete handlerA;
  93.             handlerA = (wxEvtHandler *)NULL;
  94.         }
  95.     }
  96.  
  97.     return handlerA;
  98. }
  99.  
  100. void wxCanvasObject::AppendEventHandler(wxEvtHandler *handler)
  101. {
  102.     GetEventHandler()->SetNextHandler(handler);
  103. }
  104.  
  105. wxEvtHandler *wxCanvasObject::RemoveLastEventHandler(bool deleteHandler)
  106. {
  107.     //always the first in the row
  108.     wxEvtHandler *handlerA = m_eventHandler;
  109.     wxEvtHandler *handlerB=handlerA;
  110.     //goto the end
  111.     while ( handlerA->GetNextHandler() )
  112.     {
  113.         handlerB = handlerA;
  114.         handlerA = handlerA->GetNextHandler();
  115.     }
  116.  
  117.     handlerB->SetNextHandler((wxEvtHandler *)NULL);
  118.     if ( deleteHandler )
  119.     {
  120.         delete handlerA;
  121.     }
  122.  
  123.     return GetEventHandler();
  124. }
  125.  
  126. wxRect wxCanvasObject::GetAbsoluteArea(const wxTransformMatrix& cworld)
  127. {
  128.     wxBoundingBox tmp=m_bbox;
  129.     tmp.MapBbox(cworld);
  130.  
  131.     int x1 = m_admin->LogicalToDeviceX( tmp.GetMinX() );
  132.     int y1 = m_admin->LogicalToDeviceY( tmp.GetMinY() );
  133.     int x2 = m_admin->LogicalToDeviceX( tmp.GetMaxX() );
  134.     int y2 = m_admin->LogicalToDeviceY( tmp.GetMaxY() );
  135.  
  136.     if (x1 > x2)
  137.     {
  138.         int tmp = x1;
  139.         x1 = x2;
  140.         x2 = tmp;
  141.     }
  142.     if (y1 > y2)
  143.     {
  144.         int tmp = y1;
  145.         y1 = y2;
  146.         y2 = tmp;
  147.     }
  148.  
  149.     wxRect tmparea;
  150.     tmparea.x = x1;
  151.     tmparea.y = y1;
  152.     tmparea.width = x2-x1;    // FIXME +1 ?
  153.     tmparea.height = y2-y1;   // FIXME +1 ?
  154.  
  155.     return tmparea;
  156. }
  157.  
  158. void wxCanvasObject::MoveAbsolute( double x, double y )
  159. {
  160.     //save old position of boundingbox
  161.     double oldx = GetXMin();
  162.     double oldy = GetYMin();
  163.     double w = m_bbox.GetWidth();
  164.     double h = m_bbox.GetHeight();
  165.  
  166.     SetPosXY(x,y);
  167.  
  168.     double newx=GetXMin();
  169.     double newy=GetYMin();
  170.  
  171.     double leftu,rightu,bottomu,topu ;
  172.     leftu   = wxMin (oldx, newx ) ;
  173.     rightu  = wxMax (oldx + w, newx + w) ;
  174.     topu    = wxMin (oldy, newy) ;
  175.     bottomu = wxMax (oldy + h, newy + h) ;
  176.  
  177.     if ( rightu - leftu < 2*w && bottomu - topu < 2*h )
  178.     {
  179.         m_admin->Update( this,leftu, topu, rightu - leftu, bottomu - topu);
  180.     }
  181.     else
  182.     {
  183.         m_admin->Update( this, oldx, oldy, w, h );
  184.         m_admin->Update( this, newx, newy, w, h );
  185.     }
  186. }
  187.  
  188. void wxCanvasObject::MoveRelative( double x, double y )
  189. {
  190.     //save old position of boundingbox
  191.     double oldx = GetXMin();
  192.     double oldy = GetYMin();
  193.     double w = m_bbox.GetWidth();
  194.     double h = m_bbox.GetHeight();
  195.  
  196.     TransLate(x,y);
  197.  
  198.     double newx=GetXMin();
  199.     double newy=GetYMin();
  200.  
  201.     double leftu,rightu,bottomu,topu ;
  202.     leftu   = wxMin (oldx, newx ) ;
  203.     rightu  = wxMax (oldx + w, newx + w) ;
  204.     topu    = wxMin (oldy, newy) ;
  205.     bottomu = wxMax (oldy + h, newy + h) ;
  206.  
  207.     if ( rightu - leftu < 2*w && bottomu - topu < 2*h )
  208.     {
  209.         m_admin->Update( this,leftu, topu, rightu - leftu, bottomu - topu);
  210.     }
  211.     else
  212.     {
  213.         m_admin->Update( this, oldx, oldy, w, h );
  214.         m_admin->Update( this, newx, newy, w, h );
  215.     }
  216. }
  217.  
  218.  
  219. void wxCanvasObject::DragStart()
  220. {
  221.     if (m_dragmode == wxDRAG_RECTANGLE)
  222.     {
  223.         this->SetVisible(FALSE);
  224.         wxTransformMatrix help;
  225.         double x = GetXMin();
  226.         double y = GetYMin();
  227.         double w = m_bbox.GetWidth();
  228.         double h = m_bbox.GetHeight();
  229.         m_admin->Update( this, x, y, w, h );
  230.         m_admin->UpdateNow();
  231.  
  232.         wxRect recold=GetAbsoluteArea(help);
  233.         wxClientDC dc(m_admin->GetActive());
  234.         dc.SetPen(*wxBLACK_PEN);
  235.         dc.SetBrush(*wxTRANSPARENT_BRUSH);
  236.         dc.SetLogicalFunction(wxINVERT);
  237.         dc.DrawRectangle(recold);
  238.         dc.SetBrush(wxNullBrush);
  239.         dc.SetPen(wxNullPen);
  240.     }
  241.     else if (m_dragmode != wxDRAG_REDRAW)
  242.     {
  243.         this->SetVisible(FALSE);
  244.         wxTransformMatrix help;
  245.         double x = GetXMin();
  246.         double y = GetYMin();
  247.         double w = m_bbox.GetWidth();
  248.         double h = m_bbox.GetHeight();
  249.  
  250.         wxRect recnew=GetAbsoluteArea(help);
  251.  
  252.          //redraw in buffer what should be there without this object
  253.         m_admin->Update( this, x, y, w, h );
  254.         m_admin->GetActive()->Freeze();
  255.  
  256.         //save the drawing (without the object itself to a bitmap)
  257.         m_atnewpos = wxBitmap(recnew.width,recnew.height);
  258.         wxMemoryDC dcm;
  259.         dcm.SelectObject(*m_admin->GetActive()->GetBuffer());
  260.         wxMemoryDC tmp;
  261.         tmp.SelectObject(m_atnewpos);
  262.         tmp.Blit(0,0,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE);
  263.         tmp.SelectObject(wxNullBitmap);
  264.         dcm.SelectObject(wxNullBitmap);
  265.     }
  266. }
  267.  
  268.  
  269. void wxCanvasObject::DragRelative( double x, double y)
  270. {
  271.     if (m_dragmode == wxDRAG_RECTANGLE)
  272.     {
  273.         wxTransformMatrix help;
  274.  
  275.         wxRect recold=GetAbsoluteArea(help);
  276.  
  277.         TransLate(x,y);
  278.  
  279.         wxRect recnew=GetAbsoluteArea(help);
  280.  
  281.         wxClientDC dc(m_admin->GetActive());
  282.         dc.SetPen(*wxBLACK_PEN);
  283.         dc.SetBrush(*wxTRANSPARENT_BRUSH);
  284.         dc.SetLogicalFunction(wxINVERT);
  285.         dc.DrawRectangle(recold);
  286.         dc.DrawRectangle(recnew);
  287.         dc.SetBrush(wxNullBrush);
  288.         dc.SetPen(wxNullPen);
  289.     }
  290.     else if (m_dragmode != wxDRAG_REDRAW)
  291.     {
  292.         wxClientDC dc(m_admin->GetActive());
  293.         wxMemoryDC tmp;
  294.  
  295.         wxTransformMatrix help;
  296.         wxRect recold=GetAbsoluteArea(help);
  297.  
  298.         //restore what was there (without the object itself)
  299.         wxMemoryDC dcm;
  300.         dcm.SelectObject(*m_admin->GetActive()->GetBuffer());
  301.         tmp.SelectObject(m_atnewpos);
  302.         dcm.Blit(recold.x,recold.y,recold.width,recold.height,&tmp,0,0,wxCOPY,FALSE);
  303.  
  304.         TransLate(x,y);
  305.  
  306.         wxRect recnew=GetAbsoluteArea(help);
  307.  
  308.         //save the contents of the buffer at the new position
  309.         tmp.Blit(0,0,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE);
  310.         tmp.SelectObject(wxNullBitmap);
  311.  
  312.         //m_atnewpos = m_admin->GetActive()->GetBuffer()->GetSubBitmap( recnew );
  313.  
  314.         this->SetVisible(TRUE);
  315.         //redraw object into the buffer
  316.         m_admin->GetActive()->SetDC(&dcm);
  317.         Render(&help,recnew.x,recnew.y,recnew.width,recnew.height);
  318.  
  319.         //draw the union or seperate to the canvas
  320.         double leftu,rightu,bottomu,topu ;
  321.         leftu   = wxMin (recold.x, recnew.x ) ;
  322.         rightu  = wxMax (recold.x + recold.width, recnew.x + recnew.width ) ;
  323.         topu    = wxMin (recold.y, recnew.y) ;
  324.         bottomu = wxMax (recold.y + recold.height, recnew.y + recnew.height) ;
  325.  
  326.         if ( rightu - leftu < 2*recold.width && bottomu - topu < 2*recold.height)
  327.         {
  328.             dc.Blit(leftu,topu,rightu - leftu,bottomu - topu,&dcm,leftu,topu,wxCOPY,FALSE);
  329.         }
  330.         else
  331.         {
  332.             //do them seperate
  333.             //first redraw what should be at the old position in the canvas
  334.             dc.Blit(recold.x,recold.y,recold.width,recold.height,&dcm,recold.x,recold.y,wxCOPY,FALSE);
  335.             //blit the new position of the object to the canvas
  336.             dc.Blit(recnew.x,recnew.y,recnew.width,recnew.height,&dcm,recnew.x,recnew.y,wxCOPY,FALSE);
  337.         }
  338.         dcm.SelectObject(wxNullBitmap);
  339.         this->SetVisible(FALSE);
  340.     }
  341.     else
  342.         MoveRelative(x,y);
  343. }
  344.  
  345.  
  346. void wxCanvasObject::DragEnd()
  347. {
  348.     m_atnewpos = wxBitmap(0,0);
  349.     m_admin->GetActive()->Thaw();
  350.     this->SetVisible(TRUE);
  351.     double x = GetXMin();
  352.     double y = GetYMin();
  353.     double w = m_bbox.GetWidth();
  354.     double h = m_bbox.GetHeight();
  355.     m_admin->Update( this, x, y, w, h );
  356.     m_admin->UpdateNow();
  357. }
  358.  
  359. wxCanvasObject* wxCanvasObject::IsHitWorld( double x, double y, double margin )
  360. {
  361.     if ((x >= m_bbox.GetMinX()-margin) &&
  362.         (x <= m_bbox.GetMaxX()+margin) &&
  363.         (y >= m_bbox.GetMinY()-margin) &&
  364.         (y <= m_bbox.GetMaxY()+margin))
  365.     {
  366.         return this;
  367.     }
  368.     
  369.     return (wxCanvasObject*) NULL;
  370. }
  371.  
  372. wxCanvasObject* wxCanvasObject::Contains( wxCanvasObject* obj )
  373. {
  374.     if (obj == this)
  375.         return this;
  376.         
  377.     return (wxCanvasObject*) NULL;
  378. }
  379.  
  380. void wxCanvasObject::CaptureMouse()
  381. {
  382.     m_admin->GetActive()->SetCaptureMouse( this );
  383. }
  384.  
  385. void wxCanvasObject::ReleaseMouse()
  386. {
  387.     m_admin->GetActive()->SetCaptureMouse( NULL );
  388. }
  389.  
  390. bool wxCanvasObject::IsCapturedMouse()
  391. {
  392.     return (m_admin->GetActive()->GetCaptured() == this);
  393. }
  394.  
  395.  
  396. void wxCanvasObject::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  397. {
  398. }
  399.  
  400. void wxCanvasObject::CalcBoundingBox()
  401. {
  402. }
  403.  
  404. void wxCanvasObject::WriteSVG( wxTextOutputStream &stream )
  405. {
  406. }
  407.  
  408. //----------------------------------------------------------------------------
  409. // wxCanvasObjectGroup
  410. //----------------------------------------------------------------------------
  411.  
  412. IMPLEMENT_CLASS(wxCanvasObjectGroup, wxCanvasObject)
  413.  
  414. wxCanvasObjectGroup::wxCanvasObjectGroup(double x, double y)
  415. {
  416.     lworld.Translate(x,y);
  417.     //no objects make the bounding box the x,y and take care of it later
  418.     m_bbox.Expand(x,y);
  419. }
  420.  
  421. wxCanvasObjectGroup::~wxCanvasObjectGroup()
  422. {
  423. }
  424.  
  425. void wxCanvasObjectGroup::PushEventHandler(wxEvtHandler *handler)
  426. {
  427.     wxCanvasObject::PushEventHandler(handler);
  428.     wxNode *node = m_objects.First();
  429.     while (node)
  430.     {
  431.         wxCanvasObject *obj = (wxCanvasObject*) node->Data();
  432.  
  433.         obj->PushEventHandler(handler);
  434.  
  435.         node = node->Next();
  436.     }
  437. }
  438.  
  439. wxEvtHandler *wxCanvasObjectGroup::PopEventHandler(bool deleteHandler)
  440. {
  441.     wxNode *node = m_objects.First();
  442.     while (node)
  443.     {
  444.         wxCanvasObject *obj = (wxCanvasObject*) node->Data();
  445.  
  446.         obj->PopEventHandler(deleteHandler);
  447.  
  448.         node = node->Next();
  449.     }
  450.     return wxCanvasObject::PopEventHandler(deleteHandler);
  451. }
  452.  
  453. void wxCanvasObjectGroup::AppendEventHandler(wxEvtHandler *handler)
  454. {
  455.     wxCanvasObject::AppendEventHandler(handler);
  456.     wxNode *node = m_objects.First();
  457.     while (node)
  458.     {
  459.         wxCanvasObject *obj = (wxCanvasObject*) node->Data();
  460.  
  461.         obj->AppendEventHandler(handler);
  462.  
  463.         node = node->Next();
  464.     }
  465. }
  466.  
  467. wxEvtHandler *wxCanvasObjectGroup::RemoveLastEventHandler(bool deleteHandler)
  468. {
  469.     wxNode *node = m_objects.First();
  470.     while (node)
  471.     {
  472.         wxCanvasObject *obj = (wxCanvasObject*) node->Data();
  473.  
  474.         obj->RemoveLastEventHandler(deleteHandler);
  475.  
  476.         node = node->Next();
  477.     }
  478.     return wxCanvasObject::RemoveLastEventHandler(deleteHandler);
  479. }
  480.  
  481. void wxCanvasObjectGroup::TransLate( double x, double y )
  482. {
  483.     lworld.Translate(x,y);
  484.     CalcBoundingBox();
  485. }
  486.  
  487. void wxCanvasObjectGroup::SetAdmin(wxCanvasAdmin* admin)
  488. {
  489.     m_admin=admin;
  490.     wxNode *node = m_objects.First();
  491.     while (node)
  492.     {
  493.         wxCanvasObject *obj = (wxCanvasObject*) node->Data();
  494.  
  495.         obj->SetAdmin(admin);
  496.  
  497.         node = node->Next();
  498.     }
  499. }
  500.  
  501. void wxCanvasObjectGroup::DeleteContents( bool flag)
  502. {
  503.     m_objects.DeleteContents( flag );
  504.     m_bbox.SetValid(FALSE);
  505.     CalcBoundingBox();
  506. }
  507.  
  508. void wxCanvasObjectGroup::Prepend( wxCanvasObject* obj )
  509. {
  510.     m_objects.Insert( obj );
  511.     if (m_objects.First())
  512.     {
  513.         m_bbox.Expand(obj->GetBbox());
  514.     }
  515.     else
  516.     {
  517.         m_bbox.SetValid(FALSE);
  518.         CalcBoundingBox();
  519.     }
  520. }
  521.  
  522. void wxCanvasObjectGroup::Append( wxCanvasObject* obj )
  523. {
  524.     m_objects.Append( obj );
  525.     if (m_objects.First())
  526.     {
  527.         m_bbox.Expand(obj->GetBbox());
  528.     }
  529.     else
  530.     {
  531.         m_bbox.SetValid(FALSE);
  532.         CalcBoundingBox();
  533.     }
  534. }
  535.  
  536. void wxCanvasObjectGroup::Insert( size_t before, wxCanvasObject* obj )
  537. {
  538.     m_objects.Insert( before, obj );
  539.     m_bbox.SetValid(FALSE);
  540.     if (m_objects.First())
  541.     {
  542.         m_bbox.Expand(obj->GetBbox());
  543.     }
  544.     else
  545.     {
  546.         m_bbox.SetValid(FALSE);
  547.         CalcBoundingBox();
  548.     }
  549. }
  550.  
  551. void wxCanvasObjectGroup::Remove( wxCanvasObject* obj )
  552. {
  553.     m_objects.DeleteObject( obj );
  554.     m_bbox.SetValid(FALSE);
  555.     CalcBoundingBox();
  556. }
  557.  
  558. void wxCanvasObjectGroup::CalcBoundingBox()
  559. {
  560.     m_bbox.SetValid(FALSE);
  561.     wxNode *node = m_objects.First();
  562.     while (node)
  563.     {
  564.         wxCanvasObject *obj = (wxCanvasObject*) node->Data();
  565.  
  566.  
  567.         obj->CalcBoundingBox();
  568.         wxBoundingBox tmp;
  569.         tmp=obj->GetBbox();
  570.         tmp.MapBbox(lworld);
  571.  
  572.         m_bbox.Expand( tmp );
  573.         node = node->Next();
  574.     }
  575. }
  576.  
  577. void wxCanvasObjectGroup::Render(wxTransformMatrix* cworld, int x, int y, int width, int height )
  578. {
  579.     if (!m_visible) return;
  580.  
  581.     wxTransformMatrix backup = *cworld;
  582.     *cworld *= lworld;
  583.  
  584.     wxNode *node = m_objects.First();
  585.  
  586.     if (!node) return;
  587.  
  588.  
  589. #ifdef CANVASDEBUG
  590.     wxRect absarea=GetAbsoluteArea(*cworld);
  591.     wxDC *dc = m_admin->GetActive()->GetDC();
  592.     dc->SetPen(*wxBLACK_PEN);
  593.     dc->SetBrush(*wxTRANSPARENT_BRUSH);
  594.     dc->DrawRectangle( absarea.x , absarea.y , absarea.width , absarea.height );
  595.     dc->SetBrush(wxNullBrush);
  596.     dc->SetPen(wxNullPen);
  597. #endif
  598.     //TODO the next will only work if all boundingboxes stay up to date (problem when mowing currently
  599.     /*
  600.     if (! ( wxMax(absarea.x, x) < wxMin(absarea.x + absarea.width , x + width ) &&
  601.             wxMax(absarea.y, y) < wxMin(absarea.y + absarea.height , y + height )
  602.           )
  603.        )
  604.         return;
  605.     */
  606.  
  607.     // cycle through all objects
  608.     while (node)
  609.     {
  610.         wxCanvasObject *obj = (wxCanvasObject*) node->Data();
  611.  
  612.         if (!obj->IsControl() && obj->GetVisible())
  613.         {
  614.  
  615.             //get area at the absolute position
  616.             wxRect absareaobject = obj->GetAbsoluteArea(*cworld);
  617.             
  618.             // If we have 10.000 objects, we will go through
  619.             // this 10.000 times for each update, so we have
  620.             // to optimise carefully.
  621.             int clip_x = absareaobject.x;
  622.             int clip_width = absareaobject.width;
  623.             if (clip_x < x)
  624.             {
  625.                 clip_width -= x-clip_x;
  626.                 clip_x = x;
  627.             }
  628.             if (clip_width > 0)
  629.             {
  630.                 if (clip_x + clip_width > x + width)
  631.                     clip_width = x+width-clip_x;
  632.  
  633.                 if (clip_width > 0)
  634.                 {
  635.                     int clip_y = absareaobject.y;
  636.                     int clip_height = absareaobject.height;
  637.                     if (clip_y < y)
  638.                     {
  639.                         clip_height -= y-clip_y;
  640.                         clip_y = y;
  641.                     }
  642.                     if (clip_height > 0)
  643.                     {
  644.                         if (clip_y + clip_height > y + height)
  645.                             clip_height = y+height-clip_y;
  646.  
  647.                         if (clip_height > 0)
  648.                         {
  649.                             obj->Render(cworld, clip_x, clip_y, clip_width, clip_height );
  650.                         }
  651.                     }
  652.                 }
  653.             }
  654.         }
  655.  
  656.         node = node->Next();
  657.     }
  658.     *cworld = backup;
  659. }
  660.  
  661. void wxCanvasObjectGroup::WriteSVG( wxTextOutputStream &stream )
  662. {
  663. }
  664.  
  665. wxCanvasObject* wxCanvasObjectGroup::IsHitWorld( double x, double y, double margin )
  666. {
  667.     //KKKfirst check if within bbox
  668.     //will only work if they are always uptodate
  669.     //if (!m_bbox.PointInBox(x,y,margin))
  670.     //    return (wxCanvasObject*) NULL;
  671.  
  672.     wxTransformMatrix inverse =  lworld;
  673.     double xh,yh;
  674.     inverse.Invert();
  675.     inverse.TransformPoint(x,y,xh,yh);
  676.  
  677.     wxCanvasObject *obj=0;
  678.     wxNode *node = m_objects.Last();
  679.     while (node)
  680.     {
  681.         obj=(wxCanvasObject*) node->Data();
  682.  
  683.         if (!obj->IsControl() )
  684.         {
  685.             if (obj->IsHitWorld(xh,yh,margin))
  686.             {
  687.                 return obj;
  688.             }
  689.         }
  690.         node = node->Previous();
  691.     }
  692.  
  693.     return (wxCanvasObject*) NULL;
  694. }
  695.  
  696. wxCanvasObject* wxCanvasObjectGroup::Contains( wxCanvasObject* obj )
  697. {
  698.     wxCanvasObject* cobj;
  699.     wxNode *node = m_objects.First();
  700.     while (node)
  701.     {
  702.         cobj=(wxCanvasObject*) node->Data();
  703.  
  704.         if (cobj->Contains(obj))
  705.         {
  706.             return obj;
  707.         }
  708.         node = node->Next();
  709.     }
  710.  
  711.     return (wxCanvasObject*) NULL;
  712. }
  713.  
  714. int wxCanvasObjectGroup::IndexOf( wxCanvasObject* obj )
  715. {
  716.     return m_objects.IndexOf( obj );
  717. }
  718.  
  719. //----------------------------------------------------------------------------
  720. // wxCanvasObjectRef
  721. //----------------------------------------------------------------------------
  722.  
  723. IMPLEMENT_CLASS(wxCanvasObjectRef, wxCanvasObject)
  724.  
  725. wxCanvasObjectRef::wxCanvasObjectRef(double x, double y, wxCanvasObject* obj)
  726.    : wxCanvasObject()
  727. {
  728.     lworld.Translate(x,y);
  729.     m_obj = obj;
  730.  
  731.     m_bbox.SetValid(FALSE);
  732.     wxBoundingBox tmp;
  733.     tmp=obj->GetBbox();
  734.     tmp.MapBbox(lworld);
  735.     m_bbox.Expand( tmp );
  736. }
  737.  
  738. void wxCanvasObjectRef::PushEventHandler(wxEvtHandler *handler)
  739. {
  740.     wxCanvasObject::PushEventHandler(handler);
  741.     m_obj->PushEventHandler(handler);
  742. }
  743.  
  744. wxEvtHandler *wxCanvasObjectRef::PopEventHandler(bool deleteHandler)
  745. {
  746.     m_obj->PopEventHandler(deleteHandler);
  747.     return wxCanvasObject::PopEventHandler(deleteHandler);
  748. }
  749.  
  750. void wxCanvasObjectRef::AppendEventHandler(wxEvtHandler *handler)
  751. {
  752.     wxCanvasObject::AppendEventHandler(handler);
  753.     m_obj->AppendEventHandler(handler);
  754. }
  755.  
  756. wxEvtHandler *wxCanvasObjectRef::RemoveLastEventHandler(bool deleteHandler)
  757. {
  758.     m_obj->RemoveLastEventHandler(deleteHandler);
  759.     return wxCanvasObject::RemoveLastEventHandler(deleteHandler);
  760. }
  761.  
  762. void wxCanvasObjectRef::TransLate( double x, double y )
  763. {
  764.     lworld.Translate(x,y);
  765.     CalcBoundingBox();
  766. }
  767.  
  768. wxCanvasObject* wxCanvasObjectRef::Contains( wxCanvasObject* obj )
  769. {
  770.     if (obj == this || m_obj->Contains(obj))
  771.         return this;
  772.  
  773.     return (wxCanvasObject*) NULL;
  774. }
  775.  
  776.  
  777. void wxCanvasObjectRef::SetRotation(double rotation)
  778. {
  779.     lworld.SetRotation(rotation);
  780.     CalcBoundingBox();
  781. }
  782.  
  783. void wxCanvasObjectRef::SetScale(double scalex,double scaley)
  784. {
  785.     lworld.Scale(scalex,scaley,lworld.GetValue(2,0),lworld.GetValue(2,1));
  786.     CalcBoundingBox();
  787. }
  788.  
  789. void wxCanvasObjectRef::SetAdmin(wxCanvasAdmin* admin)
  790. {
  791.     m_admin = admin;
  792.     m_obj->SetAdmin(admin);
  793. }
  794.  
  795. void wxCanvasObjectRef::CalcBoundingBox()
  796. {
  797.     m_bbox.SetValid(FALSE);
  798.     m_obj->CalcBoundingBox();
  799.  
  800.     wxBoundingBox tmp;
  801.     tmp=m_obj->GetBbox();
  802.     tmp.MapBbox(lworld);
  803.     m_bbox.Expand( tmp );
  804. }
  805.  
  806. void wxCanvasObjectRef::Render(wxTransformMatrix* cworld, int x, int y, int width, int height )
  807. {
  808.     if (!m_visible) return;
  809.  
  810.     //get the absolute area (without the local matrix included)
  811.     //the boundingbox is relative to the parent.
  812.     wxRect absarea=GetAbsoluteArea(*cworld);
  813.  
  814.     wxTransformMatrix backup = *cworld;
  815.     *cworld *= lworld;
  816.  
  817. #ifdef CANVASDEBUG
  818.     wxDC *dc = m_admin->GetActive()->GetDC();
  819.     dc->SetPen(*wxBLACK_PEN);
  820.     dc->SetBrush(*wxTRANSPARENT_BRUSH);
  821.     dc->DrawRectangle( absarea.x , absarea.y , absarea.width , absarea.height );
  822.     dc->SetBrush(wxNullBrush);
  823.     dc->SetPen(wxNullPen);
  824. #endif
  825.  
  826.     int clip_x = absarea.x;
  827.     int clip_width = absarea.width;
  828.     if (clip_x < x)
  829.     {
  830.         clip_width -= x-clip_x;
  831.         clip_x = x;
  832.     }
  833.     if (clip_width > 0)
  834.     {
  835.         if (clip_x + clip_width > x + width)
  836.             clip_width = x+width-clip_x;
  837.  
  838.         if (clip_width > 0)
  839.         {
  840.             int clip_y = absarea.y;
  841.             int clip_height = absarea.height;
  842.             if (clip_y < y)
  843.             {
  844.                 clip_height -= y-clip_y;
  845.                 clip_y = y;
  846.             }
  847.             if (clip_height > 0)
  848.             {
  849.                 if (clip_y + clip_height > y + height)
  850.                     clip_height = y+height-clip_y;
  851.  
  852.                 if (clip_height > 0)
  853.                     m_obj->Render(cworld, clip_x, clip_y, clip_width, clip_height );
  854.             }
  855.         }
  856.     }
  857.  
  858.     *cworld = backup;
  859. }
  860.  
  861. void wxCanvasObjectRef::WriteSVG( wxTextOutputStream &stream )
  862. {
  863. }
  864.  
  865. wxCanvasObject* wxCanvasObjectRef::IsHitWorld( double x, double y, double margin )
  866. {
  867.     //KKKfirst check if within bbox
  868.     //will only work if they are always uptodate
  869.     //if (!m_bbox.PointInBox(x,y,margin))
  870.     //    return (wxCanvasObject*) NULL;
  871.  
  872.     wxTransformMatrix inverse =  lworld;
  873.     double xh,yh;
  874.     inverse.Invert();
  875.     inverse.TransformPoint(x,y,xh,yh);
  876.  
  877.     if (m_obj->IsHitWorld(xh,yh,margin))
  878.         return this;
  879.  
  880.     return (wxCanvasObject*) NULL;
  881. }
  882.  
  883.  
  884.  
  885. //----------------------------------------------------------------------------
  886. // wxCanvasRect
  887. //----------------------------------------------------------------------------
  888.  
  889. IMPLEMENT_CLASS(wxCanvasRect, wxCanvasObject)
  890.  
  891. wxCanvasRect::wxCanvasRect( double x, double y, double w, double h , double radius )
  892.    : wxCanvasObject()
  893. {
  894.     m_x = x;
  895.     m_y = y;
  896.     m_width = w;
  897.     m_height = h;
  898.     m_radius = radius;
  899.  
  900.     m_brush = *wxBLACK_BRUSH;
  901.     m_pen = *wxTRANSPARENT_PEN;
  902.     CalcBoundingBox();
  903. }
  904.  
  905. void wxCanvasRect::TransLate( double x, double y )
  906. {
  907.     m_x += x;
  908.     m_y += y;
  909.     CalcBoundingBox();
  910. }
  911.  
  912. void wxCanvasRect::CalcBoundingBox()
  913. {
  914.     m_bbox.SetMin( m_x , m_y);
  915.     m_bbox.SetMax( m_x + m_width ,m_y + m_height );
  916.  
  917.     //include the pen width also
  918. //KKK    m_bbox.EnLarge(m_pen.GetWidth()+m_radius);
  919.     m_bbox.EnLarge(m_pen.GetWidth()/2);
  920. }
  921.  
  922. void wxCanvasRect::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  923. {
  924.     if (!m_visible) return;
  925.  
  926.     if (cworld->GetRotation())
  927.     {
  928.         wxPoint *cpoints = new wxPoint[4];
  929.         double x;
  930.         double y;
  931.         cworld->TransformPoint( m_x, m_y, x, y );
  932.         cpoints[0].x = m_admin->LogicalToDeviceX(x);
  933.         cpoints[0].y = m_admin->LogicalToDeviceY(y);
  934.         cworld->TransformPoint( m_x , m_y + m_height, x, y );
  935.         cpoints[1].x = m_admin->LogicalToDeviceX(x);
  936.         cpoints[1].y = m_admin->LogicalToDeviceY(y);
  937.         cworld->TransformPoint( m_x + m_width, m_y + m_height, x, y );
  938.         cpoints[2].x = m_admin->LogicalToDeviceX(x);
  939.         cpoints[2].y = m_admin->LogicalToDeviceY(y);
  940.         cworld->TransformPoint( m_x + m_width, m_y , x, y );
  941.         cpoints[3].x = m_admin->LogicalToDeviceX(x);
  942.         cpoints[3].y = m_admin->LogicalToDeviceY(y);
  943.  
  944.         wxDC *dc = m_admin->GetActive()->GetDC();
  945.         dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
  946.         dc->SetBrush(m_brush);
  947.         int pw=m_pen.GetWidth();
  948.         m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
  949.         dc->SetPen(m_pen);
  950.         dc->DrawPolygon(4, cpoints, 0,0,wxWINDING_RULE);
  951.         delete [] cpoints;
  952.         dc->SetBrush(wxNullBrush);
  953.         dc->SetPen(wxNullPen);
  954.         dc->DestroyClippingRegion();
  955.         m_pen.SetWidth(pw);
  956.     }
  957.     else
  958.     {
  959.         wxDC *dc = m_admin->GetActive()->GetDC();
  960.         dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
  961.         dc->SetBrush(m_brush);
  962.         int pw=m_pen.GetWidth();
  963.         m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
  964.         dc->SetPen(m_pen);
  965.         //yes the whole not only the clipping region, because we have a pen also
  966.         int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
  967.         int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
  968.         int w = m_admin->LogicalToDeviceXRel( m_width );
  969.         int h = m_admin->LogicalToDeviceYRel( m_height );
  970.         int r = m_admin->LogicalToDeviceYRel( m_radius );
  971.         if (w > 0 && w < 1) w=1;
  972.         if (w < 0 && w > -1) w=-1;
  973.         if (h > 0 && h < 1) h=1;
  974.         if (h < 0 && h > -1) h=-1;
  975.         if (m_radius)
  976.             dc->DrawRoundedRectangle( x,y,w,h,r);
  977.         else
  978.             dc->DrawRectangle( x,y,w,h);
  979.         dc->SetBrush(wxNullBrush);
  980.         dc->SetPen(wxNullPen);
  981.         dc->DestroyClippingRegion();
  982.         m_pen.SetWidth(pw);
  983.     }
  984. }
  985.  
  986. void wxCanvasRect::WriteSVG( wxTextOutputStream &stream )
  987. {
  988. }
  989.  
  990. //----------------------------------------------------------------------------
  991. // wxCanvasCircle
  992. //----------------------------------------------------------------------------
  993.  
  994. wxCanvasCircle::wxCanvasCircle( double x, double y, double radius )
  995.    : wxCanvasObject()
  996. {
  997.     m_x = x;
  998.     m_y = y;
  999.     m_radius = radius;
  1000.  
  1001.     m_brush = *wxBLACK_BRUSH;
  1002.     m_pen = *wxTRANSPARENT_PEN;
  1003.     CalcBoundingBox();
  1004. }
  1005.  
  1006. void wxCanvasCircle::TransLate( double x, double y )
  1007. {
  1008.     m_x += x;
  1009.     m_y += y;
  1010.     CalcBoundingBox();
  1011. }
  1012.  
  1013. void wxCanvasCircle::CalcBoundingBox()
  1014. {
  1015.     m_bbox.SetMin( m_x-m_radius , m_y-m_radius );
  1016.     m_bbox.SetMax( m_x+m_radius , m_y+m_radius );
  1017.  
  1018.     //include the pen width also
  1019.     m_bbox.EnLarge(m_pen.GetWidth()/2);
  1020. }
  1021.  
  1022. void wxCanvasCircle::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  1023. {
  1024.     if (!m_visible) return;
  1025.  
  1026.     wxDC *dc = m_admin->GetActive()->GetDC();
  1027.     dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
  1028.     dc->SetBrush(m_brush);
  1029.     int pw=m_pen.GetWidth();
  1030.     m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
  1031.     dc->SetPen(m_pen);
  1032.     //yes the whole not only the clipping region, because we have a pen also
  1033.     //and rotation on a circle is not important so only a shift with cworld
  1034.     int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
  1035.     int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
  1036.     int radius = m_admin->LogicalToDeviceXRel( m_radius );
  1037.     if (radius < 1) radius=1;
  1038.     dc->DrawCircle( x,y,radius);
  1039.     dc->SetBrush(wxNullBrush);
  1040.     dc->SetPen(wxNullPen);
  1041.     dc->DestroyClippingRegion();
  1042.     m_pen.SetWidth(pw);
  1043. }
  1044.  
  1045. void wxCanvasCircle::WriteSVG( wxTextOutputStream &stream )
  1046. {
  1047. }
  1048.  
  1049. wxCanvasObject* wxCanvasCircle::IsHitWorld( double x, double y, double margin )
  1050. {
  1051.     if ((x >= m_bbox.GetMinX()-margin) &&
  1052.         (x <= m_bbox.GetMaxX()+margin) &&
  1053.         (y >= m_bbox.GetMinY()-margin) &&
  1054.         (y <= m_bbox.GetMaxY()+margin)
  1055.        )
  1056.     {
  1057.         if (m_radius+m_pen.GetWidth()/2+margin > sqrt(pow(m_x-x,2)+pow(m_y-y,2)))
  1058.             return this;
  1059.         else
  1060.             return (wxCanvasObject*) NULL;
  1061.     }
  1062.     return (wxCanvasObject*) NULL;
  1063. }
  1064.  
  1065. //----------------------------------------------------------------------------
  1066. // wxCanvasEllipse
  1067. //----------------------------------------------------------------------------
  1068.  
  1069. wxCanvasEllipse::wxCanvasEllipse( double x, double y, double width, double height )
  1070.    : wxCanvasObject()
  1071. {
  1072.     m_x = x;
  1073.     m_y = y;
  1074.     m_width = width;
  1075.     m_height = height;
  1076.  
  1077.     m_brush = *wxBLACK_BRUSH;
  1078.     m_pen = *wxTRANSPARENT_PEN;
  1079.     CalcBoundingBox();
  1080. }
  1081.  
  1082. void wxCanvasEllipse::TransLate( double x, double y )
  1083. {
  1084.     m_x += x;
  1085.     m_y += y;
  1086.     CalcBoundingBox();
  1087. }
  1088.  
  1089. void wxCanvasEllipse::CalcBoundingBox()
  1090. {
  1091.     m_bbox.SetMin( m_x, m_y );
  1092.     m_bbox.SetMax( m_x+m_width , m_y+m_height );
  1093.  
  1094.     //include the pen width also
  1095.     m_bbox.EnLarge(m_pen.GetWidth()/2);
  1096. }
  1097.  
  1098. void wxCanvasEllipse::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  1099. {
  1100.     if (!m_visible) return;
  1101.  
  1102.     wxDC *dc = m_admin->GetActive()->GetDC();
  1103.     dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
  1104.     dc->SetBrush(m_brush);
  1105.     int pw=m_pen.GetWidth();
  1106.     m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
  1107.     dc->SetPen(m_pen);
  1108.     int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
  1109.     int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
  1110.     int w = m_admin->LogicalToDeviceXRel( m_width );
  1111.     int h = m_admin->LogicalToDeviceYRel( m_height );
  1112.     if (w > 0 && w < 1) w=1;
  1113.     if (w < 0 && w > -1) w=-1;
  1114.     if (h > 0 && h < 1) h=1;
  1115.     if (h < 0 && h > -1) h=-1;
  1116.     dc->DrawEllipse( x,y,w,h);
  1117.     dc->SetBrush(wxNullBrush);
  1118.     dc->SetPen(wxNullPen);
  1119.     dc->DestroyClippingRegion();
  1120.     m_pen.SetWidth(pw);
  1121. }
  1122.  
  1123. void wxCanvasEllipse::WriteSVG( wxTextOutputStream &stream )
  1124. {
  1125. }
  1126.  
  1127. wxCanvasObject* wxCanvasEllipse::IsHitWorld( double x, double y, double margin )
  1128. {
  1129.     if ((x >= m_bbox.GetMinX()-margin) &&
  1130.         (x <= m_bbox.GetMaxX()+margin) &&
  1131.         (y >= m_bbox.GetMinY()-margin) &&
  1132.         (y <= m_bbox.GetMaxY()+margin)
  1133.        )
  1134.     {
  1135.         double a=(m_width+m_pen.GetWidth())/2+margin ;
  1136.         double b=(m_height+m_pen.GetWidth())/2+margin;
  1137.         double c=pow((m_x+m_width/2-x)/a,2)+pow((m_y+m_height/2-y)/b,2);
  1138.         if ( 1 > c)
  1139.             return this;
  1140.         else
  1141.             return (wxCanvasObject*) NULL;
  1142.     }
  1143.     return (wxCanvasObject*) NULL;
  1144. }
  1145.  
  1146. //----------------------------------------------------------------------------
  1147. // wxCanvasEllipticArc
  1148. //----------------------------------------------------------------------------
  1149.  
  1150. wxCanvasEllipticArc::wxCanvasEllipticArc( double x, double y, double width, double height, double start, double end )
  1151.    : wxCanvasObject()
  1152. {
  1153.     m_x = x;
  1154.     m_y = y;
  1155.     m_width  = width;
  1156.     m_height = height;
  1157.     m_start  = start;
  1158.     m_end    = end;
  1159.  
  1160.     m_brush = *wxBLACK_BRUSH;
  1161.     m_pen = *wxTRANSPARENT_PEN;
  1162.     CalcBoundingBox();
  1163. }
  1164.  
  1165. void wxCanvasEllipticArc::TransLate( double x, double y )
  1166. {
  1167.     m_x += x;
  1168.     m_y += y;
  1169.     CalcBoundingBox();
  1170. }
  1171.  
  1172. void wxCanvasEllipticArc::CalcBoundingBox()
  1173. {
  1174.     m_bbox.SetMin( m_x, m_y );
  1175.     m_bbox.SetMax( m_x+m_width , m_y+m_height );
  1176.  
  1177.     //include the pen width also
  1178.     m_bbox.EnLarge(m_pen.GetWidth()/2);
  1179. }
  1180.  
  1181. void wxCanvasEllipticArc::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  1182. {
  1183.     if (!m_visible) return;
  1184.  
  1185.     wxDC *dc = m_admin->GetActive()->GetDC();
  1186.     dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
  1187.     dc->SetBrush(m_brush);
  1188.     int pw=m_pen.GetWidth();
  1189.     m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
  1190.     dc->SetPen(m_pen);
  1191.     int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
  1192.     int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
  1193.     int w = m_admin->LogicalToDeviceXRel( m_width );
  1194.     int h = m_admin->LogicalToDeviceYRel( m_height );
  1195.     if (w > 0 && w < 1) w=1;
  1196.     if (w < 0 && w > -1) w=-1;
  1197.     if (h > 0 && h < 1) h=1;
  1198.     if (h < 0 && h > -1) h=-1;
  1199.     if (m_admin->GetActive()->GetYaxis())
  1200.         dc->DrawEllipticArc( x,y,w,h,-m_end,-m_start);
  1201.     else
  1202.         dc->DrawEllipticArc( x,y,w,h,m_start,m_end);
  1203.     dc->SetBrush(wxNullBrush);
  1204.     dc->SetPen(wxNullPen);
  1205.     dc->DestroyClippingRegion();
  1206.     m_pen.SetWidth(pw);
  1207. }
  1208.  
  1209. void wxCanvasEllipticArc::WriteSVG( wxTextOutputStream &stream )
  1210. {
  1211. }
  1212.  
  1213. wxCanvasObject* wxCanvasEllipticArc::IsHitWorld( double x, double y, double margin )
  1214. {
  1215.     if ((x >= m_bbox.GetMinX()-margin) &&
  1216.         (x <= m_bbox.GetMaxX()+margin) &&
  1217.         (y >= m_bbox.GetMinY()-margin) &&
  1218.         (y <= m_bbox.GetMaxY()+margin)
  1219.        )
  1220.     {
  1221.         double a=(m_width+m_pen.GetWidth())/2+margin ;
  1222.         double b=(m_height+m_pen.GetWidth())/2+margin;
  1223.         double c=pow((m_x+m_width/2-x)/a,2)+pow((m_y+m_height/2-y)/b,2);
  1224.         if ( 1 > c)
  1225.             return this;
  1226.         else
  1227.             return (wxCanvasObject*) NULL;
  1228.     }
  1229.     return (wxCanvasObject*) NULL;
  1230. }
  1231.  
  1232. //----------------------------------------------------------------------------
  1233. // wxCanvasLine
  1234. //----------------------------------------------------------------------------
  1235.  
  1236. wxCanvasLine::wxCanvasLine( double x1, double y1, double x2, double y2 )
  1237.    : wxCanvasObject()
  1238. {
  1239.     m_x1 = x1;
  1240.     m_y1 = y1;
  1241.     m_x2 = x2;
  1242.     m_y2 = y2;
  1243.  
  1244.     m_pen = *wxBLACK_PEN;
  1245.     CalcBoundingBox();
  1246. }
  1247.  
  1248. void wxCanvasLine::TransLate( double x, double y )
  1249. {
  1250.     m_x1 += x;
  1251.     m_y1 += y;
  1252.     m_x2 += x;
  1253.     m_y2 += y;
  1254.     CalcBoundingBox();
  1255. }
  1256.  
  1257. void wxCanvasLine::CalcBoundingBox()
  1258. {
  1259.     m_bbox.SetMin( m_x1 , m_y1);
  1260.     m_bbox.SetMax( m_x2 , m_y2);
  1261.  
  1262.     //include the pen width also
  1263.     m_bbox.EnLarge(m_pen.GetWidth()/2);
  1264. }
  1265.  
  1266. void wxCanvasLine::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  1267. {
  1268.     if (!m_visible) return;
  1269.  
  1270.     double x1,y1,x2,y2;
  1271.     cworld->TransformPoint( m_x1, m_y1, x1, y1 );
  1272.     cworld->TransformPoint( m_x2, m_y2, x2, y2 );
  1273.     x1 = m_admin->LogicalToDeviceX( x1 );
  1274.     y1 = m_admin->LogicalToDeviceY( y1 );
  1275.     x2 = m_admin->LogicalToDeviceX( x2 );
  1276.     y2 = m_admin->LogicalToDeviceY( y2 );
  1277.  
  1278.     wxDC *dc = m_admin->GetActive()->GetDC();
  1279.     dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
  1280.     int pw=m_pen.GetWidth();
  1281.     m_pen.SetWidth(m_admin->LogicalToDeviceXRel(pw));
  1282.     dc->SetPen( m_pen );
  1283.     dc->DrawLine( x1, y1, x2, y2 );
  1284.  
  1285.     dc->DestroyClippingRegion();
  1286.     m_pen.SetWidth(pw);
  1287. }
  1288.  
  1289. void wxCanvasLine::WriteSVG( wxTextOutputStream &stream )
  1290. {
  1291.     // no idea
  1292. }
  1293.  
  1294. wxCanvasObject* wxCanvasLine::IsHitWorld( double x, double y, double margin )
  1295. {
  1296.     if ((x >= m_bbox.GetMinX()-margin) &&
  1297.         (x <= m_bbox.GetMaxX()+margin) &&
  1298.         (y >= m_bbox.GetMinY()-margin) &&
  1299.         (y <= m_bbox.GetMaxY()+margin)
  1300.        )
  1301.     {
  1302.         wxLine line1(m_x1,m_y1,m_x2,m_y2);
  1303.         wxPoint2DDouble P=wxPoint2DDouble(x,y);
  1304.         double distance;
  1305.         if (line1.PointInLine(P,distance,m_pen.GetWidth()/2+margin) == R_IN_AREA)
  1306.             return this;
  1307.         else
  1308.             return (wxCanvasObject*) NULL;
  1309.     }
  1310.     return (wxCanvasObject*) NULL;
  1311. }
  1312.  
  1313. //----------------------------------------------------------------------------
  1314. // wxCanvasImage
  1315. //----------------------------------------------------------------------------
  1316.  
  1317. wxCanvasImage::wxCanvasImage( const wxImage &image, double x, double y, double w, double h )
  1318.    : wxCanvasObject()
  1319. {
  1320.     m_x = x;
  1321.     m_y = y;
  1322.     m_width = w;
  1323.     m_height = h;
  1324.  
  1325.     m_image = image;
  1326.  
  1327.     m_orgw = m_image.GetWidth();
  1328.     m_orgh = m_image.GetHeight();
  1329.  
  1330.     m_isImage = TRUE;
  1331.     CalcBoundingBox();
  1332. }
  1333.  
  1334. void wxCanvasImage::SetPosXY( double x, double y)
  1335. {
  1336.     m_x = x;
  1337.     m_y = y;
  1338.     CalcBoundingBox();
  1339. }
  1340.  
  1341. void wxCanvasImage::TransLate( double x, double y )
  1342. {
  1343.     m_x += x;
  1344.     m_y += y;
  1345.     CalcBoundingBox();
  1346. }
  1347.  
  1348. void wxCanvasImage::CalcBoundingBox()
  1349. {
  1350.     m_bbox.SetMin( m_x, m_y );
  1351.     m_bbox.SetMax( m_x + m_width, m_y + m_height );
  1352. }
  1353.  
  1354. void wxCanvasImage::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  1355. {
  1356.     if (!m_visible) return;
  1357.     
  1358.     wxRect tmparea;
  1359.  
  1360.     tmparea.x = m_admin->LogicalToDeviceXRel( m_bbox.GetMinX());
  1361.     tmparea.y = m_admin->LogicalToDeviceYRel( m_bbox.GetMinY());
  1362.     tmparea.width = m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() );
  1363.     tmparea.height = m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() );
  1364.  
  1365.     double x;
  1366.     double y;
  1367.     cworld->TransformPoint( m_x, m_y, x, y );
  1368.     x = m_admin->LogicalToDeviceX(x);
  1369.     y = m_admin->LogicalToDeviceY(y);
  1370.  
  1371.  
  1372.     // What is this???
  1373.     if (  m_orgw*5 < m_admin->LogicalToDeviceXRel( m_bbox.GetWidth()  ) ||
  1374.           m_orgw/5 > m_admin->LogicalToDeviceXRel( m_bbox.GetWidth()  ) ||
  1375.           m_orgh*5 < m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) ||
  1376.           m_orgh/5 > m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() )
  1377.        )
  1378.     {
  1379.         wxDC *dc = m_admin->GetActive()->GetDC();
  1380.         dc->SetClippingRegion(clip_x, clip_y, clip_width, clip_height);
  1381.         dc->SetBrush(*wxTRANSPARENT_BRUSH);
  1382.         dc->SetPen(*wxBLACK_PEN);
  1383.         //yes the whole not only the clipping region, because we have a pen also
  1384.         int x = m_admin->LogicalToDeviceX(cworld->GetValue(2,0) + m_x );
  1385.         int y = m_admin->LogicalToDeviceY(cworld->GetValue(2,1) + m_y );
  1386.         int w = m_admin->LogicalToDeviceXRel( m_width );
  1387.         int h = m_admin->LogicalToDeviceYRel( m_height );
  1388.         if (w < 1) w=1;
  1389.         if (h < 1) h=1;
  1390.         dc->DrawRectangle( x,y,w,h);
  1391.         dc->SetBrush(wxNullBrush);
  1392.         dc->SetPen(wxNullPen);
  1393.         dc->DestroyClippingRegion();
  1394.         return;
  1395.     }
  1396.     
  1397.     wxImage tmp;
  1398.     bool is_cashed = FALSE;
  1399.  
  1400.     if (m_cImage.Ok() && (m_cW == m_bbox.GetWidth()) && (m_cH == m_bbox.GetHeight()))
  1401.     {
  1402.         // use cached image
  1403.         tmp = m_cImage;
  1404.         is_cashed = TRUE;
  1405.     }
  1406.     else
  1407.     {
  1408.         if ((m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() ) == m_image.GetWidth()) &&
  1409.             (m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() ) == m_image.GetHeight()))
  1410.         {
  1411.             tmp = m_image;
  1412.         }
  1413.         else
  1414.         {
  1415.             tmp = m_image.Scale( m_admin->LogicalToDeviceXRel( m_bbox.GetWidth()),
  1416.                                  m_admin->LogicalToDeviceYRel( m_bbox.GetHeight()) );
  1417.         }
  1418.         
  1419.         // create cached image
  1420.         m_cImage = tmp;
  1421.         m_cW = tmp.GetWidth();
  1422.         m_cH = tmp.GetHeight();
  1423.     }
  1424.  
  1425. //    wxPoint centr(m_admin->LogicalToDeviceX(m_x),m_admin->LogicalToDeviceY(m_y));
  1426.     wxPoint centr(0,0);
  1427.  
  1428.     wxBitmap bmp;
  1429.     
  1430.     if (m_cBitmap.Ok() && is_cashed && (m_cR == cworld->GetRotation()))
  1431.     {
  1432.         bmp = m_cBitmap;
  1433.     }
  1434.     else
  1435.     {
  1436.         if (cworld->GetRotation())
  1437.             tmp = tmp.Rotate(-cworld->GetRotation()/180.0 * pi, centr, TRUE, NULL );
  1438.             
  1439.         bmp = wxBitmap(tmp);
  1440.         
  1441.         // create cached bitmap
  1442.         m_cBitmap = bmp;
  1443.         m_cR = cworld->GetRotation();
  1444.     }
  1445.  
  1446.     wxDC *dc = m_admin->GetActive()->GetDC();
  1447.  
  1448.     wxPoint centr2;
  1449.     if (cworld->GetRotation()> 0)
  1450.     {
  1451.         centr2.x= (int) (x+m_height*sin(-cworld->GetRotation()/180.0 * pi));
  1452.         centr2.y= (int) y;
  1453.     }
  1454.     else
  1455.     {
  1456.         centr2.x= (int) x;
  1457.         centr2.y= (int) (y-m_width*sin(-cworld->GetRotation()/180.0 * pi));
  1458.     }
  1459.  
  1460.     if (cworld->GetRotation() != 0)
  1461.     {
  1462.         //TODO clipping not right
  1463.             dc->DrawBitmap(bmp,centr2,TRUE );
  1464. //        dc->DrawPoint(centr2);
  1465. //        dc->DrawPoint(x,y);
  1466.     }
  1467.     else
  1468.     {
  1469.         dc->SetClippingRegion( clip_x, clip_y, clip_width, clip_height );
  1470.         dc->DrawBitmap( bmp, x, y, TRUE );
  1471.         dc->DestroyClippingRegion();
  1472.     }
  1473. }
  1474.  
  1475. void wxCanvasImage::WriteSVG( wxTextOutputStream &stream )
  1476. {
  1477.     // no idea
  1478. }
  1479.  
  1480. //----------------------------------------------------------------------------
  1481. // wxCanvasCtrl
  1482. //----------------------------------------------------------------------------
  1483.  
  1484. wxCanvasControl::wxCanvasControl( wxWindow *control )
  1485.    : wxCanvasObject()
  1486. {
  1487.     m_isControl = TRUE;
  1488.     m_control = control;
  1489.     CalcBoundingBox();
  1490. }
  1491.  
  1492. double wxCanvasControl::GetPosX()
  1493. {
  1494.     int x,y ;
  1495.     m_control->GetPosition( &x, &y );
  1496.     return m_admin->DeviceToLogicalX(x);
  1497. }
  1498.  
  1499. double wxCanvasControl::GetPosY()
  1500. {
  1501.     int x,y ;
  1502.     m_control->GetPosition( &x, &y );
  1503.     return m_admin->DeviceToLogicalY(y);
  1504. }
  1505.  
  1506. void wxCanvasControl::SetPosXY( double x, double y)
  1507. {
  1508.     int xd = m_admin->LogicalToDeviceX(x);
  1509.     int yd = m_admin->LogicalToDeviceY(y);
  1510.     m_control->Move(xd,yd);
  1511. }
  1512.  
  1513.  
  1514. void wxCanvasControl::TransLate( double x, double y )
  1515. {
  1516.     int xdo,ydo;
  1517.     m_control->GetPosition( &xdo, &ydo );
  1518.     int xd = m_admin->LogicalToDeviceX(x)-xdo;
  1519.     int yd = m_admin->LogicalToDeviceY(y)-ydo;
  1520.     m_control->Move(xd,yd);
  1521.     CalcBoundingBox();
  1522. }
  1523.  
  1524. wxCanvasControl::~wxCanvasControl()
  1525. {
  1526.     m_control->Destroy();
  1527. }
  1528.  
  1529. void wxCanvasControl::CalcBoundingBox()
  1530. {
  1531.     wxRect tmparea;
  1532.  
  1533.     m_control->GetSize( &tmparea.width, &tmparea.height );
  1534.     m_control->GetPosition( &tmparea.x, &tmparea.y );
  1535.  
  1536.     m_bbox.SetMin( tmparea.x , tmparea.y);
  1537.     m_bbox.SetMax( tmparea.x + tmparea.width , tmparea.y + tmparea.height);
  1538.  
  1539. }
  1540.  
  1541. void wxCanvasControl::MoveRelative( double x, double y )
  1542. {
  1543.     m_control->Move( m_admin->LogicalToDeviceX(x),  m_admin->LogicalToDeviceX(y) );
  1544. }
  1545.  
  1546. //----------------------------------------------------------------------------
  1547. // wxCanvasText
  1548. //----------------------------------------------------------------------------
  1549.  
  1550. class wxFaceData
  1551. {
  1552. public:
  1553. #if wxUSE_FREETYPE
  1554.      FT_Face   m_face;
  1555. #else
  1556.      void     *m_dummy;
  1557. #endif
  1558. };
  1559.  
  1560. wxCanvasText::wxCanvasText( const wxString &text, double x, double y, const wxString &fontFile, int size )
  1561.    : wxCanvasObject()
  1562. {
  1563.     m_text = text;
  1564.     m_fontFileName = fontFile;
  1565.     m_size = size;
  1566.  
  1567.     m_red = 0;
  1568.     m_green = 0;
  1569.     m_blue = 0;
  1570.  
  1571.     m_alpha = NULL;
  1572.  
  1573.     m_x = x;
  1574.     m_y = y;
  1575.  
  1576. #if wxUSE_FREETYPE
  1577.     wxFaceData *data = new wxFaceData;
  1578.     m_faceData = data;
  1579.  
  1580.     int error = FT_New_Face( g_freetypeLibrary,
  1581.                              m_fontFileName,
  1582.                              0,
  1583.                              &(data->m_face) );
  1584.  
  1585.     error = FT_Set_Char_Size( data->m_face,
  1586.                               0,
  1587.                               m_size*64,
  1588.                               96,    // screen dpi
  1589.                               96 );
  1590. #endif
  1591.     CalcBoundingBox();
  1592. }
  1593.  
  1594. wxCanvasText::~wxCanvasText()
  1595. {
  1596. #if wxUSE_FREETYPE
  1597.     wxFaceData *data = (wxFaceData*) m_faceData;
  1598.     delete data;
  1599. #endif
  1600.  
  1601.     if (m_alpha) delete [] m_alpha;
  1602. }
  1603.  
  1604. void wxCanvasText::SetRGB( unsigned char red, unsigned char green, unsigned char blue )
  1605. {
  1606.     m_red = red;
  1607.     m_green = green;
  1608.     m_blue = blue;
  1609. }
  1610.  
  1611. void wxCanvasText::SetFlag( int flag )
  1612. {
  1613.     m_flag = flag;
  1614. }
  1615.  
  1616. void wxCanvasText::Render(wxTransformMatrix* cworld, int clip_x, int clip_y, int clip_width, int clip_height )
  1617. {
  1618.     if (!m_visible) return;
  1619.  
  1620.     wxRect tmparea;
  1621.     tmparea.x = m_admin->LogicalToDeviceX( m_bbox.GetMinX());
  1622.     tmparea.y = m_admin->LogicalToDeviceY( m_bbox.GetMinY());
  1623.     tmparea.width = m_admin->LogicalToDeviceXRel( m_bbox.GetWidth() );
  1624.     tmparea.height = m_admin->LogicalToDeviceYRel( m_bbox.GetHeight() );
  1625.  
  1626.     m_alpha = new unsigned char[tmparea.width*tmparea.height];
  1627.     memset( m_alpha, 0, tmparea.width*tmparea.height );
  1628.  
  1629.     if (!m_alpha) return;
  1630.  
  1631. #if wxUSE_FREETYPE
  1632.     FT_Face face = ((wxFaceData*)m_faceData)->m_face;
  1633.     FT_GlyphSlot slot = face->glyph;
  1634.     int pen_x = 0;
  1635.     int pen_y = m_size;
  1636.  
  1637.     for (int n = 0; n < (int)m_text.Len(); n++)
  1638.     {
  1639.         FT_UInt index = FT_Get_Char_Index( face, m_text[(unsigned int)n] );
  1640.  
  1641.         int error = FT_Load_Glyph( face, index, FT_LOAD_DEFAULT );
  1642.         if (error) continue;
  1643.  
  1644.         error = FT_Render_Glyph( face->glyph, ft_render_mode_normal );
  1645.         if (error) continue;
  1646.  
  1647.         FT_Bitmap *bitmap = &slot->bitmap;
  1648.         unsigned char* buffer = bitmap->buffer;
  1649.         for (int y = 0; y < bitmap->rows; y++)
  1650.             for (int x = 0; x < bitmap->width; x++)
  1651.             {
  1652.                 unsigned char alpha = buffer[ y*bitmap->pitch + x ];
  1653.                 if (alpha == 0) continue;
  1654.  
  1655.                 int xx = pen_x + slot->bitmap_left + x;
  1656.                 int yy = pen_y - slot->bitmap_top + y;
  1657.                 m_alpha[ yy * tmparea.width + xx ] = alpha;
  1658.             }
  1659.  
  1660.         pen_x += slot->advance.x >> 6;
  1661.         pen_y += slot->advance.y >> 6;
  1662.     }
  1663. #endif
  1664.  
  1665.     wxBitmap *bitmap = m_admin->GetActive()->GetBuffer();
  1666.     wxRect sub_rect( clip_x, clip_y, clip_width, clip_height );
  1667.     wxBitmap sub_bitmap( bitmap->GetSubBitmap( sub_rect ) );
  1668.  
  1669.     wxImage image( sub_bitmap.ConvertToImage() );
  1670.  
  1671.     // local coordinates
  1672.     int start_x = clip_x - tmparea.x;
  1673.     int end_x = clip_width + start_x;
  1674.     int start_y = clip_y - tmparea.y;
  1675.     int end_y = clip_height + start_y;
  1676.  
  1677.     for (int y = start_y; y < end_y; y++)
  1678.         for (int x = start_x; x < end_x; x++)
  1679.         {
  1680.             int alpha = m_alpha[y*tmparea.width + x];
  1681.             if (alpha)
  1682.             {
  1683.                 int image_x = x - start_x;
  1684.                 int image_y = y - start_y;
  1685.                 if (alpha == 255)
  1686.                 {
  1687.                     image.SetRGB( image_x, image_y, m_red, m_green, m_blue );
  1688.                     continue;
  1689.                 }
  1690.                 int red1 = (m_red * alpha) / 255;
  1691.                 int green1 = (m_green * alpha) / 255;
  1692.                 int blue1 = (m_blue * alpha) / 255;
  1693.  
  1694.                 alpha = 255-alpha;
  1695.                 int red2 = image.GetRed( image_x, image_y );
  1696.                 int green2 = image.GetGreen( image_x, image_y );
  1697.                 int blue2 = image.GetBlue( image_x, image_y );
  1698.                 red2 = (red2 * alpha) / 255;
  1699.                 green2 = (green2 * alpha) / 255;
  1700.                 blue2 = (blue2 * alpha) / 255;
  1701.  
  1702.                 image.SetRGB( image_x, image_y, red1+red2, green1+green2, blue1+blue2 );
  1703.             }
  1704.         }
  1705.  
  1706.    sub_bitmap = wxBitmap(image);
  1707.  
  1708.    wxDC *dc = m_admin->GetActive()->GetDC();
  1709.    dc->DrawBitmap( sub_bitmap, clip_x, clip_y );
  1710. }
  1711.  
  1712. void wxCanvasText::WriteSVG( wxTextOutputStream &stream )
  1713. {
  1714. }
  1715.  
  1716. void wxCanvasText::TransLate( double x, double y )
  1717. {
  1718.     m_x += x;
  1719.     m_y += y;
  1720.     CalcBoundingBox();
  1721. }
  1722.  
  1723. void wxCanvasText::CalcBoundingBox()
  1724. {
  1725.     if (m_alpha) delete [] m_alpha;
  1726.  
  1727.     m_bbox.SetMin( m_x , m_y);
  1728.     m_bbox.SetMax( m_x + 100 , m_y + m_size + (m_size/2));
  1729.  
  1730.  
  1731. }
  1732.  
  1733. //----------------------------------------------------------------------------
  1734. // wxCanvas
  1735. //----------------------------------------------------------------------------
  1736.  
  1737. IMPLEMENT_CLASS(wxCanvas,wxScrolledWindow)
  1738.  
  1739. BEGIN_EVENT_TABLE(wxCanvas,wxScrolledWindow)
  1740.     EVT_PAINT( wxCanvas::OnPaint )
  1741.     EVT_IDLE( wxCanvas::OnIdle )
  1742.     EVT_SIZE( wxCanvas::OnSize )
  1743.     EVT_MOUSE_EVENTS( wxCanvas::OnMouse )
  1744.     EVT_SET_FOCUS( wxCanvas::OnSetFocus )
  1745.     EVT_KILL_FOCUS( wxCanvas::OnKillFocus )
  1746.     EVT_ERASE_BACKGROUND( wxCanvas::OnEraseBackground )
  1747. END_EVENT_TABLE()
  1748.  
  1749. wxCanvas::wxCanvas( wxCanvasAdmin* admin, wxWindow *parent, wxWindowID id,
  1750.     const wxPoint &position, const wxSize& size, long style ) :
  1751.     wxScrolledWindow( parent, id, position, size, style )
  1752. {
  1753.     // These are unused in wxVectorCanvas
  1754.     m_bufferX = 0;
  1755.     m_bufferY = 0;
  1756.     
  1757.     m_admin = admin;
  1758.     m_admin->Append( this );
  1759.     
  1760.     m_needUpdate = FALSE;
  1761.     m_background = *wxWHITE;
  1762.     m_lastMouse = (wxCanvasObject*)NULL;
  1763.     m_captureMouse = (wxCanvasObject*)NULL;
  1764.     m_frozen = FALSE;
  1765.     m_oldDeviceX = 0;
  1766.     m_oldDeviceY = 0;
  1767.     m_root = (wxCanvasObjectGroup*)NULL;
  1768. }
  1769.  
  1770. wxCanvas::~wxCanvas()
  1771. {
  1772.     wxNode *node = m_updateRects.First();
  1773.     while (node)
  1774.     {
  1775.         wxRect *rect = (wxRect*) node->Data();
  1776.         delete rect;
  1777.         m_updateRects.DeleteNode( node );
  1778.         node = m_updateRects.First();
  1779.     }
  1780. }
  1781.  
  1782. double wxCanvas::GetMinX() const
  1783. {
  1784.     return 0.0;
  1785. }
  1786.  
  1787. double wxCanvas::GetMinY() const
  1788. {
  1789.     return 0.0;
  1790. }
  1791.  
  1792. double wxCanvas::GetMaxX() const
  1793. {
  1794.    int width;
  1795.    GetVirtualSize( &width, NULL );
  1796.    return width;
  1797. }
  1798.  
  1799. double wxCanvas::GetMaxY() const
  1800. {
  1801.    int height;
  1802.    GetVirtualSize( NULL, &height );
  1803.    return height;
  1804. }
  1805.  
  1806. void wxCanvas::SetColour( const wxColour& background )
  1807. {
  1808.     m_background = background;
  1809.     SetBackgroundColour( m_background );
  1810.  
  1811.     if (m_frozen) return;
  1812.  
  1813.     wxMemoryDC dc;
  1814.     dc.SelectObject( m_buffer );
  1815.     dc.SetPen( *wxTRANSPARENT_PEN );
  1816.     wxBrush brush( m_background, wxSOLID );
  1817.     dc.SetBrush( brush );
  1818.     dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
  1819.     dc.SelectObject( wxNullBitmap );
  1820. }
  1821.  
  1822. void wxCanvas::SetCaptureMouse( wxCanvasObject *obj )
  1823. {
  1824.     if (obj)
  1825.     {
  1826.         wxWindow::CaptureMouse();
  1827.         m_captureMouse = obj;
  1828.     }
  1829.     else
  1830.     {
  1831.         wxWindow::ReleaseMouse();
  1832.         m_captureMouse = NULL;
  1833.     }
  1834. }
  1835.  
  1836. void wxCanvas::Freeze()
  1837. {
  1838.     m_frozen = TRUE;
  1839. }
  1840.  
  1841. void wxCanvas::Thaw()
  1842. {
  1843.     wxNode *node = m_updateRects.First();
  1844.     while (node)
  1845.     {
  1846.         wxRect *rect = (wxRect*) node->Data();
  1847.         delete rect;
  1848.         m_updateRects.DeleteNode( node );
  1849.         node = m_updateRects.First();
  1850.     }
  1851.  
  1852.     m_frozen = FALSE;
  1853.  
  1854.     if (m_buffer.Ok())
  1855.         Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight() );
  1856. }
  1857.  
  1858. void wxCanvas::Update( int x, int y, int width, int height, bool blit )
  1859. {
  1860.     CalcScrolledPosition( 0, 0, &m_oldDeviceX, &m_oldDeviceY );
  1861.     
  1862.     m_admin->SetActive(this);
  1863.  
  1864.     if (!m_root) return;
  1865.  
  1866.     if (m_frozen) return;
  1867.  
  1868.     // clip to buffer
  1869.     if (x < m_bufferX)
  1870.     {
  1871.         width -= m_bufferX-x;
  1872.         x = m_bufferX;
  1873.     }
  1874.     if (width <= 0) return;
  1875.  
  1876.     if (y < m_bufferY)
  1877.     {
  1878.         height -= m_bufferY-y;
  1879.         y = m_bufferY;
  1880.     }
  1881.     if (height <= 0) return;
  1882.  
  1883.     if (x+width > m_bufferX+m_buffer.GetWidth())
  1884.     {
  1885.         width = m_bufferX+m_buffer.GetWidth() - x;
  1886.     }
  1887.     if (width <= 0) return;
  1888.  
  1889.     if (y+height > m_bufferY+m_buffer.GetHeight())
  1890.     {
  1891.         height = m_bufferY+m_buffer.GetHeight() - y;
  1892.     }
  1893.     if (height <= 0) return;
  1894.  
  1895.     // update is within the buffer
  1896.     m_needUpdate = TRUE;
  1897.  
  1898.     // has to be blitted to screen later
  1899.     if (blit)
  1900.     {
  1901.         m_updateRects.Append(
  1902.             (wxObject*) new wxRect( x,y,width,height ) );
  1903.     }
  1904.  
  1905.     wxTransformMatrix cworld;
  1906.  
  1907.     wxMemoryDC dc;
  1908.     dc.SelectObject( m_buffer );
  1909.  
  1910.     dc.SetPen( *wxTRANSPARENT_PEN );
  1911.     wxBrush brush( m_background, wxSOLID );
  1912.     dc.SetBrush( brush );
  1913.     dc.SetLogicalFunction(wxCOPY);
  1914.  
  1915. #if 0
  1916.     if (width != m_buffer.GetWidth() && height != m_buffer.GetHeight())
  1917.     {
  1918.         dc.SetClippingRegion(x,y,width,height);
  1919.         dc.DrawRectangle(x-2,y-2,width+4,height+4);
  1920.         dc.DestroyClippingRegion();
  1921.     }
  1922.     else
  1923.     {
  1924.         dc.Clear();
  1925.         dc.DrawRectangle(0,0,m_buffer.GetWidth(),m_buffer.GetHeight());
  1926.     }
  1927. #else
  1928.     // No idea, what the code up there does.
  1929.     dc.DrawRectangle( x-m_bufferX, y-m_bufferY, width, height );
  1930. #endif    
  1931.    
  1932.     dc.SetBrush(wxNullBrush);
  1933.     dc.SetPen(wxNullPen);
  1934.  
  1935.     dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
  1936.     m_renderDC = &dc;
  1937.  
  1938.     m_root->Render( &cworld, x, y, width, height );
  1939.  
  1940.     m_renderDC = NULL;
  1941.     dc.SelectObject( wxNullBitmap );
  1942. }
  1943.  
  1944. void wxCanvas::BlitBuffer( wxDC &dc )
  1945. {
  1946.     wxNode *node = m_updateRects.First();
  1947.     while (node)
  1948.     {
  1949.         wxRect *rect = (wxRect*) node->Data();
  1950.         
  1951.         wxMemoryDC mdc;
  1952.         mdc.SelectObject( m_buffer );
  1953.         dc.Blit( rect->x,
  1954.                  rect->y,
  1955.                  rect->width,
  1956.                  rect->height,
  1957.                  &mdc,
  1958.                  rect->x - m_bufferX,
  1959.                  rect->y - m_bufferY ); 
  1960.         mdc.SelectObject( wxNullBitmap );
  1961.  
  1962.         delete rect;
  1963.         m_updateRects.DeleteNode( node );
  1964.         node = m_updateRects.First();
  1965.     }
  1966.  
  1967.     m_needUpdate = FALSE;
  1968. }
  1969.  
  1970. void wxCanvas::UpdateNow()
  1971. {
  1972.     if (m_frozen) return;
  1973.  
  1974.     if (!m_needUpdate) return;
  1975.  
  1976.     wxClientDC dc( this );
  1977.     PrepareDC( dc );
  1978.  
  1979.     BlitBuffer( dc );
  1980. }
  1981.  
  1982. void wxCanvas::OnSize(wxSizeEvent &event)
  1983. {
  1984.     int w,h;
  1985.     GetClientSize( &w, &h );
  1986.     m_buffer = wxBitmap( w, h );
  1987.  
  1988.     CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
  1989.  
  1990.     wxNode *node = m_updateRects.First();
  1991.     while (node)
  1992.     {
  1993.         wxRect *rect = (wxRect*) node->Data();
  1994.         delete rect;
  1995.         m_updateRects.DeleteNode( node );
  1996.         node = m_updateRects.First();
  1997.     }
  1998.  
  1999.     m_frozen = FALSE;
  2000.  
  2001.     Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
  2002.  
  2003.     event.Skip();
  2004. }
  2005.  
  2006. void wxCanvas::OnPaint(wxPaintEvent &event)
  2007. {
  2008.     wxPaintDC dc(this);
  2009.     PrepareDC( dc );
  2010.  
  2011.     if (!m_buffer.Ok()) return;
  2012.  
  2013.     if (m_frozen) return;
  2014.  
  2015.     m_needUpdate = TRUE;
  2016.  
  2017.     wxRegionIterator it( GetUpdateRegion() );
  2018.     while (it)
  2019.     {
  2020.         int x = it.GetX();
  2021.         int y = it.GetY();
  2022.  
  2023.         int w = it.GetWidth();
  2024.         int h = it.GetHeight();
  2025.  
  2026.         if (x+w > m_buffer.GetWidth())
  2027.             w = m_buffer.GetWidth() - x;
  2028.         if (y+h > m_buffer.GetHeight())
  2029.             h = m_buffer.GetHeight() - y;
  2030.  
  2031.         if ((w > 0) && (h > 0))
  2032.         {
  2033.             x += m_bufferX;
  2034.             y += m_bufferY;
  2035.             m_updateRects.Append( (wxObject*) new wxRect( x, y, w, h ) );
  2036.         }
  2037.  
  2038.         it++;
  2039.     }
  2040.  
  2041.     BlitBuffer( dc );
  2042. }
  2043.  
  2044. void wxCanvas::ScrollWindow( int dx, int dy, const wxRect* rect )
  2045. {
  2046.     // If any updates are pending, do them now since they will
  2047.     // expect the previous m_bufferX and m_bufferY as well as
  2048.     // the previous device origin values.
  2049.     wxClientDC dc( this );
  2050.     dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
  2051.     BlitBuffer( dc );
  2052.  
  2053.     // The buffer always starts at the top left corner of the
  2054.     // client area. Indeed, it is the client area.
  2055.     CalcUnscrolledPosition( 0, 0, &m_bufferX, &m_bufferY );
  2056.     
  2057.     // Update everything.
  2058.     Update( m_bufferX, m_bufferY, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
  2059.  
  2060.     // Scroll, actually.
  2061.     wxWindow::ScrollWindow( dx, dy, rect );
  2062. }
  2063.  
  2064. void wxCanvas::OnMouse(wxMouseEvent &event)
  2065. {
  2066.     m_admin->SetActive(this);
  2067.     if (!m_root)
  2068.     {
  2069.         event.Skip();
  2070.         return;
  2071.     }
  2072.  
  2073.     int x = event.GetX();
  2074.     int y = event.GetY();
  2075.  
  2076.     //to world coordinates to do hit test in world coordinates
  2077.     double xw = DeviceToLogicalX( x );
  2078.     double yw = DeviceToLogicalY( y );
  2079.  
  2080.     //make a select margin of 2 pixels, so also zero line thickness will be hit
  2081.     double margin = DeviceToLogicalXRel( 2 );
  2082.  
  2083.     if (event.GetEventType() == wxEVT_MOTION)
  2084.     {
  2085.         if (m_captureMouse) //no matter what go to this one
  2086.         {
  2087.             wxMouseEvent child_event( wxEVT_MOTION );
  2088.             child_event.SetEventObject(m_captureMouse);
  2089.             child_event.m_x = x;
  2090.             child_event.m_y = y;
  2091.             child_event.m_leftDown = event.m_leftDown;
  2092.             child_event.m_rightDown = event.m_rightDown;
  2093.             child_event.m_middleDown = event.m_middleDown;
  2094.             child_event.m_controlDown = event.m_controlDown;
  2095.             child_event.m_shiftDown = event.m_shiftDown;
  2096.             child_event.m_altDown = event.m_altDown;
  2097.             child_event.m_metaDown = event.m_metaDown;
  2098.  
  2099.             m_captureMouse->ProcessCanvasObjectEvent( child_event );
  2100.             return;
  2101.         }
  2102.         else
  2103.         {
  2104.             wxCanvasObject *obj = m_root->IsHitWorld(xw,yw,margin);
  2105.  
  2106.             if (obj && !obj->IsControl())
  2107.             {
  2108.                 wxMouseEvent child_event( wxEVT_MOTION );
  2109.                 child_event.SetEventObject( obj );
  2110.                 child_event.m_x = x;
  2111.                 child_event.m_y = y;
  2112.                 child_event.m_leftDown = event.m_leftDown;
  2113.                 child_event.m_rightDown = event.m_rightDown;
  2114.                 child_event.m_middleDown = event.m_middleDown;
  2115.                 child_event.m_controlDown = event.m_controlDown;
  2116.                 child_event.m_shiftDown = event.m_shiftDown;
  2117.                 child_event.m_altDown = event.m_altDown;
  2118.                 child_event.m_metaDown = event.m_metaDown;
  2119.  
  2120.                 if ((obj != m_lastMouse) && (m_lastMouse != NULL))
  2121.                 {
  2122.                     child_event.SetEventType( wxEVT_LEAVE_WINDOW );
  2123.                     child_event.SetEventObject( m_lastMouse );
  2124.                     child_event.m_x = x;
  2125.                     child_event.m_y = y;
  2126.                     m_lastMouse->ProcessCanvasObjectEvent( child_event );
  2127.  
  2128.                     m_lastMouse = obj;
  2129.                     child_event.SetEventType( wxEVT_ENTER_WINDOW );
  2130.                     child_event.SetEventObject( m_lastMouse );
  2131.                     child_event.m_x = x;
  2132.                     child_event.m_y = y;
  2133.                     m_lastMouse->ProcessCanvasObjectEvent( child_event );
  2134.  
  2135.                     child_event.SetEventType( wxEVT_MOTION );
  2136.                     child_event.SetEventObject( obj );
  2137.                 }
  2138.  
  2139.                 obj->ProcessCanvasObjectEvent( child_event );
  2140.                 return;
  2141.             }
  2142.         }
  2143.         if (m_lastMouse)
  2144.         {
  2145.             wxMouseEvent child_event( wxEVT_LEAVE_WINDOW );
  2146.             child_event.SetEventObject( m_lastMouse );
  2147.             child_event.m_x = x;
  2148.             child_event.m_y = y;
  2149.             child_event.m_leftDown = event.m_leftDown;
  2150.             child_event.m_rightDown = event.m_rightDown;
  2151.             child_event.m_middleDown = event.m_middleDown;
  2152.             child_event.m_controlDown = event.m_controlDown;
  2153.             child_event.m_shiftDown = event.m_shiftDown;
  2154.             child_event.m_altDown = event.m_altDown;
  2155.             child_event.m_metaDown = event.m_metaDown;
  2156.             m_lastMouse->ProcessCanvasObjectEvent( child_event );
  2157.  
  2158.             m_lastMouse = (wxCanvasObject*) NULL;
  2159.             return;
  2160.         }
  2161.     }
  2162.     else
  2163.     {
  2164.         if (m_captureMouse) //no matter what go to this one
  2165.         {
  2166.             wxMouseEvent child_event( event.GetEventType() );
  2167.             child_event.SetEventObject(m_captureMouse);
  2168.             child_event.m_x = x;
  2169.             child_event.m_y = y;
  2170.             child_event.m_leftDown = event.m_leftDown;
  2171.             child_event.m_rightDown = event.m_rightDown;
  2172.             child_event.m_middleDown = event.m_middleDown;
  2173.             child_event.m_controlDown = event.m_controlDown;
  2174.             child_event.m_shiftDown = event.m_shiftDown;
  2175.             child_event.m_altDown = event.m_altDown;
  2176.             child_event.m_metaDown = event.m_metaDown;
  2177.             m_captureMouse->ProcessCanvasObjectEvent( child_event );
  2178.         }
  2179.         else
  2180.         {
  2181.             wxCanvasObject *obj = m_root->IsHitWorld(xw,yw,margin);
  2182.  
  2183.             if (obj && !obj->IsControl())
  2184.             {
  2185.                 wxMouseEvent child_event( event.GetEventType() );
  2186.                 child_event.SetEventObject( obj );
  2187.                 child_event.m_x = x;
  2188.                 child_event.m_y = y;
  2189.                 child_event.m_leftDown = event.m_leftDown;
  2190.                 child_event.m_rightDown = event.m_rightDown;
  2191.                 child_event.m_middleDown = event.m_middleDown;
  2192.                 child_event.m_controlDown = event.m_controlDown;
  2193.                 child_event.m_shiftDown = event.m_shiftDown;
  2194.                 child_event.m_altDown = event.m_altDown;
  2195.                 child_event.m_metaDown = event.m_metaDown;
  2196.  
  2197.                 obj->ProcessCanvasObjectEvent( child_event );
  2198.                 return;
  2199.             }
  2200.         }
  2201.     }
  2202.  
  2203.     event.Skip();
  2204. }
  2205.  
  2206. void wxCanvas::OnIdle(wxIdleEvent &event)
  2207. {
  2208.     m_admin->SetActive(this);
  2209.     UpdateNow();
  2210.     event.Skip();
  2211. }
  2212.  
  2213. void wxCanvas::OnSetFocus(wxFocusEvent &event)
  2214. {
  2215.     m_admin->SetActive(this);
  2216. }
  2217.  
  2218. void wxCanvas::OnKillFocus(wxFocusEvent &event)
  2219. {
  2220. }
  2221.  
  2222.  
  2223. void wxCanvas::OnEraseBackground(wxEraseEvent &event)
  2224. {
  2225. }
  2226.  
  2227. // coordinates conversions
  2228. // -----------------------
  2229. double wxCanvas::DeviceToLogicalX(int x) const
  2230. {
  2231.     return (double)(x);
  2232. }
  2233.  
  2234. double wxCanvas::DeviceToLogicalY(int y) const
  2235. {
  2236.     return (double)(y);
  2237. }
  2238.  
  2239. double wxCanvas::DeviceToLogicalXRel(int x) const
  2240. {
  2241.     return (double)x;
  2242. }
  2243.  
  2244. double wxCanvas::DeviceToLogicalYRel(int y) const
  2245. {
  2246.     return (double)y;
  2247. }
  2248.  
  2249. int wxCanvas::LogicalToDeviceX(double x) const
  2250. {
  2251.     return (int)(x + 0.5);
  2252. }
  2253.  
  2254. int wxCanvas::LogicalToDeviceY(double y) const
  2255. {
  2256.     return (int)(y + 0.5);
  2257. }
  2258.  
  2259. int wxCanvas::LogicalToDeviceXRel(double x) const
  2260. {
  2261.     return (int)(x + 0.5);
  2262. }
  2263.  
  2264. int wxCanvas::LogicalToDeviceYRel(double y) const
  2265. {
  2266.     return (int)(y + 0.5);
  2267. }
  2268.  
  2269. //----------------------------------------------------------------------------
  2270. // wxVectorCanvas
  2271. //----------------------------------------------------------------------------
  2272.  
  2273. IMPLEMENT_CLASS(wxVectorCanvas,wxCanvas)
  2274.  
  2275. BEGIN_EVENT_TABLE(wxVectorCanvas,wxCanvas)
  2276.     EVT_SCROLLWIN( wxVectorCanvas::OnScroll )
  2277.     EVT_CHAR( wxVectorCanvas::OnChar )
  2278.     EVT_SIZE( wxVectorCanvas::OnSize )
  2279. END_EVENT_TABLE()
  2280.  
  2281. wxVectorCanvas::wxVectorCanvas( wxCanvasAdmin* admin, wxWindow *parent, wxWindowID id,
  2282.     const wxPoint &position, const wxSize& size, long style ) :
  2283.     wxCanvas( admin, parent, id, position, size, style )
  2284. {
  2285.     m_scrolled = FALSE;
  2286.     m_yaxis = FALSE;
  2287. }
  2288.  
  2289. double wxVectorCanvas::GetMinX() const
  2290. {
  2291.     return m_virt_minX;
  2292. }
  2293.  
  2294. double wxVectorCanvas::GetMinY() const
  2295. {
  2296.     return m_virt_minY;
  2297. }
  2298.  
  2299. double wxVectorCanvas::GetMaxX() const
  2300. {
  2301.    return m_virt_maxX;
  2302. }
  2303.  
  2304. double wxVectorCanvas::GetMaxY() const
  2305. {
  2306.     return m_virt_maxY;
  2307. }
  2308.  
  2309. void wxVectorCanvas::ScrollWindow( int dx, int dy, const wxRect* rect )
  2310. {
  2311.     // If any updates are pending, do them now since they will
  2312.     // expect the previous m_bufferX and m_bufferY as well as
  2313.     // the previous device origin values.
  2314.     wxClientDC dc( this );
  2315.     dc.SetDeviceOrigin( m_oldDeviceX, m_oldDeviceY );
  2316.     BlitBuffer( dc );
  2317.  
  2318.     if (dy != 0)
  2319.     {
  2320.         double dyv=DeviceToLogicalYRel(dy);
  2321.         m_virt_minY=m_virt_minY-dyv;
  2322.         m_virt_maxY=m_virt_maxY-dyv;
  2323.     }
  2324.     if (dx != 0)
  2325.     {
  2326.         double dxv=DeviceToLogicalXRel(dx);
  2327.         m_virt_minX=m_virt_minX-dxv;
  2328.         m_virt_maxX=m_virt_maxX-dxv;
  2329.     }
  2330.  
  2331.     m_admin->SetActive(this);
  2332.     SetMappingScroll(m_virt_minX,m_virt_minY,m_virt_maxX,m_virt_maxY,FALSE);
  2333.  
  2334.  
  2335.     if (dy != 0)
  2336.     {
  2337.         if (dy > 0 && dy < m_buffer.GetHeight())
  2338.         {
  2339.             wxRect rect( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight()-dy);
  2340.             wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
  2341.             wxMemoryDC dcm;
  2342.             dcm.SelectObject( m_buffer );
  2343.             dcm.DrawBitmap( sub_bitmap, 0, dy, TRUE );
  2344.             dcm.SelectObject( wxNullBitmap );
  2345.  
  2346.             Update( 0, 0, m_buffer.GetWidth(), dy, TRUE );
  2347.         }
  2348.         else  if (dy < 0 && dy > -m_buffer.GetHeight())
  2349.         {
  2350.             wxRect rect( 0, -dy, m_buffer.GetWidth(), m_buffer.GetHeight()+dy);
  2351.             wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
  2352.             wxMemoryDC dcm;
  2353.             dcm.SelectObject( m_buffer );
  2354.             dcm.DrawBitmap( sub_bitmap, 0, 0, TRUE );
  2355.             dcm.SelectObject( wxNullBitmap );
  2356.  
  2357.             Update( 0, m_buffer.GetHeight()+dy, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
  2358.         }
  2359.         else
  2360.             Update( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
  2361.     }
  2362.  
  2363.     if (dx != 0)
  2364.     {
  2365.         if (dx > 0 && dx < m_buffer.GetWidth())
  2366.         {
  2367.             wxRect rect( 0, 0, m_buffer.GetWidth()-dx, m_buffer.GetHeight());
  2368.             wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
  2369.             wxMemoryDC dcm;
  2370.             dcm.SelectObject( m_buffer );
  2371.             dcm.DrawBitmap( sub_bitmap, dx, 0, TRUE );
  2372.             dcm.SelectObject( wxNullBitmap );
  2373.  
  2374.             Update( 0, 0, dx, m_buffer.GetHeight(), TRUE );
  2375.         }
  2376.         else if (dx < 0 && dx > -m_buffer.GetWidth())
  2377.         {
  2378.             wxRect rect( -dx, 0, m_buffer.GetWidth()+dx, m_buffer.GetHeight());
  2379.             wxBitmap sub_bitmap( m_buffer.GetSubBitmap( rect ) );
  2380.             wxMemoryDC dcm;
  2381.             dcm.SelectObject( m_buffer );
  2382.             dcm.DrawBitmap( sub_bitmap, 0, 0, TRUE );
  2383.             dcm.SelectObject( wxNullBitmap );
  2384.  
  2385.             Update( m_buffer.GetWidth()+dx, 0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
  2386.         }
  2387.         else
  2388.             Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight(), TRUE );
  2389.     }
  2390.     
  2391.     wxWindow::ScrollWindow( dx, dy, rect );
  2392.  
  2393.     //must be done now because quick repeated scrolling will prevent wxPaint
  2394.     //from doing it properly
  2395.     UpdateNow();
  2396. }
  2397.  
  2398. void wxVectorCanvas::OnSize(wxSizeEvent &event)
  2399. {
  2400.     int w,h;
  2401.  
  2402.     GetClientSize( &w, &h );
  2403.  
  2404.     wxMemoryDC dc;
  2405.     m_buffer = wxBitmap( w, h );
  2406.     dc.SelectObject( m_buffer );
  2407.     dc.SetPen( *wxTRANSPARENT_PEN );
  2408.     wxBrush brush( m_background , wxSOLID );
  2409.     dc.SetBrush( brush );
  2410.     dc.DrawRectangle( 0, 0, m_buffer.GetWidth(), m_buffer.GetHeight() );
  2411.     dc.SelectObject( wxNullBitmap );
  2412.  
  2413.     wxNode *node = m_updateRects.First();
  2414.     while (node)
  2415.     {
  2416.         wxRect *rect = (wxRect*) node->Data();
  2417.         delete rect;
  2418.         m_updateRects.DeleteNode( node );
  2419.         node = m_updateRects.First();
  2420.     }
  2421.  
  2422.     m_frozen = FALSE;
  2423.  
  2424.     m_admin->SetActive(this);
  2425.     SetMappingScroll(m_virt_minX,m_virt_minY,m_virt_maxX,m_virt_maxY,FALSE);
  2426.  
  2427.     Update( 0,0, m_buffer.GetWidth(), m_buffer.GetHeight(), FALSE );
  2428.  
  2429. //    event.Skip();
  2430. }
  2431.  
  2432. // maps the virtual window (Real drawing to the window coordinates
  2433. // also used for zooming
  2434. void wxVectorCanvas::SetMappingScroll( double vx1,    double vy1, double vx2, double vy2, bool border)
  2435. {
  2436.     int dwxi,dwyi;
  2437.     GetClientSize(&dwxi,&dwyi);
  2438.  
  2439.     if (vx2==vx1) vx2=vx1+100000;
  2440.     if (vy2==vy1) vy2=vy1+100000;
  2441.     m_virt_minX=vx1;
  2442.     m_virt_minY=vy1;
  2443.     m_virt_maxX=vx2;
  2444.     m_virt_maxY=vy2;
  2445.  
  2446.     double dwx=dwxi;
  2447.     double dwy=dwyi;
  2448.     if (dwx==0) dwx=1;
  2449.     if (dwy==0) dwy=1;
  2450.  
  2451.     double dvx = m_virt_maxX - m_virt_minX;
  2452.     double dvy = m_virt_maxY - m_virt_minY;
  2453.  
  2454.     // calculate the scaling factor for the virtual window
  2455.     double temp_x=0;
  2456.     double temp_y=0;
  2457.     if ((dvy / dvx) < (dwy / dwx))
  2458.     {
  2459.         dvy = dvx * (dwy / dwx);
  2460.         // calculate the change in the coordinates
  2461.         temp_y = (dvy - (m_virt_maxY - m_virt_minY) )/ 2.0;
  2462.     }
  2463.     else
  2464.     {
  2465.         dvx = dvy * (dwx / dwy);
  2466.         // calculate the change in the coordinates
  2467.         temp_x = (dvx - (m_virt_maxX - m_virt_minX) )/ 2.0;
  2468.     }
  2469.  
  2470.     // add or substract the change from the original coordinates
  2471.     m_virt_minX=m_virt_minX-temp_x;
  2472.     m_virt_minY=m_virt_minY-temp_y;
  2473.  
  2474.     m_virt_maxX=m_virt_maxX+temp_x;
  2475.     m_virt_maxY=m_virt_maxY+temp_y;
  2476.  
  2477.     // initialize the mapping_matrix used for mapping the
  2478.     // virtual windows to the drawing window
  2479.  
  2480.      // make mappingmatrix
  2481.     m_mapping_matrix.Identity();
  2482.     if (!border)
  2483.     {
  2484.         // translate the drawing to 0,0
  2485.         if (m_yaxis)
  2486.             m_mapping_matrix.Translate(-m_virt_minX,-m_virt_maxY);
  2487.         else
  2488.             m_mapping_matrix.Translate(-m_virt_minX,-m_virt_minY);
  2489.     }
  2490.     else
  2491.     {
  2492.         // make a small white border around the drawing
  2493.         m_virt_minX=m_virt_minX- 0.05 * dvx;
  2494.         m_virt_minY=m_virt_minY- 0.05 * dvy;
  2495.  
  2496.         m_virt_maxX=m_virt_maxX+ 0.05 * dvx;
  2497.         m_virt_maxY=m_virt_maxY+ 0.05 * dvy;
  2498.  
  2499.         // translate the drawing to 0,0
  2500.         if (m_yaxis)
  2501.             m_mapping_matrix.Translate(-m_virt_minX,-m_virt_maxY);
  2502.         else
  2503.             m_mapping_matrix.Translate(-m_virt_minX,-m_virt_minY);
  2504.     }
  2505.  
  2506.     double scalefactor_x = dwx;
  2507.     scalefactor_x /= (m_virt_maxX - m_virt_minX);
  2508.  
  2509.     double scalefactor_y = dwy;
  2510.     scalefactor_y /= (m_virt_maxY - m_virt_minY);
  2511.  
  2512.     // scale the drawing so it fit's in the window
  2513.     m_mapping_matrix.Scale(scalefactor_x, scalefactor_y, 0, 0);
  2514.  
  2515.     // because of coordinate change mirror over X
  2516.     // 0,0 in graphic computerscreens: upperleft corner
  2517.     // 0,0 in cartesian: lowerleft corner
  2518.     if (m_yaxis)
  2519.     {
  2520.         m_mapping_matrix.Mirror();
  2521.     }
  2522.     // make inverse of mapping matrix
  2523.     // this is to set coordinates in the statusbar
  2524.     // and the calculate screencoordinates to world coordinates used
  2525.     // in zooming
  2526.     m_inverse_mapping=m_mapping_matrix;
  2527.     m_inverse_mapping.Invert();
  2528.  
  2529.     if (m_scrolled)
  2530.         SetScroll(m_virtm_minX,m_virtm_minY,m_virtm_maxX,m_virtm_maxY);
  2531.  
  2532.     int dx2,dy2;
  2533.     GetClientSize(&dx2,&dy2);
  2534.     if ( dwxi != dx2 || dwyi  != dy2) //scrollbar is/became empty
  2535.         SetScroll(m_virtm_minX,m_virtm_minY,m_virtm_maxX,m_virtm_maxY);
  2536. }
  2537.  
  2538.  
  2539. void wxVectorCanvas::SetScroll(double vx1,double vy1,double vx2,double vy2)
  2540. {
  2541.     m_virtm_minX=vx1;
  2542.     m_virtm_minY=vy1;
  2543.     m_virtm_maxX=vx2;
  2544.     m_virtm_maxY=vy2;
  2545.  
  2546.     double dvx = m_virt_maxX - m_virt_minX;
  2547.     double dvy = m_virt_maxY - m_virt_minY;
  2548.     double dmvx = m_virtm_maxX - m_virtm_minX;
  2549.     double dmvy = m_virtm_maxY - m_virtm_minY;
  2550.  
  2551.     SetScrollbar(wxHORIZONTAL,(m_virt_minX-m_virtm_minX)/dmvx *1000,dvx/dmvx *1000,1000,FALSE);
  2552.     if (m_yaxis)
  2553.     {
  2554.         SetScrollbar(wxVERTICAL,(m_virtm_maxY-m_virt_maxY)/dmvy *1000,dvy/dmvy *1000,1000,FALSE);
  2555.     }
  2556.     else
  2557.     {
  2558.         SetScrollbar(wxVERTICAL,(m_virt_minY-m_virtm_minY)/dmvy *1000,dvy/dmvy *1000,1000,FALSE);
  2559.     }
  2560.  
  2561.     m_scrolled=TRUE;
  2562. }
  2563.  
  2564. // coordinates conversions
  2565. // -----------------------
  2566. double wxVectorCanvas::DeviceToLogicalX(int x) const
  2567. {
  2568.     return m_inverse_mapping.GetValue(0,0) * x + m_inverse_mapping.GetValue(2,0);
  2569. }
  2570.  
  2571. double wxVectorCanvas::DeviceToLogicalY(int y) const
  2572. {
  2573.     return m_inverse_mapping.GetValue(1,1) * y + m_inverse_mapping.GetValue(2,1);
  2574. }
  2575.  
  2576. double wxVectorCanvas::DeviceToLogicalXRel(int x) const
  2577. {
  2578.     return x*m_inverse_mapping.GetValue(0,0);
  2579. }
  2580.  
  2581. double wxVectorCanvas::DeviceToLogicalYRel(int y) const
  2582. {
  2583.     return y*m_inverse_mapping.GetValue(1,1);
  2584. }
  2585.  
  2586. int wxVectorCanvas::LogicalToDeviceX(double x) const
  2587. {
  2588.     return (int) (m_mapping_matrix.GetValue(0,0) * x + m_mapping_matrix.GetValue(2,0) + 0.5);
  2589. }
  2590.  
  2591. int wxVectorCanvas::LogicalToDeviceY(double y) const
  2592. {
  2593.     return (int) (m_mapping_matrix.GetValue(1,1) * y + m_mapping_matrix.GetValue(2,1) + 0.5);
  2594. }
  2595.  
  2596. int wxVectorCanvas::LogicalToDeviceXRel(double x) const
  2597. {
  2598.     return (int) (x*m_mapping_matrix.GetValue(0,0) + 0.5);
  2599. }
  2600.  
  2601. int wxVectorCanvas::LogicalToDeviceYRel(double y) const
  2602. {
  2603.     return (int) (y*m_mapping_matrix.GetValue(1,1) + 0.5);
  2604. }
  2605.  
  2606.  
  2607. // return the inverse mapping matrix for zooming or coordinates
  2608. wxTransformMatrix wxVectorCanvas::GetInverseMappingMatrix()
  2609. {
  2610.     return m_inverse_mapping;
  2611. }
  2612.  
  2613. wxTransformMatrix wxVectorCanvas::GetMappingMatrix()
  2614. {
  2615.     return m_mapping_matrix;
  2616. }
  2617.  
  2618.  
  2619. // ----------------------------------------------------------------------------
  2620. // scrolling behaviour
  2621. // ----------------------------------------------------------------------------
  2622.  
  2623. void wxVectorCanvas::OnScroll(wxScrollWinEvent& event)
  2624. {
  2625.     if (event.GetEventType()==wxEVT_SCROLLWIN_THUMBRELEASE)
  2626.     {
  2627.         if (event.GetOrientation()==wxHORIZONTAL)
  2628.         {
  2629.           double x=m_virtm_minX+event.GetPosition()/1000.0*(m_virtm_maxX-m_virtm_minX);
  2630.           x=LogicalToDeviceXRel(x-m_virt_minX);
  2631.           ScrollWindow(-x, 0, (const wxRect *) NULL);
  2632.         }
  2633.         else
  2634.         {
  2635.           double y=m_virtm_minY+event.GetPosition()/1000.0*(m_virtm_maxY-m_virtm_minY);
  2636.           y=LogicalToDeviceYRel(y-m_virt_minY);
  2637.           ScrollWindow(0, -y, (const wxRect *) NULL);
  2638.         }
  2639.     }
  2640.     else if (event.GetEventType()==wxEVT_SCROLLWIN_PAGEUP)
  2641.     {
  2642.         if (event.GetOrientation()==wxHORIZONTAL)
  2643.         {
  2644.           double x=GetBufferWidth();
  2645.           ScrollWindow(x, 0, (const wxRect *) NULL);
  2646.         }
  2647.         else
  2648.         {
  2649.           double y=GetBufferHeight();
  2650.           ScrollWindow(0, y, (const wxRect *) NULL);
  2651.         }
  2652.     }
  2653.     else if (event.GetEventType()==wxEVT_SCROLLWIN_PAGEDOWN)
  2654.     {
  2655.         if (event.GetOrientation()==wxHORIZONTAL)
  2656.         {
  2657.           double x=-GetBufferWidth();
  2658.           ScrollWindow(x, 0, (const wxRect *) NULL);
  2659.         }
  2660.         else
  2661.         {
  2662.           double y=-GetBufferHeight();
  2663.           ScrollWindow(0, y, (const wxRect *) NULL);
  2664.         }
  2665.     }
  2666.     else if (event.GetEventType()==wxEVT_SCROLLWIN_LINEUP)
  2667.     {
  2668.         if (event.GetOrientation()==wxHORIZONTAL)
  2669.         {
  2670.           int x=GetBufferWidth()/10;
  2671.           ScrollWindow(x, 0, (const wxRect *) NULL);
  2672.         }
  2673.         else
  2674.         {
  2675.           int y=GetBufferHeight()/10;
  2676.           ScrollWindow(0, y, (const wxRect *) NULL);
  2677.         }
  2678.     }
  2679.     else if (event.GetEventType()==wxEVT_SCROLLWIN_LINEDOWN)
  2680.     {
  2681.         if (event.GetOrientation()==wxHORIZONTAL)
  2682.         {
  2683.           int x=-GetBufferWidth()/10;
  2684.           ScrollWindow(x, 0, (const wxRect *) NULL);
  2685.         }
  2686.         else
  2687.         {
  2688.           int y=-GetBufferHeight()/10;
  2689.           ScrollWindow(0, y, (const wxRect *) NULL);
  2690.         }
  2691.     }
  2692.  
  2693. }
  2694.  
  2695. void wxVectorCanvas::OnChar(wxKeyEvent& event)
  2696. {
  2697.     switch ( event.KeyCode() )
  2698.     {
  2699.         case WXK_PAGEUP:
  2700.         case WXK_PRIOR:
  2701.             {
  2702.               double y=GetBufferHeight();
  2703.               ScrollWindow(0, y, (const wxRect *) NULL);
  2704.             }
  2705.             break;
  2706.         case WXK_PAGEDOWN:
  2707.         case WXK_NEXT:
  2708.             {
  2709.               double y=-GetBufferHeight();
  2710.               ScrollWindow(0, y, (const wxRect *) NULL);
  2711.             }
  2712.             break;
  2713.         case WXK_HOME:
  2714.             {
  2715.                 double y=m_virtm_minY;
  2716.                 y=LogicalToDeviceYRel(y-m_virt_minY);
  2717.                 ScrollWindow(0, -y, (const wxRect *) NULL);
  2718.             }
  2719.             break;
  2720.         case WXK_END:
  2721.             {
  2722.                 double y=m_virtm_minY+(m_virtm_maxY-m_virtm_minY);
  2723.                 y=LogicalToDeviceYRel(y-m_virt_minY);
  2724.                 ScrollWindow(0, -y, (const wxRect *) NULL);
  2725.             }
  2726.             break;
  2727.         case WXK_UP:
  2728.             {
  2729.                 int y;
  2730.                 if  (!event.ControlDown())
  2731.                     y=GetBufferHeight()/10;
  2732.                 else
  2733.                     y=GetBufferHeight();
  2734.                 ScrollWindow(0, y, (const wxRect *) NULL);
  2735.             }
  2736.             break;
  2737.  
  2738.         case WXK_DOWN:
  2739.             {
  2740.                 int y;
  2741.                 if  (!event.ControlDown())
  2742.                     y=-GetBufferHeight()/10;
  2743.                 else
  2744.                     y=-GetBufferHeight();
  2745.                 ScrollWindow(0, y, (const wxRect *) NULL);
  2746.             }
  2747.             break;
  2748.  
  2749.         case WXK_LEFT:
  2750.             {
  2751.                 int x;
  2752.                 if  (!event.ControlDown())
  2753.                     x=GetBufferWidth()/10;
  2754.                 else
  2755.                     x=GetBufferWidth();
  2756.                 ScrollWindow(x, 0, (const wxRect *) NULL);
  2757.             }
  2758.             break;
  2759.         case WXK_RIGHT:
  2760.             {
  2761.                 int x;
  2762.                 if  (!event.ControlDown())
  2763.                     x=-GetBufferWidth()/10;
  2764.                 else
  2765.                     x=-GetBufferWidth();
  2766.                 ScrollWindow(x, 0, (const wxRect *) NULL);
  2767.             }
  2768.             break;
  2769.         default:
  2770.             // not for us
  2771.             event.Skip();
  2772.     }
  2773. }
  2774.  
  2775.  
  2776. //----------------------------------------------------------------------------
  2777. // wxCanvasAdmin
  2778. //----------------------------------------------------------------------------
  2779.  
  2780. wxCanvasAdmin::wxCanvasAdmin()
  2781. {
  2782.  
  2783. }
  2784.  
  2785. wxCanvasAdmin::~wxCanvasAdmin()
  2786. {
  2787. }
  2788.  
  2789.  
  2790. void wxCanvasAdmin::Append( wxCanvas* canvas )
  2791. {
  2792.     m_canvaslist.Append( canvas );
  2793. }
  2794.  
  2795. void wxCanvasAdmin::Remove( wxCanvas* canvas )
  2796. {
  2797.     m_canvaslist.DeleteObject( canvas );
  2798. }
  2799.  
  2800. void wxCanvasAdmin::Update(wxCanvasObject* obj, double x, double y, double width, double height)
  2801. {
  2802.     wxNode *node = m_canvaslist.First();
  2803.     while (node)
  2804.     {
  2805.  
  2806.         wxCanvas *canvas = (wxCanvas*) node->Data();
  2807.  
  2808.         if (m_active == canvas)
  2809.         {
  2810.             int xi = canvas->LogicalToDeviceX( x);
  2811.             int yi = canvas->LogicalToDeviceY( y);
  2812.             int wi = canvas->LogicalToDeviceXRel( width );
  2813.             int hi = canvas->LogicalToDeviceYRel( height);
  2814.             //update a little more then is strictly needed,
  2815.             //to get rid of the 1 bit bugs
  2816.             if (canvas->GetYaxis())
  2817.                 canvas->Update( xi-2, yi+hi-2, wi+4, -hi+4);
  2818.             else
  2819.                 canvas->Update( xi-2, yi-2, wi+4, hi+4);
  2820.         }
  2821.         else
  2822.         {   wxCanvasObject* topobj=canvas->GetRoot()->Contains(obj);
  2823.             if (topobj)
  2824.             {
  2825.                 wxCanvas* tcanvas = m_active;
  2826.                 SetActive(canvas);
  2827.  
  2828.                 /*
  2829.                 //KKK TODO somehow the next does not work for update i do not know why
  2830.                 canvas->GetRoot()->CalcBoundingBox();
  2831.                 int xi = topobj->GetX();
  2832.                 int yi = topobj->GetY();
  2833.                 int wi = topobj->GetWidth();
  2834.                 int hi = topobj->GetHeight();
  2835.                 */
  2836.                 canvas->Update( 0,0, canvas->GetBufferWidth(),canvas->GetBufferHeight());
  2837.                 SetActive(tcanvas);
  2838.             }
  2839.         }
  2840.  
  2841.         node = node->Next();
  2842.     }
  2843. }
  2844.  
  2845. void wxCanvasAdmin::UpdateNow()
  2846. {
  2847.     wxNode *node = m_canvaslist.First();
  2848.     while (node)
  2849.     {
  2850.         wxCanvas *canvas = (wxCanvas*) node->Data();
  2851.  
  2852.         canvas->UpdateNow();
  2853.         node = node->Next();
  2854.     }
  2855. }
  2856.  
  2857. // coordinates conversions
  2858. // -----------------------
  2859. double wxCanvasAdmin::DeviceToLogicalX(int x) const
  2860. {
  2861.     return m_active->DeviceToLogicalX(x);
  2862. }
  2863.  
  2864. double wxCanvasAdmin::DeviceToLogicalY(int y) const
  2865. {
  2866.     return m_active->DeviceToLogicalY(y);
  2867. }
  2868.  
  2869. double wxCanvasAdmin::DeviceToLogicalXRel(int x) const
  2870. {
  2871.     return m_active->DeviceToLogicalXRel(x);
  2872. }
  2873.  
  2874. double wxCanvasAdmin::DeviceToLogicalYRel(int y) const
  2875. {
  2876.     return m_active->DeviceToLogicalYRel(y);
  2877. }
  2878.  
  2879. int wxCanvasAdmin::LogicalToDeviceX(double x) const
  2880. {
  2881.     return m_active->LogicalToDeviceX(x);
  2882. }
  2883.  
  2884. int wxCanvasAdmin::LogicalToDeviceY(double y) const
  2885. {
  2886.     return m_active->LogicalToDeviceY(y);
  2887. }
  2888.  
  2889. int wxCanvasAdmin::LogicalToDeviceXRel(double x) const
  2890. {
  2891.     return m_active->LogicalToDeviceXRel(x);
  2892. }
  2893.  
  2894. int wxCanvasAdmin::LogicalToDeviceYRel(double y) const
  2895. {
  2896.     return m_active->LogicalToDeviceYRel(y);
  2897. }
  2898.  
  2899. void wxCanvasAdmin::SetActive(wxCanvas* activate)
  2900. {
  2901.     wxNode *node = m_canvaslist.First();
  2902.     while (node)
  2903.     {
  2904.         wxCanvas *canvas = (wxCanvas*) node->Data();
  2905.  
  2906.         if (activate == canvas)
  2907.         {
  2908.             m_active=canvas;
  2909.             break;
  2910.         }
  2911.         node = node->Next();
  2912.     }
  2913. }
  2914. //--------------------------------------------------------------------
  2915. // wxCanvasModule
  2916. //--------------------------------------------------------------------
  2917.  
  2918. class wxCanvasModule : public wxModule
  2919. {
  2920. public:
  2921.     virtual bool OnInit();
  2922.     virtual void OnExit();
  2923.  
  2924. private:
  2925.     DECLARE_DYNAMIC_CLASS(wxCanvasModule)
  2926. };
  2927.  
  2928. IMPLEMENT_DYNAMIC_CLASS(wxCanvasModule, wxModule)
  2929.  
  2930. bool wxCanvasModule::OnInit()
  2931. {
  2932. #if wxUSE_FREETYPE
  2933.     int error = FT_Init_FreeType( &g_freetypeLibrary );
  2934.     if (error) return FALSE;
  2935. #endif
  2936.  
  2937.     return TRUE;
  2938. }
  2939.  
  2940. void wxCanvasModule::OnExit()
  2941. {
  2942. #if wxUSE_FREETYPE
  2943.     FT_Done_FreeType( g_freetypeLibrary );
  2944. #endif
  2945. }
  2946.  
  2947.  
  2948.  
  2949.  
  2950.