]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/dcbase.cpp
Provide a task-dialog based wxMSW wxMessageDialog implementation.
[wxWidgets.git] / src / common / dcbase.cpp
index 977c96637cf6dde12bd2069f0bf69804831a074b..807c0cae30cfd062ead10c1698a73ac383546c68 100644 (file)
@@ -30,6 +30,7 @@
 #include "wx/dcscreen.h"
 #include "wx/dcprint.h"
 #include "wx/prntbase.h"
+#include "wx/scopeguard.h"
 
 #ifndef WX_PRECOMP
     #include "wx/math.h"
@@ -53,9 +54,9 @@
 #endif
 
 #ifdef __WXMAC__
-    #include "wx/mac/dcclient.h"
-    #include "wx/mac/dcmemory.h"
-    #include "wx/mac/dcscreen.h"
+    #include "wx/osx/dcclient.h"
+    #include "wx/osx/dcmemory.h"
+    #include "wx/osx/dcscreen.h"
 #endif
 
 #ifdef __WXPM__
@@ -131,34 +132,25 @@ IMPLEMENT_DYNAMIC_CLASS(wxDCFactoryCleanupModule, wxModule)
 // wxNativeDCFactory
 //-----------------------------------------------------------------------------
 
-wxDCImpl* wxNativeDCFactory::CreateWindowDC( wxWindowDC *owner )
-{
-    return new wxWindowDCImpl( owner );
-}
-
 wxDCImpl* wxNativeDCFactory::CreateWindowDC( wxWindowDC *owner, wxWindow *window )
 {
-    return new wxWindowDCImpl( owner, window );
-}
-
-wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner )
-{
-    return new wxClientDCImpl( owner );
+    wxDCImpl * const impl = new wxWindowDCImpl( owner, window );
+    impl->InheritAttributes(window);
+    return impl;
 }
 
 wxDCImpl* wxNativeDCFactory::CreateClientDC( wxClientDC *owner, wxWindow *window )
 {
-    return new wxClientDCImpl( owner, window );
-}
-
-wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner )
-{
-    return new wxPaintDCImpl( owner );
+    wxDCImpl * const impl = new wxClientDCImpl( owner, window );
+    impl->InheritAttributes(window);
+    return impl;
 }
 
 wxDCImpl* wxNativeDCFactory::CreatePaintDC( wxPaintDC *owner, wxWindow *window )
 {
-    return new wxPaintDCImpl( owner, window );
+    wxDCImpl * const impl = new wxPaintDCImpl( owner, window );
+    impl->InheritAttributes(window);
+    return impl;
 }
 
 wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner )
@@ -166,9 +158,19 @@ wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner )
     return new wxMemoryDCImpl( owner );
 }
 
-wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner, wxBitmap &bitmap )
+wxDCImpl* wxNativeDCFactory::CreateMemoryDC(wxMemoryDC *owner, wxBitmap& bitmap)
 {
-    return new wxMemoryDCImpl( owner, bitmap );
+    // the bitmap may be modified when it's selected into a memory DC so make
+    // sure changing this bitmap doesn't affect any other shallow copies of it
+    // (see wxMemoryDC::SelectObject())
+    //
+    // notice that we don't provide any ctor equivalent to SelectObjectAsSource
+    // method because this should be rarely needed and easy to work around by
+    // using the default ctor and calling SelectObjectAsSource itself
+    if ( bitmap.IsOk() )
+        bitmap.UnShare();
+
+    return new wxMemoryDCImpl(owner, bitmap);
 }
 
 wxDCImpl* wxNativeDCFactory::CreateMemoryDC( wxMemoryDC *owner, wxDC *dc )
@@ -299,12 +301,12 @@ wxPrinterDC::wxPrinterDC(const wxPrintData& data)
 {
 }
 
-wxRect wxPrinterDC::GetPaperRect()
+wxRect wxPrinterDC::GetPaperRect() const
 {
     return GetImpl()->GetPaperRect();
 }
 
-int wxPrinterDC::GetResolution()
+int wxPrinterDC::GetResolution() const
 {
     return GetImpl()->GetResolution();
 }
@@ -334,7 +336,7 @@ wxDCImpl::wxDCImpl( wxDC *owner )
         , m_minX(0), m_minY(0), m_maxX(0), m_maxY(0)
         , m_clipX1(0), m_clipY1(0), m_clipX2(0), m_clipY2(0)
         , m_logicalFunction(wxCOPY)
-        , m_backgroundMode(wxTRANSPARENT)
+        , m_backgroundMode(wxBRUSHSTYLE_TRANSPARENT)
         , m_mappingMode(wxMM_TEXT)
         , m_pen()
         , m_brush()
@@ -368,12 +370,12 @@ wxDCImpl::~wxDCImpl()
 
 wxCoord wxDCImpl::DeviceToLogicalX(wxCoord x) const
 {
-    return wxRound((double)(x - m_deviceOriginX - m_deviceLocalOriginX) / m_scaleX) * m_signX + m_logicalOriginX;
+    return wxRound( (double)((x - m_deviceOriginX - m_deviceLocalOriginX) * m_signX) / m_scaleX ) + m_logicalOriginX ;
 }
 
 wxCoord wxDCImpl::DeviceToLogicalY(wxCoord y) const
 {
-    return wxRound((double)(y - m_deviceOriginY - m_deviceLocalOriginY) / m_scaleY) * m_signY + m_logicalOriginY;
+    return wxRound( (double)((y - m_deviceOriginY - m_deviceLocalOriginY) * m_signY) / m_scaleY ) + m_logicalOriginY ;
 }
 
 wxCoord wxDCImpl::DeviceToLogicalXRel(wxCoord x) const
@@ -388,12 +390,12 @@ wxCoord wxDCImpl::DeviceToLogicalYRel(wxCoord y) const
 
 wxCoord wxDCImpl::LogicalToDeviceX(wxCoord x) const
 {
-    return wxRound((double)(x - m_logicalOriginX) * m_scaleX) * m_signX + m_deviceOriginX * m_signY + m_deviceLocalOriginX;
+    return wxRound( (double)((x - m_logicalOriginX) * m_signX) * m_scaleX) + m_deviceOriginX + m_deviceLocalOriginX;
 }
 
 wxCoord wxDCImpl::LogicalToDeviceY(wxCoord y) const
 {
-    return wxRound((double)(y - m_logicalOriginY) * m_scaleY) * m_signY + m_deviceOriginY * m_signY + m_deviceLocalOriginY;
+    return wxRound( (double)((y - m_logicalOriginY) * m_signY) * m_scaleY) + m_deviceOriginY + m_deviceLocalOriginY;
 }
 
 wxCoord wxDCImpl::LogicalToDeviceXRel(wxCoord x) const
@@ -412,7 +414,7 @@ void wxDCImpl::ComputeScaleAndOrigin()
     m_scaleY = m_logicalScaleY * m_userScaleY;
 }
 
-void wxDCImpl::SetMapMode( int mode )
+void wxDCImpl::SetMapMode( wxMappingMode mode )
 {
     switch (mode)
     {
@@ -568,7 +570,7 @@ void wxDCImpl::GetMultiLineTextExtent(const wxString& text,
     wxString curLine;
     for ( wxString::const_iterator pc = text.begin(); ; ++pc )
     {
-        if ( pc == text.end() || *pc == _T('\n') )
+        if ( pc == text.end() || *pc == wxT('\n') )
         {
             if ( curLine.empty() )
             {
@@ -584,7 +586,7 @@ void wxDCImpl::GetMultiLineTextExtent(const wxString& text,
                 if ( !heightLineDefault )
                 {
                     // but we don't know it yet - choose something reasonable
-                    DoGetTextExtent(_T("W"), NULL, &heightLineDefault,
+                    DoGetTextExtent(wxT("W"), NULL, &heightLineDefault,
                                   NULL, NULL, font);
                 }
 
@@ -649,13 +651,13 @@ wxDCImpl::DoStretchBlit(wxCoord xdest, wxCoord ydest,
                         wxDC *source,
                         wxCoord xsrc, wxCoord ysrc,
                         wxCoord srcWidth, wxCoord srcHeight,
-                        int rop,
+                        wxRasterOperationMode rop,
                         bool useMask,
                         wxCoord xsrcMask,
                         wxCoord ysrcMask)
 {
     wxCHECK_MSG( srcWidth && srcHeight && dstWidth && dstHeight, false,
-                 _T("invalid blit size") );
+                 wxT("invalid blit size") );
 
     // emulate the stretching by modifying the DC scale
     double xscale = (double)srcWidth/dstWidth,
@@ -695,7 +697,7 @@ void wxDCImpl::DrawLines(const wxPointList *list, wxCoord xoffset, wxCoord yoffs
 
 void wxDCImpl::DrawPolygon(const wxPointList *list,
                            wxCoord xoffset, wxCoord yoffset,
-                           int fillStyle)
+                           wxPolygonFillMode fillStyle)
 {
     int n = list->GetCount();
     wxPoint *points = new wxPoint[n];
@@ -718,7 +720,7 @@ wxDCImpl::DoDrawPolyPolygon(int n,
                             int count[],
                             wxPoint points[],
                             wxCoord xoffset, wxCoord yoffset,
-                            int fillStyle)
+                            wxPolygonFillMode fillStyle)
 {
     if ( n == 1 )
     {
@@ -745,7 +747,7 @@ wxDCImpl::DoDrawPolyPolygon(int n,
     }
 
     pen = GetPen();
-    SetPen(wxPen(*wxBLACK, 0, wxTRANSPARENT));
+    SetPen(wxPen(*wxBLACK, 0, wxPENSTYLE_TRANSPARENT));
     DoDrawPolygon(j, pts, xoffset, yoffset, fillStyle);
     SetPen(pen);
     for (i = j = 0; i < n; i++)
@@ -758,38 +760,21 @@ wxDCImpl::DoDrawPolyPolygon(int n,
 
 #if wxUSE_SPLINES
 
-void wxDCImpl::DoDrawSpline(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord x3, wxCoord y3)
+void wxDCImpl::DrawSpline(wxCoord x1, wxCoord y1,
+                          wxCoord x2, wxCoord y2,
+                          wxCoord x3, wxCoord y3)
 {
-    wxPointList point_list;
-
-    wxPoint *point1 = new wxPoint;
-    point1->x = x1; point1->y = y1;
-    point_list.Append( point1 );
-
-    wxPoint *point2 = new wxPoint;
-    point2->x = x2; point2->y = y2;
-    point_list.Append( point2 );
-
-    wxPoint *point3 = new wxPoint;
-    point3->x = x3; point3->y = y3;
-    point_list.Append( point3 );
-
-    DoDrawSpline(&point_list);
-
-    for( wxPointList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() )
-    {
-        wxPoint *p = node->GetData();
-        delete p;
-    }
+    wxPoint points[] = { wxPoint(x1, y1), wxPoint(x2, y2), wxPoint(x3, y3) };
+    DrawSpline(WXSIZEOF(points), points);
 }
 
-void wxDCImpl::DoDrawSpline(int n, wxPoint points[])
+void wxDCImpl::DrawSpline(int n, wxPoint points[])
 {
     wxPointList list;
-    for (int i =0; i < n; i++)
-        list.Append( &points[i] );
+    for ( int i = 0; i < n; i++ )
+        list.Append(&points[i]);
 
-    DoDrawSpline(&list);
+    DrawSpline(&list);
 }
 
 // ----------------------------------- spline code ----------------------------------------
@@ -804,7 +789,7 @@ void wx_spline_push(double x1, double y1, double x2, double y2, double x3, doubl
 static bool wx_spline_add_point(double x, double y);
 static void wx_spline_draw_point_array(wxDC *dc);
 
-wxPointList wx_spline_point_list;
+static wxPointList wx_spline_point_list;
 
 #define                half(z1, z2)        ((z1+z2)/2.0)
 #define                THRESHOLD        5
@@ -1013,7 +998,7 @@ void wxDCImpl::DoGradientFillLinear(const wxRect& rect,
                 nB = nB1 + (nB2-nB1)*(w-x)/w;
 
             wxColour colour(nR,nG,nB);
-            SetPen(wxPen(colour, 1, wxSOLID));
+            SetPen(wxPen(colour, 1, wxPENSTYLE_SOLID));
             SetBrush(wxBrush(colour));
             if(nDirection == wxEAST)
                 DoDrawRectangle(rect.GetRight()-x-xDelta+1, rect.GetTop(),
@@ -1050,7 +1035,7 @@ void wxDCImpl::DoGradientFillLinear(const wxRect& rect,
                 nB = nB1 + (nB2-nB1)*(w-y)/w;
 
             wxColour colour(nR,nG,nB);
-            SetPen(wxPen(colour, 1, wxSOLID));
+            SetPen(wxPen(colour, 1, wxPENSTYLE_SOLID));
             SetBrush(wxBrush(colour));
             if(nDirection == wxNORTH)
                 DoDrawRectangle(rect.GetLeft(), rect.GetTop()+y,
@@ -1070,8 +1055,9 @@ void wxDCImpl::DoGradientFillConcentric(const wxRect& rect,
                                       const wxColour& destColour,
                                       const wxPoint& circleCenter)
 {
-    //save the old pen color
-    wxColour oldPenColour = m_pen.GetColour();
+    // save the old pen and ensure it is restored on exit
+    const wxPen penOrig = m_pen;
+    wxON_BLOCK_EXIT_SET(m_pen, penOrig);
 
     wxUint8 nR1 = destColour.Red();
     wxUint8 nG1 = destColour.Green();
@@ -1116,12 +1102,21 @@ void wxDCImpl::DoGradientFillConcentric(const wxRect& rect,
             nB = (wxUint8)(nB1 + ((nB2 - nB1) * nGradient / 100));
 
             //set the pixel
-            m_pen.SetColour(wxColour(nR,nG,nB));
+            m_pen = wxColour(nR,nG,nB);
             DoDrawPoint(x + rect.GetLeft(), y + rect.GetTop());
         }
     }
-    //return old pen color
-    m_pen.SetColour(oldPenColour);
+}
+
+void wxDCImpl::InheritAttributes(wxWindow *win)
+{
+    wxCHECK_RET( win, "window can't be NULL" );
+
+    SetFont(win->GetFont());
+    SetTextForeground(win->GetForegroundColour());
+    SetTextBackground(win->GetBackgroundColour());
+    SetBackground(win->GetBackgroundColour());
+    SetLayoutDirection(win->GetLayoutDirection());
 }
 
 //-----------------------------------------------------------------------------
@@ -1130,6 +1125,15 @@ void wxDCImpl::DoGradientFillConcentric(const wxRect& rect,
 
 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
 
+void wxDC::CopyAttributes(const wxDC& dc)
+{
+    SetFont(dc.GetFont());
+    SetTextForeground(dc.GetTextForeground());
+    SetTextBackground(dc.GetTextBackground());
+    SetBackground(dc.GetBackground());
+    SetLayoutDirection(dc.GetLayoutDirection());
+}
+
 void wxDC::DrawLabel(const wxString& text,
                          const wxBitmap& bitmap,
                          const wxRect& rect,
@@ -1201,10 +1205,16 @@ void wxDC::DrawLabel(const wxString& text,
             yUnderscore = 0;
 
     // split the string into lines and draw each of them separately
+    //
+    // NB: while wxDC::DrawText() on some platforms supports drawing multi-line
+    //     strings natively, this is not the case for all of them, notably not
+    //     wxMSW which uses this function for multi-line texts, so we may only
+    //     call DrawText() for single-line strings from here to avoid infinite
+    //     recursion.
     wxString curLine;
     for ( wxString::const_iterator pc = text.begin(); ; ++pc )
     {
-        if ( *pc == _T('\n') || pc == text.end() )
+        if ( pc == text.end() || *pc == '\n' )
         {
             int xRealStart = x; // init it here to avoid compielr warnings
 
@@ -1269,7 +1279,7 @@ void wxDC::DrawLabel(const wxString& text,
     if ( startUnderscore != endUnderscore )
     {
         // it should be of the same colour as text
-        SetPen(wxPen(GetTextForeground(), 0, wxSOLID));
+        SetPen(wxPen(GetTextForeground(), 0, wxPENSTYLE_SOLID));
 
         yUnderscore--;
 
@@ -1338,6 +1348,13 @@ void wxDC::GetClippingBox(long *x, long *y, long *w, long *h) const
         if (h) *h = hh;
     }
 
+void wxDC::DrawObject(wxDrawObject* drawobject)
+{
+    drawobject->Draw(*this);
+    CalcBoundingBox(drawobject->MinX(),drawobject->MinY());
+    CalcBoundingBox(drawobject->MaxX(),drawobject->MaxY());
+}
+
 #endif  // WXWIN_COMPATIBILITY_2_8
 
 /*
@@ -1654,3 +1671,15 @@ void wxDCImpl::CalculateEllipticPoints( wxPointList* points,
 } // CalculateEllipticPoints
 
 #endif // __WXWINCE__
+
+float wxDCImpl::GetFontPointSizeAdjustment(float dpi)
+{
+    // wxMSW has long-standing bug where wxFont point size is interpreted as
+    // "pixel size corresponding to given point size *on screen*". In other
+    // words, on a typical 600dpi printer and a typical 96dpi screen, fonts
+    // are ~6 times smaller when printing. Unfortunately, this bug is so severe
+    // that *all* printing code has to account for it and consequently, other
+    // ports need to emulate this bug too:
+    const wxSize screenPPI = wxGetDisplayPPI();
+    return float(screenPPI.y) / dpi;
+}