X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/640a91ab0b3b8ca8d3334516c19cfdbf5dc467b0..a7d354c6d75a32033f62b8ecadd837519b35b3ef:/src/common/combocmn.cpp?ds=sidebyside diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index c39695b34b..898cbfd08c 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -32,8 +32,8 @@ #include "wx/log.h" #include "wx/dcclient.h" #include "wx/settings.h" - #include "wx/dialog.h" #include "wx/timer.h" + #include "wx/textctrl.h" #endif #include "wx/tooltip.h" @@ -58,6 +58,11 @@ #if defined(__WXMSW__) +// Let's use wxFrame as a fall-back solution until wxMSW gets wxNonOwnedWindow +#include "wx/frame.h" +#define wxCC_GENERIC_TLW_IS_FRAME +#define wxComboCtrlGenericTLW wxFrame + #define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform) #define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common // native controls work on it like normal. @@ -76,8 +81,18 @@ // reflected (or something like that - atleast commenting out ->Hide() // seemed to eliminate the position change). +#include "wx/dialog.h" +#define wxCC_GENERIC_TLW_IS_DIALOG +#define wxComboCtrlGenericTLW wxDialog + +#include "wx/gtk/private.h" + +// NB: Let's not be afraid to use wxGTK's wxPopupTransientWindow as a +// 'perfect' popup, as it can succesfully host child controls even in +// popups that are shown in modal dialogs. + #define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform) -#define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common +#define TRANSIENT_POPUPWIN_IS_PERFECT 1 // wxPopupTransientWindow works, its child can have focus, and common // 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 @@ -85,10 +100,14 @@ #elif defined(__WXMAC__) -#define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform) -#define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common +#include "wx/nonownedwnd.h" +#define wxCC_GENERIC_TLW_IS_NONOWNEDWINDOW +#define wxComboCtrlGenericTLW wxNonOwnedWindow + +#define USE_TRANSIENT_POPUP 1 // Use wxPopupWindowTransient (preferred, if it works properly on platform) +#define TRANSIENT_POPUPWIN_IS_PERFECT 1 // wxPopupTransientWindow works, its child can have focus, and common // native controls work on it like normal. -#define POPUPWIN_IS_PERFECT 0 // Same, but for non-transient popup window. +#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 3 // Reserve room for the textctrl's focus ring to display @@ -99,6 +118,10 @@ #else +#include "wx/dialog.h" +#define wxCC_GENERIC_TLW_IS_DIALOG +#define wxComboCtrlGenericTLW wxDialog + #define USE_TRANSIENT_POPUP 0 // Use wxPopupWindowTransient (preferred, if it works properly on platform) #define TRANSIENT_POPUPWIN_IS_PERFECT 0 // wxPopupTransientWindow works, its child can have focus, and common // native controls work on it like normal. @@ -112,7 +135,7 @@ // Popupwin is really only supported on wxMSW (not WINCE) and wxGTK, regardless // what the wxUSE_POPUPWIN says. // FIXME: Why isn't wxUSE_POPUPWIN reliable any longer? (it was in wxW2.6.2) -#if (!defined(__WXMSW__) && !defined(__WXGTK__)) || defined(__WXWINCE__) +#if (!defined(__WXMSW__) && !defined(__WXGTK__) && !defined(__WXMAC__)) || defined(__WXWINCE__) #undef wxUSE_POPUPWIN #define wxUSE_POPUPWIN 0 #endif @@ -132,7 +155,7 @@ enum POPUPWIN_NONE = 0, POPUPWIN_WXPOPUPTRANSIENTWINDOW = 1, POPUPWIN_WXPOPUPWINDOW = 2, - POPUPWIN_WXDIALOG = 3 + POPUPWIN_GENERICTLW = 3 }; @@ -150,9 +173,9 @@ enum #define SECONDARY_POPUP_TYPE POPUPWIN_WXPOPUPWINDOW #define USES_WXPOPUPWINDOW 1 #else - #define wxComboPopupWindowBase2 wxDialog - #define SECONDARY_POPUP_TYPE POPUPWIN_WXDIALOG - #define USES_WXDIALOG 1 + #define wxComboPopupWindowBase2 wxComboCtrlGenericTLW + #define SECONDARY_POPUP_TYPE POPUPWIN_GENERICTLW + #define USES_GENERICTLW 1 #endif #elif wxUSE_POPUPWIN @@ -163,17 +186,17 @@ enum #define USES_WXPOPUPWINDOW 1 #if !POPUPWIN_IS_PERFECT - #define wxComboPopupWindowBase2 wxDialog - #define SECONDARY_POPUP_TYPE POPUPWIN_WXDIALOG - #define USES_WXDIALOG 1 + #define wxComboPopupWindowBase2 wxComboCtrlGenericTLW + #define SECONDARY_POPUP_TYPE POPUPWIN_GENERICTLW + #define USES_GENERICTLW 1 #endif #else // wxPopupWindow is not implemented - #define wxComboPopupWindowBase wxDialog - #define PRIMARY_POPUP_TYPE POPUPWIN_WXDIALOG - #define USES_WXDIALOG 1 + #define wxComboPopupWindowBase wxComboCtrlGenericTLW + #define PRIMARY_POPUP_TYPE POPUPWIN_GENERICTLW + #define USES_GENERICTLW 1 #endif @@ -186,8 +209,8 @@ enum #define USES_WXPOPUPWINDOW 0 #endif -#ifndef USES_WXDIALOG - #define USES_WXDIALOG 0 +#ifndef USES_GENERICTLW + #define USES_GENERICTLW 0 #endif @@ -284,7 +307,7 @@ void wxComboFrameEventHandler::OnIdle( wxIdleEvent& event ) winFocused != m_combo->GetButton() // GTK (atleast) requires this ) { - m_combo->HidePopup(); + m_combo->HidePopup(true); } event.Skip(); @@ -292,37 +315,37 @@ void wxComboFrameEventHandler::OnIdle( wxIdleEvent& event ) void wxComboFrameEventHandler::OnMenuEvent( wxMenuEvent& event ) { - m_combo->HidePopup(); + m_combo->HidePopup(true); event.Skip(); } void wxComboFrameEventHandler::OnMouseEvent( wxMouseEvent& event ) { - m_combo->HidePopup(); + m_combo->HidePopup(true); event.Skip(); } void wxComboFrameEventHandler::OnClose( wxCloseEvent& event ) { - m_combo->HidePopup(); + m_combo->HidePopup(true); event.Skip(); } void wxComboFrameEventHandler::OnActivate( wxActivateEvent& event ) { - m_combo->HidePopup(); + m_combo->HidePopup(true); event.Skip(); } void wxComboFrameEventHandler::OnResize( wxSizeEvent& event ) { - m_combo->HidePopup(); + m_combo->HidePopup(true); event.Skip(); } void wxComboFrameEventHandler::OnMove( wxMoveEvent& event ) { - m_combo->HidePopup(); + m_combo->HidePopup(true); event.Skip(); } @@ -406,7 +429,7 @@ void wxComboPopupWindow::OnDismiss() wxASSERT_MSG( combo->IsKindOf(CLASSINFO(wxComboCtrlBase)), wxT("parent might not be wxComboCtrl, but check IMPLEMENT_DYNAMIC_CLASS(2) macro for correctness") ); - combo->OnPopupDismiss(); + combo->OnPopupDismiss(true); } #endif // USES_WXPOPUPTRANSIENTWINDOW @@ -428,7 +451,7 @@ public: void OnSizeEvent( wxSizeEvent& event ); void OnKeyEvent(wxKeyEvent& event); -#if USES_WXDIALOG +#if USES_GENERICTLW void OnActivate( wxActivateEvent& event ); #endif @@ -442,7 +465,7 @@ private: BEGIN_EVENT_TABLE(wxComboPopupWindowEvtHandler, wxEvtHandler) EVT_KEY_DOWN(wxComboPopupWindowEvtHandler::OnKeyEvent) EVT_KEY_UP(wxComboPopupWindowEvtHandler::OnKeyEvent) -#if USES_WXDIALOG +#if USES_GENERICTLW EVT_ACTIVATE(wxComboPopupWindowEvtHandler::OnActivate) #endif EVT_SIZE(wxComboPopupWindowEvtHandler::OnSizeEvent) @@ -460,16 +483,16 @@ void wxComboPopupWindowEvtHandler::OnKeyEvent( wxKeyEvent& event ) wxWindowList children = m_combo->GetPopupWindow()->GetChildren(); wxWindowList::iterator node = children.begin(); wxWindow* child = (wxWindow*)*node; - child->AddPendingEvent(event); + child->GetEventHandler()->AddPendingEvent(event); } -#if USES_WXDIALOG +#if USES_GENERICTLW void wxComboPopupWindowEvtHandler::OnActivate( wxActivateEvent& event ) { if ( !event.GetActive() ) { // Tell combo control that we are dismissed. - m_combo->HidePopup(); + m_combo->HidePopup(true); event.Skip(); } @@ -494,6 +517,11 @@ void wxComboPopup::OnDismiss() { } +wxComboCtrl* wxComboPopup::GetComboCtrl() const +{ + return wxStaticCast(m_combo, wxComboCtrl); +} + wxSize wxComboPopup::GetAdjustedSize( int minWidth, int prefHeight, int WXUNUSED(maxHeight) ) @@ -509,7 +537,7 @@ void wxComboPopup::DefaultPaintComboControl( wxComboCtrlBase* combo, combo->PrepareBackground(dc,rect,0); dc.DrawText( combo->GetValue(), - rect.x + combo->GetTextIndent(), + rect.x + combo->m_marginLeft, (rect.height-dc.GetCharHeight())/2 + rect.y ); } } @@ -539,7 +567,7 @@ bool wxComboPopup::LazyCreate() void wxComboPopup::Dismiss() { - m_combo->HidePopup(); + m_combo->HidePopup(true); } // ---------------------------------------------------------------------------- @@ -572,6 +600,8 @@ private: BEGIN_EVENT_TABLE(wxComboBoxExtraInputHandler, wxEvtHandler) EVT_KEY_DOWN(wxComboBoxExtraInputHandler::OnKey) + EVT_KEY_UP(wxComboBoxExtraInputHandler::OnKey) + EVT_CHAR(wxComboBoxExtraInputHandler::OnKey) EVT_SET_FOCUS(wxComboBoxExtraInputHandler::OnFocus) EVT_KILL_FOCUS(wxComboBoxExtraInputHandler::OnFocus) END_EVENT_TABLE() @@ -581,14 +611,17 @@ void wxComboBoxExtraInputHandler::OnKey(wxKeyEvent& event) { // Let the wxComboCtrl event handler have a go first. wxComboCtrlBase* combo = m_combo; - wxObject* prevObj = event.GetEventObject(); - event.SetId(combo->GetId()); - event.SetEventObject(combo); - combo->GetEventHandler()->ProcessEvent(event); + wxKeyEvent redirectedEvent(event); + redirectedEvent.SetId(combo->GetId()); + redirectedEvent.SetEventObject(combo); - event.SetId(((wxWindow*)prevObj)->GetId()); - event.SetEventObject(prevObj); + if ( !combo->GetEventHandler()->ProcessEvent(redirectedEvent) ) + { + // Don't let TAB through to the text ctrl - looks ugly + if ( event.GetKeyCode() != WXK_TAB ) + event.Skip(); + } } void wxComboBoxExtraInputHandler::OnFocus(wxFocusEvent& event) @@ -756,18 +789,18 @@ IMPLEMENT_ABSTRACT_CLASS(wxComboCtrlBase, wxControl) void wxComboCtrlBase::Init() { - m_winPopup = (wxWindow *)NULL; - m_popup = (wxWindow *)NULL; + m_winPopup = NULL; + m_popup = NULL; m_popupWinState = Hidden; - m_btn = (wxWindow*) NULL; - m_text = (wxTextCtrl*) NULL; - m_popupInterface = (wxComboPopup*) NULL; + m_btn = NULL; + m_text = NULL; + m_popupInterface = NULL; - m_popupExtraHandler = (wxEvtHandler*) NULL; - m_textEvtHandler = (wxEvtHandler*) NULL; + m_popupExtraHandler = NULL; + m_textEvtHandler = NULL; #if INSTALL_TOPLEV_HANDLER - m_toplevEvtHandler = (wxEvtHandler*) NULL; + m_toplevEvtHandler = NULL; #endif m_mainCtrlWnd = this; @@ -789,7 +822,7 @@ void wxComboCtrlBase::Init() m_extLeft = 0; m_extRight = 0; - m_absIndent = -1; + m_marginLeft = -1; m_iFlags = 0; m_timeCanAcceptClick = 0; @@ -818,7 +851,7 @@ bool wxComboCtrlBase::Create(wxWindow *parent, // Get colours OnThemeChange(); - m_absIndent = GetNativeTextIndent(); + m_marginLeft = GetNativeTextIndent(); m_iFlags |= wxCC_IFLAG_CREATED; @@ -871,6 +904,7 @@ wxComboCtrlBase::CreateTextCtrl(int style, const wxValidator& validator) m_text->Create(this, wxID_ANY, m_valueString, wxDefaultPosition, wxSize(10,-1), style, validator); + m_text->SetHint(m_hintText); } } @@ -880,8 +914,27 @@ void wxComboCtrlBase::OnThemeChange() // 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 + #if defined(__WXMSW__) || defined(__WXGTK__) + wxVisualAttributes vattrs = wxComboBox::GetClassDefaultAttributes(); + #else + wxVisualAttributes vattrs; + vattrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + vattrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); + #endif + + // Only change the colours if application has not specified + // custom ones. + if ( !m_hasFgCol ) + { + SetOwnForegroundColour(vattrs.colFg); + m_hasFgCol = false; + } + if ( !m_hasBgCol ) + { + SetOwnBackgroundColour(vattrs.colBg); + m_hasBgCol = false; + } +#endif // !__WXMAC__ } wxComboCtrlBase::~wxComboCtrlBase() @@ -891,7 +944,7 @@ wxComboCtrlBase::~wxComboCtrlBase() #if INSTALL_TOPLEV_HANDLER delete ((wxComboFrameEventHandler*)m_toplevEvtHandler); - m_toplevEvtHandler = (wxEvtHandler*) NULL; + m_toplevEvtHandler = NULL; #endif DestroyPopup(); @@ -938,8 +991,8 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth ) } // Defaul indentation - if ( m_absIndent < 0 ) - m_absIndent = GetNativeTextIndent(); + if ( m_marginLeft < 0 ) + m_marginLeft = GetNativeTextIndent(); int butWidth = btnWidth; @@ -1043,43 +1096,60 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust if ( !m_text ) return; -#if !TEXTCTRL_TEXT_CENTERED - wxSize sz = GetClientSize(); int customBorder = m_widthCustomBorder; if ( (m_text->GetWindowStyleFlag() & wxBORDER_MASK) == wxNO_BORDER ) { - // Centre textctrl + int x; + + if ( !m_widthCustomPaint ) + { + // No special custom paint area - we can use 0 left margin + // with wxTextCtrl. + if ( m_text->SetMargins(0) ) + textCtrlXAdjust = 0; + x = m_tcArea.x + m_marginLeft + textCtrlXAdjust; + } + else + { + // There is special custom paint area - it is better to + // use some margin with the wxTextCtrl. + m_text->SetMargins(m_marginLeft); + x = m_tcArea.x + m_widthCustomPaint + + m_marginLeft + textCtrlXAdjust; + } + + // Centre textctrl vertically, if needed +#if !TEXTCTRL_TEXT_CENTERED int tcSizeY = m_text->GetBestSize().y; - int diff = sz.y - tcSizeY; - int y = textCtrlYAdjust + (diff/2); + int diff0 = sz.y - tcSizeY; + int y = textCtrlYAdjust + (diff0/2); +#else + wxUnusedVar(textCtrlYAdjust); + int y = 0; +#endif if ( y < customBorder ) y = customBorder; - m_text->SetSize( m_tcArea.x + m_widthCustomPaint + m_absIndent + textCtrlXAdjust, - y, - m_tcArea.width - COMBO_MARGIN - - (textCtrlXAdjust + m_widthCustomPaint + m_absIndent), - -1 ); + m_text->SetSize(x, + y, + m_tcArea.width - m_tcArea.x - x, + -1 ); // Make sure textctrl doesn't exceed the bottom custom border wxSize tsz = m_text->GetSize(); - diff = (y + tsz.y) - (sz.y - customBorder); - if ( diff >= 0 ) + int diff1 = (y + tsz.y) - (sz.y - customBorder); + if ( diff1 >= 0 ) { - tsz.y = tsz.y - diff - 1; + tsz.y = tsz.y - diff1 - 1; m_text->SetSize(tsz); } } else -#else // TEXTCTRL_TEXT_CENTERED - wxUnusedVar(textCtrlXAdjust); - wxUnusedVar(textCtrlYAdjust); -#endif // !TEXTCTRL_TEXT_CENTERED/TEXTCTRL_TEXT_CENTERED { - // If it has border, have textctrl will the entire text field. + // If it has border, have textctrl fill the entire text field. m_text->SetSize( m_tcArea.x + m_widthCustomPaint, m_tcArea.y, m_tcArea.width - m_widthCustomPaint, @@ -1177,6 +1247,8 @@ bool wxComboCtrlBase::Enable(bool enable) if ( m_text ) m_text->Enable(enable); + Refresh(); + return true; } @@ -1199,8 +1271,15 @@ bool wxComboCtrlBase::SetFont ( const wxFont& font ) if ( !wxControl::SetFont(font) ) return false; - if (m_text) + if ( m_text ) + { + // Without hiding the wxTextCtrl there would be some + // visible 'flicker' (at least on Windows XP). + m_text->Hide(); m_text->SetFont(font); + OnResize(); + m_text->Show(); + } return true; } @@ -1219,8 +1298,8 @@ void wxComboCtrlBase::DoSetToolTip(wxToolTip *tooltip) } else { - if ( m_text ) m_text->SetToolTip( (wxToolTip*) NULL ); - if ( m_btn ) m_btn->SetToolTip( (wxToolTip*) NULL ); + if ( m_text ) m_text->SetToolTip( NULL ); + if ( m_btn ) m_btn->SetToolTip( NULL ); } } #endif // wxUSE_TOOLTIPS @@ -1232,19 +1311,39 @@ void wxComboCtrlBase::SetValidator(const wxValidator& validator) if ( textCtrl ) textCtrl->SetValidator( validator ); + else + wxControl::SetValidator( validator ); } wxValidator* wxComboCtrlBase::GetValidator() { wxTextCtrl* textCtrl = GetTextCtrl(); - if ( textCtrl ) - return textCtrl->GetValidator(); - - return wxControl::GetValidator(); + return textCtrl ? textCtrl->GetValidator() : wxControl::GetValidator(); } #endif // wxUSE_VALIDATORS +bool wxComboCtrlBase::SetForegroundColour(const wxColour& colour) +{ + if ( wxControl::SetForegroundColour(colour) ) + { + if ( m_text ) + m_text->SetForegroundColour(colour); + return true; + } + return false; +} + +bool wxComboCtrlBase::SetBackgroundColour(const wxColour& colour) +{ + if ( wxControl::SetBackgroundColour(colour) ) + { + if ( m_text ) + m_text->SetBackgroundColour(colour); + return true; + } + return false; +} // ---------------------------------------------------------------------------- // painting // ---------------------------------------------------------------------------- @@ -1295,20 +1394,46 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags selRect.width -= wcp + (focusSpacingX*2); wxColour bgCol; + wxColour fgCol; + bool doDrawSelRect = true; + // Determine foreground colour + if ( isEnabled ) + { + if ( doDrawFocusRect ) + { + fgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT); + } + else if ( m_hasFgCol ) + { + // Honour the custom foreground colour + fgCol = GetForegroundColour(); + } + else + { + fgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); + } + } + else + { + fgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT); + } + + // Determine background colour if ( isEnabled ) { - // If popup is hidden and this control is focused, - // then draw the focus-indicator (selbgcolor background etc.). if ( doDrawFocusRect ) { - dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT) ); bgCol = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT); } + else if ( m_hasBgCol ) + { + // Honour the custom background colour + bgCol = GetBackgroundColour(); + } else { - dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT) ); #ifndef __WXMAC__ // see note in OnThemeChange doDrawSelRect = false; bgCol = GetBackgroundColour(); @@ -1319,7 +1444,6 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags } else { - dc.SetTextForeground( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT) ); #ifndef __WXMAC__ // see note in OnThemeChange bgCol = GetBackgroundColour(); #else @@ -1327,6 +1451,7 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags #endif } + dc.SetTextForeground( fgCol ); dc.SetBrush( bgCol ); if ( doDrawSelRect ) { @@ -1576,13 +1701,13 @@ bool wxComboCtrlBase::PreprocessMouseEvent( wxMouseEvent& event, wxLongLong t = ::wxGetLocalTimeMillis(); int evtType = event.GetEventType(); -#if USES_WXPOPUPWINDOW || USES_WXDIALOG +#if USES_WXPOPUPWINDOW || USES_GENERICTLW if ( m_popupWinType != POPUPWIN_WXPOPUPTRANSIENTWINDOW ) { if ( IsPopupWindowState(Visible) && ( evtType == wxEVT_LEFT_DOWN || evtType == wxEVT_RIGHT_DOWN ) ) { - HidePopup(); + HidePopup(true); return true; } } @@ -1610,7 +1735,7 @@ void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event ) #if USES_WXPOPUPWINDOW // Click here always hides the popup. if ( m_popupWinType == POPUPWIN_WXPOPUPWINDOW ) - HidePopup(); + HidePopup(true); #endif } else @@ -1635,7 +1760,7 @@ void wxComboCtrlBase::HandleNormalMouseEvent( wxMouseEvent& event ) { // relay (some) mouse events to the popup if ( evtType == wxEVT_MOUSEWHEEL ) - m_popup->AddPendingEvent(event); + m_popup->GetEventHandler()->AddPendingEvent(event); } else if ( evtType ) event.Skip(); @@ -1646,25 +1771,16 @@ void wxComboCtrlBase::OnKeyEvent(wxKeyEvent& event) if ( IsPopupShown() ) { // pass it to the popped up control - GetPopupControl()->GetControl()->AddPendingEvent(event); + GetPopupControl()->GetControl()->GetEventHandler()->AddPendingEvent(event); } else // no popup { - int keycode = event.GetKeyCode(); + wxWindow* mainCtrl = GetMainWindowOfCompositeControl(); - if ( keycode == WXK_TAB ) + if ( mainCtrl->GetParent()->HasFlag(wxTAB_TRAVERSAL) ) { - wxNavigationKeyEvent evt; - - wxWindow* mainCtrl = GetMainWindowOfCompositeControl(); - - evt.SetFlags(wxNavigationKeyEvent::FromTab| - (!event.ShiftDown() ? wxNavigationKeyEvent::IsForward - : wxNavigationKeyEvent::IsBackward)); - evt.SetEventObject(mainCtrl); - evt.SetCurrentFocus(mainCtrl); - mainCtrl->GetParent()->GetEventHandler()->AddPendingEvent(evt); - return; + if ( mainCtrl->HandleAsNavigationKey(event) ) + return; } if ( IsKeyPopupToggle(event) ) @@ -1682,6 +1798,8 @@ void wxComboCtrlBase::OnKeyEvent(wxKeyEvent& event) return; } + int keycode = event.GetKeyCode(); + if ( (comboStyle & wxCB_READONLY) || (keycode != WXK_RIGHT && keycode != WXK_LEFT) ) { @@ -1698,13 +1816,9 @@ void wxComboCtrlBase::OnFocusEvent( wxFocusEvent& event ) { wxWindow* tc = GetTextCtrl(); if ( tc && tc != DoFindFocus() ) -#ifdef __WXMAC__ - m_resetFocus = true; -#else { tc->SetFocus(); } -#endif } Refresh(); @@ -1724,9 +1838,9 @@ void wxComboCtrlBase::OnIdleEvent( wxIdleEvent& WXUNUSED(event) ) void wxComboCtrlBase::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event)) { OnThemeChange(); - // indentation may also have changed - if ( !(m_iFlags & wxCC_IFLAG_INDENT_SET) ) - m_absIndent = GetNativeTextIndent(); + // left margin may also have changed + if ( !(m_iFlags & wxCC_IFLAG_LEFT_MARGIN_SET) ) + m_marginLeft = GetNativeTextIndent(); RecalcAndRefresh(); } @@ -1745,12 +1859,23 @@ void wxComboCtrlBase::CreatePopup() #ifdef wxComboPopupWindowBase2 if ( m_iFlags & wxCC_IFLAG_USE_ALT_POPUP ) { - #if !USES_WXDIALOG + #if !USES_GENERICTLW m_winPopup = new wxComboPopupWindowBase2( this, wxNO_BORDER ); #else + int tlwFlags = wxNO_BORDER; + #ifdef wxCC_GENERIC_TLW_IS_FRAME + tlwFlags |= wxFRAME_NO_TASKBAR; + #endif + + #ifdef wxCC_GENERIC_TLW_IS_NONOWNEDWINDOW + m_winPopup = new wxComboPopupWindowBase2( this, wxID_ANY, + wxPoint(-21,-21), wxSize(20, 20), + tlwFlags ); + #else m_winPopup = new wxComboPopupWindowBase2( this, wxID_ANY, wxEmptyString, wxPoint(-21,-21), wxSize(20, 20), - wxNO_BORDER ); + tlwFlags ); + #endif #endif m_popupWinType = SECONDARY_POPUP_TYPE; } @@ -1781,7 +1906,7 @@ void wxComboCtrlBase::CreatePopup() // Destroy popup window and the child control void wxComboCtrlBase::DestroyPopup() { - HidePopup(); + HidePopup(true); if ( m_popup ) m_popup->RemoveEventHandler(m_popupExtraHandler); @@ -1798,10 +1923,10 @@ void wxComboCtrlBase::DestroyPopup() m_winPopup->Destroy(); } - m_popupExtraHandler = (wxEvtHandler*) NULL; - m_popupInterface = (wxComboPopup*) NULL; - m_winPopup = (wxWindow*) NULL; - m_popup = (wxWindow*) NULL; + m_popupExtraHandler = NULL; + m_popupInterface = NULL; + m_winPopup = NULL; + m_popup = NULL; } void wxComboCtrlBase::DoSetPopupControl(wxComboPopup* iface) @@ -1821,7 +1946,7 @@ void wxComboCtrlBase::DoSetPopupControl(wxComboPopup* iface) } else { - m_popup = (wxWindow*) NULL; + m_popup = NULL; } // This must be done after creation @@ -1843,7 +1968,18 @@ void wxComboCtrlBase::OnButtonClick() { // Derived classes can override this method for totally custom // popup action - ShowPopup(); + if ( !IsPopupWindowState(Visible) ) + { + wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_DROPDOWN, GetId()); + event.SetEventObject(this); + HandleWindowEvent(event); + + ShowPopup(); + } + else + { + HidePopup(true); + } } void wxComboCtrlBase::ShowPopup() @@ -1890,7 +2026,8 @@ void wxComboCtrlBase::ShowPopup() // that if transient popup is open, then tab traversal is to be ignored. // However, I think this code would still be needed for cases where // transient popup doesn't work yet (wxWinCE?). - wxWindow* parent = GetParent(); + wxWindow* mainCtrl = GetMainWindowOfCompositeControl(); + wxWindow* parent = mainCtrl->GetParent(); int parentFlags = parent->GetWindowStyle(); if ( parentFlags & wxTAB_TRAVERSAL ) { @@ -2062,7 +2199,7 @@ void wxComboCtrlBase::DoShowPopup( const wxRect& rect, int WXUNUSED(flags) ) Refresh(); } -void wxComboCtrlBase::OnPopupDismiss() +void wxComboCtrlBase::OnPopupDismiss(bool generateEvent) { // Just in case, avoid double dismiss if ( IsPopupWindowState(Hidden) ) @@ -2114,9 +2251,16 @@ void wxComboCtrlBase::OnPopupDismiss() Refresh(); SetFocus(); + + if ( generateEvent ) + { + wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_CLOSEUP, GetId()); + event.SetEventObject(this); + HandleWindowEvent(event); + } } -void wxComboCtrlBase::HidePopup() +void wxComboCtrlBase::HidePopup(bool generateEvent) { // Should be able to call this without popup interface if ( IsPopupWindowState(Hidden) ) @@ -2128,7 +2272,7 @@ void wxComboCtrlBase::HidePopup() m_winPopup->Hide(); - OnPopupDismiss(); + OnPopupDismiss(generateEvent); } // ---------------------------------------------------------------------------- @@ -2209,22 +2353,61 @@ void wxComboCtrlBase::SetCustomPaintWidth( int width ) RecalcAndRefresh(); } +bool wxComboCtrlBase::DoSetMargins(const wxPoint& margins) +{ + // For general sanity's sake, we ignore top margin. Instead + // we will always try to center the text vertically. + bool res = true; + + if ( margins.x != -1 ) + { + m_marginLeft = margins.x; + m_iFlags |= wxCC_IFLAG_LEFT_MARGIN_SET; + } + else + { + m_marginLeft = GetNativeTextIndent(); + m_iFlags &= ~(wxCC_IFLAG_LEFT_MARGIN_SET); + } + + if ( margins.y != -1 ) + { + res = false; + } + + RecalcAndRefresh(); + + return res; +} + +wxPoint wxComboCtrlBase::DoGetMargins() const +{ + return wxPoint(m_marginLeft, -1); +} + +#if WXWIN_COMPATIBILITY_2_8 void wxComboCtrlBase::SetTextIndent( int indent ) { if ( indent < 0 ) { - m_absIndent = GetNativeTextIndent(); - m_iFlags &= ~(wxCC_IFLAG_INDENT_SET); + m_marginLeft = GetNativeTextIndent(); + m_iFlags &= ~(wxCC_IFLAG_LEFT_MARGIN_SET); } else { - m_absIndent = indent; - m_iFlags |= wxCC_IFLAG_INDENT_SET; + m_marginLeft = indent; + m_iFlags |= wxCC_IFLAG_LEFT_MARGIN_SET; } RecalcAndRefresh(); } +wxCoord wxComboCtrlBase::GetTextIndent() const +{ + return m_marginLeft; +} +#endif + wxCoord wxComboCtrlBase::GetNativeTextIndent() const { return DEFAULT_TEXT_INDENT; @@ -2362,4 +2545,19 @@ void wxComboCtrlBase::Undo() m_text->Undo(); } +bool wxComboCtrlBase::SetHint(const wxString& hint) +{ + m_hintText = hint; + bool res = true; + if ( m_text ) + res = m_text->SetHint(hint); + Refresh(); + return res; +} + +wxString wxComboCtrlBase::GetHint() const +{ + return m_hintText; +} + #endif // wxUSE_COMBOCTRL