]> git.saurik.com Git - wxWidgets.git/blame - src/common/bmpcboxcmn.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / bmpcboxcmn.cpp
CommitLineData
f696015c
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/common/bmpcboxcmn.cpp
3// Purpose: wxBitmapComboBox
4// Author: Jaakko Salli
5// Created: 2008-04-09
c574bfa9 6// RCS-ID: $Id$
f696015c
VZ
7// Copyright: (c) 2008 Jaakko Salli
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
25#include "wx/bmpcbox.h"
26
27#if wxUSE_BITMAPCOMBOBOX
28
29#ifndef WX_PRECOMP
30 #include "wx/log.h"
c574bfa9
VZ
31 #include "wx/dc.h"
32 #include "wx/ctrlsub.h"
f696015c
VZ
33#endif
34
35#include "wx/settings.h"
36
37// For wxODCB_XXX flags
38#include "wx/odcombo.h"
39
40
23318a53 41const char wxBitmapComboBoxNameStr[] = "bitmapComboBox";
f696015c
VZ
42
43#if defined(wxBITMAPCOMBOBOX_OWNERDRAWN_BASED)
44
45#define IMAGE_SPACING_RIGHT 4 // Space left of image
46
47#define IMAGE_SPACING_LEFT 4 // Space right of image, left of text
48
49#define EXTRA_FONT_HEIGHT 0 // Add to increase min. height of list items
50
51#define wxBCB_DEFAULT_ITEM_HEIGHT 13
52
53
54// This macros allows wxArrayPtrVoid to be used in more convenient manner
55#define GetBitmapPtr(n) ((wxBitmap*)m_bitmaps[n])
56
57
58// ----------------------------------------------------------------------------
59// Initialization
60// ----------------------------------------------------------------------------
61
62void wxBitmapComboBoxBase::Init()
63{
64 m_fontHeight = 0;
65 m_imgAreaWidth = 0;
66 m_indent = 0;
67 m_usedImgSize = wxSize(-1, -1);
68}
69
70void wxBitmapComboBoxBase::UpdateInternals()
71{
72 m_fontHeight = GetControl()->GetCharHeight() + EXTRA_FONT_HEIGHT;
73
74 while ( m_bitmaps.GetCount() < GetItemContainer()->GetCount() )
75 m_bitmaps.Add( new wxBitmap() );
76}
77
78// ----------------------------------------------------------------------------
79// Item manipulation
80// ----------------------------------------------------------------------------
81
82void wxBitmapComboBoxBase::DoSetItemBitmap(unsigned int n, const wxBitmap& bitmap)
83{
84 wxCHECK_RET( n < m_bitmaps.size(), "invalid item index" );
85 *GetBitmapPtr(n) = bitmap;
86}
87
88wxBitmap wxBitmapComboBoxBase::GetItemBitmap(unsigned int n) const
89{
90 wxCHECK_MSG( n < m_bitmaps.size(), wxNullBitmap, "invalid item index" );
91 return *GetBitmapPtr(n);
92}
93
94// ----------------------------------------------------------------------------
95// wxItemContainer methods
96// ----------------------------------------------------------------------------
97
98void wxBitmapComboBoxBase::BCBDoClear()
99{
100 for ( unsigned i = 0; i < m_bitmaps.size(); i++ )
101 delete GetBitmapPtr(i);
102
103 m_bitmaps.Empty();
104
105 m_usedImgSize.x = -1;
106 m_usedImgSize.y = -1;
107
108 DetermineIndent();
109}
110
111void wxBitmapComboBoxBase::BCBDoDeleteOneItem(unsigned int n)
112{
113 delete GetBitmapPtr(n);
114 m_bitmaps.RemoveAt(n);
115}
116
117// ----------------------------------------------------------------------------
118// Preparation and Calculations
119// ----------------------------------------------------------------------------
120
121bool wxBitmapComboBoxBase::OnAddBitmap(const wxBitmap& bitmap)
122{
123 if ( bitmap.IsOk() )
124 {
125 int width = bitmap.GetWidth();
126 int height = bitmap.GetHeight();
127
128 if ( m_usedImgSize.x < 0 )
129 {
130 // If size not yet determined, get it from this image.
131 m_usedImgSize.x = width;
132 m_usedImgSize.y = height;
133
134 // Adjust control size to vertically fit the bitmap
135 wxWindow* ctrl = GetControl();
136 ctrl->InvalidateBestSize();
137 wxSize newSz = ctrl->GetBestSize();
138 wxSize sz = ctrl->GetSize();
139 if ( newSz.y > sz.y )
140 ctrl->SetSize(sz.x, newSz.y);
141 else
142 DetermineIndent();
143 }
144
145 wxCHECK_MSG( width == m_usedImgSize.x && height == m_usedImgSize.y,
146 false,
147 "you can only add images of same size" );
148
149 return true;
150 }
151
152 return false;
153}
154
155int wxBitmapComboBoxBase::DetermineIndent()
156{
157 // Recalculate amount of empty space needed in front of
158 // text in control itself.
159 int indent = m_imgAreaWidth = 0;
160
161 if ( m_usedImgSize.x > 0 )
162 {
163 indent = m_usedImgSize.x + IMAGE_SPACING_LEFT + IMAGE_SPACING_RIGHT;
164 m_imgAreaWidth = indent;
165
166 indent -= 3;
167 }
168
169 return indent;
170}
171
172// ----------------------------------------------------------------------------
173// Item drawing and measuring
174// ----------------------------------------------------------------------------
175
176void wxBitmapComboBoxBase::DrawBackground(wxDC& dc,
177 const wxRect& rect,
178 int WXUNUSED(item),
179 int flags) const
180{
181 if ( flags & wxODCB_PAINTING_SELECTED )
182 {
183 const int vSizeDec = 0; // Vertical size reduction of selection rectangle edges
184
185 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
186
187 wxColour selCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
188 dc.SetPen(selCol);
189 dc.SetBrush(selCol);
190 dc.DrawRectangle(rect.x,
191 rect.y+vSizeDec,
192 rect.width,
193 rect.height-(vSizeDec*2));
194 }
195 else
196 {
197 dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
198
199 wxColour selCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
200 dc.SetPen(selCol);
201 dc.SetBrush(selCol);
202 dc.DrawRectangle(rect);
203 }
204}
205
206void wxBitmapComboBoxBase::DrawItem(wxDC& dc,
207 const wxRect& rect,
208 int item,
209 const wxString& text,
210 int WXUNUSED(flags)) const
211{
212 const wxBitmap& bmp = *GetBitmapPtr(item);
213 if ( bmp.IsOk() )
214 {
215 wxCoord w = bmp.GetWidth();
216 wxCoord h = bmp.GetHeight();
217
218 // Draw the image centered
219 dc.DrawBitmap(bmp,
220 rect.x + (m_usedImgSize.x-w)/2 + IMAGE_SPACING_LEFT,
221 rect.y + (rect.height-h)/2,
222 true);
223 }
224
6636ef8d 225 if ( !text.empty() )
f696015c
VZ
226 dc.DrawText(text,
227 rect.x + m_imgAreaWidth + 1,
228 rect.y + (rect.height-dc.GetCharHeight())/2);
229}
230
231wxCoord wxBitmapComboBoxBase::MeasureItem(size_t WXUNUSED(item)) const
232{
233 if ( m_usedImgSize.y >= 0 )
234 {
235 int imgHeightArea = m_usedImgSize.y + 2;
236 return imgHeightArea > m_fontHeight ? imgHeightArea : m_fontHeight;
237 }
23318a53 238
f696015c
VZ
239 return wxBCB_DEFAULT_ITEM_HEIGHT;
240}
241
242#endif // wxBITMAPCOMBOBOX_OWNERDRAWN_BASED
243
244#endif // wxUSE_BITMAPCOMBOBOX