Allow using custom main window in wxComboCtrl
Add wxComboCtrl::SetMainControl() which can be used to use some other window instead of the default wxTextCtrl as the main window of the combo control. Update the sample and the documentation to show the new function.
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);
|
||||
@@ -1036,7 +1064,7 @@ void wxComboCtrlBase::CalculateAreas( int btnWidth )
|
||||
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));
|
||||
@@ -1046,12 +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();
|
||||
|
||||
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;
|
||||
|
||||
@@ -1096,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 );
|
||||
@@ -1108,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);
|
||||
}
|
||||
@@ -1229,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();
|
||||
|
||||
@@ -1245,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;
|
||||
}
|
||||
@@ -1256,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;
|
||||
@@ -1278,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 );
|
||||
}
|
||||
}
|
||||
@@ -1293,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;
|
||||
@@ -1302,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;
|
||||
@@ -1311,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;
|
||||
}
|
||||
|
||||
@@ -1824,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;
|
||||
}
|
||||
}
|
||||
@@ -1840,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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2387,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