1 /**
2  * Widget module.
3  *
4  * License:
5  *     MIT. See LICENSE for full details.
6  */
7 module tkd.widget.combobox;
8 
9 /**
10  * Imports.
11  */
12 import std.conv;
13 import std..string;
14 import tkd.element.element;
15 import tkd.element.uielement;
16 import tkd.widget.common.boundingbox;
17 import tkd.widget.common.color;
18 import tkd.widget.common.cursor;
19 import tkd.widget.common.data;
20 import tkd.widget.common.delete_;
21 import tkd.widget.common.exportselection;
22 import tkd.widget.common.font;
23 import tkd.widget.common.height;
24 import tkd.widget.common.index;
25 import tkd.widget.common.insert;
26 import tkd.widget.common.justify;
27 import tkd.widget.common.postcommand;
28 import tkd.widget.common.selection;
29 import tkd.widget.common.value;
30 import tkd.widget.common.width;
31 import tkd.widget.common.xscrollcommand;
32 import tkd.widget.common.xview;
33 import tkd.widget.widget;
34 
35 /**
36  * A combobox combines a text field with a pop-down list of values; the user 
37  * may select the value of the text field from among the values in the list.
38  *
39  * This widget has two types of values that can be set. First, a list of values 
40  * can be set to populate the drop-down list which can then be selected via a 
41  * mouse. Second, the value can be set independently and in addition to the 
42  * value list. See the below widget specific and common commands for an 
43  * overview of how this works.
44  *
45  * Example:
46  * ---
47  * auto data = ["foo", "bar", "baz", "qux"];
48  *
49  * auto comboBox = new ComboBox()
50  * 	.setData(data);
51  * 	.setValue(data[0])
52  * 	.pack();
53  * ---
54  *
55  * Common_Commands:
56  *     These are injected common commands that can also be used with this widget.
57  *     $(P
58  *         $(LINK2 ./common/boundingbox.html, BoundingBox) $(BR)
59  *         $(LINK2 ./common/color.html, Color) $(BR)
60  *         $(LINK2 ./common/cursor.html, Cursor) $(BR)
61  *         $(LINK2 ./common/data.html, Data) $(BR)
62  *         $(LINK2 ./common/delete_.html, Delete) $(BR)
63  *         $(LINK2 ./common/exportselection.html, Exportselection) $(BR)
64  *         $(LINK2 ./common/font.html, Font) $(BR)
65  *         $(LINK2 ./common/height.html, Height) $(BR)
66  *         $(LINK2 ./common/index.html, Index) $(BR)
67  *         $(LINK2 ./common/insert.html, Insert) $(BR)
68  *         $(LINK2 ./common/justify.html, Justify) $(BR)
69  *         $(LINK2 ./common/postcommand.html, PostCommand) $(BR)
70  *         $(LINK2 ./common/selection.html, Selection) $(BR)
71  *         $(LINK2 ./common/value.html, Value) $(BR)
72  *         $(LINK2 ./common/width.html, Width) $(BR)
73  *         $(LINK2 ./common/xscrollcommand.html, XScrollCommand) $(BR)
74  *         $(LINK2 ./common/xview.html, XView) $(BR)
75  *     )
76  *
77  * Additional_Events:
78  *     Additional events that can also be bound to using the $(LINK2 ../element/uielement.html#UiElement.bind, bind) method.
79  *     $(P
80  *         <<Clear>>,
81  *         <<Copy>>,
82  *         <<Cut>>,
83  *         <<Paste>>,
84  *         <<PasteSelection>>,
85  *         <<PrevWindow>>,
86  *         <<TraverseIn>>,
87  *         <Alt-Key>,
88  *         <B1-Enter>,
89  *         <B1-Leave>,
90  *         <B1-Motion>,
91  *         <B2-Motion>,
92  *         <Button-1>,
93  *         <Button-2>,
94  *         <Button-4>,
95  *         <Button-5>,
96  *         <ButtonRelease-1>,
97  *         <ButtonRelease-2>,
98  *         <Control-Button-1>,
99  *         <Control-Key-Left>,
100  *         <Control-Key-Right>,
101  *         <Control-Key-a>,
102  *         <Control-Key-b>,
103  *         <Control-Key-backslash>,
104  *         <Control-Key-d>,
105  *         <Control-Key-e>,
106  *         <Control-Key-f>,
107  *         <Control-Key-h>,
108  *         <Control-Key-k>,
109  *         <Control-Key-slash>,
110  *         <Control-Key>,
111  *         <Control-Shift-Key-Left>,
112  *         <Control-Shift-Key-Right>,
113  *         <Double-Button-1>,
114  *         <Key-BackSpace>,
115  *         <Key-Delete>,
116  *         <Key-Down>,
117  *         <Key-End>,
118  *         <Key-Escape>,
119  *         <Key-F10>,
120  *         <Key-Home>,
121  *         <Key-KP_Enter>,
122  *         <Key-Left>,
123  *         <Key-Return>,
124  *         <Key-Right>,
125  *         <Key-Tab>,
126  *         <Key-Up>,
127  *         <Key>,
128  *         <Meta-Key>,
129  *         <Motion>,
130  *         <Shift-Button-1>,
131  *         <Shift-Key-End>,
132  *         <Shift-Key-Home>,
133  *         <Shift-Key-Left>,
134  *         <Shift-Key-Right>,
135  *         <Triple-Button-1>,
136  *     )
137  *
138  * See_Also:
139  *     $(LINK2 ./widget.html, tkd.widget.widget)
140  */
141 class ComboBox : Widget, IXScrollable!(ComboBox)
142 {
143 	/**
144 	 * The name of the variable that contains the widget's value.
145 	 */
146 	private string _valueVariable;
147 
148 	/**
149 	 * Construct the widget.
150 	 *
151 	 * Params:
152 	 *     parent = The parent of this widget.
153 	 *
154 	 * See_Also:
155 	 *     $(LINK2 ../element/uielement.html, tkd.element.uielement) $(BR)
156 	 */
157 	this(UiElement parent = null)
158 	{
159 		super(parent);
160 		this._elementId = "combobox";
161 		this._valueVariable = format("variable-%s", this.generateHash(this.id));
162 
163 		this._tk.eval("ttk::combobox %s -textvariable %s", this.id, this._valueVariable);
164 
165 		this.setState(["readonly"]);
166 
167 		this.bind("<<ComboboxSelected>>", delegate(CommandArgs args){
168 			this.deselectText();
169 		});
170 	}
171 
172 	/**
173 	 * Get the index of the selected value from the current widget's list values.
174 	 *
175 	 * Returns:
176 	 *     The index of the selected list value.
177 	 *     Indexes start at 0 and -1 is returned if the current value does not appear in the list.
178 	 */
179 	public int getSelected()
180 	{
181 		this._tk.eval("%s current", this.id);
182 		return this._tk.getResult!(int);
183 	}
184 
185 	/**
186 	 * Select the value at a particular index in the value list.
187 	 *
188 	 * Params:
189 	 *     index = The index of the value to select.
190 	 *
191 	 * Returns:
192 	 *     This widget to aid method chaining.
193 	 */
194 	public auto select(this T)(int index)
195 	{
196 		this._tk.eval("%s current %s", this.id, index);
197 
198 		return cast(T) this;
199 	}
200 
201 	/**
202 	 * Mixin common commands.
203 	 */
204 	mixin BoundingBox;
205 	mixin Color;
206 	mixin Cursor;
207 	mixin Data;
208 	mixin Delete_;
209 	mixin ExportSelection;
210 	mixin Font;
211 	mixin Height;
212 	mixin Index;
213 	mixin Insert;
214 	mixin Justify;
215 	mixin PostCommand;
216 	mixin Selection;
217 	mixin Value!(this._valueVariable, string);
218 	mixin Width;
219 	mixin XScrollCommand!(ComboBox);
220 	mixin XView;
221 }