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 private import gtk.c.functions;
35 public  import gtk.c.types;
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(bool transferOwnership = false)
133 	{
134 		if (transferOwnership)
135 			ownedRef = false;
136 		return gtkRadioButton;
137 	}
138 
139 	/** the main Gtk struct as a void* */
140 	protected override void* getStruct()
141 	{
142 		return cast(void*)gtkRadioButton;
143 	}
144 
145 	protected override void setStruct(GObject* obj)
146 	{
147 		gtkRadioButton = cast(GtkRadioButton*)obj;
148 		super.setStruct(obj);
149 	}
150 
151 	/**
152 	 * Sets our main struct and passes it to the parent class.
153 	 */
154 	public this (GtkRadioButton* gtkRadioButton, bool ownedRef = false)
155 	{
156 		this.gtkRadioButton = gtkRadioButton;
157 		super(cast(GtkCheckButton*)gtkRadioButton, ownedRef);
158 	}
159 
160 	/**
161 	 * Creates a new RadioButton with a text label.
162 	 * Params:
163 	 *  group = an existing radio button group.
164 	 *  label = the text label to display next to the radio button.
165 	 *  mnemonic = if true the label will be created using
166 	 *  gtk_label_new_with_mnemonic(), so underscores in label indicate the
167 	 *  mnemonic for the button.
168 	 * Throws: ConstructionException GTK+ fails to create the object.
169 	 */
170 	public this (ListSG group, string label, bool mnemonic=true)
171 	{
172 		GtkRadioButton* p;
173 
174 		if ( mnemonic )
175 		{
176 			// GtkWidget* gtk_radio_button_new_with_mnemonic  (GSList *group,  const gchar *label);
177 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_mnemonic(
178 				group is null ? null : group.getListSGStruct(),
179 			Str.toStringz(label));
180 		}
181 		else
182 		{
183 			// GtkWidget* gtk_radio_button_new_with_label (GSList *group,  const gchar *label);
184 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_label(
185 				group is null ? null : group.getListSGStruct(),
186 			Str.toStringz(label));
187 		}
188 
189 		if(p is null)
190 		{
191 			throw new ConstructionException("null returned by gtk_radio_button_new_");
192 		}
193 
194 		this(p);
195 	}
196 
197 	/**
198 	 * Creates a new RadioButton with a text label, adding it to the same group
199 	 * as group.
200 	 * Params:
201 	 *  radioButton = an existing RadioButton.
202 	 *  label = a text string to display next to the radio button.
203 	 *  mnemonic = if true the label
204 	 *  will be created using gtk_label_new_with_mnemonic(), so underscores
205 	 *  in label indicate the mnemonic for the button.
206 	 * Throws: ConstructionException GTK+ fails to create the object.
207 	 */
208 	public this (RadioButton radioButton, string label, bool mnemonic=true)
209 	{
210 		GtkRadioButton* p;
211 
212 		if ( mnemonic )
213 		{
214 			// GtkWidget* gtk_radio_button_new_with_mnemonic_from_widget  (GtkRadioButton *group,  const gchar *label);
215 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_mnemonic_from_widget(
216 				radioButton.getRadioButtonStruct(),
217 			Str.toStringz(label));
218 		}
219 		else
220 		{
221 			// GtkWidget* gtk_radio_button_new_with_label_from_widget  (GtkRadioButton *group,  const gchar *label);
222 			p = cast(GtkRadioButton*)gtk_radio_button_new_with_label_from_widget(
223 				radioButton.getRadioButtonStruct(),
224 			Str.toStringz(label));
225 		}
226 
227 		if(p is null)
228 		{
229 			throw new ConstructionException("null returned by gtk_radio_button_new_");
230 		}
231 
232 		this(p);
233 	}
234 
235 	/**
236 	 * Creates a new RadioButton with a text label,
237 	 * and creates a new group.
238 	 * Params:
239 	 *  label = a text string to display next to the radio button.
240 	 *  mnemonic = if true the label
241 	 *  will be created using gtk_label_new_with_mnemonic(), so underscores
242 	 *  in label indicate the mnemonic for the button.
243 	 * Throws: ConstructionException GTK+ fails to create the object.
244 	 */
245 	public this (string label, bool mnemonic=true)
246 	{
247 		this(cast(ListSG)null, label, mnemonic);
248 	}
249 
250 	/**
251 	 */
252 
253 	/** */
254 	public static GType getType()
255 	{
256 		return gtk_radio_button_get_type();
257 	}
258 
259 	/**
260 	 * Creates a new #GtkRadioButton. To be of any practical value, a widget should
261 	 * then be packed into the radio button.
262 	 *
263 	 * Params:
264 	 *     group = an existing
265 	 *         radio button group, or %NULL if you are creating a new group.
266 	 *
267 	 * Returns: a new radio button
268 	 *
269 	 * Throws: ConstructionException GTK+ fails to create the object.
270 	 */
271 	public this(ListSG group)
272 	{
273 		auto p = gtk_radio_button_new((group is null) ? null : group.getListSGStruct());
274 
275 		if(p is null)
276 		{
277 			throw new ConstructionException("null returned by new");
278 		}
279 
280 		this(cast(GtkRadioButton*) p);
281 	}
282 
283 	/**
284 	 * Creates a new #GtkRadioButton, adding it to the same group as
285 	 * @radio_group_member. As with gtk_radio_button_new(), a widget
286 	 * should be packed into the radio button.
287 	 *
288 	 * Params:
289 	 *     radioGroupMember = an existing #GtkRadioButton.
290 	 *
291 	 * Returns: a new radio button.
292 	 *
293 	 * Throws: ConstructionException GTK+ fails to create the object.
294 	 */
295 	public this(RadioButton radioGroupMember)
296 	{
297 		auto p = gtk_radio_button_new_from_widget((radioGroupMember is null) ? null : radioGroupMember.getRadioButtonStruct());
298 
299 		if(p is null)
300 		{
301 			throw new ConstructionException("null returned by new_from_widget");
302 		}
303 
304 		this(cast(GtkRadioButton*) p);
305 	}
306 
307 	/**
308 	 * Retrieves the group assigned to a radio button.
309 	 *
310 	 * Returns: a linked list
311 	 *     containing all the radio buttons in the same group
312 	 *     as @radio_button. The returned list is owned by the radio button
313 	 *     and must not be modified or freed.
314 	 */
315 	public ListSG getGroup()
316 	{
317 		auto p = gtk_radio_button_get_group(gtkRadioButton);
318 
319 		if(p is null)
320 		{
321 			return null;
322 		}
323 
324 		return new ListSG(cast(GSList*) p);
325 	}
326 
327 	/**
328 	 * Joins a #GtkRadioButton object to the group of another #GtkRadioButton object
329 	 *
330 	 * Use this in language bindings instead of the gtk_radio_button_get_group()
331 	 * and gtk_radio_button_set_group() methods
332 	 *
333 	 * A common way to set up a group of radio buttons is the following:
334 	 * |[<!-- language="C" -->
335 	 * GtkRadioButton *radio_button;
336 	 * GtkRadioButton *last_button;
337 	 *
338 	 * while ( ...more buttons to add... )
339 	 * {
340 	 * radio_button = gtk_radio_button_new (...);
341 	 *
342 	 * gtk_radio_button_join_group (radio_button, last_button);
343 	 * last_button = radio_button;
344 	 * }
345 	 * ]|
346 	 *
347 	 * Params:
348 	 *     groupSource = a radio button object whos group we are
349 	 *         joining, or %NULL to remove the radio button from its group
350 	 *
351 	 * Since: 3.0
352 	 */
353 	public void joinGroup(RadioButton groupSource)
354 	{
355 		gtk_radio_button_join_group(gtkRadioButton, (groupSource is null) ? null : groupSource.getRadioButtonStruct());
356 	}
357 
358 	/**
359 	 * Sets a #GtkRadioButton’s group. It should be noted that this does not change
360 	 * the layout of your interface in any way, so if you are changing the group,
361 	 * it is likely you will need to re-arrange the user interface to reflect these
362 	 * changes.
363 	 *
364 	 * Params:
365 	 *     group = an existing radio
366 	 *         button group, such as one returned from gtk_radio_button_get_group(), or %NULL.
367 	 */
368 	public void setGroup(ListSG group)
369 	{
370 		gtk_radio_button_set_group(gtkRadioButton, (group is null) ? null : group.getListSGStruct());
371 	}
372 
373 	protected class OnGroupChangedDelegateWrapper
374 	{
375 		void delegate(RadioButton) dlg;
376 		gulong handlerId;
377 
378 		this(void delegate(RadioButton) dlg)
379 		{
380 			this.dlg = dlg;
381 			onGroupChangedListeners ~= this;
382 		}
383 
384 		void remove(OnGroupChangedDelegateWrapper source)
385 		{
386 			foreach(index, wrapper; onGroupChangedListeners)
387 			{
388 				if (wrapper.handlerId == source.handlerId)
389 				{
390 					onGroupChangedListeners[index] = null;
391 					onGroupChangedListeners = std.algorithm.remove(onGroupChangedListeners, index);
392 					break;
393 				}
394 			}
395 		}
396 	}
397 	OnGroupChangedDelegateWrapper[] onGroupChangedListeners;
398 
399 	/**
400 	 * Emitted when the group of radio buttons that a radio button belongs
401 	 * to changes. This is emitted when a radio button switches from
402 	 * being alone to being part of a group of 2 or more buttons, or
403 	 * vice-versa, and when a button is moved from one group of 2 or
404 	 * more buttons to a different one, but not when the composition
405 	 * of the group that a button belongs to changes.
406 	 *
407 	 * Since: 2.4
408 	 */
409 	gulong addOnGroupChanged(void delegate(RadioButton) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
410 	{
411 		auto wrapper = new OnGroupChangedDelegateWrapper(dlg);
412 		wrapper.handlerId = Signals.connectData(
413 			this,
414 			"group-changed",
415 			cast(GCallback)&callBackGroupChanged,
416 			cast(void*)wrapper,
417 			cast(GClosureNotify)&callBackGroupChangedDestroy,
418 			connectFlags);
419 		return wrapper.handlerId;
420 	}
421 
422 	extern(C) static void callBackGroupChanged(GtkRadioButton* radiobuttonStruct, OnGroupChangedDelegateWrapper wrapper)
423 	{
424 		wrapper.dlg(wrapper.outer);
425 	}
426 
427 	extern(C) static void callBackGroupChangedDestroy(OnGroupChangedDelegateWrapper wrapper, GClosure* closure)
428 	{
429 		wrapper.remove(wrapper);
430 	}
431 }