X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6d0ce565ff6a0db2e7c6e3240ef4cf6fe7950a35..4e15d1caa03346c126015019c1fdf093033ef40b:/src/generic/combog.cpp diff --git a/src/generic/combog.cpp b/src/generic/combog.cpp index edf2bba3d6..615106085c 100644 --- a/src/generic/combog.cpp +++ b/src/generic/combog.cpp @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: combog.cpp -// Purpose: Generic wxComboControl +// Name: src/generic/combog.cpp +// Purpose: Generic wxComboCtrl // Author: Jaakko Salli // Modified by: // Created: Apr-30-2006 @@ -23,55 +23,65 @@ #pragma hdrstop #endif -#if wxUSE_COMBOCONTROL +#if wxUSE_COMBOCTRL + +#include "wx/combo.h" #ifndef WX_PRECOMP #include "wx/log.h" #include "wx/combobox.h" #include "wx/dcclient.h" #include "wx/settings.h" + #include "wx/textctrl.h" #endif #include "wx/dcbuffer.h" -#include "wx/combo.h" - - // ---------------------------------------------------------------------------- // Some constant adjustments to make the generic more bearable #if defined(__WXUNIVERSAL__) -#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent -#define TEXTCTRLYADJUST 0 +// position adjustment for wxTextCtrl, to achieve zero left margin +// meaningless if LEFT_MARGIN_CAN_BE_SET set to 1 in combocmn.cpp +#define TEXTCTRLXADJUST 0 + #define TEXTXADJUST 0 // how much is read-only text's x adjusted #define DEFAULT_DROPBUTTON_WIDTH 19 #elif defined(__WXMSW__) -#define TEXTCTRLXADJUST 2 // position adjustment for wxTextCtrl, with zero indent -#define TEXTCTRLYADJUST 3 +// position adjustment for wxTextCtrl, to achieve zero left margin +// meaningless if LEFT_MARGIN_CAN_BE_SET set to 1 in combocmn.cpp +#define TEXTCTRLXADJUST 2 + #define TEXTXADJUST 0 // how much is read-only text's x adjusted #define DEFAULT_DROPBUTTON_WIDTH 17 #elif defined(__WXGTK__) -#define TEXTCTRLXADJUST -1 // position adjustment for wxTextCtrl, with zero indent -#define TEXTCTRLYADJUST 0 +// position adjustment for wxTextCtrl, to achieve zero left margin +// meaningless if LEFT_MARGIN_CAN_BE_SET set to 1 in combocmn.cpp +#define TEXTCTRLXADJUST -1 + #define TEXTXADJUST 1 // how much is read-only text's x adjusted #define DEFAULT_DROPBUTTON_WIDTH 23 #elif defined(__WXMAC__) -#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent -#define TEXTCTRLYADJUST 0 +// position adjustment for wxTextCtrl, to achieve zero left margin +// meaningless if LEFT_MARGIN_CAN_BE_SET set to 1 in combocmn.cpp +#define TEXTCTRLXADJUST 0 + #define TEXTXADJUST 0 // how much is read-only text's x adjusted -#define DEFAULT_DROPBUTTON_WIDTH 19 +#define DEFAULT_DROPBUTTON_WIDTH 22 #else -#define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent -#define TEXTCTRLYADJUST 0 +// position adjustment for wxTextCtrl, to achieve zero left margin +// meaningless if LEFT_MARGIN_CAN_BE_SET set to 1 in combocmn.cpp +#define TEXTCTRLXADJUST 0 + #define TEXTXADJUST 0 // how much is read-only text's x adjusted #define DEFAULT_DROPBUTTON_WIDTH 19 @@ -87,97 +97,121 @@ // ---------------------------------------------------------------------------- -// wxGenericComboControl +// wxGenericComboCtrl // ---------------------------------------------------------------------------- -BEGIN_EVENT_TABLE(wxGenericComboControl, wxComboControlBase) - EVT_PAINT(wxGenericComboControl::OnPaintEvent) - EVT_MOUSE_EVENTS(wxGenericComboControl::OnMouseEvent) +BEGIN_EVENT_TABLE(wxGenericComboCtrl, wxComboCtrlBase) + EVT_PAINT(wxGenericComboCtrl::OnPaintEvent) + EVT_MOUSE_EVENTS(wxGenericComboCtrl::OnMouseEvent) END_EVENT_TABLE() -IMPLEMENT_DYNAMIC_CLASS(wxGenericComboControl, wxComboControlBase) +IMPLEMENT_DYNAMIC_CLASS(wxGenericComboCtrl, wxComboCtrlBase) -void wxGenericComboControl::Init() +void wxGenericComboCtrl::Init() { } -bool wxGenericComboControl::Create(wxWindow *parent, - wxWindowID id, - const wxString& value, - const wxPoint& pos, - const wxSize& size, - long style, - const wxValidator& validator, - const wxString& name) +bool wxGenericComboCtrl::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + const wxValidator& validator, + const wxString& name) { - - // Set border + // + // Note that technically we only support 'default' border and wxNO_BORDER. long border = style & wxBORDER_MASK; + int tcBorder = wxNO_BORDER; - if ( !border ) - { #if defined(__WXUNIVERSAL__) + if ( !border ) border = wxBORDER_SIMPLE; #elif defined(__WXMSW__) + if ( !border ) // For XP, have 1-width custom border, for older version use sunken - if ( wxUxThemeEngine::GetIfActive() ) + /*if ( wxUxThemeEngine::GetIfActive() ) { border = wxBORDER_NONE; m_widthCustomBorder = 1; } - else + else*/ border = wxBORDER_SUNKEN; -#elif defined(__WXGTK__) - border = wxBORDER_NONE; - //m_widthCustomBorder = 2; - m_widthCustomBorder = 1; #else - border = wxBORDER_SIMPLE; -#endif - style = (style & ~(wxBORDER_MASK)) | border; + // + // Generic version is optimized for wxGTK + // + + #define UNRELIABLE_TEXTCTRL_BORDER + + if ( !border ) + { + if ( style & wxCB_READONLY ) + { + m_widthCustomBorder = 1; + } + else + { + m_widthCustomBorder = 0; + tcBorder = 0; + } + } + else + { + // Have textctrl instead use the border given. + tcBorder = border; } -#if defined(__WXGTK__) + // Because we are going to have button outside the border, + // let's use wxBORDER_NONE for the whole control. + border = wxBORDER_NONE; + Customize( wxCC_BUTTON_OUTSIDE_BORDER | - wxCC_NO_TEXT_AUTO_SELECT ); + wxCC_NO_TEXT_AUTO_SELECT | + wxCC_BUTTON_STAYS_DOWN ); + #endif + style = (style & ~(wxBORDER_MASK)) | border; if ( style & wxCC_STD_BUTTON ) m_iFlags |= wxCC_POPUP_ON_MOUSE_UP; // create main window - if ( !wxComboControlBase::Create(parent, - id, - value, - wxDefaultPosition, - wxDefaultSize, - style | wxFULL_REPAINT_ON_RESIZE, - wxDefaultValidator, - name) ) + if ( !wxComboCtrlBase::Create(parent, + id, + value, + pos, + size, + style | wxFULL_REPAINT_ON_RESIZE, + validator, + name) ) return false; // Create textctrl, if necessary - CreateTextCtrl( wxNO_BORDER, validator ); + CreateTextCtrl( tcBorder ); // Add keyboard input handlers for main control and textctrl - InstallInputHandlers( true ); + InstallInputHandlers(); - // Set background - SetBackgroundStyle( wxBG_STYLE_CUSTOM ); // for double-buffering + // Set background style for double-buffering, when needed + // (cannot use when system draws background automatically) + if ( !HasTransparentBackground() ) + SetBackgroundStyle( wxBG_STYLE_PAINT ); - // SetSize should be called last - SetSize(pos.x,pos.y,size.x,size.y); + // SetInitialSize should be called last + SetInitialSize(size); return true; } -wxGenericComboControl::~wxGenericComboControl() +wxGenericComboCtrl::~wxGenericComboCtrl() { } -void wxGenericComboControl::OnResize() +void wxGenericComboCtrl::OnResize() { // Recalculates button and textctrl areas @@ -196,16 +230,24 @@ void wxGenericComboControl::OnResize() #endif // Move textctrl, if any, accordingly - PositionTextCtrl( TEXTCTRLXADJUST, TEXTCTRLYADJUST ); + PositionTextCtrl( TEXTCTRLXADJUST ); } -void wxGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) +void wxGenericComboCtrl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) { - wxSize sz = GetClientSize(); - wxBufferedPaintDC dc(this,GetBufferBitmap(sz)); + // Determine wxDC to use based on need to double-buffer or + // use system-generated transparent background portions + wxDC* dcPtr; + if ( HasTransparentBackground() ) + dcPtr = new wxPaintDC(this); + else + dcPtr = new wxAutoBufferedPaintDC(this); + wxDC& dc = *dcPtr; - const wxRect& rectb = m_btnArea; - wxRect rect = m_tcArea; + wxSize sz = GetClientSize(); + const wxRect& butRect = m_btnArea; + wxRect tcRect = m_tcArea; + wxRect fullRect(0, 0, sz.x, sz.y); // artificial simple border if ( m_widthCustomBorder ) @@ -213,16 +255,22 @@ void wxGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) int customBorder = m_widthCustomBorder; // Set border colour - wxPen pen1( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT), +#ifdef __WXMAC__ + wxPen pen1( wxColour(133,133,133), customBorder, wxSOLID ); +#else + wxPen pen1( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT), + customBorder, + wxPENSTYLE_SOLID); +#endif dc.SetPen( pen1 ); // area around both controls - wxRect rect2(0,0,sz.x,sz.y); + wxRect rect2(fullRect); if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE ) { - rect2 = m_tcArea; + rect2 = tcRect; if ( customBorder == 1 ) { rect2.Inflate(1); @@ -245,55 +293,61 @@ void wxGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) dc.DrawRectangle(rect2); } - wxColour winCol = GetBackgroundColour(); - dc.SetBrush(winCol); - dc.SetPen(winCol); - - //wxLogDebug(wxT("hei: %i tcy: %i tchei: %i"),GetClientSize().y,m_tcArea.y,m_tcArea.height); - //wxLogDebug(wxT("btnx: %i tcx: %i tcwid: %i"),m_btnArea.x,m_tcArea.x,m_tcArea.width); + // Clear the main background if the system doesn't do it by itself + if ( !HasTransparentBackground() && + (tcRect.x > 0 || tcRect.y > 0) ) + { + wxColour winCol = GetParent()->GetBackgroundColour(); + dc.SetBrush(winCol); + dc.SetPen(winCol); - // clear main background - dc.DrawRectangle(rect); + dc.DrawRectangle(fullRect); + } if ( !m_btn ) + { // Standard button rendering - DrawButton(dc,rectb,true); + DrawButton(dc, butRect); + } // paint required portion on the control - if ( (!m_text || m_widthCustomPaint) ) + if ( !m_text || m_widthCustomPaint ) { wxASSERT( m_widthCustomPaint >= 0 ); + // Clear the text-control area background + wxColour tcCol = GetBackgroundColour(); + dc.SetBrush(tcCol); + dc.SetPen(tcCol); + dc.DrawRectangle(tcRect); + // this is intentionally here to allow drawed rectangle's // right edge to be hidden if ( m_text ) - rect.width = m_widthCustomPaint; + tcRect.width = m_widthCustomPaint; dc.SetFont( GetFont() ); - dc.SetClippingRegion(rect); + dc.SetClippingRegion(tcRect); if ( m_popupInterface ) - m_popupInterface->PaintComboControl(dc,rect); + m_popupInterface->PaintComboControl(dc, tcRect); else - wxComboPopup::DefaultPaintComboControl(this,dc,rect); + wxComboPopup::DefaultPaintComboControl(this, dc, tcRect); } + + delete dcPtr; } -void wxGenericComboControl::OnMouseEvent( wxMouseEvent& event ) +void wxGenericComboCtrl::OnMouseEvent( wxMouseEvent& event ) { - bool isOnButtonArea = m_btnArea.Inside(event.m_x,event.m_y); + int mx = event.m_x; + bool isOnButtonArea = m_btnArea.Contains(mx,event.m_y); int handlerFlags = isOnButtonArea ? wxCC_MF_ON_BUTTON : 0; - // Preprocessing fabricates double-clicks and prevents - // (it may also do other common things in future) if ( PreprocessMouseEvent(event,handlerFlags) ) return; -#ifdef __WXMSW__ - const bool ctrlIsButton = true; -#else - const bool ctrlIsButton = false; -#endif + const bool ctrlIsButton = wxPlatformIs(wxOS_WINDOWS); if ( ctrlIsButton && (m_windowStyle & (wxCC_SPECIAL_DCLICK|wxCB_READONLY)) == wxCB_READONLY ) @@ -306,8 +360,11 @@ void wxGenericComboControl::OnMouseEvent( wxMouseEvent& event ) } else { - if ( isOnButtonArea || HasCapture() ) + if ( isOnButtonArea || HasCapture() || + (m_widthCustomPaint && mx < (m_tcArea.x+m_widthCustomPaint)) ) { + handlerFlags |= wxCC_MF_ON_CLICK_AREA; + if ( HandleButtonMouseEvent(event,handlerFlags) ) return; } @@ -326,16 +383,90 @@ void wxGenericComboControl::OnMouseEvent( wxMouseEvent& event ) } +void wxGenericComboCtrl::SetCustomPaintWidth( int width ) +{ +#ifdef UNRELIABLE_TEXTCTRL_BORDER + // + // If starting/stopping to show an image in front + // of a writable text-field, then re-create textctrl + // with different kind of border (because we can't + // assume that textctrl fully supports wxNO_BORDER). + // + wxTextCtrl* tc = GetTextCtrl(); + + if ( tc && (m_iFlags & wxCC_BUTTON_OUTSIDE_BORDER) ) + { + int borderType = tc->GetWindowStyle() & wxBORDER_MASK; + int tcCreateStyle = -1; + + if ( width > 0 ) + { + // Re-create textctrl with no border + if ( borderType != wxNO_BORDER ) + { + m_widthCustomBorder = 1; + tcCreateStyle = wxNO_BORDER; + } + } + else if ( width == 0 ) + { + // Re-create textctrl with normal border + if ( borderType == wxNO_BORDER ) + { + m_widthCustomBorder = 0; + tcCreateStyle = 0; + } + } + + // Common textctrl re-creation code + if ( tcCreateStyle != -1 ) + { + tc->RemoveEventHandler(m_textEvtHandler); + delete m_textEvtHandler; + + CreateTextCtrl( tcCreateStyle ); + + InstallInputHandlers(); + } + } +#endif // UNRELIABLE_TEXTCTRL_BORDER + + wxComboCtrlBase::SetCustomPaintWidth( width ); +} + +bool wxGenericComboCtrl::IsKeyPopupToggle(const wxKeyEvent& event) const +{ + int keycode = event.GetKeyCode(); + bool isPopupShown = IsPopupShown(); + + // This code is AFAIK appropriate for wxGTK. + + if ( isPopupShown ) + { + if ( keycode == WXK_ESCAPE || + ( keycode == WXK_UP && event.AltDown() ) ) + return true; + } + else + { + if ( (keycode == WXK_DOWN && event.AltDown()) || + (keycode == WXK_F4) ) + return true; + } + + return false; +} + #ifdef __WXUNIVERSAL__ -bool wxGenericComboControl::PerformAction(const wxControlAction& action, - long numArg, - const wxString& strArg) +bool wxGenericComboCtrl::PerformAction(const wxControlAction& action, + long numArg, + const wxString& strArg) { bool processed = false; if ( action == wxACTION_COMBOBOX_POPUP ) { - if ( !m_isPopupShown ) + if ( !IsPopupShown() ) { ShowPopup(); @@ -344,7 +475,7 @@ bool wxGenericComboControl::PerformAction(const wxControlAction& action, } else if ( action == wxACTION_COMBOBOX_DISMISS ) { - if ( m_isPopupShown ) + if ( IsPopupShown() ) { HidePopup(); @@ -363,12 +494,12 @@ bool wxGenericComboControl::PerformAction(const wxControlAction& action, #endif // __WXUNIVERSAL__ -// If native wxComboControl was not defined, then prepare a simple +// If native wxComboCtrl was not defined, then prepare a simple // front-end so that wxRTTI works as expected. #ifndef _WX_COMBOCONTROL_H_ -IMPLEMENT_DYNAMIC_CLASS(wxComboControl, wxGenericComboControl) +IMPLEMENT_DYNAMIC_CLASS(wxComboCtrl, wxGenericComboCtrl) #endif #endif // !wxCOMBOCONTROL_FULLY_FEATURED -#endif // wxUSE_COMBOCONTROL +#endif // wxUSE_COMBOCTRL