]>
git.saurik.com Git - wxWidgets.git/blob - src/os2/ownerdrw.cpp
   1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/os2/ownerdrw.cpp 
   3 // Purpose:     implementation of wxOwnerDrawn class 
   4 // Author:      David Webster 
   8 // Copyright:   (c) David Webster 
   9 // Licence:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  18     #include "wx/window.h" 
  19     #include "wx/os2/private.h" 
  21     #include "wx/bitmap.h" 
  22     #include "wx/dcmemory.h" 
  25     #include "wx/settings.h" 
  26     #include "wx/menuitem.h" 
  29 #include "wx/ownerdrw.h" 
  31 // ============================================================================ 
  32 // implementation of wxOwnerDrawn class 
  33 // ============================================================================ 
  39 wxOwnerDrawn::wxOwnerDrawn( const wxString
& rsStr
, 
  41                             bool            WXUNUSED(bMenuItem
) ) 
  44     m_bCheckable   
= bCheckable
; 
  45     m_bOwnerDrawn  
= false; 
  47     m_nMarginWidth 
= ms_nLastMarginWidth
; 
  49         m_font 
= *wxNORMAL_FONT
; 
  50 } // end of wxOwnerDrawn::wxOwnerDrawn 
  52 wxOwnerDrawn::~wxOwnerDrawn() { } 
  54 size_t wxOwnerDrawn::ms_nDefaultMarginWidth 
= 15; 
  56 size_t wxOwnerDrawn::ms_nLastMarginWidth 
= ms_nDefaultMarginWidth
; 
  63 bool wxOwnerDrawn::OnMeasureItem( size_t* pWidth
, 
  68     wxString  sStr 
= wxStripMenuCodes(m_strName
); 
  71     // If we have a valid accel string, then pad out 
  72     // the menu string so that the menu and accel string are not 
  73     // placed on top of each other. 
  74     if (!m_strAccel
.empty() ) 
  76         sStr
.Pad(sStr
.length()%8
); 
  79     vDC
.SetFont(GetFont()); 
  80     vDC
.GetTextExtent( sStr
 
  84     if (!m_strAccel
.empty()) 
  87         // Measure the accelerator string, and add its width to 
  88         // the total item width, plus 16 (Accelerators are right justified, 
  89         // with the right edge of the text rectangle 16 pixels left of 
  90         // the right edge of the menu) 
  95         vDC
.GetTextExtent( m_strAccel
 
  99         *pWidth 
+= nAccelWidth
; 
 103     // Add space at the end of the menu for the submenu expansion arrow. 
 104     // This will also allow offsetting the accel string from the right edge 
 106     *pWidth 
= (size_t)(*pWidth 
+ GetDefaultMarginWidth() * 1.5); 
 109     // JACS: items still look too tightly packed, so adding 5 pixels. 
 114     // Ray Gilbert's changes - Corrects the problem of a BMP 
 115     // being placed next to text in a menu item, and the BMP does 
 116     // not match the size expected by the system.  This will 
 117     // resize the space so the BMP will fit.  Without this, BMPs 
 118     // must be no larger or smaller than 16x16. 
 120     if (m_bmpChecked
.Ok()) 
 123         // Is BMP height larger then text height? 
 125         size_t                      nAdjustedHeight 
= m_bmpChecked
.GetHeight() + 
 126                                                       wxSystemSettings::GetMetric(wxSYS_EDGE_Y
); 
 127         if (*pHeight 
< nAdjustedHeight
) 
 128             *pHeight 
= nAdjustedHeight
; 
 131         // Does BMP encroach on default check menu position? 
 133         size_t                      nAdjustedWidth 
= m_bmpChecked
.GetWidth() + 
 134                                                      (wxSystemSettings::GetMetric(wxSYS_EDGE_X
) * 2); 
 137         // Do we need to widen margin to fit BMP? 
 139         if ((size_t)GetMarginWidth() < nAdjustedWidth
) 
 140             SetMarginWidth(nAdjustedWidth
); 
 143         // Add the size of the bitmap to our total size... 
 145         *pWidth 
+= GetMarginWidth(); 
 149     // Add the size of the bitmap to our total size - even if we don't have 
 150     // a bitmap we leave room for one... 
 152     *pWidth 
+= GetMarginWidth(); 
 155     // Make sure that this item is at least as 
 156     // tall as the user's system settings specify 
 158     if (*pHeight 
< m_nMinHeight
) 
 159         *pHeight 
= m_nMinHeight
; 
 160     m_nHeight 
= *pHeight
;                // remember height for use in OnDrawItem 
 162 } // end of wxOwnerDrawn::OnMeasureItem 
 165 bool wxOwnerDrawn::OnDrawItem( wxDC
& rDC
, 
 171     // We do nothing on focus change 
 173     if (eAction 
== wxODFocusChanged 
) 
 177     // Select the font and draw the text 
 178     // --------------------------------- 
 182     HPS                             hPS
= rDC
.GetHPS(); 
 186     RECTL                           vRect 
= {rRect
.x 
+ 4, rRect
.y 
+ 1, rRect
.x 
+ (rRect
.width 
- 2), rRect
.y 
+ rRect
.height
}; 
 188     memset(&vCbnd
, 0, sizeof(CHARBUNDLE
)); 
 191     // Use default font if no font set 
 195         m_font
.RealizeResource(); 
 199         ::GpiSetCharSet(hPS
, LCID_DEFAULT
); 
 203     // Based on the status of the menu item, pick the right colors 
 205     if (eStatus 
& wxODSelected
) 
 207         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 208                                          ,SYSCLR_MENUHILITEBGND
 
 211         vColBack
.Set( GetRValue(vRef
) 
 215         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 219         vColText
.Set( GetRValue(vRef
) 
 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 wxWidgets 
 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     // mnemonics 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 mnemonics either.  We display 
 297     // them, though, in the hope we can figure them out some day. 
 301     // Display main text and accel text separately to align better 
 303     wxString sTgt 
= wxT("\t"); 
 304     wxString sFullString 
= m_strName
; // need to save the original text 
 310     bool     bFoundMnemonic 
= false; 
 311     bool     bFoundAccel 
= false; 
 314     // Deal with the tab, extracting the Accel text 
 316     nIndex 
= sFullString
.Find(sTgt
); 
 320         sAccel 
= sFullString
.Mid(nIndex 
+ 1); 
 321         sFullString
.Remove(nIndex
); 
 325     // Deal with the mnemonic character 
 328     nIndex 
= sFullString
.Find(sTgt
); 
 331         wxString sTmp 
= sFullString
; 
 333         bFoundMnemonic 
= true; 
 335         rDC
.GetTextExtent( sTmp
 
 339         sTmp 
= sFullString
[(size_t)(nIndex 
+ 1)]; 
 340         rDC
.GetTextExtent( sTmp
 
 344         sFullString
.Replace(sTgt
.c_str(), wxEmptyString
, 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                       ,sFullString
.char_str() 
 359         // Underline the mnemonic -- 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                 POINTL              vPnt1 
= {rRect
.x 
+ 1, rRect
.y 
+ 3}; // Leave a little background border 
 468                 POINTL              vPnt2 
= {rRect
.x 
+ GetMarginWidth(), rRect
.y 
+ m_nHeight 
- 3}; 
 472                 vLine
.lColor 
= vColBack
.GetPixel(); 
 479                 ::GpiMove(hPS
, &vPnt1
); 
 487             vBmp
.SetSelectedInto(NULL
); 
 491 } // end of wxOwnerDrawn::OnDrawItem 
 493 #endif //wxUSE_OWNER_DRAWN