]>
git.saurik.com Git - wxWidgets.git/blob - src/os2/ownerdrw.cpp
   1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        msw/ownerdrw.cpp 
   3 // Purpose:     implementation of wxOwnerDrawn class 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  13 #pragma implementation 
  16 // For compilers that support precompilation, includes "wx.h". 
  17 #include "wx/wxprec.h" 
  20   #include "wx/window.h" 
  21   #include "wx/os2/private.h" 
  23   #include "wx/bitmap.h" 
  24   #include "wx/dcmemory.h" 
  31 #include "wx/settings.h" 
  32 #include "wx/ownerdrw.h" 
  33 #include "wx/menuitem.h" 
  36 // ============================================================================ 
  37 // implementation of wxOwnerDrawn class 
  38 // ============================================================================ 
  44 wxOwnerDrawn::wxOwnerDrawn( const wxString
& rsStr
, 
  46                             bool            WXUNUSED(bMenuItem
) ) 
  49     m_bCheckable   
= bCheckable
; 
  50     m_bOwnerDrawn  
= FALSE
; 
  52     m_nMarginWidth 
= ms_nLastMarginWidth
; 
  54         m_font 
= *wxNORMAL_FONT
; 
  55 } // end of wxOwnerDrawn::wxOwnerDrawn 
  57 wxOwnerDrawn::~wxOwnerDrawn() { } 
  59 size_t wxOwnerDrawn::ms_nDefaultMarginWidth 
= 15; 
  61 size_t wxOwnerDrawn::ms_nLastMarginWidth 
= ms_nDefaultMarginWidth
; 
  68 bool wxOwnerDrawn::OnMeasureItem( size_t* pWidth
, 
  73     wxString  sStr 
= wxStripMenuCodes(m_strName
); 
  76     // If we have a valid accel string, then pad out 
  77     // the menu string so that the menu and accel string are not 
  78     // placed on top of each other. 
  79     if (!m_strAccel
.empty() ) 
  81         sStr
.Pad(sStr
.Length()%8
); 
  84     vDC
.SetFont(GetFont()); 
  85     vDC
.GetTextExtent( sStr
 
  89     if (!m_strAccel
.empty()) 
  92         // Measure the accelerator string, and add its width to 
  93         // the total item width, plus 16 (Accelerators are right justified, 
  94         // with the right edge of the text rectangle 16 pixels left of 
  95         // the right edge of the menu) 
 100         vDC
.GetTextExtent( m_strAccel
 
 104         *pWidth 
+= nAccelWidth
; 
 108     // Add space at the end of the menu for the submenu expansion arrow. 
 109     // This will also allow offsetting the accel string from the right edge 
 111     *pWidth 
= (size_t)(*pWidth 
+ GetDefaultMarginWidth() * 1.5); 
 114     // JACS: items still look too tightly packed, so adding 5 pixels. 
 119     // Ray Gilbert's changes - Corrects the problem of a BMP 
 120     // being placed next to text in a menu item, and the BMP does 
 121     // not match the size expected by the system.  This will 
 122     // resize the space so the BMP will fit.  Without this, BMPs 
 123     // must be no larger or smaller than 16x16. 
 125     if (m_bmpChecked
.Ok()) 
 128         // Is BMP height larger then text height? 
 130         size_t                      nAdjustedHeight 
= m_bmpChecked
.GetHeight() + 
 131                                                       wxSystemSettings::GetMetric(wxSYS_EDGE_Y
); 
 132         if (*pHeight 
< nAdjustedHeight
) 
 133             *pHeight 
= nAdjustedHeight
; 
 136         // Does BMP encroach on default check menu position? 
 138         size_t                      nAdjustedWidth 
= m_bmpChecked
.GetWidth() + 
 139                                                      (wxSystemSettings::GetMetric(wxSYS_EDGE_X
) * 2); 
 142         // Do we need to widen margin to fit BMP? 
 144         if ((size_t)GetMarginWidth() < nAdjustedWidth
) 
 145             SetMarginWidth(nAdjustedWidth
); 
 148         // Add the size of the bitmap to our total size... 
 150         *pWidth 
+= GetMarginWidth(); 
 154     // Add the size of the bitmap to our total size - even if we don't have 
 155     // a bitmap we leave room for one... 
 157     *pWidth 
+= GetMarginWidth(); 
 160     // Make sure that this item is at least as 
 161     // tall as the user's system settings specify 
 163     if (*pHeight 
< m_nMinHeight
) 
 164         *pHeight 
= m_nMinHeight
; 
 165     m_nHeight 
= *pHeight
;                // remember height for use in OnDrawItem 
 167 } // end of wxOwnerDrawn::OnMeasureItem 
 170 bool wxOwnerDrawn::OnDrawItem( wxDC
& rDC
, 
 176     // We do nothing on focus change 
 178     if (eAction 
== wxODFocusChanged 
) 
 182     // Select the font and draw the text 
 183     // --------------------------------- 
 187     HPS                             hPS
= rDC
.GetHPS(); 
 191     RECTL                           vRect 
= {rRect
.x 
+ 4, rRect
.y 
+ 1, rRect
.x 
+ (rRect
.width 
- 2), rRect
.y 
+ rRect
.height
}; 
 193     memset(&vCbnd
, 0, sizeof(CHARBUNDLE
)); 
 196     // Use default font if no font set 
 200         m_font
.RealizeResource(); 
 204         ::GpiSetCharSet(hPS
, LCID_DEFAULT
); 
 208     // Based on the status of the menu item, pick the right colors 
 210     if (eStatus 
& wxODSelected
) 
 212         wxColour                        
vCol2(wxT("WHITE")); 
 213         vColBack
.Set( (unsigned char)0 
 216                     ); // no dark blue in color table 
 219     else if (eStatus 
& wxODDisabled
) 
 221         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 222                                          ,SYSCLR_MENU 
// Light gray 
 225         vColBack
.Set( GetRValue(vRef
) 
 229         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 230                                          ,SYSCLR_MENUDISABLEDTEXT 
// dark gray 
 233         vColText
.Set( GetRValue(vRef
) 
 241         // Fall back to default colors if none explicitly specified 
 243         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 244                                   ,SYSCLR_MENU  
// we are using gray for all our window backgrounds in wxWidgets 
 247         vColBack
.Set( GetRValue(vRef
) 
 251         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 252                                   ,SYSCLR_WINDOWTEXT 
// Black 
 255         vColText
.Set( GetRValue(vRef
) 
 261     rDC
.SetTextBackground(vColBack
); 
 262     rDC
.SetTextForeground(vColText
); 
 263     rDC
.SetBackgroundMode(wxTRANSPARENT
); 
 264     vCbnd
.lColor     
= vColText
.GetPixel(); 
 265     vCbnd
.lBackColor 
= vColBack
.GetPixel(); 
 268                   ,CBB_BACK_COLOR 
| CBB_COLOR
 
 277     // Paint the background 
 279     ::WinFillRect(hPS
, &vRect
, vColBack
.GetPixel()); 
 282     // Determine where to draw and leave space for a check-mark. 
 284     int                             nX 
= rRect
.x 
+ GetMarginWidth(); 
 287     // Unfortunately, unlike Win32, PM has no owner drawn specific text 
 288     // drawing methods like ::DrawState that can cleanly handle accel 
 289     // mnemonics and deal, automatically, with various states, so we have 
 290     // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn 
 291     // strings either.  We cannot handle mnemonics either.  We display 
 292     // them, though, in the hope we can figure them out some day. 
 296     // Display main text and accel text separately to align better 
 298     wxString sTgt 
= wxT("\t"); 
 299     wxString sFullString 
= m_strName
; // need to save the original text 
 305     bool     bFoundMnemonic 
= false; 
 306     bool     bFoundAccel 
= false; 
 309     // Deal with the tab, extracting the Accel text 
 311     nIndex 
= sFullString
.Find(sTgt
.c_str()); 
 315         sAccel 
= sFullString
.Mid(nIndex 
+ 1); 
 316         sFullString
.Remove(nIndex
); 
 320     // Deal with the mnemonic character 
 323     nIndex 
= sFullString
.Find(sTgt
.c_str()); 
 326         wxString sTmp 
= sFullString
; 
 328         bFoundMnemonic 
= true; 
 330         rDC
.GetTextExtent( sTmp
 
 334         sTmp 
= sFullString
[(size_t)(nIndex 
+ 1)]; 
 335         rDC
.GetTextExtent( sTmp
 
 339         sFullString
.Replace(sTgt
.c_str(), wxEmptyString
, true); 
 343     // Draw the main item text sans the accel text 
 345     POINTL                      vPntStart 
= {nX
, rRect
.y 
+ 4}; 
 346     ::GpiCharStringAt( rDC
.GetHPS() 
 348                       ,sFullString
.length() 
 349                       ,(PCH
)sFullString
.c_str() 
 354         // Underline the mnemonic -- still won't work, but at least it "looks" right 
 357         POINTL                      vPntEnd 
= {nX 
+ nWidth 
+ nCharWidth 
- 3, rRect
.y 
+ 2}; //CharWidth is bit wide 
 359         vPntStart
.x 
= nX 
+ nWidth 
- 1; 
 360         vPntStart
.y 
= rRect
.y 
+ 2; // Make it look pretty! 
 361         vPen 
= wxPen(vColText
, 1, wxSOLID
); // Assuming we are always black 
 363         ::GpiMove(hPS
, &vPntStart
); 
 364         ::GpiLine(hPS
, &vPntEnd
); 
 368     // Now draw the accel text 
 375         rDC
.GetTextExtent( sAccel
 
 380         // Back off the starting position from the right edge 
 382         vPntStart
.x 
= rRect
.width 
- (nWidth 
+ 7); 
 383         vPntStart
.y 
= rRect
.y 
+ 4; 
 384         ::GpiCharStringAt( rDC
.GetHPS() 
 395     if (IsCheckable() && !m_bmpChecked
.Ok()) 
 397         if (eStatus 
& wxODChecked
) 
 400             HBITMAP                 hBmpCheck 
= ::WinGetSysBitmap(HWND_DESKTOP
, SBMP_MENUCHECK
); 
 402             vRect
.xLeft   
= rRect
.x
; 
 403             vRect
.xRight  
= rRect
.x 
+ GetMarginWidth(); 
 404             vRect
.yBottom 
= rRect
.y
; 
 405             vRect
.yTop    
= rRect
.y 
+ m_nHeight 
- 3; 
 407             ::WinDrawBitmap( hPS             
// PS for this menuitem 
 408                             ,hBmpCheck       
// system checkmark 
 409                             ,NULL            
// draw the whole bitmap 
 410                             ,(PPOINTL
)&vRect 
// destination -- bottom left corner of the menuitem area 
 413                             ,DBM_NORMAL      
// draw normal size 
 420         // For uncheckable item we use only the 'checked' bitmap 
 422         wxBitmap 
vBmp(GetBitmap(IsCheckable() ? ((eStatus 
& wxODChecked
) != 0) : TRUE
)); 
 427             wxMemoryDC              
vDCMem(&rDC
); 
 428             wxMemoryDC
*             pOldDC 
= (wxMemoryDC
*)vBmp
.GetSelectedInto(); 
 432                 vBmp
.SetSelectedInto(NULL
); 
 434             vDCMem
.SelectObject(vBmp
); 
 439             int                     nBmpWidth 
= vBmp
.GetWidth(); 
 440             int                     nBmpHeight 
= vBmp
.GetHeight(); 
 443             // There should be enough space! 
 445             wxASSERT((nBmpWidth 
<= rRect
.width
) && (nBmpHeight 
<= rRect
.height
)); 
 447             int                     nHeightDiff 
= m_nHeight 
- nBmpHeight
; 
 449             rDC
.Blit( rRect
.x 
+ (GetMarginWidth() - nBmpWidth
) / 2 
 450                      ,rRect
.y 
+ nHeightDiff 
/ 2 
 460             if (eStatus 
& wxODSelected
) 
 462                 POINTL              vPnt1 
= {rRect
.x 
+ 1, rRect
.y 
+ 3}; // Leave a little background border 
 463                 POINTL              vPnt2 
= {rRect
.x 
+ GetMarginWidth(), rRect
.y 
+ m_nHeight 
- 3}; 
 467                 vLine
.lColor 
= vColBack
.GetPixel(); 
 474                 ::GpiMove(hPS
, &vPnt1
); 
 482             vBmp
.SetSelectedInto(NULL
); 
 486 } // end of wxOwnerDrawn::OnDrawItem 
 488 #endif //wxUSE_OWNER_DRAWN