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