1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/combog.cpp
3 // Purpose: Generic wxComboCtrl
4 // Author: Jaakko Salli
6 // Created: Apr-30-2006
8 // Copyright: (c) 2005 Jaakko Salli
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
32 #include "wx/combobox.h"
33 #include "wx/dcclient.h"
34 #include "wx/settings.h"
37 #include "wx/dcbuffer.h"
39 // ----------------------------------------------------------------------------
40 // Some constant adjustments to make the generic more bearable
42 #if defined(__WXUNIVERSAL__)
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
49 #elif defined(__WXMSW__)
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
56 #elif defined(__WXGTK__)
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
63 #elif defined(__WXMAC__)
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
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
80 // ============================================================================
82 // ============================================================================
84 // Only implement if no native or it wasn't fully featured
85 #ifndef wxCOMBOCONTROL_FULLY_FEATURED
88 // ----------------------------------------------------------------------------
90 // ----------------------------------------------------------------------------
92 BEGIN_EVENT_TABLE(wxGenericComboCtrl
, wxComboCtrlBase
)
93 EVT_PAINT(wxGenericComboCtrl::OnPaintEvent
)
94 EVT_MOUSE_EVENTS(wxGenericComboCtrl::OnMouseEvent
)
98 IMPLEMENT_DYNAMIC_CLASS(wxGenericComboCtrl
, wxComboCtrlBase
)
100 void wxGenericComboCtrl::Init()
104 bool wxGenericComboCtrl::Create(wxWindow
*parent
,
106 const wxString
& value
,
110 const wxValidator
& validator
,
111 const wxString
& name
)
115 long border
= style
& wxBORDER_MASK
;
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
123 /*if ( wxUxThemeEngine::GetIfActive() )
125 border = wxBORDER_NONE;
126 m_widthCustomBorder = 1;
129 border
= wxBORDER_SUNKEN
;
130 #elif defined(__WXGTK__)
131 border
= wxBORDER_NONE
;
132 //m_widthCustomBorder = 2;
133 m_widthCustomBorder
= 1;
135 border
= wxBORDER_SIMPLE
;
138 style
= (style
& ~(wxBORDER_MASK
)) | border
;
141 #if defined(__WXGTK__)
142 Customize( wxCC_BUTTON_OUTSIDE_BORDER
|
143 wxCC_NO_TEXT_AUTO_SELECT
);
146 if ( style
& wxCC_STD_BUTTON
)
147 m_iFlags
|= wxCC_POPUP_ON_MOUSE_UP
;
149 // create main window
150 if ( !wxComboCtrlBase::Create(parent
,
155 style
| wxFULL_REPAINT_ON_RESIZE
,
160 // Create textctrl, if necessary
161 CreateTextCtrl( wxNO_BORDER
, validator
);
163 // Add keyboard input handlers for main control and textctrl
164 InstallInputHandlers();
167 SetBackgroundStyle( wxBG_STYLE_CUSTOM
); // for double-buffering
169 // SetBestSize should be called last
175 wxGenericComboCtrl::~wxGenericComboCtrl()
179 void wxGenericComboCtrl::OnResize()
182 // Recalculates button and textctrl areas
183 CalculateAreas(DEFAULT_DROPBUTTON_WIDTH
);
186 // Move separate button control, if any, to correct position
189 wxSize sz
= GetClientSize();
190 m_btn
->SetSize( m_btnArea
.x
+ m_btnSpacingX
,
191 (sz
.y
-m_btnSize
.y
)/2,
197 // Move textctrl, if any, accordingly
198 PositionTextCtrl( TEXTCTRLXADJUST
, TEXTCTRLYADJUST
);
201 void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent
& WXUNUSED(event
) )
203 wxSize sz
= GetClientSize();
204 wxBufferedPaintDC
dc(this,GetBufferBitmap(sz
));
206 const wxRect
& rectb
= m_btnArea
;
207 wxRect rect
= m_tcArea
;
209 // artificial simple border
210 if ( m_widthCustomBorder
)
212 int customBorder
= m_widthCustomBorder
;
215 wxPen
pen1( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT
),
220 // area around both controls
221 wxRect
rect2(0,0,sz
.x
,sz
.y
);
222 if ( m_iFlags
& wxCC_IFLAG_BUTTON_OUTSIDE
)
225 if ( customBorder
== 1 )
235 rect2
.x
-= customBorder
;
236 rect2
.y
-= customBorder
;
238 rect2
.width
+= 1 + customBorder
;
239 rect2
.height
+= 1 + customBorder
;
243 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
244 dc
.DrawRectangle(rect2
);
247 wxColour winCol
= GetBackgroundColour();
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);
254 // clear main background
255 dc
.DrawRectangle(rect
);
258 // Standard button rendering
259 DrawButton(dc
,rectb
,true);
261 // paint required portion on the control
262 if ( (!m_text
|| m_widthCustomPaint
) )
264 wxASSERT( m_widthCustomPaint
>= 0 );
266 // this is intentionally here to allow drawed rectangle's
267 // right edge to be hidden
269 rect
.width
= m_widthCustomPaint
;
271 dc
.SetFont( GetFont() );
273 dc
.SetClippingRegion(rect
);
274 if ( m_popupInterface
)
275 m_popupInterface
->PaintComboControl(dc
,rect
);
277 wxComboPopup::DefaultPaintComboControl(this,dc
,rect
);
281 void wxGenericComboCtrl::OnMouseEvent( wxMouseEvent
& event
)
283 bool isOnButtonArea
= m_btnArea
.Contains(event
.m_x
,event
.m_y
);
284 int handlerFlags
= isOnButtonArea
? wxCC_MF_ON_BUTTON
: 0;
286 // Preprocessing fabricates double-clicks and prevents
287 // (it may also do other common things in future)
288 if ( PreprocessMouseEvent(event
,handlerFlags
) )
291 const bool ctrlIsButton
= wxPlatformIs(wxOS_WINDOWS
);
294 (m_windowStyle
& (wxCC_SPECIAL_DCLICK
|wxCB_READONLY
)) == wxCB_READONLY
)
296 // if no textctrl and no special double-click, then the entire control acts
298 handlerFlags
|= wxCC_MF_ON_BUTTON
;
299 if ( HandleButtonMouseEvent(event
,handlerFlags
) )
304 if ( isOnButtonArea
|| HasCapture() )
306 if ( HandleButtonMouseEvent(event
,handlerFlags
) )
309 else if ( m_btnState
)
311 // otherwise need to clear the hover status
313 RefreshRect(m_btnArea
);
318 // This will handle left_down and left_dclick events outside button in a Windows/GTK-like manner.
319 // See header file for further information on this method.
320 HandleNormalMouseEvent(event
);
324 bool wxGenericComboCtrl::IsKeyPopupToggle(const wxKeyEvent
& event
) const
326 int keycode
= event
.GetKeyCode();
327 bool isPopupShown
= IsPopupShown();
329 // This code is AFAIK appropriate for wxGTK.
333 if ( keycode
== WXK_ESCAPE
||
334 ( keycode
== WXK_UP
&& event
.AltDown() ) )
339 if ( keycode
== WXK_DOWN
&& event
.AltDown() )
346 #ifdef __WXUNIVERSAL__
348 bool wxGenericComboCtrl::PerformAction(const wxControlAction
& action
,
350 const wxString
& strArg
)
352 bool processed
= false;
353 if ( action
== wxACTION_COMBOBOX_POPUP
)
355 if ( !m_isPopupShown
)
362 else if ( action
== wxACTION_COMBOBOX_DISMISS
)
364 if ( m_isPopupShown
)
375 return wxControl::PerformAction(action
, numArg
, strArg
);
381 #endif // __WXUNIVERSAL__
383 // If native wxComboCtrl was not defined, then prepare a simple
384 // front-end so that wxRTTI works as expected.
385 #ifndef _WX_COMBOCONTROL_H_
386 IMPLEMENT_DYNAMIC_CLASS(wxComboCtrl
, wxGenericComboCtrl
)
389 #endif // !wxCOMBOCONTROL_FULLY_FEATURED
391 #endif // wxUSE_COMBOCTRL