// $Id: combog.cpp 1417 2006-07-06 19:56:27Z alex $ /* @@tag:xara-cn-tp@@ THIRD PARTY COPYRIGHT */ // The following line makes normalize.pl skip type fixing /* SKIPFIXTYPES: START */ ///////////////////////////////////////////////////////////////////////////// // Name: combog.cpp // Purpose: Generic wxComboControl // Author: Jaakko Salli // Modified by: // Created: Apr-30-2006 // RCS-ID: // Copyright: (c) 2005 Jaakko Salli // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ // declarations // ============================================================================ // ---------------------------------------------------------------------------- // headers // ---------------------------------------------------------------------------- #include "combog.h" #if wxXTRA_COMBOCTRL #include "combo.h" #include // ---------------------------------------------------------------------------- // 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 #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 #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 #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 #define TEXTXADJUST 0 // how much is read-only text's x adjusted #define DEFAULT_DROPBUTTON_WIDTH 19 #else #define TEXTCTRLXADJUST 0 // position adjustment for wxTextCtrl, with zero indent #define TEXTCTRLYADJUST 0 #define TEXTXADJUST 0 // how much is read-only text's x adjusted #define DEFAULT_DROPBUTTON_WIDTH 19 #endif // ============================================================================ // implementation // ============================================================================ // Only implement if no native or it wasn't fully featured #ifndef wxCOMBOCONTROL_FULLY_FEATURED // ---------------------------------------------------------------------------- // wxGenericComboControl // ---------------------------------------------------------------------------- BEGIN_EVENT_TABLE(wxGenericComboControl, wxComboCtrlBase) EVT_PAINT(wxGenericComboControl::OnPaintEvent) EVT_MOUSE_EVENTS(wxGenericComboControl::OnMouseEvent) END_EVENT_TABLE() IMPLEMENT_DYNAMIC_CLASS(wxGenericComboControl, wxComboCtrlBase) void wxGenericComboControl::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) { // Set border long border = style & wxBORDER_MASK; if ( !border ) { #if defined(__WXUNIVERSAL__) border = wxBORDER_SIMPLE; #elif defined(__WXMSW__) // For XP, have 1-width custom border, for older version use sunken if ( wxUxThemeEngine::GetIfActive() ) { border = wxBORDER_NONE; m_widthCustomBorder = 1; } 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; } #if defined(__WXGTK__) Customize( wxCC_BUTTON_OUTSIDE_BORDER | wxCC_NO_TEXT_AUTO_SELECT ); #endif if ( style & wxCC_STD_BUTTON ) m_iFlags |= wxCC_POPUP_ON_MOUSE_UP; // create main window if ( !wxComboCtrlBase::Create(parent, id, value, pos, size, style | wxFULL_REPAINT_ON_RESIZE, wxDefaultValidator, name) ) return false; // Create textctrl, if necessary CreateTextCtrl( wxNO_BORDER, validator ); // Add keyboard input handlers for main control and textctrl InstallInputHandlers( true ); // Set background SetBackgroundStyle( wxBG_STYLE_CUSTOM ); // for double-buffering // SetBestSize should be called last SetBestSize(size); return true; } wxGenericComboControl::~wxGenericComboControl() { } void wxGenericComboControl::OnResize() { // Recalculates button and textctrl areas CalculateAreas(DEFAULT_DROPBUTTON_WIDTH); #if 0 // Move separate button control, if any, to correct position if ( m_btn ) { wxSize sz = GetClientSize(); m_btn->SetSize( m_btnArea.x + m_btnSpacingX, (sz.y-m_btnSize.y)/2, m_btnSize.x, m_btnSize.y ); } #endif // Move textctrl, if any, accordingly PositionTextCtrl( TEXTCTRLXADJUST, TEXTCTRLYADJUST ); } void wxGenericComboControl::OnPaintEvent( wxPaintEvent& WXUNUSED(event) ) { wxSize sz = GetClientSize(); wxBufferedPaintDC dc(this,GetBufferBitmap(sz)); const wxRect& rectb = m_btnArea; wxRect rect = m_tcArea; // artificial simple border if ( m_widthCustomBorder ) { int customBorder = m_widthCustomBorder; // Set border colour wxPen pen1( wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT), customBorder, wxSOLID ); dc.SetPen( pen1 ); // area around both controls wxRect rect2(0,0,sz.x,sz.y); if ( m_iFlags & wxCC_IFLAG_BUTTON_OUTSIDE ) { rect2 = m_tcArea; if ( customBorder == 1 ) { rect2.Inflate(1); } else { #ifdef __WXGTK__ rect2.x -= 1; rect2.y -= 1; #else rect2.x -= customBorder; rect2.y -= customBorder; #endif rect2.width += 1 + customBorder; rect2.height += 1 + customBorder; } } dc.SetBrush( *wxTRANSPARENT_BRUSH ); 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 main background dc.DrawRectangle(rect); if ( !m_btn ) // Standard button rendering DrawButton(dc,rectb,true); // paint required portion on the control if ( (!m_text || m_widthCustomPaint) ) { wxASSERT( m_widthCustomPaint >= 0 ); // this is intentionally here to allow drawed rectangle's // right edge to be hidden if ( m_text ) rect.width = m_widthCustomPaint; dc.SetFont( GetFont() ); dc.SetClippingRegion(rect); if ( m_popupInterface ) m_popupInterface->PaintComboControl(dc,rect); else wxComboPopup::DefaultPaintComboControl(this,dc,rect); } } void wxGenericComboControl::OnMouseEvent( wxMouseEvent& event ) { bool isOnButtonArea = m_btnArea.Inside(event.m_x,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 if ( ctrlIsButton && (m_windowStyle & (wxCC_SPECIAL_DCLICK|wxCB_READONLY)) == wxCB_READONLY ) { // if no textctrl and no special double-click, then the entire control acts // as a button handlerFlags |= wxCC_MF_ON_BUTTON; if ( HandleButtonMouseEvent(event,handlerFlags) ) return; } else { if ( isOnButtonArea || HasCapture() ) { if ( HandleButtonMouseEvent(event,handlerFlags) ) return; } else if ( m_btnState ) { // otherwise need to clear the hover status m_btnState = 0; RefreshRect(m_btnArea); } } // // This will handle left_down and left_dclick events outside button in a Windows/GTK-like manner. // See header file for further information on this method. HandleNormalMouseEvent(event); } #ifdef __WXUNIVERSAL__ bool wxGenericComboControl::PerformAction(const wxControlAction& action, long numArg, const wxString& strArg) { bool processed = false; if ( action == wxACTION_COMBOBOX_POPUP ) { if ( !m_isPopupShown ) { ShowPopup(); processed = true; } } else if ( action == wxACTION_COMBOBOX_DISMISS ) { if ( m_isPopupShown ) { HidePopup(); processed = true; } } if ( !processed ) { // pass along return wxControl::PerformAction(action, numArg, strArg); } return true; } #endif // __WXUNIVERSAL__ // If native wxComboControl was not defined, then prepare a simple // front-end so that wxRTTI works as expected. #ifndef _WXXTRA_COMBOCONTROL_H_ IMPLEMENT_DYNAMIC_CLASS(wxComboCtrl, wxGenericComboControl) #endif #endif // !wxCOMBOCONTROL_FULLY_FEATURED #endif // wxUSE_COMBOCONTROL