⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 odcombo.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/////////////////////////////////////////////////////////////////////////////
// Name:        odcombo.cpp
// Purpose:     wxPGComboBox and related classes implementation
// Author:      Jaakko Salli
//              (loosely based on wxUniv combo.cpp by Vadim Zeitlin)
// Modified by:
// Created:     Jan-25-2005
// RCS-ID:      $Id:
// Copyright:   (c) 2005 Jaakko Salli
// Licence:     wxWindows licence
/////////////////////////////////////////////////////////////////////////////

// ============================================================================
// declarations
// ============================================================================

// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------

#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
    #pragma implementation "odcombobox.h"
#endif

#include "wx/wxprec.h"

#ifdef __BORLANDC__
    #pragma hdrstop
#endif

#if wxUSE_COMBOBOX

#ifndef WX_PRECOMP
    #include "wx/log.h"

    #include "wx/button.h"
    #include "wx/combobox.h"
    #include "wx/textctrl.h"
    #include "wx/dcclient.h"
    #include "wx/settings.h"

#endif

#include "wx/vlbox.h"
#include "wx/tooltip.h"

#include "wx/propgrid/odcombo.h"

//
// Some platform specific constants
//

//
// wxODC_SELECTION_STYLE
//
// 0 = Windows Style (both control and popup: blue background plus lighter dotted edge)
// 1 = GTK'ish Style (popup: blue background. control: text-col dotted edge)
//

//
// wxODC_BORDER_STYLE
//
// 0 = Borders in main control (they surround borderless textctrl and button)
// 1 = GTK Style (border only to textctrl)
//

#if defined(__WXMSW__)
    // tested

#define wxODC_TEXTCTRLXADJUST               4 // position adjustment for wxTextCtrl
#define wxODC_TEXTCTRLYADJUST               3

#define wxODC_TEXTXADJUST                   0 // how much is read-only text's x adjusted

#define wxODC_DROPDOWN_BUTTON_MAX_WIDTH     19

#define wxODC_SUNKEN_BORDER_WIDTH           2

#define wxODC_SELECTION_STYLE               0

#define wxODC_BORDER_STYLE                  0

#define wxODC_BUTTON_DOWN_WHILE_POPUP       0 // button pressed while popup is shown

#define wxODC_ALLOW_FAKE_POPUP              1 // Use only on plats with problems with wxPopupWindow

//#undef wxUSE_POPUPWIN
//#define wxUSE_POPUPWIN 0

#elif defined(__WXGTK__)
    // tested
#define wxODC_TEXTCTRLXADJUST               2 // position adjustment for wxTextCtrl
#define wxODC_TEXTCTRLYADJUST               0

#define wxODC_TEXTXADJUST                   1 // how much is read-only text's x adjusted

#define wxODC_DROPDOWN_BUTTON_MAX_WIDTH     19

#define wxODC_SUNKEN_BORDER_WIDTH           2

#define wxODC_SELECTION_STYLE               1

#define wxODC_BORDER_STYLE                  1

#define wxODC_BUTTON_DOWN_WHILE_POPUP       1 // button pressed while popup is shown

#define wxODC_ALLOW_FAKE_POPUP              1 // Use only on plats with problems with wxPopupWindow

#elif defined(__WXMAC__)
    // *not* tested

#define wxODC_TEXTCTRLXADJUST               3 // position adjustment for wxTextCtrl
#define wxODC_TEXTCTRLYADJUST               0

#define wxODC_TEXTXADJUST                   0 // how much is read-only text's x adjusted

#define wxODC_DROPDOWN_BUTTON_MAX_WIDTH     19

#define wxODC_SUNKEN_BORDER_WIDTH           2

#define wxODC_SELECTION_STYLE               1

#define wxODC_BORDER_STYLE                  0

#define wxODC_BUTTON_DOWN_WHILE_POPUP       0 // button pressed while popup is shown

#define wxODC_ALLOW_FAKE_POPUP              1 // Use only on plats with problems with wxPopupWindow

#else
    // defaults
    // tested on: none

#define wxODC_TEXTCTRLXADJUST               0 // position adjustment for wxTextCtrl
#define wxODC_TEXTCTRLYADJUST               0

#define wxODC_TEXTXADJUST                   0 // how much is read-only text's x adjusted

#define wxODC_DROPDOWN_BUTTON_MAX_WIDTH     17

#define wxODC_SUNKEN_BORDER_WIDTH           2

#define wxODC_SELECTION_STYLE               1

#define wxODC_BORDER_STYLE                  0

#define wxODC_BUTTON_DOWN_WHILE_POPUP       1 // button pressed while popup is shown

#define wxODC_ALLOW_FAKE_POPUP              1 // Use only on plats with problems with wxPopupWindow

#endif


#if wxUSE_POPUPWIN
# include "wx/popupwin.h"
#endif


#define wxODC_USE_TRANSIENT_POPUP           0

#if wxODC_USE_TRANSIENT_POPUP
# undef wxODC_ALLOW_FAKE_POPUP
# define wxODC_ALLOW_FAKE_POPUP 0

# define wxComboPopupWindowBase wxPopupTransientWindow
# define wxODC_INSTALL_TOPLEV_HANDLER       0

#elif wxUSE_POPUPWIN

# define wxComboPopupWindowBase wxPopupWindow
# define wxODC_INSTALL_TOPLEV_HANDLER       1

#else

# define wxComboPopupWindowBase wxDialog
# if !wxODC_ALLOW_FAKE_POPUP
#  define wxODC_INSTALL_TOPLEV_HANDLER      0 // Doesn't need since can monitor active event
# else
#  define wxODC_INSTALL_TOPLEV_HANDLER      1 // Doesn't need since can monitor active event
# endif

#endif


//
// ** TODO **
//
// * proper tab traversal.
// * simple border detection (currently only sunken)
// * correct/faster/better colour acquisition
// * maybe: wxOwnerDrawnChoice. Simple derivate with forced read-only style.
//     Need to use m_typeSelectEvent to use different wx event type.
// * maybe: wxODCB_CUSTOM_ACTION style - redirects button clicks to combo's
//     event handler and ignores them itself.
// * bug: the cursor inconsistency in writable mode
//     (maybe a wxPropertyGrid bug - doesn't matter in that case 'cause 'grid
//     only uses it in read-only mode). Try focusing textctrl?
// * maybe: ability switch between read-only and writable.
// * maybe: msw dropdown button use parent's background colour
//     (needs changes in native_drawdropbutton)
// * maybe: patch wxVListBox to scroll to selected in OnSize handler
//     (con: relatively expensive operation)
//

// constants
// ----------------------------------------------------------------------------

// the margin between the text control and the combo button
static const wxCoord g_comboMargin = 2;

// ----------------------------------------------------------------------------
// wxComboDropButton
// ----------------------------------------------------------------------------

#include "wx/renderer.h"

#if wxMINOR_VERSION < 5 || ( wxMINOR_VERSION == 5 && wxRELEASE_NUMBER < 5 )
// Temp stuff
#define wxCONTROL_POPUP_ARROW       wxCONTROL_CHECKED
extern void wxRendererNative_DrawButton( wxWindow* win, wxDC& dc, const wxRect& r1,
                                         int flags );
#endif

#define wxDropDownButtonBase wxWindow

class wxComboDropButton : public wxDropDownButtonBase
{
public:

    wxComboDropButton();
    wxComboDropButton(wxWindow *parent,
             wxWindowID id,
             const wxPoint& pos = wxDefaultPosition,
             const wxSize& size = wxDefaultSize,
             long style = 0,
             const wxString& name = wxButtonNameStr)
    {
        Init();
        Create(parent, id, pos, size, style, name);
    }

    bool Create(wxWindow *parent,
                wxWindowID id,
                const wxPoint& pos = wxDefaultPosition,
                const wxSize& size = wxDefaultSize,
                long style = 0,
                const wxString& name = wxButtonNameStr);

    virtual ~wxComboDropButton();

    // Calling this with ptr and NULL indicates whether
    // popup is visible or not. required for correct event
    // handling.
    void SetPopup ( wxWindow* popup );

protected:

    void Init();

    // event handlers
    void OnMouseEvent(wxMouseEvent& event);
    void OnPaint(wxPaintEvent& event);
    void OnKeyEvent(wxKeyEvent& event);

    virtual wxSize DoGetBestSize() const;

protected:

    wxWindow* m_popup;

    int m_state;

private:
    //wxPGComboBox *m_combo;

    DECLARE_DYNAMIC_CLASS(wxComboDropButton)

    DECLARE_EVENT_TABLE()
};

BEGIN_EVENT_TABLE(wxComboDropButton, wxDropDownButtonBase)
    EVT_MOUSE_EVENTS(wxComboDropButton::OnMouseEvent)
    EVT_PAINT(wxComboDropButton::OnPaint)
    EVT_KEY_DOWN(wxComboDropButton::OnKeyEvent)
    EVT_KEY_UP(wxComboDropButton::OnKeyEvent)
END_EVENT_TABLE()

IMPLEMENT_DYNAMIC_CLASS(wxComboDropButton,wxDropDownButtonBase)

wxComboDropButton::wxComboDropButton()
{
    Init();
}

void wxComboDropButton::Init()
{
    m_popup = (wxWindow*) NULL;
    m_state = 0;
}

bool wxComboDropButton::Create(wxWindow *parent,
                              wxWindowID id,
                              const wxPoint& pos,
                              const wxSize& size,
                              long style,
                              const wxString& name)
{
    if ( wxDropDownButtonBase::Create(parent,id,pos,size,style,name) )
    {
        return true;
    }
    return false;
}

wxComboDropButton::~wxComboDropButton()
{
    if ( HasCapture() )
        ReleaseMouse ();
}

wxSize wxComboDropButton::DoGetBestSize() const
{

    int fhei = 20;
    if ( m_font.Ok() )
        fhei = m_font.GetPointSize()*2;

    return wxSize(wxODC_DROPDOWN_BUTTON_MAX_WIDTH,fhei);
}

void wxComboDropButton::OnMouseEvent(wxMouseEvent& event)
{
    int type = event.GetEventType();
    int x = event.m_x;
    int y = event.m_y;
    wxSize sz = GetClientSize();
    bool is_inside = ( (x > 0 && x < sz.x) && (y > 0 && y < sz.y) );

    if ( type == wxEVT_MOTION )
    {
        if ( is_inside )
        {
            if ( !(m_state & wxCONTROL_CURRENT) )
            {
                // Mouse hover begins
                m_state |= wxCONTROL_CURRENT;
                if ( HasCapture() ) // Retain pressed state.
                    m_state |= wxCONTROL_PRESSED;
                Refresh();
            }
        }
        else if ( (m_state & wxCONTROL_CURRENT) )
        {
            // Mouse hover ends
            m_state &= ~(wxCONTROL_CURRENT|wxCONTROL_PRESSED);
            Refresh();
        }
    }
    else if ( type == wxEVT_LEFT_DOWN )
    {
        // Need to test this, because it might be outside.
        if ( is_inside )
        {
            m_state |= wxCONTROL_PRESSED;
            Refresh();
            CaptureMouse();
        }
    }
    else if ( type == wxEVT_LEFT_UP )
    {
        if ( HasCapture() )
            ReleaseMouse();

        // If mouse was inside, fire the click event.
        if ( is_inside )
        {
            //wxLogDebug(wxT("wxComboDropButton::OnMouseEvent(%i)"),(int)event.GetEventType());
            wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, GetId());
            event.SetEventObject(this);
            GetEventHandler()->AddPendingEvent(event);
        }

        m_state &= ~(wxCONTROL_PRESSED);
        Refresh();
    }
    else if ( type == wxEVT_LEAVE_WINDOW )
    {
        if ( m_state & wxCONTROL_CURRENT )
        {
            // Mouse hover ends
            m_state &= ~(wxCONTROL_CURRENT|wxCONTROL_PRESSED);
            Refresh();
        }
    }
    else if ( m_popup )
    {
        //wxLogDebug(wxT("wxComboDropButton::OnMouseEvent(%i)"),(int)event.GetEventType());
        m_popup->AddPendingEvent(event);
    }
}

void wxComboDropButton::OnPaint(wxPaintEvent& )
{
    wxPaintDC dc(this);

    wxRect rect( wxPoint(0,0), GetClientSize() );

    //wxLogDebug( wxT("width=%i"), (int)GetSize().x );
    //wxLogDebug( wxT("client_width=%i"), (int)GetClientSize().x );

    int draw_state = m_state;

#if wxODC_BUTTON_DOWN_WHILE_POPUP
    if ( m_popup )
        draw_state |= wxCONTROL_PRESSED;
#endif

#if wxMINOR_VERSION < 5 || ( wxMINOR_VERSION == 5 && wxRELEASE_NUMBER < 5 )
    wxRendererNative_DrawButton(this,dc,rect,draw_state|wxCONTROL_POPUP_ARROW);
#else
    wxRendererNative::Get().DrawComboBoxDropButton(this,
                                                   dc,
                                                   rect,
                                                   draw_state);
#endif
}

// relay keys handling (this *is* required atleast for wxMSW)
// FIXME: Remove this after popup window can get focus.
void wxComboDropButton::OnKeyEvent(wxKeyEvent& event)
{
    if ( m_popup )
        m_popup->AddPendingEvent(event);
    //else wxLogDebug(wxT("NOT RELAYED"));
}

// Calling this with ptr and NULL indicates whether
// popup is visible or not. required for correct event
// handling.
void wxComboDropButton::SetPopup ( wxWindow* popup )
{
    m_popup = popup;
#if wxODC_BUTTON_DOWN_WHILE_POPUP
    Refresh();
#endif
}

// ----------------------------------------------------------------------------
// wxComboFrameEventHandler takes care of hiding the popup when stuff happens
// in its top level parent.
// ----------------------------------------------------------------------------

#if wxODC_INSTALL_TOPLEV_HANDLER

class wxComboFrameEventHandler : public wxEvtHandler
{
public:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -