]> git.saurik.com Git - wxWidgets.git/blame - src/generic/combog.cpp
simplify mouse wheel signal handler
[wxWidgets.git] / src / generic / combog.cpp
CommitLineData
a340b80d
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: combog.cpp
3// Purpose: Generic wxComboControl
4// Author: Jaakko Salli
5// Modified by:
6// Created: Apr-30-2006
7// RCS-ID: $Id$
8// Copyright: (c) 2005 Jaakko Salli
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#if wxUSE_COMBOCONTROL
27
28#ifndef WX_PRECOMP
29 #include "wx/log.h"
30 #include "wx/combobox.h"
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
33#endif
34
35#include "wx/dcbuffer.h"
36
37#include "wx/combo.h"
38
39
40// ----------------------------------------------------------------------------
41// Some constant adjustments to make the generic more bearable
42
43#if defined(__WXUNIVERSAL__)
44
45#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent
46#define TEXTCTRLYADJUST 0
47#define TEXTXADJUST 0 // how much is read-only text's x adjusted
48#define DEFAULT_DROPBUTTON_WIDTH 19
49
50#elif defined(__WXMSW__)
51
52#define TEXTCTRLXADJUST 2 // position adjustment for wxTextCtrl, with zero indent
53#define TEXTCTRLYADJUST 3
54#define TEXTXADJUST 0 // how much is read-only text's x adjusted
55#define DEFAULT_DROPBUTTON_WIDTH 17
56
57#elif defined(__WXGTK__)
58
59#define TEXTCTRLXADJUST -1 // position adjustment for wxTextCtrl, with zero indent
60#define TEXTCTRLYADJUST 0
61#define TEXTXADJUST 1 // how much is read-only text's x adjusted
62#define DEFAULT_DROPBUTTON_WIDTH 23
63
64#elif defined(__WXMAC__)
65
66#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent
67#define TEXTCTRLYADJUST 0
68#define TEXTXADJUST 0 // how much is read-only text's x adjusted
69#define DEFAULT_DROPBUTTON_WIDTH 19
70
71#else
72
73#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent
74#define TEXTCTRLYADJUST 0
75#define TEXTXADJUST 0 // how much is read-only text's x adjusted
76#define DEFAULT_DROPBUTTON_WIDTH 19
77
78#endif
79
80
81// ============================================================================
82// implementation
83// ============================================================================
84
85// Only implement if no native or it wasn't fully featured
86#ifndef wxCOMBOCONTROL_FULLY_FEATURED
87
88
89// ----------------------------------------------------------------------------
90// wxGenericComboControl
91// ----------------------------------------------------------------------------
92
93BEGIN_EVENT_TABLE(wxGenericComboControl, wxComboControlBase)
94 EVT_PAINT(wxGenericComboControl::OnPaintEvent)
95 EVT_MOUSE_EVENTS(wxGenericComboControl::OnMouseEvent)
96END_EVENT_TABLE()
97
98
99IMPLEMENT_DYNAMIC_CLASS(wxGenericComboControl, wxComboControlBase)
100
101void wxGenericComboControl::Init()
102{
103}
104
105bool wxGenericComboControl::Create(wxWindow *parent,
106 wxWindowID id,
107 const wxString& value,
108 const wxPoint& pos,
109 const wxSize& size,
110 long style,
111 const wxValidator& validator,
112 const wxString& name)
113{
114
115 // Set border
116 long border = style & wxBORDER_MASK;
117
118 if ( !border )
119 {
120#if defined(__WXUNIVERSAL__)
121 border = wxBORDER_SIMPLE;
122#elif defined(__WXMSW__)
123 // For XP, have 1-width custom border, for older version use sunken
124 if ( wxUxThemeEngine::GetIfActive() )
125 {
126 border = wxBORDER_NONE;
127 m_widthCustomBorder = 1;
128 }
129 else
130 border = wxBORDER_SUNKEN;
131#elif defined(__WXGTK__)
132 border = wxBORDER_NONE;
133 //m_widthCustomBorder = 2;
134 m_widthCustomBorder = 1;
135#else
136 border = wxBORDER_SIMPLE;
137#endif
138
139 style = (style & ~(wxBORDER_MASK)) | border;
140 }
141
142#if defined(__WXGTK__)
143 Customize( wxCC_BUTTON_OUTSIDE_BORDER |
144 wxCC_NO_TEXT_AUTO_SELECT );
145#endif
146
147 if ( style & wxCC_STD_BUTTON )
148 m_iFlags |= wxCC_POPUP_ON_MOUSE_UP;
149
150 // create main window
151 if ( !wxComboControlBase::Create(parent,
152 id,
153 value,
154 wxDefaultPosition,
155 wxDefaultSize,
156 style | wxFULL_REPAINT_ON_RESIZE,
157 wxDefaultValidator,
158 name) )
159 return false;
160
161 // Create textctrl, if necessary
162 CreateTextCtrl( wxNO_BORDER, validator );
163
164 // Add keyboard input handlers for main control and textctrl
165 InstallInputHandlers( true );
166
167 // Set background
168 SetBackgroundStyle( wxBG_STYLE_CUSTOM ); // for double-buffering
169
170 // SetSize should be called last
171 SetSize(pos.x,pos.y,size.x,size.y);
172
173 return true;
174}
175
176wxGenericComboControl::~wxGenericComboControl()
177{
178}
179
180void wxGenericComboControl::OnResize()
181{
182
183 // Recalculates button and textctrl areas
184 CalculateAreas(DEFAULT_DROPBUTTON_WIDTH);
185
186#if 0
187 // Move separate button control, if any, to correct position
188 if ( m_btn )
189 {
190 wxSize sz = GetClientSize();
191 m_btn->SetSize( m_btnArea.x + m_btnSpacingX,
192 (sz.y-m_btnSize.y)/2,
193 m_btnSize.x,
194 m_btnSize.y );
195 }
196#endif
197
198 // Move textctrl, if any, accordingly
199 PositionTextCtrl( TEXTCTRLXADJUST, TEXTCTRLYADJUST );
200}
201
202void wxGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) )
203{
204 wxSize sz = GetClientSize();
205 wxBufferedPaintDC dc(this,GetBufferBitmap(sz));
206
207 const wxRect& rectb = m_btnArea;
208 wxRect rect = m_tcArea;
209
210 // artificial simple border
211 if ( m_widthCustomBorder )
212 {
213 int customBorder = m_widthCustomBorder;
214
215 // Set border colour
216 wxPen pen1( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT),
217 customBorder,
218 wxSOLID );
219 dc.SetPen( pen1 );
220
221 // area around both controls
222 wxRect rect2(0,0,sz.x,sz.y);
223 if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE )
224 {
225 rect2 = m_tcArea;
226 if ( customBorder == 1 )
227 {
228 rect2.Inflate(1);
229 }
230 else
231 {
232 #ifdef __WXGTK__
233 rect2.x -= 1;
234 rect2.y -= 1;
235 #else
236 rect2.x -= customBorder;
237 rect2.y -= customBorder;
238 #endif
239 rect2.width += 1 + customBorder;
240 rect2.height += 1 + customBorder;
241 }
242 }
243
244 dc.SetBrush( *wxTRANSPARENT_BRUSH );
245 dc.DrawRectangle(rect2);
246 }
247
248 wxColour winCol = GetBackgroundColour();
249 dc.SetBrush(winCol);
250 dc.SetPen(winCol);
251
252 //wxLogDebug(wxT("hei: %i tcy: %i tchei: %i"),GetClientSize().y,m_tcArea.y,m_tcArea.height);
253 //wxLogDebug(wxT("btnx: %i tcx: %i tcwid: %i"),m_btnArea.x,m_tcArea.x,m_tcArea.width);
254
255 // clear main background
256 dc.DrawRectangle(rect);
257
258 if ( !m_btn )
259 // Standard button rendering
260 DrawButton(dc,rectb,true);
261
262 // paint required portion on the control
6d0ce565 263 if ( (!m_text || m_widthCustomPaint) )
a340b80d
VZ
264 {
265 wxASSERT( m_widthCustomPaint >= 0 );
266
267 // this is intentionally here to allow drawed rectangle's
268 // right edge to be hidden
269 if ( m_text )
270 rect.width = m_widthCustomPaint;
271
272 dc.SetFont( GetFont() );
273
274 dc.SetClippingRegion(rect);
6d0ce565
VZ
275 if ( m_popupInterface )
276 m_popupInterface->PaintComboControl(dc,rect);
277 else
278 wxComboPopup::DefaultPaintComboControl(this,dc,rect);
a340b80d
VZ
279 }
280}
281
282void wxGenericComboControl::OnMouseEvent( wxMouseEvent& event )
283{
284 bool isOnButtonArea = m_btnArea.Inside(event.m_x,event.m_y);
285 int handlerFlags = isOnButtonArea ? wxCC_MF_ON_BUTTON : 0;
286
287 // Preprocessing fabricates double-clicks and prevents
288 // (it may also do other common things in future)
289 if ( PreprocessMouseEvent(event,handlerFlags) )
290 return;
291
6d0ce565
VZ
292#ifdef __WXMSW__
293 const bool ctrlIsButton = true;
294#else
295 const bool ctrlIsButton = false;
296#endif
297
298 if ( ctrlIsButton &&
299 (m_windowStyle & (wxCC_SPECIAL_DCLICK|wxCB_READONLY)) == wxCB_READONLY )
a340b80d
VZ
300 {
301 // if no textctrl and no special double-click, then the entire control acts
302 // as a button
303 handlerFlags |= wxCC_MF_ON_BUTTON;
304 if ( HandleButtonMouseEvent(event,handlerFlags) )
305 return;
306 }
307 else
308 {
309 if ( isOnButtonArea || HasCapture() )
310 {
311 if ( HandleButtonMouseEvent(event,handlerFlags) )
312 return;
313 }
314 else if ( m_btnState )
315 {
316 // otherwise need to clear the hover status
317 m_btnState = 0;
318 RefreshRect(m_btnArea);
319 }
320 }
321
322 //
323 // This will handle left_down and left_dclick events outside button in a Windows/GTK-like manner.
324 // See header file for further information on this method.
325 HandleNormalMouseEvent(event);
326
327}
328
329#ifdef __WXUNIVERSAL__
330
331bool wxGenericComboControl::PerformAction(const wxControlAction& action,
332 long numArg,
333 const wxString& strArg)
334{
335 bool processed = false;
336 if ( action == wxACTION_COMBOBOX_POPUP )
337 {
338 if ( !m_isPopupShown )
339 {
340 ShowPopup();
341
342 processed = true;
343 }
344 }
345 else if ( action == wxACTION_COMBOBOX_DISMISS )
346 {
347 if ( m_isPopupShown )
348 {
349 HidePopup();
350
351 processed = true;
352 }
353 }
354
355 if ( !processed )
356 {
357 // pass along
358 return wxControl::PerformAction(action, numArg, strArg);
359 }
360
361 return true;
362}
363
364#endif // __WXUNIVERSAL__
365
366// If native wxComboControl was not defined, then prepare a simple
367// front-end so that wxRTTI works as expected.
368#ifndef _WX_COMBOCONTROL_H_
369IMPLEMENT_DYNAMIC_CLASS(wxComboControl, wxGenericComboControl)
370#endif
371
372#endif // !wxCOMBOCONTROL_FULLY_FEATURED
373
374#endif // wxUSE_COMBOCONTROL