📄 odcombo.cpp
字号:
/////////////////////////////////////////////////////////////////////////////
// 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 + -