]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/dcbase.cpp
Fix [ 1574240 ] wx.RadioButton doesn't navigate correctly
[wxWidgets.git] / src / common / dcbase.cpp
index 73653ffc7d26ae2a717c2e1472554e5242c0ac96..e5063b5ed844a34657443fc7d2ac99efb4790ea0 100644 (file)
@@ -1,11 +1,11 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        common/dcbase.cpp
+// Name:        src/common/dcbase.cpp
 // Purpose:     generic methods of the wxDC Class
 // Author:      Vadim Zeitlin
 // Modified by:
 // Created:     05/25/99
 // RCS-ID:      $Id$
-// Copyright:   (c) wxWindows team
+// Copyright:   (c) wxWidgets team
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // declarations
 // ============================================================================
 
-#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
-    #pragma implementation "dcbase.h"
-#endif
-
 // ----------------------------------------------------------------------------
 // headers
 // ----------------------------------------------------------------------------
 
 #include "wx/dc.h"
 
-#include <math.h>
+#ifndef WX_PRECOMP
+    #include "wx/math.h"
+#endif
+
+// bool wxDCBase::sm_cacheing = false;
 
-// bool wxDCBase::sm_cacheing = FALSE;
+IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject)
 
 // ============================================================================
 // implementation
 // ============================================================================
 
+#if WXWIN_COMPATIBILITY_2_6
+void wxDCBase::BeginDrawing()
+{
+}
+
+void wxDCBase::EndDrawing()
+{
+}
+#endif // WXWIN_COMPATIBILITY_2_6
+
 // ----------------------------------------------------------------------------
 // special symbols
 // ----------------------------------------------------------------------------
@@ -106,6 +116,49 @@ void wxDCBase::DrawPolygon(const wxList *list,
     delete [] points;
 }
 
+void
+wxDCBase::DoDrawPolyPolygon(int n,
+                            int count[],
+                            wxPoint points[],
+                            wxCoord xoffset, wxCoord yoffset,
+                            int fillStyle)
+{
+    if ( n == 1 )
+    {
+        DoDrawPolygon(count[0], points, xoffset, yoffset, fillStyle);
+        return;
+    }
+
+    int      i, j, lastOfs;
+    wxPoint* pts;
+    wxPen    pen;
+
+    for (i = j = lastOfs = 0; i < n; i++)
+    {
+        lastOfs = j;
+        j      += count[i];
+    }
+    pts = new wxPoint[j+n-1];
+    for (i = 0; i < j; i++)
+        pts[i] = points[i];
+    for (i = 2; i <= n; i++)
+    {
+        lastOfs -= count[n-i];
+        pts[j++] = pts[lastOfs];
+    }
+
+    pen = GetPen();
+    SetPen(wxPen(*wxBLACK, 0, wxTRANSPARENT));
+    DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
+    SetPen(pen);
+    for (i = j = 0; i < n; i++)
+    {
+        DoDrawLines(count[i], pts+j, xoffset, yoffset);
+        j += count[i];
+    }
+    delete[] pts;
+}
+
 // ----------------------------------------------------------------------------
 // splines
 // ----------------------------------------------------------------------------
@@ -248,7 +301,7 @@ static bool wx_spline_add_point(double x, double y)
   point->x = (int) x;
   point->y = (int) y;
   wx_spline_point_list.Append((wxObject*)point);
-  return TRUE;
+  return true;
 }
 
 static void wx_spline_draw_point_array(wxDCBase *dc)
@@ -273,6 +326,10 @@ void wxDCBase::DoDrawSpline( wxList *points )
     double           x1, y1, x2, y2;
 
     wxList::compatibility_iterator node = points->GetFirst();
+    if (node == wxList::compatibility_iterator())
+        // empty list
+        return;
+
     p = (wxPoint *)node->GetData();
 
     x1 = p->x;
@@ -322,6 +379,85 @@ void wxDCBase::DoDrawSpline( wxList *points )
 
 #endif // wxUSE_SPLINES
 
+// ----------------------------------------------------------------------------
+// Partial Text Extents
+// ----------------------------------------------------------------------------
+
+
+// Each element of the widths array will be the width of the string up to and
+// including the corresponding character in text.  This is the generic
+// implementation, the port-specific classes should do this with native APIs
+// if available and if faster.  Note: pango_layout_index_to_pos is much slower
+// than calling GetTextExtent!!
+
+#define FWC_SIZE 256
+
+class FontWidthCache
+{
+public:
+    FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
+    ~FontWidthCache() { delete []m_widths; }
+
+    void Reset()
+    {
+        if (!m_widths)
+            m_widths = new int[FWC_SIZE];
+
+        memset(m_widths, 0, sizeof(int)*FWC_SIZE);
+    }
+
+    wxFont m_font;
+    double m_scaleX;
+    int *m_widths;
+};
+
+static FontWidthCache s_fontWidthCache;
+
+bool wxDCBase::DoGetPartialTextExtents(const wxString& text, wxArrayInt& widths) const
+{
+    int totalWidth = 0;
+
+    const size_t len = text.length();
+    widths.Empty();
+    widths.Add(0, len);
+
+    // reset the cache if font or horizontal scale have changed
+    if ( !s_fontWidthCache.m_widths ||
+         !wxIsSameDouble(s_fontWidthCache.m_scaleX, m_scaleX) ||
+         (s_fontWidthCache.m_font != GetFont()) )
+    {
+        s_fontWidthCache.Reset();
+        s_fontWidthCache.m_font = GetFont();
+        s_fontWidthCache.m_scaleX = m_scaleX;
+    }
+
+    // Calculate the position of each character based on the widths of
+    // the previous characters
+    int w, h;
+    for ( size_t i = 0; i < len; i++ )
+    {
+        const wxChar c = text[i];
+        unsigned int c_int = (unsigned int)c;
+
+        if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
+        {
+            w = s_fontWidthCache.m_widths[c_int];
+        }
+        else
+        {
+            GetTextExtent(c, &w, &h);
+            if (c_int < FWC_SIZE)
+                s_fontWidthCache.m_widths[c_int] = w;
+        }
+
+        totalWidth += w;
+        widths[i] = totalWidth;
+    }
+
+    return true;
+}
+
+
 // ----------------------------------------------------------------------------
 // enhanced text drawing
 // ----------------------------------------------------------------------------
@@ -449,7 +585,7 @@ void wxDCBase::DrawLabel(const wxString& text,
             width0 = width;
     if ( bitmap.Ok() )
     {
-        DrawBitmap(bitmap, x, y, TRUE /* use mask */);
+        DrawBitmap(bitmap, x, y, true /* use mask */);
 
         wxCoord offset = bitmap.GetWidth() + 4;
         x += offset;
@@ -549,8 +685,158 @@ void wxDCBase::DrawLabel(const wxString& text,
     CalcBoundingBox(x0 + width0, y0 + height);
 }
 
+
+void wxDCBase::DoGradientFillLinear(const wxRect& rect,
+                                    const wxColour& initialColour,
+                                    const wxColour& destColour,
+                                    wxDirection nDirection)
+{
+    // save old pen
+    wxPen oldPen = m_pen;
+
+    wxUint8 nR1 = destColour.Red();
+    wxUint8 nG1 = destColour.Green();
+    wxUint8 nB1 = destColour.Blue();
+    wxUint8 nR2 = initialColour.Red();
+    wxUint8 nG2 = initialColour.Green();
+    wxUint8 nB2 = initialColour.Blue();
+    wxUint8 nR, nG, nB;
+
+    if ( nDirection == wxEAST || nDirection == wxWEST )
+    {
+        wxInt32 x = rect.GetWidth();
+        wxInt32 w = x;              // width of area to shade
+        wxInt32 xDelta = w/256;     // height of one shade bend
+        if (xDelta < 1)
+            xDelta = 1;
+
+        while (x >= xDelta)
+        {
+            x -= xDelta;
+            if (nR1 > nR2)
+                nR = nR1 - (nR1-nR2)*(w-x)/w;
+            else
+                nR = nR1 + (nR2-nR1)*(w-x)/w;
+
+            if (nG1 > nG2)
+                nG = nG1 - (nG1-nG2)*(w-x)/w;
+            else
+                nG = nG1 + (nG2-nG1)*(w-x)/w;
+
+            if (nB1 > nB2)
+                nB = nB1 - (nB1-nB2)*(w-x)/w;
+            else
+                nB = nB1 + (nB2-nB1)*(w-x)/w;
+
+            SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
+            if(nDirection == wxEAST)
+                DrawRectangle(rect.GetLeft()+x, rect.GetTop(),
+                        xDelta, rect.GetHeight());
+            else //nDirection == wxWEST
+                DrawRectangle(rect.GetRight()-x-xDelta, rect.GetTop(),
+                        xDelta, rect.GetHeight());
+        }
+    }
+    else  // nDirection == wxNORTH || nDirection == wxSOUTH
+    {
+        wxInt32 y = rect.GetHeight();
+        wxInt32 w = y;              // height of area to shade
+        wxInt32 yDelta = w/255;     // height of one shade bend
+        if (yDelta < 1)
+            yDelta = 1;
+
+        while (y > 0)
+        {
+            y -= yDelta;
+            if (nR1 > nR2)
+                nR = nR1 - (nR1-nR2)*(w-y)/w;
+            else
+                nR = nR1 + (nR2-nR1)*(w-y)/w;
+
+            if (nG1 > nG2)
+                nG = nG1 - (nG1-nG2)*(w-y)/w;
+            else
+                nG = nG1 + (nG2-nG1)*(w-y)/w;
+
+            if (nB1 > nB2)
+                nB = nB1 - (nB1-nB2)*(w-y)/w;
+            else
+                nB = nB1 + (nB2-nB1)*(w-y)/w;
+
+            SetPen(wxPen(wxColour(nR, nG, nB), 1, wxSOLID));
+            if(nDirection == wxNORTH)
+                DrawRectangle(rect.GetLeft(), rect.GetTop()+y,
+                        rect.GetWidth(), yDelta);
+            else //nDirection == wxSOUTH
+                DrawRectangle(rect.GetLeft(), rect.GetBottom()-y-yDelta,
+                        rect.GetWidth(), yDelta);
+        }
+    }
+
+    SetPen(oldPen);
+}
+
+void wxDCBase::DoGradientFillConcentric(const wxRect& rect,
+                                      const wxColour& initialColour,
+                                      const wxColour& destColour,
+                                      const wxPoint& circleCenter)
+{
+    //save the old pen color
+    wxColour oldPenColour = m_pen.GetColour();
+
+    wxUint8 nR1 = destColour.Red();
+    wxUint8 nG1 = destColour.Green();
+    wxUint8 nB1 = destColour.Blue();
+    wxUint8 nR2 = initialColour.Red();
+    wxUint8 nG2 = initialColour.Green();
+    wxUint8 nB2 = initialColour.Blue();
+    wxUint8 nR, nG, nB;
+
+
+    //Radius
+    wxInt32 cx = rect.GetWidth() / 2;
+    wxInt32 cy = rect.GetHeight() / 2;
+    wxInt32 nRadius;
+    if (cx < cy)
+        nRadius = cx;
+    else
+        nRadius = cy;
+
+    //Offset of circle
+    wxInt32 nCircleOffX = circleCenter.x - (rect.GetWidth() / 2);
+    wxInt32 nCircleOffY = circleCenter.y - (rect.GetHeight() / 2);
+
+    for ( wxInt32 x = 0; x < rect.GetWidth(); x++ )
+    {
+        for ( wxInt32 y = 0; y < rect.GetHeight(); y++ )
+        {
+            //get color difference
+            wxInt32 nGradient = ((nRadius -
+                                  (wxInt32)sqrt(
+                                    pow((double)(x - cx - nCircleOffX), 2) +
+                                    pow((double)(y - cy - nCircleOffY), 2)
+                                  )) * 100) / nRadius;
+
+            //normalize Gradient
+            if (nGradient < 0 )
+                nGradient = 0;
+
+            //get dest colors
+            nR = (wxUint8)(nR1 + ((nR2 - nR1) * nGradient / 100));
+            nG = (wxUint8)(nG1 + ((nG2 - nG1) * nGradient / 100));
+            nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100));
+
+            //set the pixel
+            m_pen.SetColour(wxColour(nR,nG,nB));
+            DrawPoint(wxPoint(x + rect.GetLeft(), y + rect.GetTop()));
+        }
+    }
+    //return old pen color
+    m_pen.SetColour(oldPenColour);
+}
+
 /*
-Notes for wxWindows DrawEllipticArcRot(...)
+Notes for wxWidgets DrawEllipticArcRot(...)
 
 wxDCBase::DrawEllipticArcRot(...) draws a rotated elliptic arc or an ellipse.
 It uses wxDCBase::CalculateEllipticPoints(...) and wxDCBase::Rotate(...),
@@ -561,19 +847,19 @@ DoDrawEllipticArcRot(...) is virtual, so it can be called from deeper
 methods like (WinCE) wxDC::DoDrawArc(...).
 
 CalculateEllipticPoints(...) fills a given list of wxPoints with some points
-of an elliptic arc. The algorithm is pixel-based: In every row (in flat 
+of an elliptic arc. The algorithm is pixel-based: In every row (in flat
 parts) or every column (in steep parts) only one pixel is calculated.
 Trigonometric calculation (sin, cos, tan, atan) is only done if the
-starting angle is not equal to the ending angle. The calculation of the 
+starting angle is not equal to the ending angle. The calculation of the
 pixels is done using simple arithmetic only and should perform not too
 bad even on devices without floating point processor. I didn't test this yet.
 
 Rotate(...) rotates a list of point pixel-based, you will see rounding errors.
-For instance: an ellipse rotated 180 degrees is drawn 
+For instance: an ellipse rotated 180 degrees is drawn
 slightly different from the original.
 
-The points are then moved to an array and used to draw a polyline and/or polygon 
-(with center added, the pie). 
+The points are then moved to an array and used to draw a polyline and/or polygon
+(with center added, the pie).
 The result looks quite similar to the native ellipse, only e few pixels differ.
 
 The performance on a desktop system (Athlon 1800, WinXP) is about 7 times
@@ -581,7 +867,7 @@ slower as DrawEllipse(...), which calls the native API.
 An rotated ellipse outside the clipping region takes nearly the same time,
 while an native ellipse outside takes nearly no time to draw.
 
-If you draw an arc with this new method, you will see the starting and ending angles 
+If you draw an arc with this new method, you will see the starting and ending angles
 are calculated properly.
 If you use DrawEllipticArc(...), you will see they are only correct for circles
 and not properly calculated for ellipses.
@@ -591,8 +877,8 @@ p.lenhard@t-online.de
 */
 
 #ifdef __WXWINCE__
-void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y, 
-                                     wxCoord w, wxCoord h, 
+void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
+                                     wxCoord w, wxCoord h,
                                      double sa, double ea, double angle )
 {
     wxList list;
@@ -604,20 +890,20 @@ void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
     list.Append( (wxObject*) new wxPoint( x+w/2, y+h/2 ) );
 
     // copy list into array and delete list elements
-    int n = list.Number();
+    int n = list.GetCount();
     wxPoint *points = new wxPoint[n];
     int i = 0;
-    wxNode* node = 0;    
-    for ( node = list.First(); node; node = node->Next(), i++ )
+    wxNode* node = 0;
+    for ( node = list.GetFirst(); node; node = node->GetNext(), i++ )
     {
-        wxPoint *point = (wxPoint *)node->Data();
+        wxPoint *point = (wxPoint *)node->GetData();
         points[i].x = point->x;
         points[i].y = point->y;
         delete point;
     }
 
     // first draw the pie without pen, if necessary
-       if( GetBrush() != *wxTRANSPARENT_BRUSH )
+    if( GetBrush() != *wxTRANSPARENT_BRUSH )
     {
         wxPen tempPen( GetPen() );
         SetPen( *wxTRANSPARENT_PEN );
@@ -626,7 +912,7 @@ void wxDCBase::DoDrawEllipticArcRot( wxCoord x, wxCoord y,
     }
 
     // then draw the arc without brush, if necessary
-       if( GetPen() != *wxTRANSPARENT_PEN )
+    if( GetPen() != *wxTRANSPARENT_PEN )
     {
         // without center
         DoDrawLines( n-1, points, 0, 0 );
@@ -640,13 +926,13 @@ void wxDCBase::Rotate( wxList* points, double angle, wxPoint center )
 {
     if( angle != 0.0 )
     {
-        double pi(3.1415926536);
+        double pi(M_PI);
         double dSinA = -sin(angle*2.0*pi/360.0);
         double dCosA = cos(angle*2.0*pi/360.0);
-        for ( wxNode* node = points->First(); node; node = node->Next() )
+        for ( wxNode* node = points->GetFirst(); node; node = node->GetNext() )
         {
-            wxPoint* point = (wxPoint*)node->Data();
-    
+            wxPoint* point = (wxPoint*)node->GetData();
+
             // transform coordinates, if necessary
             if( center.x ) point->x -= center.x;
             if( center.y ) point->y -= center.y;
@@ -663,12 +949,12 @@ void wxDCBase::Rotate( wxList* points, double angle, wxPoint center )
     }
 }
 
-void wxDCBase::CalculateEllipticPoints( wxList* points, 
-                                        wxCoord xStart, wxCoord yStart, 
-                                        wxCoord w, wxCoord h, 
+void wxDCBase::CalculateEllipticPoints( wxList* points,
+                                        wxCoord xStart, wxCoord yStart,
+                                        wxCoord w, wxCoord h,
                                         double sa, double ea )
 {
-    double pi = 3.1415926535;
+    double pi = M_PI;
     double sar = 0;
     double ear = 0;
     int xsa = 0;
@@ -685,9 +971,9 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
     wxCoord b = h/2;
     // decrement 1 pixel if ellipse is smaller than 2*a, 2*b
     int decrX = 0;
-    if( 2*a == w ) decrX = 1; 
+    if( 2*a == w ) decrX = 1;
     int decrY = 0;
-    if( 2*b == h ) decrY = 1; 
+    if( 2*b == h ) decrY = 1;
     // center
     wxCoord xCenter = xStart + a;
     wxCoord yCenter = yStart + b;
@@ -711,7 +997,7 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
         ear = ea * pi / 180.0;
         // correct angle circle -> ellipse
         sar = atan( -a/(double)b * tan( sar ) );
-        if ( sq == 1 || sq == 2 ) sar += pi; 
+        if ( sq == 1 || sq == 2 ) sar += pi;
         ear = atan( -a/(double)b * tan( ear ) );
         if ( eq == 1 || eq == 2 ) ear += pi;
         // coordinates of points
@@ -750,7 +1036,7 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
             y2 = y2-y-y+1;
             --y;
         }
-        // old y now to big: set point with old y, old x 
+        // old y now to big: set point with old y, old x
         if( bNewPoint && x>1)
         {
             int x1 = x - 1;
@@ -761,7 +1047,7 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
             pointsarray[3].Append( (wxObject*) new wxPoint( xCenter + x1 - decrX, yCenter + y_old - decrY ) );
         } // set point
     } // calculate point
-    
+
     // Starting and/or ending points for the quadrants, first quadrant gets both.
     pointsarray[0].Insert( (wxObject*) new wxPoint( xCenter + a - decrX, yCenter ) );
     pointsarray[0].Append( (wxObject*) new wxPoint( xCenter, yCenter - b ) );
@@ -781,16 +1067,16 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
         bool bForceTurn = ( sq == eq && sa > ea );
         while( !bReady )
         {
-            for( wxNode *node = pointsarray[q].First(); node; node = node->Next() )
+            for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() )
             {
                 // once: go to starting point in start quadrant
                 if( !bStarted &&
-                    ( 
-                      ( (wxPoint*) node->Data() )->x < xsa+1 && q <= 1 
-                      ||  
-                      ( (wxPoint*) node->Data() )->x > xsa-1 && q >= 2
+                    (
+                      ( (wxPoint*) node->GetData() )->x < xsa+1 && q <= 1
+                      ||
+                      ( (wxPoint*) node->GetData() )->x > xsa-1 && q >= 2
                     )
-                  ) 
+                  )
                 {
                     bStarted = true;
                 }
@@ -800,18 +1086,18 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
                 {
                     if( q != eq || bForceTurn
                         ||
-                        ( (wxPoint*) node->Data() )->x > xea+1 && q <= 1 
-                        ||  
-                        ( (wxPoint*) node->Data() )->x < xea-1 && q >= 2
+                        ( (wxPoint*) node->GetData() )->x > xea+1 && q <= 1
+                        ||
+                        ( (wxPoint*) node->GetData() )->x < xea-1 && q >= 2
                       )
                     {
                         // copy point
-                        wxPoint* pPoint = new wxPoint( *((wxPoint*) node->Data() ) );
+                        wxPoint* pPoint = new wxPoint( *((wxPoint*) node->GetData() ) );
                         points->Append( (wxObject*) pPoint );
                     }
-                    else if( q == eq && !bForceTurn || ( (wxPoint*) node->Data() )->x == xea)
+                    else if( q == eq && !bForceTurn || ( (wxPoint*) node->GetData() )->x == xea)
                     {
-                        bReady = true; 
+                        bReady = true;
                     }
                 }
             } // for node
@@ -825,35 +1111,35 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
         // delete points
         for( q = 0; q < 4; ++q )
         {
-            for( wxNode *node = pointsarray[q].First(); node; node = node->Next() )
+            for( wxNode *node = pointsarray[q].GetFirst(); node; node = node->GetNext() )
             {
-                wxPoint *p = (wxPoint *)node->Data();
+                wxPoint *p = (wxPoint *)node->GetData();
                 delete p;
             }
-        }            
-        
+        }
     }
     else
     {
+        wxNode* node;
         // copy whole ellipse, wxPoints will be deleted outside
-        for( wxNode *node = pointsarray[0].First(); node; node = node->Next() )
+        for( node = pointsarray[0].GetFirst(); node; node = node->GetNext() )
         {
-            wxObject *p = node->Data();
+            wxObject *p = node->GetData();
             points->Append( p );
         }
-        for( node = pointsarray[1].First(); node; node = node->Next() )
+        for( node = pointsarray[1].GetFirst(); node; node = node->GetNext() )
         {
-            wxObject *p = node->Data();
+            wxObject *p = node->GetData();
             points->Append( p );
         }
-        for( node = pointsarray[2].First(); node; node = node->Next() )
+        for( node = pointsarray[2].GetFirst(); node; node = node->GetNext() )
         {
-            wxObject *p = node->Data();
+            wxObject *p = node->GetData();
             points->Append( p );
         }
-        for( node = pointsarray[3].First(); node; node = node->Next() )
+        for( node = pointsarray[3].GetFirst(); node; node = node->GetNext() )
         {
-            wxObject *p = node->Data();
+            wxObject *p = node->GetData();
             points->Append( p );
         }
     } // not iUseAngles
@@ -861,3 +1147,356 @@ void wxDCBase::CalculateEllipticPoints( wxList* points,
 
 #endif
 
+//
+// temporary home for wxOverlay
+//
+
+#include "wx/dcclient.h"
+#include "wx/dcmemory.h"
+
+#if defined(wxMAC_USE_CORE_GRAPHICS) && wxMAC_USE_CORE_GRAPHICS
+
+#include "wx/mac/private.h"
+#include "wx/toplevel.h"
+
+class wxOverlayImpl
+{
+public:
+    wxOverlayImpl() ;
+    ~wxOverlayImpl() ;
+    
+    
+    // clears the overlay without restoring the former state
+    // to be done eg when the window content has been changed and repainted
+    void Reset();
+    
+    // returns true if it has been setup
+    bool IsOk();
+    
+    void Init( wxWindowDC* dc, int x , int y , int width , int height );
+    
+    void BeginDrawing( wxWindowDC* dc);
+    
+    void EndDrawing( wxWindowDC* dc);
+    
+    void Clear( wxWindowDC* dc);
+
+private:
+    OSStatus CreateOverlayWindow();
+    
+    void MacGetBounds( Rect *bounds );
+    
+    WindowRef m_overlayWindow;
+    WindowRef m_overlayParentWindow;
+    CGContextRef m_overlayContext ;
+    // we store the window in case we would have to issue a Refresh()
+    wxWindow* m_window ;
+    
+    int m_x ;
+    int m_y ;
+    int m_width ;
+    int m_height ;
+} ;
+
+wxOverlayImpl::wxOverlayImpl()
+{
+    m_window = NULL ;
+    m_overlayContext = NULL ;
+    m_overlayWindow = NULL ;
+}
+
+wxOverlayImpl::~wxOverlayImpl()
+{
+    Reset();
+}
+
+bool wxOverlayImpl::IsOk() 
+{
+    return m_overlayWindow != NULL ;
+}
+
+void wxOverlayImpl::MacGetBounds( Rect *bounds )
+{
+    wxPoint origin(0,0);
+    origin = m_window->ClientToScreen( origin );
+    bounds->top = origin.y;
+    bounds->left = origin.x;
+    bounds->bottom = origin.y+m_y+m_height;
+    bounds->right = origin.x+m_x+m_width;
+}
+
+OSStatus wxOverlayImpl::CreateOverlayWindow()
+{
+    OSStatus err;
+
+    WindowAttributes overlayAttributes  = kWindowIgnoreClicksAttribute;
+        
+    m_overlayParentWindow =(WindowRef) m_window->MacGetTopLevelWindowRef();
+    
+    Rect bounds ;
+    MacGetBounds(&bounds);
+    err  = CreateNewWindow( kOverlayWindowClass, overlayAttributes, &bounds, &m_overlayWindow );  
+    if ( err == noErr ) 
+    {
+        SetWindowGroup( m_overlayWindow, GetWindowGroup(m_overlayParentWindow));    //  Put them in the same group so that their window layers are consistent
+        ShowWindow(m_overlayWindow);
+    }
+    return err;
+}
+
+void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height )
+{
+    wxASSERT_MSG( !IsOk() , _("You cannot Init an overlay twice") );
+
+    m_window = dc->GetWindow(); 
+    m_x = x ;
+    m_y = y ;
+    m_width = width ;
+    m_height = height ;
+    
+    OSStatus err = CreateOverlayWindow();
+    wxASSERT_MSG(  err == noErr , _("Couldn't create the overlay window") );
+
+    err = QDBeginCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
+    CGContextTranslateCTM( m_overlayContext, 0, m_height+m_y );
+    CGContextScaleCTM( m_overlayContext, 1, -1 );
+    wxASSERT_MSG(  err == noErr , _("Couldn't init the context on the overlay window") );
+}
+
+void wxOverlayImpl::BeginDrawing( wxWindowDC* dc)
+{
+    delete dc->m_graphicContext ;
+    dc->m_graphicContext = new wxMacCGContext( m_overlayContext );
+    // we are right now startin at 0,0 not at the wxWindow's origin, so most of the calculations 
+    // int dc are already corect
+    // just to make sure :
+    dc->m_macLocalOrigin.x = 0 ;
+    dc->m_macLocalOrigin.y = 0 ;
+    wxSize size = m_window->GetSize() ;
+    dc->SetClippingRegion( 0 , 0 , size.x , size.y ) ;
+}
+
+void wxOverlayImpl::EndDrawing( wxWindowDC* dc)
+{
+    delete dc->m_graphicContext ;
+    dc->m_graphicContext = NULL ;
+
+}
+
+void wxOverlayImpl::Clear(wxWindowDC* dc) 
+{
+    wxASSERT_MSG( IsOk() , _("You cannot Clear an overlay that is not inited") );
+    CGRect box  = CGRectMake( m_x - 1, m_y - 1 , m_width + 2 , m_height + 2 );
+    CGContextClearRect( m_overlayContext, box );
+}
+
+void wxOverlayImpl::Reset()
+{
+    if ( m_overlayContext )
+    {
+        OSStatus err = QDEndCGContext(GetWindowPort(m_overlayWindow), &m_overlayContext);
+        wxASSERT_MSG(  err == noErr , _("Couldn't end the context on the overlay window") );
+
+        m_overlayContext = NULL ;
+    }    
+    
+    // todo : don't dispose, only hide and reposition on next run
+    if (m_overlayWindow)
+    {
+        DisposeWindow(m_overlayWindow);
+        m_overlayWindow = NULL ;
+    }
+}
+
+//
+//
+//
+
+#else // ie not wxMAC_USE_CORE_GRAPHICS
+
+class wxOverlayImpl
+{
+public:
+    wxOverlayImpl() ;
+    ~wxOverlayImpl() ;
+    
+    
+    // clears the overlay without restoring the former state
+    // to be done eg when the window content has been changed and repainted
+    void Reset();
+    
+    // returns true if it has been setup
+    bool IsOk();
+    
+    void Init( wxWindowDC* dc, int x , int y , int width , int height );
+    
+    void BeginDrawing( wxWindowDC* dc);
+    
+    void EndDrawing( wxWindowDC* dc);
+    
+    void Clear( wxWindowDC* dc);
+
+private:
+    wxBitmap m_bmpSaved ;
+    int m_x ;
+    int m_y ;
+    int m_width ;
+    int m_height ;
+// this is to enable wxMOTIF and UNIV to compile....
+// currently (10 oct 06) we don't use m_window
+// ce - how do we fix this
+#if defined(__WXGTK__) || defined(__WXMSW__)
+//    
+    wxWindow* m_window ;
+#endif   
+} ;
+
+wxOverlayImpl::wxOverlayImpl()
+{
+#if defined(__WXGTK__) || defined(__WXMSW__)
+     m_window = NULL ;
+#endif   
+     m_x = m_y = m_width = m_height = 0 ;
+}
+
+wxOverlayImpl::~wxOverlayImpl()
+{
+}
+
+bool wxOverlayImpl::IsOk() 
+{
+    return m_bmpSaved.Ok() ;
+}
+
+void wxOverlayImpl::Init( wxWindowDC* dc, int x , int y , int width , int height )
+{
+#if defined(__WXGTK__)
+    m_window = dc->m_owner;
+#else
+    #if defined (__WXMSW__) 
+    m_window = dc->GetWindow();
+    #endif  // __WXMSW__
+   
+#endif
+    wxMemoryDC dcMem ;
+    m_bmpSaved.Create( width, height );
+    dcMem.SelectObject( m_bmpSaved );
+    m_x = x ;
+    m_y = y ;
+    m_width = width ;
+    m_height = height ;
+#if defined(__WXGTK__) && !defined(__WX_DC_BLIT_FIXED__)
+    wxPoint pt = dc->GetDeviceOrigin();
+    x += pt.x;
+    y += pt.y;
+#endif // broken wxGTK wxDC::Blit
+    dcMem.Blit(0, 0, m_width, m_height,
+        dc, x, y);
+    dcMem.SelectObject( wxNullBitmap );
+}
+
+void wxOverlayImpl::Clear(wxWindowDC* dc) 
+{
+    wxMemoryDC dcMem ;
+    dcMem.SelectObject( m_bmpSaved );
+    dc->Blit( m_x, m_y, m_width, m_height , &dcMem , 0 , 0 );
+    dcMem.SelectObject( wxNullBitmap );
+}
+
+void wxOverlayImpl::Reset()
+{
+    m_bmpSaved = wxBitmap();
+}
+
+void wxOverlayImpl::BeginDrawing(wxWindowDC*  WXUNUSED(dc))
+{
+}
+
+void wxOverlayImpl::EndDrawing(wxWindowDC* WXUNUSED(dc))
+{
+}
+
+#endif
+
+// common code
+
+wxOverlay::wxOverlay()
+{
+    m_impl = new wxOverlayImpl();
+    m_inDrawing = false;
+}
+
+wxOverlay::~wxOverlay()
+{
+    wxDELETE( m_impl );
+}
+
+bool wxOverlay::IsOk()
+{
+    return m_impl->IsOk();
+}
+
+void wxOverlay::Init( wxWindowDC* dc, int x , int y , int width , int height )
+{
+    m_impl->Init(dc, x, y, width, height);
+}
+
+void wxOverlay::BeginDrawing( wxWindowDC* dc)
+{
+    m_impl->BeginDrawing(dc);
+    m_inDrawing = true ;
+}
+
+void wxOverlay::EndDrawing( wxWindowDC* dc)
+{
+    m_impl->EndDrawing(dc);
+    m_inDrawing = false ;
+}
+
+void wxOverlay::Clear( wxWindowDC* dc)
+{
+    m_impl->Clear(dc);
+}
+
+void wxOverlay::Reset()
+{
+    wxASSERT_MSG(m_inDrawing==false,wxT("cannot reset overlay during drawing"));
+    m_impl->Reset();
+}
+
+// dc connector
+
+wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc, int x , int y , int width , int height) :
+    m_overlay(overlay)
+{
+    Init(dc, x, y, width, height);
+}
+
+wxDCOverlay::wxDCOverlay(wxOverlay &overlay, wxWindowDC *dc) :
+    m_overlay(overlay)
+{
+    int width;
+    int height;
+    dc->GetSize(&width,&height);
+    Init(dc, 0, 0, width, height);
+}
+
+wxDCOverlay::~wxDCOverlay()
+{
+    m_overlay.EndDrawing(m_dc);
+}
+
+void wxDCOverlay::Init(wxWindowDC *dc, int x , int y , int width , int height )
+{
+    m_dc = dc ;
+    if ( !m_overlay.IsOk() )
+    {
+        m_overlay.Init(dc,x,y,width,height);
+    }
+    m_overlay.BeginDrawing(dc);
+}
+
+void wxDCOverlay::Clear() 
+{
+    m_overlay.Clear(m_dc);
+}