Add RAII wrapper for GTKDisableEvents/GTKEnableEvents() calls
Ensure GTKEnableEvents() is called automatically on scope exit whenever GTKDisableEvents() is called. This fixes a couple of potential bugs where GTKEnableEvents() could be not called if wxCHECK() condition failed and makes the code shorter and safer.
This commit is contained in:
41
include/wx/gtk/private/eventsdisabler.h
Normal file
41
include/wx/gtk/private/eventsdisabler.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Name: wx/gtk/private/eventsdisabler.h
|
||||||
|
// Purpose: Helper for temporarily disabling events.
|
||||||
|
// Author: Vadim Zeitlin
|
||||||
|
// Created: 2016-02-06
|
||||||
|
// Copyright: (c) 2016 Vadim Zeitlin <vadim@wxwidgets.org>
|
||||||
|
// Licence: wxWindows licence
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef _GTK_PRIVATE_EVENTSDISABLER_H_
|
||||||
|
#define _GTK_PRIVATE_EVENTSDISABLER_H_
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxGtkEventsDisabler: calls GTKDisableEvents() and GTKEnableEvents() in dtor.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Template parameter T must be a wxGTK class providing the required methods,
|
||||||
|
// e.g. wxCheckBox, wxChoice, ...
|
||||||
|
template <typename T>
|
||||||
|
class wxGtkEventsDisabler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Disable the events for the specified (non-NULL, having lifetime greater
|
||||||
|
// than ours) window for the lifetime of this object.
|
||||||
|
explicit wxGtkEventsDisabler(T* win) : m_win(win)
|
||||||
|
{
|
||||||
|
m_win->GTKDisableEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
~wxGtkEventsDisabler()
|
||||||
|
{
|
||||||
|
m_win->GTKEnableEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* const m_win;
|
||||||
|
|
||||||
|
wxDECLARE_NO_COPY_TEMPLATE_CLASS(wxGtkEventsDisabler, T);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _GTK_PRIVATE_EVENTSDISABLER_H_
|
@@ -54,10 +54,10 @@ public:
|
|||||||
static wxVisualAttributes
|
static wxVisualAttributes
|
||||||
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
|
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
|
||||||
|
|
||||||
protected:
|
|
||||||
void GTKDisableEvents();
|
void GTKDisableEvents();
|
||||||
void GTKEnableEvents();
|
void GTKEnableEvents();
|
||||||
|
|
||||||
|
protected:
|
||||||
virtual wxSize DoGetBestSize() const wxOVERRIDE;
|
virtual wxSize DoGetBestSize() const wxOVERRIDE;
|
||||||
virtual void DoApplyWidgetStyle(GtkRcStyle *style) wxOVERRIDE;
|
virtual void DoApplyWidgetStyle(GtkRcStyle *style) wxOVERRIDE;
|
||||||
|
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include "wx/gtk/private/gtk2-compat.h"
|
#include "wx/gtk/private/gtk2-compat.h"
|
||||||
|
#include "wx/gtk/private/eventsdisabler.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// data
|
// data
|
||||||
@@ -45,7 +46,7 @@ static void gtk_checkbox_toggled_callback(GtkWidget *widget, wxCheckBox *cb)
|
|||||||
bool active = gtk_toggle_button_get_active(toggle) != 0;
|
bool active = gtk_toggle_button_get_active(toggle) != 0;
|
||||||
bool inconsistent = gtk_toggle_button_get_inconsistent(toggle) != 0;
|
bool inconsistent = gtk_toggle_button_get_inconsistent(toggle) != 0;
|
||||||
|
|
||||||
cb->GTKDisableEvents();
|
wxGtkEventsDisabler<wxCheckBox> noEvents(cb);
|
||||||
|
|
||||||
if (!active && !inconsistent)
|
if (!active && !inconsistent)
|
||||||
{
|
{
|
||||||
@@ -67,8 +68,6 @@ static void gtk_checkbox_toggled_callback(GtkWidget *widget, wxCheckBox *cb)
|
|||||||
{
|
{
|
||||||
wxFAIL_MSG(wxT("3state wxCheckBox in unexpected state!"));
|
wxFAIL_MSG(wxT("3state wxCheckBox in unexpected state!"));
|
||||||
}
|
}
|
||||||
|
|
||||||
cb->GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -171,11 +170,8 @@ void wxCheckBox::SetValue( bool state )
|
|||||||
if (state == GetValue())
|
if (state == GetValue())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxCheckBox> noEvents(this);
|
||||||
|
|
||||||
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_widgetCheckbox), state );
|
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_widgetCheckbox), state );
|
||||||
|
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxCheckBox::GetValue() const
|
bool wxCheckBox::GetValue() const
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include "wx/gtk/private.h"
|
#include "wx/gtk/private.h"
|
||||||
#include "wx/gtk/private/gtk2-compat.h"
|
#include "wx/gtk/private/gtk2-compat.h"
|
||||||
|
#include "wx/gtk/private/eventsdisabler.h"
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// GTK callbacks
|
// GTK callbacks
|
||||||
@@ -155,7 +156,7 @@ void wxChoice::DoClear()
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( m_widget != NULL, wxT("invalid control") );
|
wxCHECK_RET( m_widget != NULL, wxT("invalid control") );
|
||||||
|
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxChoice> noEvents(this);
|
||||||
|
|
||||||
GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
|
GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
|
||||||
GtkTreeModel* model = gtk_combo_box_get_model( combobox );
|
GtkTreeModel* model = gtk_combo_box_get_model( combobox );
|
||||||
@@ -166,8 +167,6 @@ void wxChoice::DoClear()
|
|||||||
if (m_strings)
|
if (m_strings)
|
||||||
m_strings->Clear();
|
m_strings->Clear();
|
||||||
|
|
||||||
GTKEnableEvents();
|
|
||||||
|
|
||||||
InvalidateBestSize();
|
InvalidateBestSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,12 +289,10 @@ void wxChoice::SetSelection( int n )
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( m_widget != NULL, wxT("invalid control") );
|
wxCHECK_RET( m_widget != NULL, wxT("invalid control") );
|
||||||
|
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxChoice> noEvents(this);
|
||||||
|
|
||||||
GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
|
GtkComboBox* combobox = GTK_COMBO_BOX( m_widget );
|
||||||
gtk_combo_box_set_active( combobox, n );
|
gtk_combo_box_set_active( combobox, n );
|
||||||
|
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxChoice::SetColumns(int n)
|
void wxChoice::SetColumns(int n)
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include "wx/gtk/private.h"
|
#include "wx/gtk/private.h"
|
||||||
|
#include "wx/gtk/private/eventsdisabler.h"
|
||||||
#include "wx/gtk/private/gtk2-compat.h"
|
#include "wx/gtk/private/gtk2-compat.h"
|
||||||
#include "wx/gtk/private/object.h"
|
#include "wx/gtk/private/object.h"
|
||||||
#include "wx/gtk/private/treeentry_gtk.h"
|
#include "wx/gtk/private/treeentry_gtk.h"
|
||||||
@@ -479,13 +480,13 @@ void wxListBox::DoClear()
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( m_treeview != NULL, wxT("invalid listbox") );
|
wxCHECK_RET( m_treeview != NULL, wxT("invalid listbox") );
|
||||||
|
|
||||||
GTKDisableEvents(); // just in case
|
{
|
||||||
|
wxGtkEventsDisabler<wxListBox> noEvents(this);
|
||||||
|
|
||||||
InvalidateBestSize();
|
InvalidateBestSize();
|
||||||
|
|
||||||
gtk_list_store_clear( m_liststore ); /* well, THAT was easy :) */
|
gtk_list_store_clear( m_liststore ); /* well, THAT was easy :) */
|
||||||
|
}
|
||||||
GTKEnableEvents();
|
|
||||||
|
|
||||||
UpdateOldSelections();
|
UpdateOldSelections();
|
||||||
}
|
}
|
||||||
@@ -496,7 +497,7 @@ void wxListBox::DoDeleteOneItem(unsigned int n)
|
|||||||
|
|
||||||
InvalidateBestSize();
|
InvalidateBestSize();
|
||||||
|
|
||||||
GTKDisableEvents(); // just in case
|
wxGtkEventsDisabler<wxListBox> noEvents(this);
|
||||||
|
|
||||||
GtkTreeIter iter;
|
GtkTreeIter iter;
|
||||||
wxCHECK_RET( GTKGetIteratorFor(n, &iter), wxT("wrong listbox index") );
|
wxCHECK_RET( GTKGetIteratorFor(n, &iter), wxT("wrong listbox index") );
|
||||||
@@ -504,8 +505,6 @@ void wxListBox::DoDeleteOneItem(unsigned int n)
|
|||||||
// this returns false if iter is invalid (e.g. deleting item at end) but
|
// this returns false if iter is invalid (e.g. deleting item at end) but
|
||||||
// since we don't use iter, we ignore the return value
|
// since we don't use iter, we ignore the return value
|
||||||
gtk_list_store_remove(m_liststore, &iter);
|
gtk_list_store_remove(m_liststore, &iter);
|
||||||
|
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -701,7 +700,7 @@ void wxListBox::DoSetSelection( int n, bool select )
|
|||||||
{
|
{
|
||||||
wxCHECK_RET( m_treeview != NULL, wxT("invalid listbox") );
|
wxCHECK_RET( m_treeview != NULL, wxT("invalid listbox") );
|
||||||
|
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxListBox> noEvents(this);
|
||||||
|
|
||||||
GtkTreeSelection* selection = gtk_tree_view_get_selection(m_treeview);
|
GtkTreeSelection* selection = gtk_tree_view_get_selection(m_treeview);
|
||||||
|
|
||||||
@@ -709,7 +708,6 @@ void wxListBox::DoSetSelection( int n, bool select )
|
|||||||
if ( n == wxNOT_FOUND )
|
if ( n == wxNOT_FOUND )
|
||||||
{
|
{
|
||||||
gtk_tree_selection_unselect_all(selection);
|
gtk_tree_selection_unselect_all(selection);
|
||||||
GTKEnableEvents();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,8 +726,6 @@ void wxListBox::DoSetSelection( int n, bool select )
|
|||||||
gtk_tree_model_get_path(GTK_TREE_MODEL(m_liststore), &iter));
|
gtk_tree_model_get_path(GTK_TREE_MODEL(m_liststore), &iter));
|
||||||
|
|
||||||
gtk_tree_view_scroll_to_cell(m_treeview, path, NULL, FALSE, 0.0f, 0.0f);
|
gtk_tree_view_scroll_to_cell(m_treeview, path, NULL, FALSE, 0.0f, 0.0f);
|
||||||
|
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxListBox::DoScrollToCell(int n, float alignY, float alignX)
|
void wxListBox::DoScrollToCell(int n, float alignY, float alignX)
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include "wx/gtk/private/gtk2-compat.h"
|
#include "wx/gtk/private/gtk2-compat.h"
|
||||||
|
#include "wx/gtk/private/eventsdisabler.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// data
|
// data
|
||||||
@@ -231,9 +232,8 @@ gtk_event_after(GtkRange* range, GdkEvent* event, wxSlider* win)
|
|||||||
ProcessScrollEvent(win, wxEVT_SCROLL_THUMBRELEASE);
|
ProcessScrollEvent(win, wxEVT_SCROLL_THUMBRELEASE);
|
||||||
}
|
}
|
||||||
// Keep slider at an integral position
|
// Keep slider at an integral position
|
||||||
win->GTKDisableEvents();
|
wxGtkEventsDisabler<wxSlider> noEvents(win);
|
||||||
gtk_range_set_value(GTK_RANGE (win->m_scale), win->GetValue());
|
gtk_range_set_value(GTK_RANGE (win->m_scale), win->GetValue());
|
||||||
win->GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,21 +422,20 @@ void wxSlider::SetValue( int value )
|
|||||||
|
|
||||||
void wxSlider::GTKSetValue(int value)
|
void wxSlider::GTKSetValue(int value)
|
||||||
{
|
{
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxSlider> noEvents(this);
|
||||||
|
|
||||||
gtk_range_set_value(GTK_RANGE (m_scale), value);
|
gtk_range_set_value(GTK_RANGE (m_scale), value);
|
||||||
// GTK only updates value label if handle moves at least 1 pixel
|
// GTK only updates value label if handle moves at least 1 pixel
|
||||||
gtk_widget_queue_draw(m_scale);
|
gtk_widget_queue_draw(m_scale);
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxSlider::SetRange( int minValue, int maxValue )
|
void wxSlider::SetRange( int minValue, int maxValue )
|
||||||
{
|
{
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxSlider> noEvents(this);
|
||||||
if (minValue == maxValue)
|
if (minValue == maxValue)
|
||||||
maxValue++;
|
maxValue++;
|
||||||
gtk_range_set_range(GTK_RANGE (m_scale), minValue, maxValue);
|
gtk_range_set_range(GTK_RANGE (m_scale), minValue, maxValue);
|
||||||
gtk_range_set_increments(GTK_RANGE (m_scale), 1, (maxValue - minValue + 9) / 10);
|
gtk_range_set_increments(GTK_RANGE (m_scale), 1, (maxValue - minValue + 9) / 10);
|
||||||
GTKEnableEvents();
|
|
||||||
|
|
||||||
if (HasFlag(wxSL_MIN_MAX_LABELS))
|
if (HasFlag(wxSL_MIN_MAX_LABELS))
|
||||||
{
|
{
|
||||||
@@ -471,9 +470,8 @@ int wxSlider::GetMax() const
|
|||||||
|
|
||||||
void wxSlider::SetPageSize( int pageSize )
|
void wxSlider::SetPageSize( int pageSize )
|
||||||
{
|
{
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxSlider> noEvents(this);
|
||||||
gtk_range_set_increments(GTK_RANGE (m_scale), GetLineSize(), pageSize);
|
gtk_range_set_increments(GTK_RANGE (m_scale), GetLineSize(), pageSize);
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxSlider::GetPageSize() const
|
int wxSlider::GetPageSize() const
|
||||||
@@ -494,9 +492,8 @@ int wxSlider::GetThumbLength() const
|
|||||||
|
|
||||||
void wxSlider::SetLineSize( int lineSize )
|
void wxSlider::SetLineSize( int lineSize )
|
||||||
{
|
{
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxSlider> noEvents(this);
|
||||||
gtk_range_set_increments(GTK_RANGE (m_scale), lineSize, GetPageSize());
|
gtk_range_set_increments(GTK_RANGE (m_scale), lineSize, GetPageSize());
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int wxSlider::GetLineSize() const
|
int wxSlider::GetLineSize() const
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
#include "wx/gtk/private.h"
|
#include "wx/gtk/private.h"
|
||||||
|
#include "wx/gtk/private/eventsdisabler.h"
|
||||||
#include "wx/gtk/private/list.h"
|
#include "wx/gtk/private/list.h"
|
||||||
|
|
||||||
extern bool g_blockEventsOnDrag;
|
extern bool g_blockEventsOnDrag;
|
||||||
@@ -145,11 +146,9 @@ void wxToggleButton::SetValue(bool state)
|
|||||||
if (state == GetValue())
|
if (state == GetValue())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GTKDisableEvents();
|
wxGtkEventsDisabler<wxToggleButton> noEvents(this);
|
||||||
|
|
||||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget), state);
|
||||||
|
|
||||||
GTKEnableEvents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool GetValue() const
|
// bool GetValue() const
|
||||||
|
Reference in New Issue
Block a user