1 #include "Toggle.h"
2 
Toggle(const Callback & callback)3 Toggle::Toggle(const Callback& callback) :
4 	_callback(callback),
5 	_callbackActive(false),
6 	_toggled(false)
7 {}
8 
isToggle() const9 bool Toggle::isToggle() const {
10 	return true;
11 }
12 
13 // Set the toggled state to true/false, according to <toggled> and update
14 // any associated widgets or notify any callbacks.
setToggled(const bool toggled)15 bool Toggle::setToggled(const bool toggled) {
16 	if (_callbackActive) {
17 		return false;
18 	}
19 
20 	// Update the toggle status and export it to the GTK button
21 	_toggled = toggled;
22 	updateWidgets();
23 
24 	return true;
25 }
26 
updateWidgets()27 void Toggle::updateWidgets() {
28 	_callbackActive = true;
29 
30 	for (ToggleWidgetList::iterator i = _toggleWidgets.begin();
31 		 i != _toggleWidgets.end();
32 		 ++i)
33 	{
34 		GtkWidget* widget = *i;
35 		if (GTK_IS_TOGGLE_TOOL_BUTTON(widget)) {
36 			gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), _toggled);
37 		}
38 		else if (GTK_IS_CHECK_MENU_ITEM(widget)) {
39 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), _toggled);
40 		}
41 	}
42 
43 	_callbackActive = false;
44 }
45 
46 // On key press >> toggle the internal state
keyDown()47 void Toggle::keyDown() {
48 	toggle();
49 }
50 
isToggled() const51 bool Toggle::isToggled() const {
52 	return _toggled;
53 }
54 
connectWidget(GtkWidget * widget)55 void Toggle::connectWidget(GtkWidget* widget) {
56 	if (GTK_IS_TOGGLE_TOOL_BUTTON(widget)) {
57 		_toggleWidgets.push_back(widget);
58 
59 		gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(widget), _toggled);
60 
61 		// Connect the toggleToolbutton to the static callback of this class
62 		g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(onToggleToolButtonClicked), this);
63 	}
64 	else if (GTK_IS_TOGGLE_BUTTON(widget)) {
65 		// Store the pointer for later use
66 		_toggleWidgets.push_back(widget);
67 
68 		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), _toggled);
69 
70 		g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(onToggleToolButtonClicked), this);
71 	}
72 	else if (GTK_IS_CHECK_MENU_ITEM(widget)) {
73 		// Store it internally
74 		_toggleWidgets.push_back(widget);
75 
76 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(widget), _toggled);
77 
78 		g_signal_connect(G_OBJECT(widget), "toggled", G_CALLBACK(onCheckMenuItemClicked), this);
79 	}
80 }
81 
82 // Invoke the registered callback and update/notify
toggle()83 void Toggle::toggle() {
84 	if (_callbackActive) {
85 		return;
86 	}
87 
88 	// Check if the toggle event is enabled
89 	if (_enabled) {
90 		// Invert the <toggled> state
91 		_toggled = !_toggled;
92 
93 		// Call the connected function
94 		_callback();
95 	}
96 
97 	// Update any attached GtkObjects in any case
98 	updateWidgets();
99 }
100 
101 // The static GTK callback methods that can be connected to a ToolButton or a MenuItem
onToggleToolButtonClicked(GtkToggleToolButton * toolButton,gpointer data)102 gboolean Toggle::onToggleToolButtonClicked(GtkToggleToolButton* toolButton, gpointer data) {
103 
104 	// Cast the passed pointer onto a Toggle class. Note: this may also call a toggle() method
105 	// of a derived class.
106 	Toggle* self = reinterpret_cast<Toggle*>(data);
107 
108 	// Check sanity and toggle this item
109 	if (self != NULL) {
110 		self->toggle();
111 	}
112 
113 	return true;
114 }
115 
onToggleButtonClicked(GtkToggleButton * toggleButton,gpointer data)116 gboolean Toggle::onToggleButtonClicked(GtkToggleButton* toggleButton, gpointer data) {
117 	// Cast the passed pointer onto a Toggle class. Note: this may also call a toggle() method
118 	// of a derived class.
119 	Toggle* self = reinterpret_cast<Toggle*>(data);
120 
121 	// Check sanity and toggle this item
122 	if (self != NULL) {
123 		self->toggle();
124 	}
125 
126 	return true;
127 }
128 
onCheckMenuItemClicked(GtkMenuItem * menuitem,gpointer data)129 gboolean Toggle::onCheckMenuItemClicked(GtkMenuItem* menuitem, gpointer data) {
130 	Toggle* self = reinterpret_cast<Toggle*>(data);
131 
132 	// Check sanity and toggle this item
133 	if (self != NULL) {
134 		self->toggle();
135 	}
136 
137 	return true;
138 }
139