]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/dcbase.cpp
Use WM_INITMENUPOPUP
[wxWidgets.git] / src / common / dcbase.cpp
index 9cd65312e32085841ea565c1e74172520169c2f2..8534732e7ba1577775e4a9e70b8b59365cea589c 100644 (file)
@@ -1,18 +1,26 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        dc.cpp
-// Purpose:     wxDC Class
-// Author:      Brian Macy
+// Name:        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
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
+// ============================================================================
+// declarations
+// ============================================================================
+
 #ifdef __GNUG__
-#pragma implementation "dcbase.h"
+    #pragma implementation "dcbase.h"
 #endif
 
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 
 #include "wx/dc.h"
 
+#include <math.h>
+
+// bool wxDCBase::sm_cacheing = FALSE;
+
+// ============================================================================
+// implementation
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// special symbols
+// ----------------------------------------------------------------------------
+
 void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1,
                                wxCoord width, wxCoord height)
 {
@@ -43,15 +63,19 @@ void wxDCBase::DoDrawCheckMark(wxCoord x1, wxCoord y1,
     CalcBoundingBox(x2, y2);
 }
 
+// ----------------------------------------------------------------------------
+// line/polygons
+// ----------------------------------------------------------------------------
+
 void wxDCBase::DrawLines(const wxList *list, wxCoord xoffset, wxCoord yoffset)
 {
-    int n = list->Number();
+    int n = list->GetCount();
     wxPoint *points = new wxPoint[n];
 
     int i = 0;
-    for ( wxNode *node = list->First(); node; node = node->Next(), i++ )
+    for ( wxList::compatibility_iterator 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;
     }
@@ -66,13 +90,13 @@ void wxDCBase::DrawPolygon(const wxList *list,
                            wxCoord xoffset, wxCoord yoffset,
                            int fillStyle)
 {
-    int n = list->Number();
+    int n = list->GetCount();
     wxPoint *points = new wxPoint[n];
 
     int i = 0;
-    for ( wxNode *node = list->First(); node; node = node->Next(), i++ )
+    for ( wxList::compatibility_iterator 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;
     }
@@ -82,6 +106,9 @@ void wxDCBase::DrawPolygon(const wxList *list,
     delete [] points;
 }
 
+// ----------------------------------------------------------------------------
+// splines
+// ----------------------------------------------------------------------------
 
 #if wxUSE_SPLINES
 
@@ -104,9 +131,9 @@ void wxDCBase::DrawSpline(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoor
 
     DrawSpline(&point_list);
 
-    for( wxNode *node = point_list.First(); node; node = node->Next() )
+    for( wxList::compatibility_iterator node = point_list.GetFirst(); node; node = node->GetNext() )
     {
-        wxPoint *p = (wxPoint *)node->Data();
+        wxPoint *p = (wxPoint *)node->GetData();
         delete p;
     }
 }
@@ -227,13 +254,13 @@ static bool wx_spline_add_point(double x, double y)
 static void wx_spline_draw_point_array(wxDCBase *dc)
 {
   dc->DrawLines(&wx_spline_point_list, 0, 0 );
-  wxNode *node = wx_spline_point_list.First();
+  wxList::compatibility_iterator node = wx_spline_point_list.GetFirst();
   while (node)
   {
-    wxPoint *point = (wxPoint *)node->Data();
+    wxPoint *point = (wxPoint *)node->GetData();
     delete point;
-    delete node;
-    node = wx_spline_point_list.First();
+    wx_spline_point_list.Erase(node);
+    node = wx_spline_point_list.GetFirst();
   }
 }
 
@@ -245,14 +272,14 @@ void wxDCBase::DoDrawSpline( wxList *points )
     double           cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
     double           x1, y1, x2, y2;
 
-    wxNode *node = points->First();
-    p = (wxPoint *)node->Data();
+    wxList::compatibility_iterator node = points->GetFirst();
+    p = (wxPoint *)node->GetData();
 
     x1 = p->x;
     y1 = p->y;
 
-    node = node->Next();
-    p = (wxPoint *)node->Data();
+    node = node->GetNext();
+    p = (wxPoint *)node->GetData();
 
     x2 = p->x;
     y2 = p->y;
@@ -263,9 +290,9 @@ void wxDCBase::DoDrawSpline( wxList *points )
 
     wx_spline_add_point(x1, y1);
 
-    while ((node = node->Next()) != NULL)
+    while ((node = node->GetNext()))
     {
-        p = (wxPoint *)node->Data();
+        p = (wxPoint *)node->GetData();
         x1 = x2;
         y1 = y2;
         x2 = p->x;
@@ -290,3 +317,230 @@ void wxDCBase::DoDrawSpline( wxList *points )
 }
 
 #endif // wxUSE_SPLINES
+
+// ----------------------------------------------------------------------------
+// enhanced text drawing
+// ----------------------------------------------------------------------------
+
+void wxDCBase::GetMultiLineTextExtent(const wxString& text,
+                                      wxCoord *x,
+                                      wxCoord *y,
+                                      wxCoord *h,
+                                      wxFont *font)
+{
+    wxCoord widthTextMax = 0, widthLine,
+            heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
+
+    wxString curLine;
+    for ( const wxChar *pc = text; ; pc++ )
+    {
+        if ( *pc == _T('\n') || *pc == _T('\0') )
+        {
+            if ( curLine.empty() )
+            {
+                // we can't use GetTextExtent - it will return 0 for both width
+                // and height and an empty line should count in height
+                // calculation
+
+                // assume that this line has the same height as the previous
+                // one
+                if ( !heightLineDefault )
+                    heightLineDefault = heightLine;
+
+                if ( !heightLineDefault )
+                {
+                    // but we don't know it yet - choose something reasonable
+                    GetTextExtent(_T("W"), NULL, &heightLineDefault,
+                                  NULL, NULL, font);
+                }
+
+                heightTextTotal += heightLineDefault;
+            }
+            else
+            {
+                GetTextExtent(curLine, &widthLine, &heightLine,
+                              NULL, NULL, font);
+                if ( widthLine > widthTextMax )
+                    widthTextMax = widthLine;
+                heightTextTotal += heightLine;
+            }
+
+            if ( *pc == _T('\n') )
+            {
+               curLine.clear();
+            }
+            else
+            {
+               // the end of string
+               break;
+            }
+        }
+        else
+        {
+            curLine += *pc;
+        }
+    }
+
+    if ( x )
+        *x = widthTextMax;
+    if ( y )
+        *y = heightTextTotal;
+    if ( h )
+        *h = heightLine;
+}
+
+void wxDCBase::DrawLabel(const wxString& text,
+                         const wxBitmap& bitmap,
+                         const wxRect& rect,
+                         int alignment,
+                         int indexAccel,
+                         wxRect *rectBounding)
+{
+    // find the text position
+    wxCoord widthText, heightText, heightLine;
+    GetMultiLineTextExtent(text, &widthText, &heightText, &heightLine);
+
+    wxCoord width, height;
+    if ( bitmap.Ok() )
+    {
+        width = widthText + bitmap.GetWidth();
+        height = bitmap.GetHeight();
+    }
+    else // no bitmap
+    {
+        width = widthText;
+        height = heightText;
+    }
+
+    wxCoord x, y;
+    if ( alignment & wxALIGN_RIGHT )
+    {
+        x = rect.GetRight() - width;
+    }
+    else if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
+    {
+        x = (rect.GetLeft() + rect.GetRight() + 1 - width) / 2;
+    }
+    else // alignment & wxALIGN_LEFT
+    {
+        x = rect.GetLeft();
+    }
+
+    if ( alignment & wxALIGN_BOTTOM )
+    {
+        y = rect.GetBottom() - height;
+    }
+    else if ( alignment & wxALIGN_CENTRE_VERTICAL )
+    {
+        y = (rect.GetTop() + rect.GetBottom() + 1 - height) / 2;
+    }
+    else // alignment & wxALIGN_TOP
+    {
+        y = rect.GetTop();
+    }
+
+    // draw the bitmap first
+    wxCoord x0 = x,
+            y0 = y,
+            width0 = width;
+    if ( bitmap.Ok() )
+    {
+        DrawBitmap(bitmap, x, y, TRUE /* use mask */);
+
+        wxCoord offset = bitmap.GetWidth() + 4;
+        x += offset;
+        width -= offset;
+
+        y += (height - heightText) / 2;
+    }
+
+    // we will draw the underscore under the accel char later
+    wxCoord startUnderscore = 0,
+            endUnderscore = 0,
+            yUnderscore = 0;
+
+    // split the string into lines and draw each of them separately
+    wxString curLine;
+    for ( const wxChar *pc = text; ; pc++ )
+    {
+        if ( *pc == _T('\n') || *pc == _T('\0') )
+        {
+            int xRealStart = x; // init it here to avoid compielr warnings
+
+            if ( !curLine.empty() )
+            {
+                // NB: can't test for !(alignment & wxALIGN_LEFT) because
+                //     wxALIGN_LEFT is 0
+                if ( alignment & (wxALIGN_RIGHT | wxALIGN_CENTRE_HORIZONTAL) )
+                {
+                    wxCoord widthLine;
+                    GetTextExtent(curLine, &widthLine, NULL);
+
+                    if ( alignment & wxALIGN_RIGHT )
+                    {
+                        xRealStart += width - widthLine;
+                    }
+                    else // if ( alignment & wxALIGN_CENTRE_HORIZONTAL )
+                    {
+                        xRealStart += (width - widthLine) / 2;
+                    }
+                }
+                //else: left aligned, nothing to do
+
+                DrawText(curLine, xRealStart, y);
+            }
+
+            y += heightLine;
+
+            // do we have underscore in this line? we can check yUnderscore
+            // because it is set below to just y + heightLine if we do
+            if ( y == yUnderscore )
+            {
+                // adjust the horz positions to account for the shift
+                startUnderscore += xRealStart;
+                endUnderscore += xRealStart;
+            }
+
+            if ( *pc == _T('\0') )
+                break;
+
+            curLine.clear();
+        }
+        else // not end of line
+        {
+            if ( pc - text.c_str() == indexAccel )
+            {
+                // remeber to draw underscore here
+                GetTextExtent(curLine, &startUnderscore, NULL);
+                curLine += *pc;
+                GetTextExtent(curLine, &endUnderscore, NULL);
+
+                yUnderscore = y + heightLine;
+            }
+            else
+            {
+                curLine += *pc;
+            }
+        }
+    }
+
+    // draw the underscore if found
+    if ( startUnderscore != endUnderscore )
+    {
+        // it should be of the same colour as text
+        SetPen(wxPen(GetTextForeground(), 0, wxSOLID));
+
+        yUnderscore--;
+
+        DrawLine(startUnderscore, yUnderscore, endUnderscore, yUnderscore);
+    }
+
+    // return bounding rect if requested
+    if ( rectBounding )
+    {
+        *rectBounding = wxRect(x, y - heightText, widthText, heightText);
+    }
+
+    CalcBoundingBox(x0, y0);
+    CalcBoundingBox(x0 + width0, y0 + height);
+}