X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/126bb30567f54abac739bdd339affe1d50113381..8bd410eb8082d9e009ece7cc279faa5f73ea1f5e:/src/common/combocmn.cpp diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index 65066b56c7..898cbfd08c 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -32,7 +32,6 @@ #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 @@ -59,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. @@ -71,14 +75,18 @@ #elif defined(__WXGTK__) -#include "wx/gtk/private.h" - // NB: It is not recommended to use wxDialog as popup on wxGTK, because of // this bug: If wxDialog is hidden, its position becomes corrupt // between hide and next show, but without internal coordinates being // 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. @@ -92,6 +100,10 @@ #elif defined(__WXMAC__) +#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. @@ -106,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. @@ -139,7 +155,7 @@ enum POPUPWIN_NONE = 0, POPUPWIN_WXPOPUPTRANSIENTWINDOW = 1, POPUPWIN_WXPOPUPWINDOW = 2, - POPUPWIN_WXDIALOG = 3 + POPUPWIN_GENERICTLW = 3 }; @@ -157,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 @@ -170,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 @@ -193,8 +209,8 @@ enum #define USES_WXPOPUPWINDOW 0 #endif -#ifndef USES_WXDIALOG - #define USES_WXDIALOG 0 +#ifndef USES_GENERICTLW + #define USES_GENERICTLW 0 #endif @@ -291,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(); @@ -299,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(); } @@ -413,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 @@ -435,7 +451,7 @@ public: void OnSizeEvent( wxSizeEvent& event ); void OnKeyEvent(wxKeyEvent& event); -#if USES_WXDIALOG +#if USES_GENERICTLW void OnActivate( wxActivateEvent& event ); #endif @@ -449,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) @@ -470,13 +486,13 @@ void wxComboPopupWindowEvtHandler::OnKeyEvent( wxKeyEvent& 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(); } @@ -551,7 +567,7 @@ bool wxComboPopup::LazyCreate() void wxComboPopup::Dismiss() { - m_combo->HidePopup(); + m_combo->HidePopup(true); } // ---------------------------------------------------------------------------- @@ -888,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); } } @@ -897,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() @@ -1287,6 +1323,27 @@ wxValidator* wxComboCtrlBase::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 // ---------------------------------------------------------------------------- @@ -1337,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(); @@ -1361,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 @@ -1369,6 +1451,7 @@ void wxComboCtrlBase::PrepareBackground( wxDC& dc, const wxRect& rect, int flags #endif } + dc.SetTextForeground( fgCol ); dc.SetBrush( bgCol ); if ( doDrawSelRect ) { @@ -1618,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; } } @@ -1652,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 @@ -1692,9 +1775,13 @@ void wxComboCtrlBase::OnKeyEvent(wxKeyEvent& event) } else // no popup { - if ( GetParent()->HasFlag(wxTAB_TRAVERSAL) && - HandleAsNavigationKey(event) ) - return; + wxWindow* mainCtrl = GetMainWindowOfCompositeControl(); + + if ( mainCtrl->GetParent()->HasFlag(wxTAB_TRAVERSAL) ) + { + if ( mainCtrl->HandleAsNavigationKey(event) ) + return; + } if ( IsKeyPopupToggle(event) ) { @@ -1772,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; } @@ -1808,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); @@ -1871,9 +1969,17 @@ void wxComboCtrlBase::OnButtonClick() // Derived classes can override this method for totally custom // popup action if ( !IsPopupWindowState(Visible) ) + { + wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_DROPDOWN, GetId()); + event.SetEventObject(this); + HandleWindowEvent(event); + ShowPopup(); + } else - HidePopup(); + { + HidePopup(true); + } } void wxComboCtrlBase::ShowPopup() @@ -1920,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 ) { @@ -2092,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) ) @@ -2144,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) ) @@ -2158,7 +2272,7 @@ void wxComboCtrlBase::HidePopup() m_winPopup->Hide(); - OnPopupDismiss(); + OnPopupDismiss(generateEvent); } // ---------------------------------------------------------------------------- @@ -2271,7 +2385,7 @@ wxPoint wxComboCtrlBase::DoGetMargins() const return wxPoint(m_marginLeft, -1); } -#if WXWIN_COMPATIBILITY_2_6 +#if WXWIN_COMPATIBILITY_2_8 void wxComboCtrlBase::SetTextIndent( int indent ) { if ( indent < 0 ) @@ -2431,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