1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gtk.RadioButton;
26 
27 private import glib.ConstructionException;
28 private import glib.ListSG;
29 private import glib.Str;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 private import gtk.CheckButton;
33 private import gtk.Widget;
34 public  import gtkc.gdktypes;
35 private import gtkc.gtk;
36 public  import gtkc.gtktypes;
37 private import std.algorithm;
38 
39 
40 /**
41  * A single radio button performs the same basic function as a #GtkCheckButton,
42  * as its position in the object hierarchy reflects. It is only when multiple
43  * radio buttons are grouped together that they become a different user
44  * interface component in their own right.
45  * 
46  * Every radio button is a member of some group of radio buttons. When one is
47  * selected, all other radio buttons in the same group are deselected. A
48  * #GtkRadioButton is one way of giving the user a choice from many options.
49  * 
50  * Radio button widgets are created with gtk_radio_button_new(), passing %NULL
51  * as the argument if this is the first radio button in a group. In subsequent
52  * calls, the group you wish to add this button to should be passed as an
53  * argument. Optionally, gtk_radio_button_new_with_label() can be used if you
54  * want a text label on the radio button.
55  * 
56  * Alternatively, when adding widgets to an existing group of radio buttons,
57  * use gtk_radio_button_new_from_widget() with a #GtkRadioButton that already
58  * has a group assigned to it. The convenience function
59  * gtk_radio_button_new_with_label_from_widget() is also provided.
60  * 
61  * To retrieve the group a #GtkRadioButton is assigned to, use
62  * gtk_radio_button_get_group().
63  * 
64  * To remove a #GtkRadioButton from one group and make it part of a new one,
65  * use gtk_radio_button_set_group().
66  * 
67  * The group list does not need to be freed, as each #GtkRadioButton will remove
68  * itself and its list item when it is destroyed.
69  * 
70  * # CSS nodes
71  * 
72  * |[<!-- language="plain" -->
73  * radiobutton
74  * ├── radio
75  * ╰── <child>
76  * ]|
77  * 
78  * A GtkRadioButton with indicator (see gtk_toggle_button_set_mode()) has a
79  * main CSS node with name radiobutton and a subnode with name radio.
80  * 
81  * |[<!-- language="plain" -->
82  * button.radio
83  * ├── radio
84  * ╰── <child>
85  * ]|
86  * 
87  * A GtkRadioButton without indicator changes the name of its main node
88  * to button and adds a .radio style class to it. The subnode is invisible
89  * in this case.
90  * 
91  * ## How to create a group of two radio buttons.
92  * 
93  * |[<!-- language="C" -->
94  * void create_radio_buttons (void) {
95  * 
96  * GtkWidget *window, *radio1, *radio2, *box, *entry;
97  * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
98  * box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
99  * gtk_box_set_homogeneous (GTK_BOX (box), TRUE);
100  * 
101  * // Create a radio button with a GtkEntry widget
102  * radio1 = gtk_radio_button_new (NULL);
103  * entry = gtk_entry_new ();
104  * gtk_container_add (GTK_CONTAINER (radio1), entry);
105  * 
106  * 
107  * // Create a radio button with a label
108  * radio2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio1),
109  * "I’m the second radio button.");
110  * 
111  * // Pack them into a box, then show all the widgets
112  * gtk_box_pack_start (GTK_BOX (box), radio1, TRUE, TRUE, 2);
113  * gtk_box_pack_start (GTK_BOX (box), radio2, TRUE, TRUE, 2);
114  * gtk_container_add (GTK_CONTAINER (window), box);
115  * gtk_widget_show_all (window);
116  * return;
117  * }
118  * ]|
119  * 
120  * When an unselected button in the group is clicked the clicked button
121  * receives the #GtkToggleButton::toggled signal, as does the previously
122  * selected button.
123  * Inside the #GtkToggleButton::toggled handler, gtk_toggle_button_get_active()
124  * can be used to determine if the button has been selected or deselected.
125  */
126 public class RadioButton : CheckButton
127 {
128 	/** the main Gtk struct */
129 	protected GtkRadioButton* gtkRadioButton;
130 
131 	/** Get the main Gtk struct */
132 	public GtkRadioButton* getRadioButtonStruct()
133 	{
134 		return gtkRadioButton;
135 	}
136 
137 	/** the main Gtk struct as a void* */
138 	protected override void* getStruct()
139 	{
140 		return cast(void*)gtkRadioButton;
141 	}
142 
143 	protected override void setStruct(GObject* obj)
144 	{
145 		gtkRadioButton = cast(GtkRadioButton*)obj;
146 		super.setStruct(obj);
147 	}
148 
149 	/**
150 	 * Sets our main struct and passes it to the parent class.
151 	 */
152 	public this (GtkRadioButton* gtkRadioButton, bool ownedRef = false)
153 	{
154 		this.gtkRadioButton = gtkRadioButton;
155 		super(cast(GtkCheckButton*)gtkRadioButton, ownedRef);
156 	}
157 
158 	/**
159 	 * Creates a new RadioButton with a text label.
160 	 * Params:
161 	 *  group = an existing radio button group.
162 	 *  label = the text label to display next to the radio button.
163 	 *  mnemonic = if true the label will be created using
164 	 *  gtk_label_new_with_mnemonic(), so underscores in label indicate the
165 	 *  mnemonic for the button.
166 	 * Throws: ConstructionException GTK+ fails to create the object.
167 	 */
168 	public this (ListSG group, string label, bool mnemonic=true)
169 	{
170 		GtkRadioButton* p;
171 		
172 		if ( mnemonic )
173 		{
174 			// GtkWidget* gtk_radio_button_new_with_mnemonic  (GSList *group,  const gchar *label);
175 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_mnemonic(
176 				group is null ? null : group.getListSGStruct(),
177 			Str.toStringz(label));
178 		}
179 		else
180 		{
181 			// GtkWidget* gtk_radio_button_new_with_label (GSList *group,  const gchar *label);
182 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_label(
183 				group is null ? null : group.getListSGStruct(),
184 			Str.toStringz(label));
185 		}
186 		
187 		if(p is null)
188 		{
189 			throw new ConstructionException("null returned by gtk_radio_button_new_");
190 		}
191 		
192 		this(p);
193 	}
194 	
195 	/**
196 	 * Creates a new RadioButton with a text label, adding it to the same group
197 	 * as group.
198 	 * Params:
199 	 *  radioButton = an existing RadioButton.
200 	 *  label = a text string to display next to the radio button.
201 	 *  mnemonic = if true the label
202 	 *  will be created using gtk_label_new_with_mnemonic(), so underscores
203 	 *  in label indicate the mnemonic for the button.
204 	 * Throws: ConstructionException GTK+ fails to create the object.
205 	 */
206 	public this (RadioButton radioButton, string label, bool mnemonic=true)
207 	{
208 		GtkRadioButton* p;
209 		
210 		if ( mnemonic )
211 		{
212 			// GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget  (GtkRadioButton *group,  const gchar *label);
213 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_mnemonic_from_widget(
214 				radioButton.getRadioButtonStruct(),
215 			Str.toStringz(label));
216 		}
217 		else
218 		{
219 			// GtkWidget* gtk_radio_button_new_with_label_from_widget  (GtkRadioButton *group,  const gchar *label);
220 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_label_from_widget(
221 				radioButton.getRadioButtonStruct(),
222 			Str.toStringz(label));
223 		}
224 		
225 		if(p is null)
226 		{
227 			throw new ConstructionException("null returned by gtk_radio_button_new_");
228 		}
229 		
230 		this(p);
231 	}
232 	
233 	/**
234 	 * Creates a new RadioButton with a text label,
235 	 * and creates a new group.
236 	 * Params:
237 	 *  label = a text string to display next to the radio button.
238 	 *  mnemonic = if true the label
239 	 *  will be created using gtk_label_new_with_mnemonic(), so underscores
240 	 *  in label indicate the mnemonic for the button.
241 	 * Throws: ConstructionException GTK+ fails to create the object.
242 	 */
243 	public this (string label, bool mnemonic=true)
244 	{
245 		this(cast(ListSG)null, label, mnemonic);
246 	}
247 
248 	/**
249 	 */
250 
251 	/** */
252 	public static GType getType()
253 	{
254 		return gtk_radio_button_get_type();
255 	}
256 
257 	/**
258 	 * Creates a new #GtkRadioButton. To be of any practical value, a widget should
259 	 * then be packed into the radio button.
260 	 *
261 	 * Params:
262 	 *     group = an existing
263 	 *         radio button group, or %NULL if you are creating a new group.
264 	 *
265 	 * Return: a new radio button
266 	 *
267 	 * Throws: ConstructionException GTK+ fails to create the object.
268 	 */
269 	public this(ListSG group)
270 	{
271 		auto p = gtk_radio_button_new((group is null) ? null : group.getListSGStruct());
272 		
273 		if(p is null)
274 		{
275 			throw new ConstructionException("null returned by new");
276 		}
277 		
278 		this(cast(GtkRadioButton*) p);
279 	}
280 
281 	/**
282 	 * Creates a new #GtkRadioButton, adding it to the same group as
283 	 * @radio_group_member. As with gtk_radio_button_new(), a widget
284 	 * should be packed into the radio button.
285 	 *
286 	 * Params:
287 	 *     radioGroupMember = an existing #GtkRadioButton.
288 	 *
289 	 * Return: a new radio button.
290 	 *
291 	 * Throws: ConstructionException GTK+ fails to create the object.
292 	 */
293 	public this(RadioButton radioGroupMember)
294 	{
295 		auto p = gtk_radio_button_new_from_widget((radioGroupMember is null) ? null : radioGroupMember.getRadioButtonStruct());
296 		
297 		if(p is null)
298 		{
299 			throw new ConstructionException("null returned by new_from_widget");
300 		}
301 		
302 		this(cast(GtkRadioButton*) p);
303 	}
304 
305 	/**
306 	 * Retrieves the group assigned to a radio button.
307 	 *
308 	 * Return: a linked list
309 	 *     containing all the radio buttons in the same group
310 	 *     as @radio_button. The returned list is owned by the radio button
311 	 *     and must not be modified or freed.
312 	 */
313 	public ListSG getGroup()
314 	{
315 		auto p = gtk_radio_button_get_group(gtkRadioButton);
316 		
317 		if(p is null)
318 		{
319 			return null;
320 		}
321 		
322 		return new ListSG(cast(GSList*) p);
323 	}
324 
325 	/**
326 	 * Joins a #GtkRadioButton object to the group of another #GtkRadioButton object
327 	 *
328 	 * Use this in language bindings instead of the gtk_radio_button_get_group()
329 	 * and gtk_radio_button_set_group() methods
330 	 *
331 	 * A common way to set up a group of radio buttons is the following:
332 	 * |[<!-- language="C" -->
333 	 * GtkRadioButton *radio_button;
334 	 * GtkRadioButton *last_button;
335 	 *
336 	 * while ( ...more buttons to add... )
337 	 * {
338 	 * radio_button = gtk_radio_button_new (...);
339 	 *
340 	 * gtk_radio_button_join_group (radio_button, last_button);
341 	 * last_button = radio_button;
342 	 * }
343 	 * ]|
344 	 *
345 	 * Params:
346 	 *     groupSource = a radio button object whos group we are
347 	 *         joining, or %NULL to remove the radio button from its group
348 	 *
349 	 * Since: 3.0
350 	 */
351 	public void joinGroup(RadioButton groupSource)
352 	{
353 		gtk_radio_button_join_group(gtkRadioButton, (groupSource is null) ? null : groupSource.getRadioButtonStruct());
354 	}
355 
356 	/**
357 	 * Sets a #GtkRadioButton’s group. It should be noted that this does not change
358 	 * the layout of your interface in any way, so if you are changing the group,
359 	 * it is likely you will need to re-arrange the user interface to reflect these
360 	 * changes.
361 	 *
362 	 * Params:
363 	 *     group = an existing radio
364 	 *         button group, such as one returned from gtk_radio_button_get_group(), or %NULL.
365 	 */
366 	public void setGroup(ListSG group)
367 	{
368 		gtk_radio_button_set_group(gtkRadioButton, (group is null) ? null : group.getListSGStruct());
369 	}
370 
371 	protected class OnGroupChangedDelegateWrapper
372 	{
373 		void delegate(RadioButton) dlg;
374 		gulong handlerId;
375 		ConnectFlags flags;
376 		this(void delegate(RadioButton) dlg, gulong handlerId, ConnectFlags flags)
377 		{
378 			this.dlg = dlg;
379 			this.handlerId = handlerId;
380 			this.flags = flags;
381 		}
382 	}
383 	protected OnGroupChangedDelegateWrapper[] onGroupChangedListeners;
384 
385 	/**
386 	 * Emitted when the group of radio buttons that a radio button belongs
387 	 * to changes. This is emitted when a radio button switches from
388 	 * being alone to being part of a group of 2 or more buttons, or
389 	 * vice-versa, and when a button is moved from one group of 2 or
390 	 * more buttons to a different one, but not when the composition
391 	 * of the group that a button belongs to changes.
392 	 *
393 	 * Since: 2.4
394 	 */
395 	gulong addOnGroupChanged(void delegate(RadioButton) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
396 	{
397 		onGroupChangedListeners ~= new OnGroupChangedDelegateWrapper(dlg, 0, connectFlags);
398 		onGroupChangedListeners[onGroupChangedListeners.length - 1].handlerId = Signals.connectData(
399 			this,
400 			"group-changed",
401 			cast(GCallback)&callBackGroupChanged,
402 			cast(void*)onGroupChangedListeners[onGroupChangedListeners.length - 1],
403 			cast(GClosureNotify)&callBackGroupChangedDestroy,
404 			connectFlags);
405 		return onGroupChangedListeners[onGroupChangedListeners.length - 1].handlerId;
406 	}
407 	
408 	extern(C) static void callBackGroupChanged(GtkRadioButton* radiobuttonStruct,OnGroupChangedDelegateWrapper wrapper)
409 	{
410 		wrapper.dlg(wrapper.outer);
411 	}
412 	
413 	extern(C) static void callBackGroupChangedDestroy(OnGroupChangedDelegateWrapper wrapper, GClosure* closure)
414 	{
415 		wrapper.outer.internalRemoveOnGroupChanged(wrapper);
416 	}
417 
418 	protected void internalRemoveOnGroupChanged(OnGroupChangedDelegateWrapper source)
419 	{
420 		foreach(index, wrapper; onGroupChangedListeners)
421 		{
422 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
423 			{
424 				onGroupChangedListeners[index] = null;
425 				onGroupChangedListeners = std.algorithm.remove(onGroupChangedListeners, index);
426 				break;
427 			}
428 		}
429 	}
430 	
431 }