]>
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( 
  51     m_bCheckable   
= bCheckable
; 
  52     m_bOwnerDrawn  
= FALSE
; 
  54     m_nMarginWidth 
= ms_nLastMarginWidth
; 
  56         m_font 
= *wxNORMAL_FONT
; 
  57 } // end of wxOwnerDrawn::wxOwnerDrawn 
  59 size_t wxOwnerDrawn::ms_nDefaultMarginWidth 
= 15; 
  61 size_t wxOwnerDrawn::ms_nLastMarginWidth 
= ms_nDefaultMarginWidth
; 
  68 bool wxOwnerDrawn::OnMeasureItem( 
  76     wxString                        sStr 
= wxStripMenuCodes(m_strName
); 
  79     // If we have a valid accel string, then pad out 
  80     // the menu string so the menu and accel string are not 
  81     // placed ontop of eachother. 
  82     if (!m_strAccel
.empty() ) 
  84         sStr
.Pad(sStr
.Length()%8
); 
  87     vDC
.SetFont(GetFont()); 
  88     vDC
.GetTextExtent( sStr
 
  92     if (!m_strAccel
.IsEmpty()) 
  95         // Measure the accelerator string, and add it's width to 
  96         // the total item width, plus 16 (Accelerators are right justified, 
  97         // with the right edge of the text rectangle 16 pixels left of 
  98         // the right edge of the menu) 
 103         vDC
.GetTextExtent( m_strAccel
 
 107         *pWidth 
+= nAccelWidth
; 
 111     // Add space at the end of the menu for the submenu expansion arrow 
 112     // this will also allow offsetting the accel string from the right edge 
 114     *pWidth 
+= GetDefaultMarginWidth() * 1.5; 
 117     // JACS: items still look too tightly packed, so adding 5 pixels. 
 122     // Ray Gilbert's changes - Corrects the problem of a BMP 
 123     // being placed next to text in a menu item, and the BMP does 
 124     // not match the size expected by the system.  This will 
 125     // resize the space so the BMP will fit.  Without this, BMPs 
 126     // must be no larger or smaller than 16x16. 
 128     if (m_bmpChecked
.Ok()) 
 131         // Is BMP height larger then text height? 
 133         size_t                      nAdjustedHeight 
= m_bmpChecked
.GetHeight() + 
 134                                                       wxSystemSettings::GetMetric(wxSYS_EDGE_Y
); 
 135         if (*pHeight 
< nAdjustedHeight
) 
 136             *pHeight 
= nAdjustedHeight
; 
 139         // Does BMP encroach on default check menu position? 
 141         size_t                      nAdjustedWidth 
= m_bmpChecked
.GetWidth() + 
 142                                                      (wxSystemSettings::GetMetric(wxSYS_EDGE_X
) * 2); 
 145         // Do we need to widen margin to fit BMP? 
 147         if ((size_t)GetMarginWidth() < nAdjustedWidth
) 
 148             SetMarginWidth(nAdjustedWidth
); 
 151         // Add the size of the bitmap to our total size... 
 153         *pWidth 
+= GetMarginWidth(); 
 157     // Add the size of the bitmap to our total size - even if we don't have 
 158     // a bitmap we leave room for one... 
 160     *pWidth 
+= GetMarginWidth(); 
 163     // Make sure that this item is at least as 
 164     // tall as the user's system settings specify 
 166     if (*pHeight 
< m_nMinHeight
) 
 167         *pHeight 
= m_nMinHeight
; 
 168     m_nHeight 
= *pHeight
;                // remember height for use in OnDrawItem 
 170 } // end of wxOwnerDrawn::OnMeasureItem 
 173 bool wxOwnerDrawn::OnDrawItem( 
 175 , const wxRect
&                     rRect
 
 181     // We do nothing on focus change 
 183     if (eAction 
== wxODFocusChanged 
) 
 187     // Select the font and draw the text 
 188     // --------------------------------- 
 192     HPS                             hPS
= rDC
.GetHPS(); 
 196     RECTL                           vRect 
= {rRect
.x 
+ 4, rRect
.y 
+ 1, rRect
.x 
+ (rRect
.width 
- 2), rRect
.y 
+ rRect
.height
}; 
 198     memset(&vCbnd
, 0, sizeof(CHARBUNDLE
)); 
 201     // Use default font if no font set 
 205         m_font
.RealizeResource(); 
 209         ::GpiSetCharSet(hPS
, LCID_DEFAULT
); 
 213     // Base on the status of the menu item pick the right colors 
 215     if (eStatus 
& wxODSelected
) 
 217         wxColour                        
vCol2("WHITE"); 
 218         vColBack
.Set( (unsigned char)0 
 221                     ); // no dark blue in color table 
 224     else if (eStatus 
& wxODDisabled
) 
 226         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 227                                          ,SYSCLR_MENU 
// Light gray 
 230         vColBack
.Set( GetRValue(vRef
) 
 234         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 235                                          ,SYSCLR_MENUDISABLEDTEXT 
// dark gray 
 238         vColText
.Set( GetRValue(vRef
) 
 246         // Fall back to default colors if none explicitly specified 
 248         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 249                                   ,SYSCLR_MENU  
// we are using gray for all our window backgrounds in wxWindows 
 252         vColBack
.Set( GetRValue(vRef
) 
 256         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 257                                   ,SYSCLR_WINDOWTEXT 
// Black 
 260         vColText
.Set( GetRValue(vRef
) 
 266     rDC
.SetTextBackground(vColBack
); 
 267     rDC
.SetTextForeground(vColText
); 
 268     rDC
.SetBackgroundMode(wxTRANSPARENT
); 
 269     vCbnd
.lColor     
= vColText
.GetPixel(); 
 270     vCbnd
.lBackColor 
= vColBack
.GetPixel(); 
 273                   ,CBB_BACK_COLOR 
| CBB_COLOR
 
 282     // Paint the background 
 284     ::WinFillRect(hPS
, &vRect
, vColBack
.GetPixel()); 
 287     // Determine where to draw and leave space for a check-mark. 
 289     int                             nX 
= rRect
.x 
+ GetMarginWidth(); 
 292     // Unfortunately, unlike Win32, PM has no owner drawn specific text 
 293     // drawing methods like ::DrawState that can cleanly handle accel 
 294     // pneumonics and deal, automatically, with various states, so we have 
 295     // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn 
 296     // strings either.  We cannot handle mneumonics either.  We display 
 297     // it, though, in hopes we can figure it out some day. 
 301     // Display main text and accel text separately to allign better 
 303     wxString                        sTgt 
= "\t"; 
 304     wxString                        sFullString 
= m_strName
; // need to save the original text 
 310     bool                            bFoundMneumonic 
= FALSE
; 
 311     bool                            bFoundAccel 
= FALSE
; 
 314     // Deal with the tab, extracting the Accel text 
 316     nIndex 
= sFullString
.Find(sTgt
.c_str()); 
 320         sAccel 
= sFullString
.Mid(nIndex 
+ 1); 
 321         sFullString
.Remove(nIndex
); 
 325     // Deal with the mneumonic character 
 328     nIndex 
= sFullString
.Find(sTgt
.c_str()); 
 331         wxString                    sTmp 
= sFullString
; 
 333         bFoundMneumonic 
= TRUE
; 
 335         rDC
.GetTextExtent( sTmp
 
 339         sTmp 
= sFullString
[nIndex 
+ 1]; 
 340         rDC
.GetTextExtent( sTmp
 
 344         sFullString
.Replace(sTgt
.c_str(), "", TRUE
); 
 348     // Draw the main item text sans the accel text 
 350     POINTL                      vPntStart 
= {nX
, rRect
.y 
+ 4}; 
 351     ::GpiCharStringAt( rDC
.GetHPS() 
 353                       ,sFullString
.length() 
 354                       ,(PCH
)sFullString
.c_str() 
 359         // Underline the mneumonic -- still won't work, but at least it "looks" right 
 362         POINTL                      vPntEnd 
= {nX 
+ nWidth 
+ nCharWidth 
- 3, rRect
.y 
+ 2}; //CharWidth is bit wide 
 364         vPntStart
.x 
= nX 
+ nWidth 
- 1; 
 365         vPntStart
.y 
= rRect
.y 
+ 2; // Make it look pretty! 
 366         vPen 
= wxPen(vColText
, 1, wxSOLID
); // Assuming we are always black 
 368         ::GpiMove(hPS
, &vPntStart
); 
 369         ::GpiLine(hPS
, &vPntEnd
); 
 373     // Now draw the accel text 
 380         rDC
.GetTextExtent( sAccel
 
 385         // Back off the starting position from the right edge 
 387         vPntStart
.x 
= rRect
.width 
- (nWidth 
+ 7); 
 388         vPntStart
.y 
= rRect
.y 
+ 4; 
 389         ::GpiCharStringAt( rDC
.GetHPS() 
 400     if (IsCheckable() && !m_bmpChecked
.Ok()) 
 402         if (eStatus 
& wxODChecked
) 
 405             HBITMAP                 hBmpCheck 
= ::WinGetSysBitmap(HWND_DESKTOP
, SBMP_MENUCHECK
); 
 407             vRect
.xLeft   
= rRect
.x
; 
 408             vRect
.xRight  
= rRect
.x 
+ GetMarginWidth(); 
 409             vRect
.yBottom 
= rRect
.y
; 
 410             vRect
.yTop    
= rRect
.y 
+ m_nHeight 
- 3; 
 412             ::WinDrawBitmap( hPS             
// PS for this menuitem 
 413                             ,hBmpCheck       
// system checkmark 
 414                             ,NULL            
// draw the whole bitmap 
 415                             ,(PPOINTL
)&vRect 
// destination -- bottom left corner of the menuitem area 
 418                             ,DBM_NORMAL      
// draw normal size 
 425         // For uncheckable item we use only the 'checked' bitmap 
 427         wxBitmap                    
vBmp(GetBitmap(IsCheckable() ? ((eStatus 
& wxODChecked
) != 0) : TRUE
)); 
 432             wxMemoryDC              
vDCMem(&rDC
); 
 433             wxMemoryDC
*             pOldDC 
= (wxMemoryDC
*)vBmp
.GetSelectedInto(); 
 437                 vBmp
.SetSelectedInto(NULL
); 
 439             vDCMem
.SelectObject(vBmp
); 
 444             int                     nBmpWidth 
= vBmp
.GetWidth(); 
 445             int                     nBmpHeight 
= vBmp
.GetHeight(); 
 448             // There should be enough space! 
 450             wxASSERT((nBmpWidth 
<= rRect
.width
) && (nBmpHeight 
<= rRect
.height
)); 
 452             int                     nHeightDiff 
= m_nHeight 
- nBmpHeight
; 
 454             rDC
.Blit( rRect
.x 
+ (GetMarginWidth() - nBmpWidth
) / 2 
 455                      ,rRect
.y 
+ nHeightDiff 
/ 2 
 465             if (eStatus 
& wxODSelected
) 
 467                 RECT                vRectBmp 
= { rRect
.x
 
 469                                                 ,rRect
.x 
+ GetMarginWidth() - 1 
 470                                                 ,rRect
.y 
+ m_nHeight 
- 1 
 472                 POINTL              vPnt1 
= {rRect
.x 
+ 1, rRect
.y 
+ 3}; // Leave a little background border 
 473                 POINTL              vPnt2 
= {rRect
.x 
+ GetMarginWidth(), rRect
.y 
+ m_nHeight 
- 3}; 
 477                 vLine
.lColor 
= vColBack
.GetPixel(); 
 484                 ::GpiMove(hPS
, &vPnt1
); 
 492             vBmp
.SetSelectedInto(NULL
); 
 496 } // end of wxOwnerDrawn::OnDrawItem 
 498 #endif //wxUSE_OWNER_DRAWN