]>
git.saurik.com Git - wxWidgets.git/blob - src/os2/ownerdrw.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: msw/ownerdrw.cpp
3 // Purpose: implementation of wxOwnerDrawn class
4 // Author: David Webster
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
13 #pragma implementation
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
20 #include "wx/window.h"
21 #include "wx/os2/private.h"
23 #include "wx/bitmap.h"
24 #include "wx/dcmemory.h"
31 #include "wx/ownerdrw.h"
32 #include "wx/menuitem.h"
35 // ============================================================================
36 // implementation of wxOwnerDrawn class
37 // ============================================================================
43 wxOwnerDrawn::wxOwnerDrawn(
50 m_bCheckable
= bCheckable
;
51 m_bOwnerDrawn
= FALSE
;
53 m_nMarginWidth
= ms_nLastMarginWidth
;
55 m_font
= *wxNORMAL_FONT
;
56 } // end of wxOwnerDrawn::wxOwnerDrawn
58 size_t wxOwnerDrawn::ms_nDefaultMarginWidth
= 15;
60 size_t wxOwnerDrawn::ms_nLastMarginWidth
= ms_nDefaultMarginWidth
;
67 bool wxOwnerDrawn::OnMeasureItem(
75 wxString sStr
= wxStripMenuCodes(m_strName
);
78 // If we have a valid accel string, then pad out
79 // the menu string so the menu and accel string are not
80 // placed ontop of eachother.
81 if (!m_strAccel
.empty() )
83 sStr
.Pad(sStr
.Length()%8
);
86 vDC
.SetFont(GetFont());
87 vDC
.GetTextExtent( sStr
91 if (!m_strAccel
.IsEmpty())
94 // Measure the accelerator string, and add it's width to
95 // the total item width, plus 16 (Accelerators are right justified,
96 // with the right edge of the text rectangle 16 pixels left of
97 // the right edge of the menu)
102 vDC
.GetTextExtent( m_strAccel
106 *pWidth
+= nAccelWidth
;
110 // Add space at the end of the menu for the submenu expansion arrow
111 // this will also allow offsetting the accel string from the right edge
113 *pWidth
+= GetDefaultMarginWidth() * 1.5;
116 // JACS: items still look too tightly packed, so adding 5 pixels.
121 // Ray Gilbert's changes - Corrects the problem of a BMP
122 // being placed next to text in a menu item, and the BMP does
123 // not match the size expected by the system. This will
124 // resize the space so the BMP will fit. Without this, BMPs
125 // must be no larger or smaller than 16x16.
127 if (m_bmpChecked
.Ok())
130 // Is BMP height larger then text height?
132 size_t nAdjustedHeight
= m_bmpChecked
.GetHeight() +
133 wxSystemSettings::GetMetric(wxSYS_EDGE_Y
);
134 if (*pHeight
< nAdjustedHeight
)
135 *pHeight
= nAdjustedHeight
;
138 // Does BMP encroach on default check menu position?
140 size_t nAdjustedWidth
= m_bmpChecked
.GetWidth() +
141 (wxSystemSettings::GetMetric(wxSYS_EDGE_X
) * 2);
144 // Do we need to widen margin to fit BMP?
146 if ((size_t)GetMarginWidth() < nAdjustedWidth
)
147 SetMarginWidth(nAdjustedWidth
);
150 // Add the size of the bitmap to our total size...
152 *pWidth
+= GetMarginWidth();
156 // Add the size of the bitmap to our total size - even if we don't have
157 // a bitmap we leave room for one...
159 *pWidth
+= GetMarginWidth();
162 // Make sure that this item is at least as
163 // tall as the user's system settings specify
165 if (*pHeight
< m_nMinHeight
)
166 *pHeight
= m_nMinHeight
;
167 m_nHeight
= *pHeight
; // remember height for use in OnDrawItem
169 } // end of wxOwnerDrawn::OnMeasureItem
172 bool wxOwnerDrawn::OnDrawItem(
174 , const wxRect
& rRect
180 // We do nothing on focus change
182 if (eAction
== wxODFocusChanged
)
186 // Select the font and draw the text
187 // ---------------------------------
191 HPS hPS
= rDC
.GetHPS();
195 RECTL vRect
= {rRect
.x
+ 4, rRect
.y
+ 1, rRect
.x
+ (rRect
.width
- 2), rRect
.y
+ rRect
.height
};
197 memset(&vCbnd
, 0, sizeof(CHARBUNDLE
));
200 // Use default font if no font set
204 m_font
.RealizeResource();
208 ::GpiSetCharSet(hPS
, LCID_DEFAULT
);
212 // Base on the status of the menu item pick the right colors
214 if (eStatus
& wxODSelected
)
216 wxColour
vCol2("WHITE");
217 vColBack
.Set( (unsigned char)0
220 ); // no dark blue in color table
223 else if (eStatus
& wxODDisabled
)
225 vRef
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
226 ,SYSCLR_MENU
// Light gray
229 vColBack
.Set( GetRValue(vRef
)
233 vRef
= (ULONG
)::WinQuerySysColor( HWND_DESKTOP
234 ,SYSCLR_MENUDISABLEDTEXT
// dark gray
237 vColText
.Set( GetRValue(vRef
)
245 // Fall back to default colors if none explicitly specified
247 vRef
= ::WinQuerySysColor( HWND_DESKTOP
248 ,SYSCLR_MENU
// we are using gray for all our window backgrounds in wxWindows
251 vColBack
.Set( GetRValue(vRef
)
255 vRef
= ::WinQuerySysColor( HWND_DESKTOP
256 ,SYSCLR_WINDOWTEXT
// Black
259 vColText
.Set( GetRValue(vRef
)
265 rDC
.SetTextBackground(vColBack
);
266 rDC
.SetTextForeground(vColText
);
267 rDC
.SetBackgroundMode(wxTRANSPARENT
);
268 vCbnd
.lColor
= vColText
.GetPixel();
269 vCbnd
.lBackColor
= vColBack
.GetPixel();
272 ,CBB_BACK_COLOR
| CBB_COLOR
281 // Paint the background
283 ::WinFillRect(hPS
, &vRect
, vColBack
.GetPixel());
286 // Determine where to draw and leave space for a check-mark.
288 int nX
= rRect
.x
+ GetMarginWidth();
291 // Unfortunately, unlike Win32, PM has no owner drawn specific text
292 // drawing methods like ::DrawState that can cleanly handle accel
293 // pneumonics and deal, automatically, with various states, so we have
294 // to handle them ourselves. Notice Win32 can't handle \t in ownerdrawn
295 // strings either. We cannot handle mneumonics either. We display
296 // it, though, in hopes we can figure it out some day.
300 // Display main text and accel text separately to allign better
302 wxString sTgt
= "\t";
303 wxString sFullString
= m_strName
; // need to save the original text
309 bool bFoundMneumonic
= FALSE
;
310 bool bFoundAccel
= FALSE
;
313 // Deal with the tab, extracting the Accel text
315 nIndex
= sFullString
.Find(sTgt
.c_str());
319 sAccel
= sFullString
.Mid(nIndex
+ 1);
320 sFullString
.Remove(nIndex
);
324 // Deal with the mneumonic character
327 nIndex
= sFullString
.Find(sTgt
.c_str());
330 wxString sTmp
= sFullString
;
332 bFoundMneumonic
= TRUE
;
334 rDC
.GetTextExtent( sTmp
338 sTmp
= sFullString
[nIndex
+ 1];
339 rDC
.GetTextExtent( sTmp
343 sFullString
.Replace(sTgt
.c_str(), "", TRUE
);
347 // Draw the main item text sans the accel text
349 POINTL vPntStart
= {nX
, rRect
.y
+ 4};
350 ::GpiCharStringAt( rDC
.GetHPS()
352 ,sFullString
.length()
353 ,(PCH
)sFullString
.c_str()
358 // Underline the mneumonic -- still won't work, but at least it "looks" right
361 POINTL vPntEnd
= {nX
+ nWidth
+ nCharWidth
- 3, rRect
.y
+ 2}; //CharWidth is bit wide
363 vPntStart
.x
= nX
+ nWidth
- 1;
364 vPntStart
.y
= rRect
.y
+ 2; // Make it look pretty!
365 vPen
= wxPen(vColText
, 1, wxSOLID
); // Assuming we are always black
367 ::GpiMove(hPS
, &vPntStart
);
368 ::GpiLine(hPS
, &vPntEnd
);
372 // Now draw the accel text
379 rDC
.GetTextExtent( sAccel
384 // Back off the starting position from the right edge
386 vPntStart
.x
= rRect
.width
- (nWidth
+ 7);
387 vPntStart
.y
= rRect
.y
+ 4;
388 ::GpiCharStringAt( rDC
.GetHPS()
399 if (IsCheckable() && !m_bmpChecked
.Ok())
401 if (eStatus
& wxODChecked
)
404 HBITMAP hBmpCheck
= ::WinGetSysBitmap(HWND_DESKTOP
, SBMP_MENUCHECK
);
406 vRect
.xLeft
= rRect
.x
;
407 vRect
.xRight
= rRect
.x
+ GetMarginWidth();
408 vRect
.yBottom
= rRect
.y
;
409 vRect
.yTop
= rRect
.y
+ m_nHeight
- 3;
411 ::WinDrawBitmap( hPS
// PS for this menuitem
412 ,hBmpCheck
// system checkmark
413 ,NULL
// draw the whole bitmap
414 ,(PPOINTL
)&vRect
// destination -- bottom left corner of the menuitem area
417 ,DBM_NORMAL
// draw normal size
424 // For uncheckable item we use only the 'checked' bitmap
426 wxBitmap
vBmp(GetBitmap(IsCheckable() ? ((eStatus
& wxODChecked
) != 0) : TRUE
));
431 wxMemoryDC
vDCMem(&rDC
);
432 wxMemoryDC
* pOldDC
= (wxMemoryDC
*)vBmp
.GetSelectedInto();
436 vBmp
.SetSelectedInto(NULL
);
438 vDCMem
.SelectObject(vBmp
);
443 int nBmpWidth
= vBmp
.GetWidth();
444 int nBmpHeight
= vBmp
.GetHeight();
447 // There should be enough space!
449 wxASSERT((nBmpWidth
<= rRect
.width
) && (nBmpHeight
<= rRect
.height
));
451 int nHeightDiff
= m_nHeight
- nBmpHeight
;
453 rDC
.Blit( rRect
.x
+ (GetMarginWidth() - nBmpWidth
) / 2
454 ,rRect
.y
+ nHeightDiff
/ 2
464 if (eStatus
& wxODSelected
)
466 RECT vRectBmp
= { rRect
.x
468 ,rRect
.x
+ GetMarginWidth() - 1
469 ,rRect
.y
+ m_nHeight
- 1
471 POINTL vPnt1
= {rRect
.x
+ 1, rRect
.y
+ 3}; // Leave a little background border
472 POINTL vPnt2
= {rRect
.x
+ GetMarginWidth(), rRect
.y
+ m_nHeight
- 3};
476 vLine
.lColor
= vColBack
.GetPixel();
483 ::GpiMove(hPS
, &vPnt1
);
491 vBmp
.SetSelectedInto(NULL
);
495 } // end of wxOwnerDrawn::OnDrawItem
497 #endif //wxUSE_OWNER_DRAWN