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