1 /**
2  * Widget module.
3  *
4  * License:
5  *     MIT. See LICENSE for full details.
6  */
7 module tkd.widget.radiobutton;
8 
9 /**
10  * Imports.
11  */
12 import std..string;
13 import tkd.element.uielement;
14 import tkd.widget.common.command;
15 import tkd.widget.common.invoke;
16 import tkd.widget.common.value;
17 import tkd.widget.textwidget;
18 
19 /**
20  * Radio button widgets are used in groups to show or change a set of 
21  * mutually-exclusive options. Radio buttons have an associated selected value; 
22  * when a radio button is selected, it sets the associated value.
23  *
24  * To create a group of radio button that work properly in unison, all radio 
25  * button widgets within the group must share the same immediate parent 
26  * (usually a frame) and all must have individual selected values set.
27  *
28  * Example:
29  * ---
30  * // The radio button group parent.
31  * auto frame = new Frame()
32  * 	.pack();
33  *
34  * auto option1 = new RadioButton(frame, "Foo")
35  * 	.setSelectedValue("foo")
36  * 	.select()
37  * 	.pack();
38  *
39  * auto option2 = new RadioButton(frame, "Bar")
40  * 	.setSelectedValue("bar")
41  * 	.pack();
42  * ---
43  *
44  * Common_Commands:
45  *     These are injected common commands that can also be used with this widget.
46  *     $(P
47  *         $(LINK2 ./common/command.html, Command) $(BR)
48  *         $(LINK2 ./common/invoke.html, Invoke) $(BR)
49  *         $(LINK2 ./common/value.html, Value) $(BR)
50  *     )
51  *
52  * Additional_Events:
53  *     Additional events that can also be bound to using the $(LINK2 ../element/uielement.html#UiElement.bind, bind) method.
54  *     $(P
55  *         <<Invoke>>,
56  *         <<PrevWindow>>,
57  *         <Alt-Key>,
58  *         <B1-Enter>,
59  *         <B1-Leave>,
60  *         <Button-1>,
61  *         <ButtonRelease-1>,
62  *         <Enter>,
63  *         <Key-Down>,
64  *         <Key-F10>,
65  *         <Key-Tab>,
66  *         <Key-Up>,
67  *         <Key-space>,
68  *         <Leave>,
69  *     )
70  *
71  * States:
72  *     This widget does not respond to user input if the disabled state is set. 
73  *     The widget sets the selected state whenever the value to set to the 
74  *     selected value, and clears it otherwise. This widget sets the alternate 
75  *     state whenever value is unset. (The alternate state may be used to 
76  *     indicate a "tri-state" or "indeterminate" selection.)
77  *
78  * Styles:
79  *     Radio button widgets support the Toolbutton style in all standard 
80  *     themes, which is useful for creating widgets for toolbars.
81  *
82  * See_Also:
83  *     $(LINK2 ./textwidget.html, tkd.widget.textwidget) $(BR)
84  */
85 class RadioButton : TextWidget
86 {
87 	/**
88 	 * The name of the variable that contains the widget's value.
89 	 */
90 	private string _valueVariable;
91 
92 	/**
93 	 * The value of the radio button if it's selected.
94 	 * The default is '1'.
95 	 */
96 	private string _selectedValue = "1";
97 
98 	/**
99 	 * Construct the widget.
100 	 *
101 	 * Params:
102 	 *     parent = The parent of this widget.
103 	 *     text = The text of the button.
104 	 *
105 	 * See_Also:
106 	 *     $(LINK2 ../element/uielement.html, tkd.element.uielement) $(BR)
107 	 */
108 	this(UiElement parent, string text)
109 	{
110 		super(parent);
111 		this._elementId = "radiobutton";
112 
113 		if (parent is null)
114 		{
115 			this._valueVariable = format("variable-%s", this.generateHash(this._elementId));
116 		}
117 		else
118 		{
119 			this._valueVariable = format("variable-%s", this.generateHash("%s%s", this._elementId, parent.id));
120 		}
121 
122 		this._tk.eval("ttk::radiobutton %s -textvariable %s -variable %s", this.id, this._textVariable, this._valueVariable);
123 
124 		this.setText(text);
125 	}
126 
127 	/**
128 	 * Construct the widget.
129 	 *
130 	 * Params:
131 	 *     text = The text of the button.
132 	 */
133 	this(string text)
134 	{
135 		this(null, text);
136 	}
137 
138 	/**
139 	 * Get the value of the selected state.
140 	 *
141 	 * Returns:
142 	 *     A string contain the value of the selected state.
143 	 */
144 	public string getSelectedValue()
145 	{
146 		return this._selectedValue;
147 	}
148 
149 	/**
150 	 * Set the value of the selected state.
151 	 *
152 	 * Params:
153 	 *     value = The value of the widget for the selected state.
154 	 *
155 	 * Returns:
156 	 *     This widget to aid method chaining.
157 	 */
158 	public auto setSelectedValue(this T)(string value)
159 	{
160 		this._selectedValue = value;
161 		this._tk.eval("%s configure -value %s", this.id, this._selectedValue);
162 
163 		return cast(T) this;
164 	}
165 
166 	/**
167 	 * Select the radio button and execute the command if bound.
168 	 */
169 	public auto select(this T)()
170 	{
171 		this._tk.setVariable(this._valueVariable, this._selectedValue);
172 
173 		return cast(T) this;
174 	}
175 
176 	/**
177 	 * Mixin common commands.
178 	 */
179 	mixin Command;
180 	mixin Invoke;
181 	mixin Value!(this._valueVariable, string);
182 }