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