Merge branch 'combo-non-text'
Allow using non-text control as main window of wxComboCtrl. See https://github.com/wxWidgets/wxWidgets/pull/2515
This commit is contained in:
@@ -197,6 +197,10 @@ public:
|
||||
// get the popup window containing the popup control
|
||||
wxWindow *GetPopupWindow() const { return m_winPopup; }
|
||||
|
||||
// Set the control to use instead of the default text control for the main
|
||||
// (always visible) part of the combobox.
|
||||
void SetMainControl(wxWindow* win);
|
||||
|
||||
// Get the text control which is part of the combobox.
|
||||
wxTextCtrl *GetTextCtrl() const { return m_text; }
|
||||
|
||||
@@ -623,8 +627,12 @@ protected:
|
||||
// This is used when control is unfocused and m_valueString is empty
|
||||
wxString m_hintText;
|
||||
|
||||
// the text control and button we show all the time
|
||||
// This pointer is non-null if we use a text control, and not some other
|
||||
// window, as the main control.
|
||||
wxTextCtrl* m_text;
|
||||
|
||||
// the window and button we show all the time
|
||||
wxWindow* m_mainWindow;
|
||||
wxWindow* m_btn;
|
||||
|
||||
// wxPopupWindow or similar containing the window managed by the interface.
|
||||
|
@@ -751,6 +751,47 @@ public:
|
||||
*/
|
||||
virtual void SetInsertionPointEnd();
|
||||
|
||||
/**
|
||||
Uses the given window instead of the default text control as the main
|
||||
window of the combo control.
|
||||
|
||||
By default, combo controls without @c wxCB_READONLY style create a
|
||||
wxTextCtrl which shows the current value and allows to edit it. This
|
||||
method allows to use some other window instead of this wxTextCtrl.
|
||||
|
||||
This method can be called after creating the combo fully, however in
|
||||
this case a wxTextCtrl is unnecessarily created just to be immediately
|
||||
destroyed when it's replaced by a custom window. If you wish to avoid
|
||||
this, you can use the following approach, also shown in the combo
|
||||
sample:
|
||||
|
||||
@code
|
||||
// Create the combo control using its default ctor.
|
||||
wxComboCtrl* combo = new wxComboCtrl();
|
||||
|
||||
// Create the custom main control using its default ctor too.
|
||||
SomeWindow* main = new SomeWindow();
|
||||
|
||||
// Set the custom main control before creating the combo.
|
||||
combo->SetMainControl(main);
|
||||
|
||||
// And only create it now: wxTextCtrl won't be unnecessarily
|
||||
// created because the combo already has a main window.
|
||||
combo->Create(panel, wxID_ANY, wxEmptyString);
|
||||
|
||||
// Finally create the main window itself, now that its parent was
|
||||
// created.
|
||||
main->Create(combo, ...);
|
||||
@endcode
|
||||
|
||||
Note that when a custom main window is used, none of the methods of
|
||||
this class inherited from wxTextEntry, such as SetValue(), Replace(),
|
||||
SetInsertionPoint() etc do anything and simply return.
|
||||
|
||||
@since 3.1.6
|
||||
*/
|
||||
void SetMainControl(wxWindow* win);
|
||||
|
||||
//@{
|
||||
/**
|
||||
Attempts to set the control margins. When margins are given as wxPoint,
|
||||
|
@@ -884,7 +884,7 @@ MyFrame::MyFrame(const wxString& title)
|
||||
//
|
||||
rowSizer = new wxBoxSizer( wxHORIZONTAL );
|
||||
rowSizer->Add( new wxStaticText(panel,wxID_ANY,
|
||||
"wxComboCtrl with custom button action:"), 1,
|
||||
"wxComboCtrl with custom button and custom main control:"), 1,
|
||||
wxALIGN_CENTER_VERTICAL|wxRIGHT, 4 );
|
||||
|
||||
|
||||
@@ -898,7 +898,31 @@ MyFrame::MyFrame(const wxString& title)
|
||||
(long)0
|
||||
);
|
||||
|
||||
// This is a perfectly useless control, as the popup and main control
|
||||
// don't interact with each other, but it shows that we can use something
|
||||
// other than wxTextCtrl for the main part of wxComboCtrl too.
|
||||
//
|
||||
// In a real program, custom popup and main control would work together,
|
||||
// i.e. changing selection in one of them would update the other one.
|
||||
//
|
||||
// Also note the complicated dance we need to go through to create the
|
||||
// controls in the right order: we want to create the custom main control
|
||||
// before actually creating the wxComboCtrl window, as otherwise it would
|
||||
// unnecessarily create a wxTextCtrl by default, forcing us to use its
|
||||
// default ctor and Create() later, but this, in turn, also requires using
|
||||
// default ctor for the main control and creating it later too, as it can't
|
||||
// be created before its parent window is.
|
||||
wxComboCtrl* comboCustom = new wxComboCtrl();
|
||||
wxCheckBox* cbox = new wxCheckBox();
|
||||
comboCustom->SetMainControl(cbox);
|
||||
comboCustom->Create(panel, wxID_ANY, wxEmptyString);
|
||||
cbox->Create(comboCustom, wxID_ANY, "Checkbox as main control");
|
||||
cbox->SetBackgroundColour(*wxWHITE);
|
||||
|
||||
comboCustom->SetPopupControl(new ListViewComboPopup());
|
||||
|
||||
rowSizer->Add( fsc, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
||||
rowSizer->Add( comboCustom, 1, wxALIGN_CENTER_VERTICAL|wxALL, 4 );
|
||||
colSizer->Add( rowSizer, 0, wxEXPAND|wxALL, 5 );
|
||||
|
||||
|
||||
|
@@ -748,6 +748,7 @@ void wxComboCtrlBase::Init()
|
||||
m_popupWinState = Hidden;
|
||||
m_btn = NULL;
|
||||
m_text = NULL;
|
||||
m_mainWindow = NULL;
|
||||
m_popupInterface = NULL;
|
||||
|
||||
#if !wxUSE_POPUPWIN
|
||||
@@ -825,9 +826,34 @@ bool wxComboCtrlBase::Create(wxWindow *parent,
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
wxComboCtrlBase::SetMainControl(wxWindow* win)
|
||||
{
|
||||
// We can't have both a custom window and a text control, so get rid of the
|
||||
// latter if we have it.
|
||||
if ( m_text )
|
||||
{
|
||||
m_text->Destroy();
|
||||
|
||||
// Note that we currently always set it to NULL, even if the custom
|
||||
// window is a (subclass of) wxTextCtrl because our m_text must be a
|
||||
// wxComboCtrlTextCtrl for things to work correctly.
|
||||
m_text = NULL;
|
||||
}
|
||||
|
||||
// We don't do anything with the previous main window, if any, it's the
|
||||
// caller's responsibility to delete or hide it, as needed.
|
||||
m_mainWindow = win;
|
||||
}
|
||||
|
||||
void
|
||||
wxComboCtrlBase::CreateTextCtrl(int style)
|
||||
{
|
||||
// If we're using a custom main window explicitly set using
|
||||
// SetMainControl(), don't recreate it and just keep using it.
|
||||
if ( m_mainWindow && !m_text )
|
||||
return;
|
||||
|
||||
if ( !(m_windowStyle & wxCB_READONLY) )
|
||||
{
|
||||
if ( m_text )
|
||||
@@ -843,6 +869,8 @@ wxComboCtrlBase::CreateTextCtrl(int style)
|
||||
style |= wxTE_PROCESS_ENTER;
|
||||
|
||||
m_text = new wxComboCtrlTextCtrl();
|
||||
m_mainWindow = m_text;
|
||||
|
||||
m_text->Create(this, wxID_ANY, m_valueString,
|
||||
wxDefaultPosition, wxSize(10,-1),
|
||||
style);
|
||||
@@ -918,7 +946,6 @@ wxComboCtrlBase::~wxComboCtrlBase()
|
||||
void wxComboCtrlBase::CalculateAreas( int btnWidth )
|
||||
{
|
||||
wxSize sz = GetClientSize();
|
||||
int customBorder = m_widthCustomBorder;
|
||||
int btnBorder; // border for button only
|
||||
|
||||
// check if button should really be outside the border: we'll do it it if
|
||||
@@ -941,7 +968,7 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth )
|
||||
else
|
||||
{
|
||||
m_iFlags &= ~(wxCC_IFLAG_BUTTON_OUTSIDE);
|
||||
btnBorder = customBorder;
|
||||
btnBorder = m_widthCustomBorder;
|
||||
}
|
||||
|
||||
// Defaul indentation
|
||||
@@ -1008,9 +1035,9 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth )
|
||||
butHeight = bmpReqHeight;
|
||||
|
||||
// Need to fix height?
|
||||
if ( (sz.y-(customBorder*2)) < butHeight && btnWidth == 0 )
|
||||
if ( (sz.y-(m_widthCustomBorder*2)) < butHeight && btnWidth == 0 )
|
||||
{
|
||||
int newY = butHeight+(customBorder*2);
|
||||
int newY = butHeight+(m_widthCustomBorder*2);
|
||||
SetClientSize(wxDefaultCoord,newY);
|
||||
if ( m_bmpNormal.IsOk() || m_btnArea.width != butWidth || m_btnArea.height != butHeight )
|
||||
m_iFlags |= wxCC_IFLAG_HAS_NONSTANDARD_BUTTON;
|
||||
@@ -1031,13 +1058,13 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth )
|
||||
m_btnArea.width = butAreaWid;
|
||||
m_btnArea.height = sz.y - ((btnBorder+FOCUS_RING)*2);
|
||||
|
||||
m_tcArea.x = ( m_btnSide==wxRIGHT ? 0 : butAreaWid ) + customBorder;
|
||||
m_tcArea.y = customBorder + FOCUS_RING;
|
||||
m_tcArea.width = sz.x - butAreaWid - (customBorder*2) - FOCUS_RING;
|
||||
m_tcArea.height = sz.y - ((customBorder+FOCUS_RING)*2);
|
||||
m_tcArea.x = ( m_btnSide==wxRIGHT ? 0 : butAreaWid ) + m_widthCustomBorder;
|
||||
m_tcArea.y = m_widthCustomBorder + FOCUS_RING;
|
||||
m_tcArea.width = sz.x - butAreaWid - (m_widthCustomBorder*2) - FOCUS_RING;
|
||||
m_tcArea.height = sz.y - ((m_widthCustomBorder+FOCUS_RING)*2);
|
||||
|
||||
/*
|
||||
if ( m_text )
|
||||
if ( m_mainWindow )
|
||||
{
|
||||
::wxMessageBox(wxString::Format(wxT("ButtonArea (%i,%i,%i,%i)\n"),m_btnArea.x,m_btnArea.y,m_btnArea.width,m_btnArea.height) +
|
||||
wxString::Format(wxT("TextCtrlArea (%i,%i,%i,%i)"),m_tcArea.x,m_tcArea.y,m_tcArea.width,m_tcArea.height));
|
||||
@@ -1047,13 +1074,14 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth )
|
||||
|
||||
void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust )
|
||||
{
|
||||
if ( !m_text )
|
||||
if ( !m_mainWindow || !m_mainWindow->GetHandle() )
|
||||
return;
|
||||
|
||||
wxSize sz = GetClientSize();
|
||||
|
||||
int customBorder = m_widthCustomBorder;
|
||||
if ( (m_text->GetWindowStyleFlag() & wxBORDER_MASK) == wxNO_BORDER )
|
||||
// This function actually positions any main window, not just a text
|
||||
// control, but it only does any special adjustments for m_text.
|
||||
if ( m_text && (m_text->GetWindowStyleFlag() & wxBORDER_MASK) == wxNO_BORDER )
|
||||
{
|
||||
int x;
|
||||
|
||||
@@ -1079,8 +1107,8 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust
|
||||
int diff0 = sz.y - tcSizeY;
|
||||
int y = textCtrlYAdjust + (diff0/2);
|
||||
|
||||
if ( y < customBorder )
|
||||
y = customBorder;
|
||||
if ( y < m_widthCustomBorder )
|
||||
y = m_widthCustomBorder;
|
||||
|
||||
m_text->SetSize(x,
|
||||
y,
|
||||
@@ -1089,7 +1117,7 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust
|
||||
|
||||
// Make sure textctrl doesn't exceed the bottom custom border
|
||||
wxSize tsz = m_text->GetSize();
|
||||
int diff1 = (y + tsz.y) - (sz.y - customBorder);
|
||||
int diff1 = (y + tsz.y) - (sz.y - m_widthCustomBorder);
|
||||
if ( diff1 >= 0 )
|
||||
{
|
||||
tsz.y = tsz.y - diff1 - 1;
|
||||
@@ -1098,10 +1126,11 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust
|
||||
}
|
||||
else
|
||||
{
|
||||
// If it has border, have textctrl fill the entire text field.
|
||||
// If the main window has border or is not a text control at all, have
|
||||
// it fill the entire available space.
|
||||
int w = m_tcArea.width - m_widthCustomPaint;
|
||||
if (w < 0) w = 0;
|
||||
m_text->SetSize( m_tcArea.x + m_widthCustomPaint,
|
||||
m_mainWindow->SetSize( m_tcArea.x + m_widthCustomPaint,
|
||||
m_tcArea.y,
|
||||
w,
|
||||
m_tcArea.height );
|
||||
@@ -1110,7 +1139,8 @@ void wxComboCtrlBase::PositionTextCtrl( int textCtrlXAdjust, int textCtrlYAdjust
|
||||
|
||||
wxSize wxComboCtrlBase::DoGetBestSize() const
|
||||
{
|
||||
int width = m_text ? m_text->GetBestSize().x : FromDIP(80);
|
||||
int width = m_mainWindow && m_mainWindow->GetHandle()
|
||||
? m_mainWindow->GetBestSize().x : FromDIP(80);
|
||||
|
||||
return GetSizeFromTextSize(width);
|
||||
}
|
||||
@@ -1231,8 +1261,8 @@ bool wxComboCtrlBase::Enable(bool enable)
|
||||
|
||||
if ( m_btn )
|
||||
m_btn->Enable(enable);
|
||||
if ( m_text )
|
||||
m_text->Enable(enable);
|
||||
if ( m_mainWindow )
|
||||
m_mainWindow->Enable(enable);
|
||||
|
||||
Refresh();
|
||||
|
||||
@@ -1247,8 +1277,8 @@ bool wxComboCtrlBase::Show(bool show)
|
||||
if (m_btn)
|
||||
m_btn->Show(show);
|
||||
|
||||
if (m_text)
|
||||
m_text->Show(show);
|
||||
if (m_mainWindow)
|
||||
m_mainWindow->Show(show);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1258,14 +1288,14 @@ bool wxComboCtrlBase::SetFont ( const wxFont& font )
|
||||
if ( !wxControl::SetFont(font) )
|
||||
return false;
|
||||
|
||||
if ( m_text )
|
||||
if ( m_mainWindow )
|
||||
{
|
||||
// Without hiding the wxTextCtrl there would be some
|
||||
// visible 'flicker' (at least on Windows XP).
|
||||
m_text->Hide();
|
||||
m_text->SetFont(font);
|
||||
m_mainWindow->Hide();
|
||||
m_mainWindow->SetFont(font);
|
||||
OnResize();
|
||||
m_text->Show();
|
||||
m_mainWindow->Show();
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1280,12 +1310,12 @@ void wxComboCtrlBase::DoSetToolTip(wxToolTip *tooltip)
|
||||
if ( tooltip )
|
||||
{
|
||||
const wxString &tip = tooltip->GetTip();
|
||||
if ( m_text ) m_text->SetToolTip(tip);
|
||||
if ( m_mainWindow ) m_mainWindow->SetToolTip(tip);
|
||||
if ( m_btn ) m_btn->SetToolTip(tip);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_text ) m_text->SetToolTip( NULL );
|
||||
if ( m_mainWindow ) m_mainWindow->SetToolTip( NULL );
|
||||
if ( m_btn ) m_btn->SetToolTip( NULL );
|
||||
}
|
||||
}
|
||||
@@ -1295,8 +1325,8 @@ bool wxComboCtrlBase::SetForegroundColour(const wxColour& colour)
|
||||
{
|
||||
if ( wxControl::SetForegroundColour(colour) )
|
||||
{
|
||||
if ( m_text )
|
||||
m_text->SetForegroundColour(colour);
|
||||
if ( m_mainWindow )
|
||||
m_mainWindow->SetForegroundColour(colour);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1304,8 +1334,8 @@ bool wxComboCtrlBase::SetForegroundColour(const wxColour& colour)
|
||||
|
||||
bool wxComboCtrlBase::SetBackgroundColour(const wxColour& colour)
|
||||
{
|
||||
if ( m_text )
|
||||
m_text->SetBackgroundColour(colour);
|
||||
if ( m_mainWindow )
|
||||
m_mainWindow->SetBackgroundColour(colour);
|
||||
m_tcBgCol = colour;
|
||||
m_hasTcBgCol = true;
|
||||
return true;
|
||||
@@ -1313,8 +1343,8 @@ bool wxComboCtrlBase::SetBackgroundColour(const wxColour& colour)
|
||||
|
||||
wxColour wxComboCtrlBase::GetBackgroundColour() const
|
||||
{
|
||||
if ( m_text )
|
||||
return m_text->GetBackgroundColour();
|
||||
if ( m_mainWindow )
|
||||
return m_mainWindow->GetBackgroundColour();
|
||||
return m_tcBgCol;
|
||||
}
|
||||
|
||||
@@ -1826,10 +1856,10 @@ void wxComboCtrlBase::OnFocusEvent( wxFocusEvent& event )
|
||||
|
||||
if ( event.GetEventType() == wxEVT_SET_FOCUS )
|
||||
{
|
||||
if ( !m_resetFocus && GetTextCtrl() && !GetTextCtrl()->HasFocus() )
|
||||
if ( !m_resetFocus && m_mainWindow && !m_mainWindow->HasFocus() )
|
||||
{
|
||||
m_resetFocus = true;
|
||||
GetTextCtrl()->SetFocus();
|
||||
m_mainWindow->SetFocus();
|
||||
m_resetFocus = false;
|
||||
}
|
||||
}
|
||||
@@ -1842,8 +1872,8 @@ void wxComboCtrlBase::OnIdleEvent( wxIdleEvent& WXUNUSED(event) )
|
||||
if ( m_resetFocus )
|
||||
{
|
||||
m_resetFocus = false;
|
||||
if ( GetTextCtrl() )
|
||||
GetTextCtrl()->SetFocus();
|
||||
if ( m_mainWindow )
|
||||
m_mainWindow->SetFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2389,14 +2419,14 @@ void wxComboCtrlBase::SetButtonBitmaps( const wxBitmap& bmpNormal,
|
||||
|
||||
void wxComboCtrlBase::SetCustomPaintWidth( int width )
|
||||
{
|
||||
if ( m_text )
|
||||
if ( m_mainWindow )
|
||||
{
|
||||
// move textctrl accordingly
|
||||
wxRect r = m_text->GetRect();
|
||||
// move the main window accordingly
|
||||
wxRect r = m_mainWindow->GetRect();
|
||||
int inc = width - m_widthCustomPaint;
|
||||
r.x += inc;
|
||||
r.width -= inc;
|
||||
m_text->SetSize( r );
|
||||
m_mainWindow->SetSize( r );
|
||||
}
|
||||
|
||||
m_widthCustomPaint = width;
|
||||
|
Reference in New Issue
Block a user