Ownerdrawn stuff for OS/2
[wxWidgets.git] / src / os2 / ownerdrw.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/ownerdrw.cpp
3 // Purpose: implementation of wxOwnerDrawn class
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/12/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows license
10 ///////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/window.h"
21 #include "wx/msw/private.h"
22 #include "wx/font.h"
23 #include "wx/bitmap.h"
24 #include "wx/dcmemory.h"
25 #include "wx/menu.h"
26 #include "wx/utils.h"
27 #endif
28
29 #if wxUSE_OWNER_DRAWN
30
31 #include "wx/ownerdrw.h"
32 #include "wx/menuitem.h"
33
34
35 // ============================================================================
36 // implementation of wxOwnerDrawn class
37 // ============================================================================
38
39 //
40 // ctor
41 // ----
42 //
43 wxOwnerDrawn::wxOwnerDrawn(
44 const wxString& rsStr
45 , bool bCheckable
46 , bool bMenuItem
47 )
48 : m_strName(rsStr)
49 {
50 m_bCheckable = bCheckable;
51 m_bOwnerDrawn = FALSE;
52 m_nHeight = 0;
53 m_nMarginWidth = ms_nLastMarginWidth;
54 if (wxNORMAL_FONT)
55 m_font = *wxNORMAL_FONT;
56 } // end of wxOwnerDrawn::wxOwnerDrawn
57
58 size_t wxOwnerDrawn::ms_nDefaultMarginWidth = 15;
59
60 size_t wxOwnerDrawn::ms_nLastMarginWidth = ms_nDefaultMarginWidth;
61
62 //
63 // Drawing
64 // -------
65 //
66
67 bool wxOwnerDrawn::OnMeasureItem(
68 size_t* pWidth
69 , size_t* pHeight
70 )
71 {
72 wxMemoryDC vDC;
73
74 vDC.SetFont(GetFont());
75
76 wxString sStr = wxStripMenuCodes(m_strName);
77
78 //
79 // # without this menu items look too tightly packed (at least under Windows)
80 //
81 sStr += wxT('W'); // 'W' is typically the widest letter
82 vDC.GetTextExtent( sStr
83 ,(long *)pWidth
84 ,(long *)pHeight
85 );
86
87 //
88 // JACS: items still look too tightly packed, so adding 2 pixels.
89 //
90 (*pHeight) = (*pHeight) + 2;
91 m_nHeight = *pHeight; // remember height for use in OnDrawItem
92 return TRUE;
93 } // end of wxOwnerDrawn::OnMeasureItem
94
95 // searching for this macro you'll find all the code where I'm using the native
96 // Win32 GDI functions and not wxWindows ones. Might help to whoever decides to
97 // port this code to X. (VZ)
98
99 // JACS: TODO. Why does a disabled but highlighted item still
100 // get drawn embossed? How can we tell DrawState that we don't want the
101 // embossing?
102
103 // draw the item
104 bool wxOwnerDrawn::OnDrawItem(
105 wxDC& rDC
106 , const wxRect& rRect
107 , wxODAction eAction
108 , wxODStatus eStatus
109 )
110 {
111 //
112 // For now we let PM deal with highlighting and framing and such in a
113 // default manner. So we leave fsAttribute and fsOldAttribute ( or
114 // fsState and fsOldState ) the same and pass it on. We may want to add
115 // code later to draw theseattributes in a more custom manner.
116 //
117
118 //
119 // WxWinGdi_CColour <-> RGB
120 //
121 #define ToRGB(col) OS2RGB(col.Red(), col.Green(), col.Blue())
122 #define UnRGB(col) GetRValue(col), GetGValue(col), GetBValue(col)
123
124 CHARBUNDLE vCbndText;
125 CHARBUNDLE vCbndBack;
126 HPS hPS= rDC.GetHPS();
127 ULONG lColBack;
128 ULONG lColText;
129
130 if (eStatus & wxODSelected)
131 {
132 lColBack = (DWORD)::WinQuerySysColor( HWND_DESKTOP
133 ,SYSCLR_MENUHILITEBGND // Light gray
134 ,0L
135 );
136 lColText = (DWORD)::WinQuerySysColor( HWND_DESKTOP
137 ,SYSCLR_MENUTEXT // Black
138 ,0L
139 );
140 }
141 else if (eStatus & wxODDisabled)
142 {
143 lColBack = (DWORD)::WinQuerySysColor( HWND_DESKTOP
144 ,SYSCLR_MENU // Light gray
145 ,0L
146 );
147 lColText = (DWORD)::WinQuerySysColor( HWND_DESKTOP
148 ,SYSCLR_MENUDISABLEDTEXT // dark gray
149 ,0L
150 );
151 }
152 else
153 {
154 //
155 // Fall back to default colors if none explicitly specified
156 //
157 lColBack = m_colBack.Ok() ? ToRGB(m_colBack) : ::WinQuerySysColor( HWND_DESKTOP
158 ,SYSCLR_MENU // we are using gray for all our window backgrounds in wxWindows
159 ,0L
160 );
161 lColText = m_colText.Ok() ? ToRGB(m_colText) : ::WinQuerySysColor( HWND_DESKTOP
162 ,SYSCLR_WINDOWTEXT // Black
163 ,0L
164 );
165 }
166 vCbndText.lColor = (LONG)lColText;
167 vCbndBack.lColor = (LONG)lColBack;
168
169 ::GpiSetAttrs( hPS
170 ,PRIM_CHAR
171 ,CBB_BACK_COLOR
172 ,0
173 ,&vCbndBack
174 );
175 ::GpiSetAttrs( hPS
176 ,PRIM_CHAR
177 ,CBB_COLOR
178 ,0
179 ,&vCbndText
180 );
181
182
183 //
184 // Determine where to draw and leave space for a check-mark.
185 //
186 int nX = rRect.x + GetMarginWidth();
187
188 //
189 // Select the font and draw the text
190 // ---------------------------------
191 //
192
193 //
194 // Use default font if no font set
195 //
196 if (m_font.Ok())
197 {
198 m_font.RealizeResource();
199 }
200 else
201 {
202 ::GpiSetCharSet(hPS, LCID_DEFAULT);
203 }
204
205 //
206 // Unfortunately, unlike Win32, PM has no owner drawn specific text
207 // drawing methods like ::DrawState that can cleanly handle accel
208 // pneumonics and deal, automatically, with various states, so we have
209 // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn
210 // strings either.
211
212 rDC.DrawText( m_strName
213 ,nX
214 ,rRect.y
215 );
216
217 //
218 // Draw the bitmap
219 // ---------------
220 //
221 if (IsCheckable() && !m_bmpChecked.Ok())
222 {
223 if (eStatus & wxODChecked)
224 {
225 RECTL vRect;
226 HBITMAP hBmpCheck = ::WinGetSysBitmap(HWND_DESKTOP, SBMP_MENUCHECK);
227
228 vRect.xLeft = rRect.x;
229 vRect.xRight = rRect.x + GetMarginWidth();
230 vRect.yBottom = rRect.y;
231 vRect.yTop = rRect.y + m_nHeight;
232
233 ::WinDrawBitmap( hPS // PS for this menuitem
234 ,hBmpCheck // system checkmark
235 ,NULL // draw the whole bitmap
236 ,(PPOINTL)&vRect // destination -- bottom left corner of the menuitem area
237 ,0L // ignored
238 ,0L // draw a bitmap
239 ,DBM_NORMAL // draw normal size
240 );
241 }
242 }
243 else
244 {
245 //
246 // For uncheckable item we use only the 'checked' bitmap
247 //
248 wxBitmap vBmp(GetBitmap(IsCheckable() ? ((eStatus & wxODChecked) != 0) : TRUE));
249
250 if (vBmp.Ok())
251 {
252 wxMemoryDC vDCMem(&rDC);
253
254 vDCMem.SelectObject(vBmp);
255
256 //
257 // Center bitmap
258 //
259 int nBmpWidth = vBmp.GetWidth();
260 int nBmpHeight = vBmp.GetHeight();
261
262 //
263 // There should be enough space!
264 //
265 wxASSERT((nBmpWidth <= rRect.width) && (nBmpHeight <= rRect.height));
266
267 //
268 //MT: blit with mask enabled.
269 //
270 rDC.Blit( rRect.x + (GetMarginWidth() - nBmpWidth) / 2
271 ,rRect.y + (m_nHeight - nBmpHeight) /2
272 ,nBmpWidth
273 ,nBmpHeight
274 ,&vDCMem
275 ,0
276 ,0
277 ,wxCOPY
278 ,TRUE
279 );
280
281 if (eStatus & wxODSelected)
282 {
283 RECT vRectBmp = { rRect.x
284 ,rRect.y
285 ,rRect.x + GetMarginWidth()
286 ,rRect.y + m_nHeight
287 };
288 LINEBUNDLE vLine;
289
290 vLine.lColor = lColBack;
291 ::GpiSetAttrs( hPS
292 ,PRIM_LINE
293 ,LBB_COLOR
294 ,0
295 ,&vLine
296 );
297 ::GpiBox( hPS
298 ,DRO_OUTLINE
299 ,(PPOINTL)&vRectBmp
300 ,0L
301 ,0L
302 );
303 }
304 }
305 }
306
307 return TRUE;
308 }
309
310 #endif //wxUSE_OWNER_DRAWN