Stop using wxList in wxGTK wxRadioBox

Note that using vector of incomplete class required moving all ctors out
of line.
This commit is contained in:
Vadim Zeitlin 2023-04-12 01:04:18 +02:00
parent c237d9ee49
commit 1ca7499221
2 changed files with 104 additions and 121 deletions

View file

@ -11,12 +11,9 @@
#include "wx/bitmap.h"
class WXDLLIMPEXP_FWD_CORE wxGTKRadioButtonInfo;
#include "wx/list.h"
WX_DECLARE_EXPORTED_LIST(wxGTKRadioButtonInfo, wxRadioBoxButtonsInfoList);
#include <vector>
class wxGTKRadioButtonInfo;
//-----------------------------------------------------------------------------
// wxRadioBox
@ -27,7 +24,7 @@ class WXDLLIMPEXP_CORE wxRadioBox : public wxControl,
{
public:
// ctors and dtor
wxRadioBox() { }
wxRadioBox();
wxRadioBox(wxWindow *parent,
wxWindowID id,
const wxString& title,
@ -38,10 +35,7 @@ public:
int majorDim = 0,
long style = wxRA_SPECIFY_COLS,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxASCII_STR(wxRadioBoxNameStr))
{
Create( parent, id, title, pos, size, n, choices, majorDim, style, val, name );
}
const wxString& name = wxASCII_STR(wxRadioBoxNameStr));
wxRadioBox(wxWindow *parent,
wxWindowID id,
@ -52,10 +46,7 @@ public:
int majorDim = 0,
long style = wxRA_SPECIFY_COLS,
const wxValidator& val = wxDefaultValidator,
const wxString& name = wxASCII_STR(wxRadioBoxNameStr))
{
Create( parent, id, title, pos, size, choices, majorDim, style, val, name );
}
const wxString& name = wxASCII_STR(wxRadioBoxNameStr));
bool Create(wxWindow *parent,
wxWindowID id,
@ -129,7 +120,7 @@ public:
virtual void GTKApplyToolTip(const char* tip) override;
#endif // wxUSE_TOOLTIPS
wxRadioBoxButtonsInfoList m_buttonsInfo;
std::vector<wxGTKRadioButtonInfo> m_buttonsInfo;
protected:
virtual wxBorder GetDefaultBorder() const override { return wxBORDER_NONE; }

View file

@ -24,11 +24,11 @@
//-----------------------------------------------------------------------------
// structure internally used by wxRadioBox to store its child buttons
class wxGTKRadioButtonInfo : public wxObject
class wxGTKRadioButtonInfo
{
public:
wxGTKRadioButtonInfo( GtkRadioButton * abutton, const wxRect & arect )
: button( abutton ), rect( arect ) {}
explicit wxGTKRadioButtonInfo( GtkRadioButton * abutton )
: button( abutton ) {}
GtkRadioButton * button;
wxRect rect;
@ -38,9 +38,6 @@ public:
// data
//-----------------------------------------------------------------------------
#include "wx/listimpl.cpp"
WX_DEFINE_LIST( wxRadioBoxButtonsInfoList )
extern bool g_blockEventsOnDrag;
//-----------------------------------------------------------------------------
@ -93,12 +90,15 @@ static gint gtk_radiobox_keypress_callback( GtkWidget *widget, GdkEventKey *gdk_
return FALSE;
}
wxRadioBoxButtonsInfoList::compatibility_iterator node = rb->m_buttonsInfo.GetFirst();
while( node && GTK_WIDGET( node->GetData()->button ) != widget )
const auto begin = rb->m_buttonsInfo.begin();
const auto end = rb->m_buttonsInfo.end();
auto it = begin;
while( it != end && GTK_WIDGET( it->button ) != widget )
{
node = node->GetNext();
++it;
}
if (!node)
if (it == end)
{
return FALSE;
}
@ -106,20 +106,20 @@ static gint gtk_radiobox_keypress_callback( GtkWidget *widget, GdkEventKey *gdk_
if ((gdk_event->keyval == GDK_KEY_Up) ||
(gdk_event->keyval == GDK_KEY_Left))
{
if (node == rb->m_buttonsInfo.GetFirst())
node = rb->m_buttonsInfo.GetLast();
else
node = node->GetPrevious();
if (it == begin)
it = end;
--it;
}
else
{
if (node == rb->m_buttonsInfo.GetLast())
node = rb->m_buttonsInfo.GetFirst();
else
node = node->GetNext();
++it;
if (it == end)
it = begin;
}
GtkWidget *button = (GtkWidget*) node->GetData()->button;
GtkWidget *button = GTK_WIDGET( it->button );
gtk_widget_grab_focus( button );
@ -164,16 +164,14 @@ static void gtk_radiobutton_size_allocate( GtkWidget *widget,
GtkAllocation * alloc,
wxRadioBox *win )
{
for ( wxRadioBoxButtonsInfoList::compatibility_iterator node = win->m_buttonsInfo.GetFirst();
node;
node = node->GetNext())
for ( auto& info : win->m_buttonsInfo )
{
if (widget == GTK_WIDGET(node->GetData()->button))
if (widget == GTK_WIDGET(info.button))
{
const wxPoint origin = win->GetPosition();
wxRect rect = wxRect( alloc->x - origin.x, alloc->y - origin.y,
alloc->width, alloc->height );
node->GetData()->rect = rect;
info.rect = rect;
break;
}
}
@ -198,6 +196,37 @@ static gboolean expose_event(GtkWidget* widget, GdkEventExpose*, wxWindow*)
wxIMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl);
wxRadioBox::wxRadioBox() = default;
wxRadioBox::wxRadioBox(wxWindow *parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
int n,
const wxString choices[],
int majorDim,
long style,
const wxValidator& val,
const wxString& name)
{
Create( parent, id, title, pos, size, n, choices, majorDim, style, val, name );
}
wxRadioBox::wxRadioBox(wxWindow *parent,
wxWindowID id,
const wxString& title,
const wxPoint& pos,
const wxSize& size,
const wxArrayString& choices,
int majorDim,
long style,
const wxValidator& val,
const wxString& name)
{
Create( parent, id, title, pos, size, choices, majorDim, style, val, name );
}
bool wxRadioBox::Create( wxWindow *parent, wxWindowID id,
const wxString& title,
const wxPoint &pos, const wxSize &size,
@ -313,7 +342,7 @@ bool wxRadioBox::Create( wxWindow *parent, wxWindowID id, const wxString& title,
g_signal_connect (rbtn, "key_press_event",
G_CALLBACK (gtk_radiobox_keypress_callback), this);
m_buttonsInfo.Append( new wxGTKRadioButtonInfo( rbtn, wxRect() ) );
m_buttonsInfo.emplace_back(rbtn);
#ifdef __WXGTK3__
int left, top;
@ -373,15 +402,12 @@ bool wxRadioBox::Create( wxWindow *parent, wxWindowID id, const wxString& title,
wxRadioBox::~wxRadioBox()
{
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
GtkWidget *button = GTK_WIDGET( node->GetData()->button );
GtkWidget *button = GTK_WIDGET( info.button );
GTKDisconnect(button);
gtk_widget_destroy( button );
node = node->GetNext();
}
WX_CLEAR_LIST( wxRadioBoxButtonsInfoList, m_buttonsInfo );
}
bool wxRadioBox::Show( bool show )
@ -397,17 +423,14 @@ bool wxRadioBox::Show( bool show )
if ( HasFlag(wxNO_BORDER) )
gtk_widget_hide( m_widget );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
GtkWidget *button = GTK_WIDGET( node->GetData()->button );
GtkWidget *button = GTK_WIDGET( info.button );
if (show)
gtk_widget_show( button );
else
gtk_widget_hide( button );
node = node->GetNext();
}
return true;
@ -417,11 +440,9 @@ void wxRadioBox::SetSelection( int n )
{
wxCHECK_RET( m_widget != nullptr, wxT("invalid radiobox") );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( n );
wxCHECK_RET( n >= 0 && n < (int)m_buttonsInfo.size(), wxT("radiobox wrong index") );
wxCHECK_RET( node, wxT("radiobox wrong index") );
GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->GetData()->button );
GtkToggleButton *button = GTK_TOGGLE_BUTTON( m_buttonsInfo[n].button );
GtkDisableEvents();
@ -436,13 +457,11 @@ int wxRadioBox::GetSelection(void) const
int count = 0;
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
GtkToggleButton *button = GTK_TOGGLE_BUTTON( node->GetData()->button );
GtkToggleButton *button = GTK_TOGGLE_BUTTON( info.button );
if (gtk_toggle_button_get_active(button)) return count;
count++;
node = node->GetNext();
}
wxFAIL_MSG( wxT("wxRadioBox none selected") );
@ -454,11 +473,9 @@ wxString wxRadioBox::GetString(unsigned int n) const
{
wxCHECK_MSG( m_widget != nullptr, wxEmptyString, wxT("invalid radiobox") );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( n );
wxCHECK_MSG( n < m_buttonsInfo.size(), wxEmptyString, wxT("radiobox wrong index") );
wxCHECK_MSG( node, wxEmptyString, wxT("radiobox wrong index") );
GtkLabel* label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(node->GetData()->button)));
GtkLabel* label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(m_buttonsInfo[n].button)));
return wxString::FromUTF8Unchecked( gtk_label_get_text(label) );
}
@ -470,15 +487,13 @@ void wxRadioBox::SetLabel( const wxString& label )
GTKSetLabelForFrame(GTK_FRAME(m_widget), label);
}
void wxRadioBox::SetString(unsigned int item, const wxString& label)
void wxRadioBox::SetString(unsigned int n, const wxString& label)
{
wxCHECK_RET( m_widget != nullptr, wxT("invalid radiobox") );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
wxCHECK_RET( n < m_buttonsInfo.size(), wxT("radiobox wrong index") );
wxCHECK_RET( node, wxT("radiobox wrong index") );
GtkLabel* g_label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(node->GetData()->button)));
GtkLabel* g_label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(m_buttonsInfo[n].button)));
gtk_label_set_text( g_label, label.utf8_str() );
}
@ -498,30 +513,26 @@ void wxRadioBox::DoEnable(bool enable)
wxControl::DoEnable(enable);
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
GtkButton *button = GTK_BUTTON( node->GetData()->button );
GtkButton *button = GTK_BUTTON( info.button );
GtkLabel *label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(button)));
gtk_widget_set_sensitive( GTK_WIDGET(button), enable );
gtk_widget_set_sensitive( GTK_WIDGET(label), enable );
node = node->GetNext();
}
if (enable)
GTKFixSensitivity();
}
bool wxRadioBox::Enable(unsigned int item, bool enable)
bool wxRadioBox::Enable(unsigned int n, bool enable)
{
wxCHECK_MSG( m_widget != nullptr, false, wxT("invalid radiobox") );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
wxCHECK_MSG( n < m_buttonsInfo.size(), false, wxT("radiobox wrong index") );
wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
GtkButton *button = GTK_BUTTON( node->GetData()->button );
GtkButton *button = GTK_BUTTON( m_buttonsInfo[n].button );
GtkLabel *label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(button)));
gtk_widget_set_sensitive( GTK_WIDGET(button), enable );
@ -530,30 +541,26 @@ bool wxRadioBox::Enable(unsigned int item, bool enable)
return true;
}
bool wxRadioBox::IsItemEnabled(unsigned int item) const
bool wxRadioBox::IsItemEnabled(unsigned int n) const
{
wxCHECK_MSG( m_widget != nullptr, false, wxT("invalid radiobox") );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
wxCHECK_MSG( n < m_buttonsInfo.size(), false, wxT("radiobox wrong index") );
wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
GtkButton *button = GTK_BUTTON( node->GetData()->button );
GtkButton *button = GTK_BUTTON( m_buttonsInfo[n].button );
// don't use GTK_WIDGET_IS_SENSITIVE() here, we want to return true even if
// the parent radiobox is disabled
return gtk_widget_get_sensitive(GTK_WIDGET(button)) != 0;
}
bool wxRadioBox::Show(unsigned int item, bool show)
bool wxRadioBox::Show(unsigned int n, bool show)
{
wxCHECK_MSG( m_widget != nullptr, false, wxT("invalid radiobox") );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
wxCHECK_MSG( n < m_buttonsInfo.size(), false, wxT("radiobox wrong index") );
wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
GtkWidget *button = GTK_WIDGET( node->GetData()->button );
GtkWidget *button = GTK_WIDGET( m_buttonsInfo[n].button );
if (show)
gtk_widget_show( button );
@ -563,45 +570,37 @@ bool wxRadioBox::Show(unsigned int item, bool show)
return true;
}
bool wxRadioBox::IsItemShown(unsigned int item) const
bool wxRadioBox::IsItemShown(unsigned int n) const
{
wxCHECK_MSG( m_widget != nullptr, false, wxT("invalid radiobox") );
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.Item( item );
wxCHECK_MSG( n < m_buttonsInfo.size(), false, wxT("radiobox wrong index") );
wxCHECK_MSG( node, false, wxT("radiobox wrong index") );
GtkButton *button = GTK_BUTTON( node->GetData()->button );
GtkButton *button = GTK_BUTTON( m_buttonsInfo[n].button );
return gtk_widget_get_visible(GTK_WIDGET(button)) != 0;
}
unsigned int wxRadioBox::GetCount() const
{
return m_buttonsInfo.GetCount();
return m_buttonsInfo.size();
}
void wxRadioBox::GtkDisableEvents()
{
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
g_signal_handlers_block_by_func(node->GetData()->button,
g_signal_handlers_block_by_func(info.button,
(gpointer)gtk_radiobutton_clicked_callback, this);
node = node->GetNext();
}
}
void wxRadioBox::GtkEnableEvents()
{
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
g_signal_handlers_unblock_by_func(node->GetData()->button,
g_signal_handlers_unblock_by_func(info.button,
(gpointer)gtk_radiobutton_clicked_callback, this);
node = node->GetNext();
}
}
@ -609,15 +608,12 @@ void wxRadioBox::DoApplyWidgetStyle(GtkRcStyle *style)
{
GTKFrameApplyWidgetStyle(GTK_FRAME(m_widget), style);
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
GtkWidget *widget = GTK_WIDGET( node->GetData()->button );
GtkWidget *widget = GTK_WIDGET( info.button );
GTKApplyStyle(widget, style);
GTKApplyStyle(gtk_bin_get_child(GTK_BIN(widget)), style);
node = node->GetNext();
}
#ifndef __WXGTK3__
@ -642,13 +638,11 @@ void wxRadioBox::GTKApplyToolTip(const char* tip)
{
// set this tooltip for all radiobuttons which don't have their own tips
unsigned n = 0;
for ( wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
node;
node = node->GetNext(), n++ )
for ( const auto& info : m_buttonsInfo )
{
if ( !GetItemToolTip(n) )
if ( !GetItemToolTip(n++) )
{
wxToolTip::GTKApply(GTK_WIDGET(node->GetData()->button), tip);
wxToolTip::GTKApply(GTK_WIDGET(info.button), tip);
}
}
}
@ -661,7 +655,7 @@ void wxRadioBox::DoSetItemToolTip(unsigned int n, wxToolTip *tooltip)
if ( tooltip )
buf = tooltip->GetTip().utf8_str();
wxToolTip::GTKApply(GTK_WIDGET(m_buttonsInfo[n]->button), buf);
wxToolTip::GTKApply(GTK_WIDGET(m_buttonsInfo[n].button), buf);
}
#endif // wxUSE_TOOLTIPS
@ -670,16 +664,13 @@ GdkWindow *wxRadioBox::GTKGetWindow(wxArrayGdkWindows& windows) const
{
windows.push_back(gtk_widget_get_window(m_widget));
wxRadioBoxButtonsInfoList::compatibility_iterator node = m_buttonsInfo.GetFirst();
while (node)
for ( const auto& info : m_buttonsInfo )
{
GtkWidget *button = GTK_WIDGET( node->GetData()->button );
GtkWidget *button = GTK_WIDGET( info.button );
// don't put null pointers in the 'windows' array!
if (gtk_widget_get_window(button))
windows.push_back(gtk_widget_get_window(button));
node = node->GetNext();
}
return nullptr;
@ -696,11 +687,12 @@ int wxRadioBox::GetItemFromPoint(const wxPoint& point) const
{
const wxPoint pt = ScreenToClient(point);
unsigned n = 0;
for ( wxRadioBoxButtonsInfoList::compatibility_iterator
node = m_buttonsInfo.GetFirst(); node; node = node->GetNext(), n++ )
for ( const auto& info : m_buttonsInfo )
{
if ( m_buttonsInfo[n]->rect.Contains(pt) )
if ( info.rect.Contains(pt) )
return n;
++n;
}
return wxNOT_FOUND;