]>
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