]>
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" 
  30 #include "wx/os2/dcclient.h" 
  32 // ============================================================================ 
  33 // implementation of wxOwnerDrawn class 
  34 // ============================================================================ 
  40 wxOwnerDrawn::wxOwnerDrawn( const wxString
& rsStr
, 
  42                             bool            WXUNUSED(bMenuItem
) ) 
  45     m_bCheckable   
= bCheckable
; 
  46     m_bOwnerDrawn  
= false; 
  48     m_nMarginWidth 
= ms_nLastMarginWidth
; 
  50         m_font 
= *wxNORMAL_FONT
; 
  51 } // end of wxOwnerDrawn::wxOwnerDrawn 
  53 wxOwnerDrawn::~wxOwnerDrawn() { } 
  55 size_t wxOwnerDrawn::ms_nDefaultMarginWidth 
= 15; 
  57 size_t wxOwnerDrawn::ms_nLastMarginWidth 
= ms_nDefaultMarginWidth
; 
  64 bool wxOwnerDrawn::OnMeasureItem( size_t* pWidth
, 
  69     wxString  sStr 
= wxStripMenuCodes(m_strName
); 
  72     // If we have a valid accel string, then pad out 
  73     // the menu string so that the menu and accel string are not 
  74     // placed on top of each other. 
  75     if (!m_strAccel
.empty() ) 
  77         sStr
.Pad(sStr
.length()%8
); 
  80     vDC
.SetFont(GetFont()); 
  81     vDC
.GetTextExtent( sStr
 
  85     if (!m_strAccel
.empty()) 
  88         // Measure the accelerator string, and add its width to 
  89         // the total item width, plus 16 (Accelerators are right justified, 
  90         // with the right edge of the text rectangle 16 pixels left of 
  91         // the right edge of the menu) 
  96         vDC
.GetTextExtent( m_strAccel
 
 100         *pWidth 
+= nAccelWidth
; 
 104     // Add space at the end of the menu for the submenu expansion arrow. 
 105     // This will also allow offsetting the accel string from the right edge 
 107     *pWidth 
= (size_t)(*pWidth 
+ GetDefaultMarginWidth() * 1.5); 
 110     // JACS: items still look too tightly packed, so adding 5 pixels. 
 115     // Ray Gilbert's changes - Corrects the problem of a BMP 
 116     // being placed next to text in a menu item, and the BMP does 
 117     // not match the size expected by the system.  This will 
 118     // resize the space so the BMP will fit.  Without this, BMPs 
 119     // must be no larger or smaller than 16x16. 
 121     if (m_bmpChecked
.Ok()) 
 124         // Is BMP height larger then text height? 
 126         size_t                      nAdjustedHeight 
= m_bmpChecked
.GetHeight() + 
 127                                                       wxSystemSettings::GetMetric(wxSYS_EDGE_Y
); 
 128         if (*pHeight 
< nAdjustedHeight
) 
 129             *pHeight 
= nAdjustedHeight
; 
 132         // Does BMP encroach on default check menu position? 
 134         size_t                      nAdjustedWidth 
= m_bmpChecked
.GetWidth() + 
 135                                                      (wxSystemSettings::GetMetric(wxSYS_EDGE_X
) * 2); 
 138         // Do we need to widen margin to fit BMP? 
 140         if ((size_t)GetMarginWidth() < nAdjustedWidth
) 
 141             SetMarginWidth(nAdjustedWidth
); 
 144         // Add the size of the bitmap to our total size... 
 146         *pWidth 
+= GetMarginWidth(); 
 150     // Add the size of the bitmap to our total size - even if we don't have 
 151     // a bitmap we leave room for one... 
 153     *pWidth 
+= GetMarginWidth(); 
 156     // Make sure that this item is at least as 
 157     // tall as the user's system settings specify 
 159     const size_t heightStd 
= 6; // FIXME: get value from the system 
 160     if ( *pHeight 
< heightStd 
) 
 161       *pHeight 
= heightStd
; 
 162     m_nHeight 
= *pHeight
;                // remember height for use in OnDrawItem 
 164 } // end of wxOwnerDrawn::OnMeasureItem 
 167 bool wxOwnerDrawn::OnDrawItem( wxDC
& rDC
, 
 173     // We do nothing on focus change 
 175     if (eAction 
== wxODFocusChanged 
) 
 179     // Select the font and draw the text 
 180     // --------------------------------- 
 184     wxPMDCImpl                      
*impl 
= (wxPMDCImpl
*) rDC
.GetImpl(); 
 185     HPS                             hPS
= impl
->GetHPS(); 
 189     RECTL                           vRect 
= {rRect
.x 
+ 4, rRect
.y 
+ 1, rRect
.x 
+ (rRect
.width 
- 2), rRect
.y 
+ rRect
.height
}; 
 191     memset(&vCbnd
, 0, sizeof(CHARBUNDLE
)); 
 194     // Use default font if no font set 
 198         m_font
.RealizeResource(); 
 202         ::GpiSetCharSet(hPS
, LCID_DEFAULT
); 
 206     // Based on the status of the menu item, pick the right colors 
 208     if (eStatus 
& wxODSelected
) 
 210         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 211                                          ,SYSCLR_MENUHILITEBGND
 
 214         vColBack
.Set( GetRValue(vRef
) 
 218         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 222         vColText
.Set( GetRValue(vRef
) 
 227     else if (eStatus 
& wxODDisabled
) 
 229         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 230                                          ,SYSCLR_MENU 
// Light gray 
 233         vColBack
.Set( GetRValue(vRef
) 
 237         vRef 
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
 
 238                                          ,SYSCLR_MENUDISABLEDTEXT 
// dark gray 
 241         vColText
.Set( GetRValue(vRef
) 
 249         // Fall back to default colors if none explicitly specified 
 251         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 252                                   ,SYSCLR_MENU  
// we are using gray for all our window backgrounds in wxWidgets 
 255         vColBack
.Set( GetRValue(vRef
) 
 259         vRef 
= ::WinQuerySysColor( HWND_DESKTOP
 
 260                                   ,SYSCLR_WINDOWTEXT 
// Black 
 263         vColText
.Set( GetRValue(vRef
) 
 269     rDC
.SetTextBackground(vColBack
); 
 270     rDC
.SetTextForeground(vColText
); 
 271     rDC
.SetBackgroundMode(wxTRANSPARENT
); 
 272     vCbnd
.lColor     
= vColText
.GetPixel(); 
 273     vCbnd
.lBackColor 
= vColBack
.GetPixel(); 
 276                   ,CBB_BACK_COLOR 
| CBB_COLOR
 
 285     // Paint the background 
 287     ::WinFillRect(hPS
, &vRect
, vColBack
.GetPixel()); 
 290     // Determine where to draw and leave space for a check-mark. 
 292     int                             nX 
= rRect
.x 
+ GetMarginWidth(); 
 295     // Unfortunately, unlike Win32, PM has no owner drawn specific text 
 296     // drawing methods like ::DrawState that can cleanly handle accel 
 297     // mnemonics and deal, automatically, with various states, so we have 
 298     // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn 
 299     // strings either.  We cannot handle mnemonics either.  We display 
 300     // them, though, in the hope we can figure them out some day. 
 304     // Display main text and accel text separately to align better 
 306     wxString sTgt 
= wxT("\t"); 
 307     wxString sFullString 
= m_strName
; // need to save the original text 
 313     bool     bFoundMnemonic 
= false; 
 314     bool     bFoundAccel 
= false; 
 317     // Deal with the tab, extracting the Accel text 
 319     nIndex 
= sFullString
.Find(sTgt
); 
 323         sAccel 
= sFullString
.Mid(nIndex 
+ 1); 
 324         sFullString
.Remove(nIndex
); 
 328     // Deal with the mnemonic character 
 331     nIndex 
= sFullString
.Find(sTgt
); 
 334         wxString sTmp 
= sFullString
; 
 336         bFoundMnemonic 
= true; 
 338         rDC
.GetTextExtent( sTmp
 
 342         sTmp 
= sFullString
[(size_t)(nIndex 
+ 1)]; 
 343         rDC
.GetTextExtent( sTmp
 
 344                           ,(wxCoord 
*)&nCharWidth
 
 347         sFullString
.Replace(sTgt
.c_str(), wxEmptyString
, true); 
 351     // Draw the main item text sans the accel text 
 353     POINTL                      vPntStart 
= {nX
, rRect
.y 
+ 4}; 
 354     ::GpiCharStringAt( impl
->GetHPS() 
 356                       ,sFullString
.length() 
 357                       ,sFullString
.char_str() 
 362         // Underline the mnemonic -- still won't work, but at least it "looks" right 
 365         POINTL                      vPntEnd 
= {nX 
+ nWidth 
+ nCharWidth 
- 3, rRect
.y 
+ 2}; //CharWidth is bit wide 
 367         vPntStart
.x 
= nX 
+ nWidth 
- 1; 
 368         vPntStart
.y 
= rRect
.y 
+ 2; // Make it look pretty! 
 369         vPen 
= wxPen(vColText
, 1, wxSOLID
); // Assuming we are always black 
 371         ::GpiMove(hPS
, &vPntStart
); 
 372         ::GpiLine(hPS
, &vPntEnd
); 
 376     // Now draw the accel text 
 383         rDC
.GetTextExtent( sAccel
 
 388         // Back off the starting position from the right edge 
 390         vPntStart
.x 
= rRect
.width 
- (nWidth 
+ 7); 
 391         vPntStart
.y 
= rRect
.y 
+ 4; 
 392         ::GpiCharStringAt( impl
->GetHPS() 
 403     if (IsCheckable() && !m_bmpChecked
.Ok()) 
 405         if (eStatus 
& wxODChecked
) 
 408             HBITMAP                 hBmpCheck 
= ::WinGetSysBitmap(HWND_DESKTOP
, SBMP_MENUCHECK
); 
 410             vRect
.xLeft   
= rRect
.x
; 
 411             vRect
.xRight  
= rRect
.x 
+ GetMarginWidth(); 
 412             vRect
.yBottom 
= rRect
.y
; 
 413             vRect
.yTop    
= rRect
.y 
+ m_nHeight 
- 3; 
 415             ::WinDrawBitmap( hPS             
// PS for this menuitem 
 416                             ,hBmpCheck       
// system checkmark 
 417                             ,NULL            
// draw the whole bitmap 
 418                             ,(PPOINTL
)&vRect 
// destination -- bottom left corner of the menuitem area 
 421                             ,DBM_NORMAL      
// draw normal size 
 428         // For uncheckable item we use only the 'checked' bitmap 
 430         wxBitmap 
vBmp(GetBitmap(IsCheckable() ? ((eStatus 
& wxODChecked
) != 0) : TRUE
)); 
 435             wxMemoryDC              
vDCMem(&rDC
); 
 436             wxMemoryDC
*             pOldDC 
= (wxMemoryDC
*)vBmp
.GetSelectedInto(); 
 440                 vBmp
.SetSelectedInto(NULL
); 
 442             vDCMem
.SelectObject(vBmp
); 
 447             int                     nBmpWidth 
= vBmp
.GetWidth(); 
 448             int                     nBmpHeight 
= vBmp
.GetHeight(); 
 451             // There should be enough space! 
 453             wxASSERT((nBmpWidth 
<= rRect
.width
) && (nBmpHeight 
<= rRect
.height
)); 
 455             int                     nHeightDiff 
= m_nHeight 
- nBmpHeight
; 
 457             rDC
.Blit( rRect
.x 
+ (GetMarginWidth() - nBmpWidth
) / 2 
 458                      ,rRect
.y 
+ nHeightDiff 
/ 2 
 468             if (eStatus 
& wxODSelected
) 
 470                 POINTL              vPnt1 
= {rRect
.x 
+ 1, rRect
.y 
+ 3}; // Leave a little background border 
 471                 POINTL              vPnt2 
= {rRect
.x 
+ GetMarginWidth(), rRect
.y 
+ m_nHeight 
- 3}; 
 475                 vLine
.lColor 
= vColBack
.GetPixel(); 
 482                 ::GpiMove(hPS
, &vPnt1
); 
 490             vBmp
.SetSelectedInto(NULL
); 
 494 } // end of wxOwnerDrawn::OnDrawItem 
 496 #endif //wxUSE_OWNER_DRAWN