]>
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         wxColour                        
vCol2(wxT("WHITE")); 
 208         vColBack
.Set( (unsigned char)0 
 211                     ); // no dark blue in color table 
 214     else if (eStatus 
& wxODDisabled
) 
 216         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 217                                          ,SYSCLR_MENU 
// Light gray 
 220         vColBack
.Set( GetRValue(vRef
) 
 224         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 225                                          ,SYSCLR_MENUDISABLEDTEXT 
// dark gray 
 228         vColText
.Set( GetRValue(vRef
) 
 236         // Fall back to default colors if none explicitly specified 
 238         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 239                                   ,SYSCLR_MENU  
// we are using gray for all our window backgrounds in wxWidgets 
 242         vColBack
.Set( GetRValue(vRef
) 
 246         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 247                                   ,SYSCLR_WINDOWTEXT 
// Black 
 250         vColText
.Set( GetRValue(vRef
) 
 256     rDC
.SetTextBackground(vColBack
); 
 257     rDC
.SetTextForeground(vColText
); 
 258     rDC
.SetBackgroundMode(wxTRANSPARENT
); 
 259     vCbnd
.lColor     
= vColText
.GetPixel(); 
 260     vCbnd
.lBackColor 
= vColBack
.GetPixel(); 
 263                   ,CBB_BACK_COLOR 
| CBB_COLOR
 
 272     // Paint the background 
 274     ::WinFillRect(hPS
, &vRect
, vColBack
.GetPixel()); 
 277     // Determine where to draw and leave space for a check-mark. 
 279     int                             nX 
= rRect
.x 
+ GetMarginWidth(); 
 282     // Unfortunately, unlike Win32, PM has no owner drawn specific text 
 283     // drawing methods like ::DrawState that can cleanly handle accel 
 284     // mnemonics and deal, automatically, with various states, so we have 
 285     // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn 
 286     // strings either.  We cannot handle mnemonics either.  We display 
 287     // them, though, in the hope we can figure them out some day. 
 291     // Display main text and accel text separately to align better 
 293     wxString sTgt 
= wxT("\t"); 
 294     wxString sFullString 
= m_strName
; // need to save the original text 
 300     bool     bFoundMnemonic 
= false; 
 301     bool     bFoundAccel 
= false; 
 304     // Deal with the tab, extracting the Accel text 
 306     nIndex 
= sFullString
.Find(sTgt
.c_str()); 
 310         sAccel 
= sFullString
.Mid(nIndex 
+ 1); 
 311         sFullString
.Remove(nIndex
); 
 315     // Deal with the mnemonic character 
 318     nIndex 
= sFullString
.Find(sTgt
.c_str()); 
 321         wxString sTmp 
= sFullString
; 
 323         bFoundMnemonic 
= true; 
 325         rDC
.GetTextExtent( sTmp
 
 329         sTmp 
= sFullString
[(size_t)(nIndex 
+ 1)]; 
 330         rDC
.GetTextExtent( sTmp
 
 334         sFullString
.Replace(sTgt
.c_str(), wxEmptyString
, true); 
 338     // Draw the main item text sans the accel text 
 340     POINTL                      vPntStart 
= {nX
, rRect
.y 
+ 4}; 
 341     ::GpiCharStringAt( rDC
.GetHPS() 
 343                       ,sFullString
.length() 
 344                       ,(PCH
)sFullString
.c_str() 
 349         // Underline the mnemonic -- still won't work, but at least it "looks" right 
 352         POINTL                      vPntEnd 
= {nX 
+ nWidth 
+ nCharWidth 
- 3, rRect
.y 
+ 2}; //CharWidth is bit wide 
 354         vPntStart
.x 
= nX 
+ nWidth 
- 1; 
 355         vPntStart
.y 
= rRect
.y 
+ 2; // Make it look pretty! 
 356         vPen 
= wxPen(vColText
, 1, wxSOLID
); // Assuming we are always black 
 358         ::GpiMove(hPS
, &vPntStart
); 
 359         ::GpiLine(hPS
, &vPntEnd
); 
 363     // Now draw the accel text 
 370         rDC
.GetTextExtent( sAccel
 
 375         // Back off the starting position from the right edge 
 377         vPntStart
.x 
= rRect
.width 
- (nWidth 
+ 7); 
 378         vPntStart
.y 
= rRect
.y 
+ 4; 
 379         ::GpiCharStringAt( rDC
.GetHPS() 
 390     if (IsCheckable() && !m_bmpChecked
.Ok()) 
 392         if (eStatus 
& wxODChecked
) 
 395             HBITMAP                 hBmpCheck 
= ::WinGetSysBitmap(HWND_DESKTOP
, SBMP_MENUCHECK
); 
 397             vRect
.xLeft   
= rRect
.x
; 
 398             vRect
.xRight  
= rRect
.x 
+ GetMarginWidth(); 
 399             vRect
.yBottom 
= rRect
.y
; 
 400             vRect
.yTop    
= rRect
.y 
+ m_nHeight 
- 3; 
 402             ::WinDrawBitmap( hPS             
// PS for this menuitem 
 403                             ,hBmpCheck       
// system checkmark 
 404                             ,NULL            
// draw the whole bitmap 
 405                             ,(PPOINTL
)&vRect 
// destination -- bottom left corner of the menuitem area 
 408                             ,DBM_NORMAL      
// draw normal size 
 415         // For uncheckable item we use only the 'checked' bitmap 
 417         wxBitmap 
vBmp(GetBitmap(IsCheckable() ? ((eStatus 
& wxODChecked
) != 0) : TRUE
)); 
 422             wxMemoryDC              
vDCMem(&rDC
); 
 423             wxMemoryDC
*             pOldDC 
= (wxMemoryDC
*)vBmp
.GetSelectedInto(); 
 427                 vBmp
.SetSelectedInto(NULL
); 
 429             vDCMem
.SelectObject(vBmp
); 
 434             int                     nBmpWidth 
= vBmp
.GetWidth(); 
 435             int                     nBmpHeight 
= vBmp
.GetHeight(); 
 438             // There should be enough space! 
 440             wxASSERT((nBmpWidth 
<= rRect
.width
) && (nBmpHeight 
<= rRect
.height
)); 
 442             int                     nHeightDiff 
= m_nHeight 
- nBmpHeight
; 
 444             rDC
.Blit( rRect
.x 
+ (GetMarginWidth() - nBmpWidth
) / 2 
 445                      ,rRect
.y 
+ nHeightDiff 
/ 2 
 455             if (eStatus 
& wxODSelected
) 
 457                 POINTL              vPnt1 
= {rRect
.x 
+ 1, rRect
.y 
+ 3}; // Leave a little background border 
 458                 POINTL              vPnt2 
= {rRect
.x 
+ GetMarginWidth(), rRect
.y 
+ m_nHeight 
- 3}; 
 462                 vLine
.lColor 
= vColBack
.GetPixel(); 
 469                 ::GpiMove(hPS
, &vPnt1
); 
 477             vBmp
.SetSelectedInto(NULL
); 
 481 } // end of wxOwnerDrawn::OnDrawItem 
 483 #endif //wxUSE_OWNER_DRAWN