#include "wx/combobox.h"
#ifndef WX_PRECOMP
+ #include "wx/app.h"
#include "wx/log.h"
#include "wx/dcclient.h"
#include "wx/settings.h"
// native controls work on it like normal.
#define POPUPWIN_IS_PERFECT 0 // Same, but for non-transient popup window.
#define TEXTCTRL_TEXT_CENTERED 0 // 1 if text in textctrl is vertically centered
+#define FOCUS_RING 0 // No focus ring on wxMSW
//#undef wxUSE_POPUPWIN
//#define wxUSE_POPUPWIN 0
// native controls work on it like normal.
#define POPUPWIN_IS_PERFECT 1 // Same, but for non-transient popup window.
#define TEXTCTRL_TEXT_CENTERED 1 // 1 if text in textctrl is vertically centered
+#define FOCUS_RING 0 // No focus ring on wxGTK
#elif defined(__WXMAC__)
// native controls work on it like normal.
#define POPUPWIN_IS_PERFECT 0 // Same, but for non-transient popup window.
#define TEXTCTRL_TEXT_CENTERED 1 // 1 if text in textctrl is vertically centered
+#define FOCUS_RING 3 // Reserve room for the textctrl's focus ring to display
+
+#undef DEFAULT_DROPBUTTON_WIDTH
+#define DEFAULT_DROPBUTTON_WIDTH 22
+#undef COMBO_MARGIN
+#define COMBO_MARGIN FOCUS_RING
#else
// native controls work on it like normal.
#define POPUPWIN_IS_PERFECT 0 // Same, but for non-transient popup window.
#define TEXTCTRL_TEXT_CENTERED 1 // 1 if text in textctrl is vertically centered
+#define FOCUS_RING 0
#endif
#if USES_WXPOPUPTRANSIENTWINDOW
virtual bool Show( bool show );
virtual bool ProcessLeftDown(wxMouseEvent& event);
+protected:
virtual void OnDismiss();
#endif
EVT_SIZE(wxComboCtrlBase::OnSizeEvent)
EVT_SET_FOCUS(wxComboCtrlBase::OnFocusEvent)
EVT_KILL_FOCUS(wxComboCtrlBase::OnFocusEvent)
+ EVT_IDLE(wxComboCtrlBase::OnIdleEvent)
//EVT_BUTTON(wxID_ANY,wxComboCtrlBase::OnButtonClickEvent)
EVT_KEY_DOWN(wxComboCtrlBase::OnKeyEvent)
EVT_TEXT_ENTER(wxID_ANY,wxComboCtrlBase::OnTextCtrlEvent)
m_toplevEvtHandler = (wxEvtHandler*) NULL;
#endif
+ m_mainCtrlWnd = this;
+
m_heightPopup = -1;
m_widthMinPopup = -1;
m_anchorSide = 0;
m_absIndent = -1;
m_iFlags = 0;
m_timeCanAcceptClick = 0;
+
+ m_resetFocus = false;
}
bool wxComboCtrlBase::Create(wxWindow *parent,
m_ignoreEvtText = 0;
m_text = new wxTextCtrl(this, wxID_ANY, m_valueString,
- wxDefaultPosition, wxDefaultSize,
+ wxDefaultPosition, wxSize(10,-1),
style, validator);
-
- // This is required for some platforms (GTK+ atleast)
- m_text->SetSizeHints(2,4);
}
}
void wxComboCtrlBase::OnThemeChange()
{
- SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+ // Leave the default bg on the Mac so the area used by the focus ring will
+ // be the correct colour and themed brush. Instead we'll use
+ // wxSYS_COLOUR_WINDOW in the EVT_PAINT handler as needed.
+#ifndef __WXMAC__
+ SetOwnBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
+#endif
}
wxComboCtrlBase::~wxComboCtrlBase()
m_btnSize.y = butHeight;
m_btnArea.x = ( m_btnSide==wxRIGHT ? sz.x - butAreaWid - btnBorder : btnBorder );
- m_btnArea.y = btnBorder;
+ m_btnArea.y = btnBorder + FOCUS_RING;
m_btnArea.width = butAreaWid;
- m_btnArea.height = sz.y - (btnBorder*2);
+ m_btnArea.height = sz.y - ((btnBorder+FOCUS_RING)*2);
- m_tcArea.x = ( m_btnSide==wxRIGHT ? 0 : butAreaWid ) + customBorder;
- m_tcArea.y = customBorder;
- m_tcArea.width = sz.x - butAreaWid - (customBorder*2);
- m_tcArea.height = sz.y - (customBorder*2);
+ m_tcArea.x = ( m_btnSide==wxRIGHT ? 0 : butAreaWid ) + customBorder + FOCUS_RING;
+ m_tcArea.y = customBorder + FOCUS_RING;
+ m_tcArea.width = sz.x - butAreaWid - (customBorder*2) - (FOCUS_RING*2);
+ m_tcArea.height = sz.y - ((customBorder+FOCUS_RING)*2);
/*
if ( m_text )
if ( !m_text )
return;
+#if !TEXTCTRL_TEXT_CENTERED
+
wxSize sz = GetClientSize();
- int customBorder = m_widthCustomBorder;
-#if !TEXTCTRL_TEXT_CENTERED
+ int customBorder = m_widthCustomBorder;
if ( (m_text->GetWindowStyleFlag() & wxBORDER_MASK) == wxNO_BORDER )
{
// Centre textctrl
}
}
else
-#else
+#else // TEXTCTRL_TEXT_CENTERED
wxUnusedVar(textCtrlXAdjust);
wxUnusedVar(textCtrlYAdjust);
-#endif
+#endif // !TEXTCTRL_TEXT_CENTERED/TEXTCTRL_TEXT_CENTERED
{
// If it has border, have textctrl will the entire text field.
m_text->SetSize( m_tcArea.x + m_widthCustomPaint,
- customBorder,
- sz.x - m_btnArea.width - m_widthCustomPaint - customBorder,
- sz.y-(customBorder*2) );
+ m_tcArea.y,
+ m_tcArea.width - m_widthCustomPaint,
+ m_tcArea.height );
}
}
fhei += 1;
#endif
- wxSize ret(sizeText.x + COMBO_MARGIN + DEFAULT_DROPBUTTON_WIDTH,
- fhei);
+#ifdef __WXMAC__
+ // these are the numbers from the HIG:
+ switch ( m_windowVariant )
+ {
+ case wxWINDOW_VARIANT_NORMAL:
+ default :
+ fhei = 22;
+ break;
+ case wxWINDOW_VARIANT_SMALL:
+ fhei = 19;
+ break;
+ case wxWINDOW_VARIANT_MINI:
+ fhei = 15;
+ break;
+ }
+#endif
+
+ fhei += 2 * FOCUS_RING;
+ int width = sizeText.x + FOCUS_RING + COMBO_MARGIN + DEFAULT_DROPBUTTON_WIDTH;
+ wxSize ret(width, fhei);
CacheBestSize(ret);
return ret;
}
}
#endif // wxUSE_TOOLTIPS
+#if wxUSE_VALIDATORS
+void wxComboCtrlBase::SetValidator(const wxValidator& validator)
+{
+ wxTextCtrl* textCtrl = GetTextCtrl();
+
+ if ( textCtrl )
+ textCtrl->SetValidator( validator );
+}
+
+wxValidator* wxComboCtrlBase::GetValidator()
+{
+ wxTextCtrl* textCtrl = GetTextCtrl();
+
+ if ( textCtrl )
+ return textCtrl->GetValidator();
+
+ return wxControl::GetValidator();
+}
+#endif // wxUSE_VALIDATORS
+
// ----------------------------------------------------------------------------
// painting
// ----------------------------------------------------------------------------
else
{
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) );
+#ifndef __WXMAC__ // see note in OnThemeChange
bgCol = GetBackgroundColour();
+#else
+ bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+#endif
}
}
else
{
dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) );
+#ifndef __WXMAC__ // see note in OnThemeChange
bgCol = GetBackgroundColour();
+#else
+ bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
+#endif
}
dc.SetBrush( bgCol );
}
#endif
-void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, bool paintBg )
+void wxComboCtrlBase::DrawButton( wxDC& dc, const wxRect& rect, int paintBg )
{
int drawState = m_btnState;
if ( keycode == WXK_TAB )
{
wxNavigationKeyEvent evt;
+
+ wxWindow* mainCtrl = GetMainWindowOfCompositeControl();
+
evt.SetFlags(wxNavigationKeyEvent::FromTab|
(!event.ShiftDown() ? wxNavigationKeyEvent::IsForward
: wxNavigationKeyEvent::IsBackward));
- evt.SetEventObject(this);
- GetParent()->GetEventHandler()->AddPendingEvent(evt);
+ evt.SetEventObject(mainCtrl);
+ evt.SetCurrentFocus(mainCtrl);
+ mainCtrl->GetParent()->GetEventHandler()->AddPendingEvent(evt);
return;
}
{
if ( event.GetEventType() == wxEVT_SET_FOCUS )
{
- if ( m_text && m_text != ::wxWindow::FindFocus() )
- m_text->SetFocus();
+ wxWindow* tc = GetTextCtrl();
+ if ( tc && tc != DoFindFocus() )
+#ifdef __WXMAC__
+ m_resetFocus = true;
+#else
+ tc->SetFocus();
+#endif
}
Refresh();
}
+void wxComboCtrlBase::OnIdleEvent( wxIdleEvent& WXUNUSED(event) )
+{
+ if ( m_resetFocus )
+ {
+ m_resetFocus = false;
+ wxWindow* tc = GetTextCtrl();
+ if ( tc )
+ tc->SetFocus();
+ }
+}
+
void wxComboCtrlBase::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
{
OnThemeChange();
popup = m_popup;
}
+ winPopup->Enable();
+
wxASSERT( !m_popup || m_popup == popup ); // Consistency check.
wxSize adjustedSize = m_popupInterface->GetAdjustedSize(widthPopup,
int rightX = scrPos.x + ctrlSz.x + m_extRight - szp.x;
int leftX = scrPos.x - m_extLeft;
+
+ if ( wxTheApp->GetLayoutDirection() == wxLayout_RightToLeft )
+ leftX -= ctrlSz.x;
+
int screenWidth = wxSystemSettings::GetMetric( wxSYS_SCREEN_X );
// If there is not enough horizontal space, anchor on the other side.
wxRect popupWinRect( popupX, popupY, szp.x, szp.y );
m_popup = popup;
- if ( AnimateShow( popupWinRect, showFlags ) )
+ if ( (m_iFlags & wxCC_IFLAG_DISABLE_POPUP_ANIM) ||
+ AnimateShow( popupWinRect, showFlags ) )
{
DoShowPopup( popupWinRect, showFlags );
}
if ( IsPopupWindowState(Hidden) )
return;
- // NB: Focus setting is really funny, atleast on wxMSW. First of all,
- // we need to have SetFocus at the end. Otherwise wxTextCtrl may
- // freeze until focus goes somewhere else. Second, wxTreeCtrl as
- // popup, when dismissing, "steals" focus back to itself unless
- // SetFocus is called also here, exactly before m_popupWinState
- // is set to false. Which is truly weird since SetFocus is just
- // wxWindowMSW method and does not call event handler or anything like
- // that (ie. does not care about m_popupWinState).
-
- SetFocus();
-
- // This should preferably be set before focus.
+ // This must be set before focus - otherwise there will be recursive
+ // OnPopupDismisses.
m_popupWinState = Hidden;
+ //SetFocus();
+ m_winPopup->Disable();
+
// Inform popup control itself
m_popupInterface->OnDismiss();