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.ComboBoxText;
26 
27 public  import gdk.c.types;
28 private import glib.ConstructionException;
29 private import glib.Str;
30 private import gobject.Signals;
31 private import gtk.ComboBox;
32 private import gtk.TreeIter;
33 private import gtk.TreeModelIF;
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 GtkComboBoxText is a simple variant of #GtkComboBox that hides
42  * the model-view complexity for simple text-only use cases.
43  * 
44  * To create a GtkComboBoxText, use gtk_combo_box_text_new() or
45  * gtk_combo_box_text_new_with_entry().
46  * 
47  * You can add items to a GtkComboBoxText with
48  * gtk_combo_box_text_append_text(), gtk_combo_box_text_insert_text()
49  * or gtk_combo_box_text_prepend_text() and remove options with
50  * gtk_combo_box_text_remove().
51  * 
52  * If the GtkComboBoxText contains an entry (via the “has-entry” property),
53  * its contents can be retrieved using gtk_combo_box_text_get_active_text().
54  * The entry itself can be accessed by calling gtk_bin_get_child() on the
55  * combo box.
56  * 
57  * You should not call gtk_combo_box_set_model() or attempt to pack more cells
58  * into this combo box via its GtkCellLayout interface.
59  * 
60  * # GtkComboBoxText as GtkBuildable
61  * 
62  * The GtkComboBoxText implementation of the GtkBuildable interface supports
63  * adding items directly using the <items> element and specifying <item>
64  * elements for each item. Each <item> element can specify the “id”
65  * corresponding to the appended text and also supports the regular
66  * translation attributes “translatable”, “context” and “comments”.
67  * 
68  * Here is a UI definition fragment specifying GtkComboBoxText items:
69  * |[
70  * <object class="GtkComboBoxText">
71  * <items>
72  * <item translatable="yes" id="factory">Factory</item>
73  * <item translatable="yes" id="home">Home</item>
74  * <item translatable="yes" id="subway">Subway</item>
75  * </items>
76  * </object>
77  * ]|
78  * 
79  * # CSS nodes
80  * 
81  * |[<!-- language="plain" -->
82  * combobox
83  * ╰── box.linked
84  * ├── entry.combo
85  * ├── button.combo
86  * ╰── window.popup
87  * ]|
88  * 
89  * GtkComboBoxText has a single CSS node with name combobox. It adds
90  * the style class .combo to the main CSS nodes of its entry and button
91  * children, and the .linked class to the node of its internal box.
92  */
93 public class ComboBoxText : ComboBox
94 {
95 	/** the main Gtk struct */
96 	protected GtkComboBoxText* gtkComboBoxText;
97 
98 	/** Get the main Gtk struct */
99 	public GtkComboBoxText* getComboBoxTextStruct(bool transferOwnership = false)
100 	{
101 		if (transferOwnership)
102 			ownedRef = false;
103 		return gtkComboBoxText;
104 	}
105 
106 	/** the main Gtk struct as a void* */
107 	protected override void* getStruct()
108 	{
109 		return cast(void*)gtkComboBoxText;
110 	}
111 
112 	protected override void setStruct(GObject* obj)
113 	{
114 		gtkComboBoxText = cast(GtkComboBoxText*)obj;
115 		super.setStruct(obj);
116 	}
117 
118 	/**
119 	 * Sets our main struct and passes it to the parent class.
120 	 */
121 	public this (GtkComboBoxText* gtkComboBoxText, bool ownedRef = false)
122 	{
123 		this.gtkComboBoxText = gtkComboBoxText;
124 		super(cast(GtkComboBox*)gtkComboBoxText, ownedRef);
125 	}
126 
127 	/**
128 	 * Creates a new ComboBoxText, which is a ComboBox just displaying strings.
129 	 * Params:
130 	 *   entry = If true, create an ComboBox with an entry.
131 	 * Throws: ConstructionException GTK+ fails to create the object.
132 	 */
133 	public this (bool entry=true)
134 	{
135 		GtkComboBoxText* p;
136 		if ( entry )
137 		{
138 			// GtkWidget* gtk_combo_box_text_new_with_entry (void);
139 			p = cast(GtkComboBoxText*)gtk_combo_box_text_new_with_entry();
140 		}
141 		else
142 		{
143 			// GtkWidget* gtk_combo_box_text_new (void);
144 			p = cast(GtkComboBoxText*)gtk_combo_box_text_new();
145 		}
146 
147 		if(p is null)
148 		{
149 			throw new ConstructionException("null returned by gtk_combo_box_new");
150 		}
151 
152 		this(p);
153 	}
154 
155 	/** */
156 	public void setActiveText(string text, bool insert=false)
157 	{
158 		int active = 0;
159 		setActive(0);
160 		while ( getActive() >= 0 ) // returns -1 if end of list if reached
161 		{
162 			if( text == getActiveText() ) return;
163 			++active;
164 			setActive(active);
165 		}
166 		// was not found, the combo has now nothing selected
167 		if ( insert )
168 		{
169 			append("", text);
170 			setActive(active);
171 		}
172 	}
173 
174 	/** */
175 	int getIndex(string text)
176 	{
177 		TreeIter iter;
178 		TreeModelIF model = getModel();
179 		int index = 0;
180 		bool found = false;
181 		bool end = false;
182 		if ( model.getIterFirst(iter) )
183 		{
184 			iter.setModel(model);
185 			while ( !end && iter !is  null && !found )
186 			{
187 				found = iter.getValueString(0) == text;
188 				if ( !found )
189 				{
190 					end = !model.iterNext(iter);
191 					++index;
192 				}
193 			}
194 		}
195 		else
196 		{
197 			end = true;
198 		}
199 		return end ? -1 : index;
200 	}
201 
202 	/** */
203 	void prependOrReplaceText(string text)
204 	{
205 		int index = getIndex(text);
206 		if ( index > 0 )
207 		{
208 			remove(index);
209 			prepend("", text);
210 		}
211 		else if ( index == -1 )
212 		{
213 			prepend("", text);
214 		}
215 	}
216 
217 	protected class OnChangedDelegateWrapper
218 	{
219 		void delegate(ComboBoxText) dlg;
220 		gulong handlerId;
221 
222 		this(void delegate(ComboBoxText) dlg)
223 		{
224 			this.dlg = dlg;
225 			onChangedListeners ~= this;
226 		}
227 
228 		void remove(OnChangedDelegateWrapper source)
229 		{
230 			foreach(index, wrapper; onChangedListeners)
231 			{
232 				if (wrapper.handlerId == source.handlerId)
233 				{
234 					onChangedListeners[index] = null;
235 					onChangedListeners = std.algorithm.remove(onChangedListeners, index);
236 					break;
237 				}
238 			}
239 		}
240 	}
241 	OnChangedDelegateWrapper[] onChangedListeners;
242 
243 	/**
244 	 * The changed signal is emitted when the active
245 	 * item is changed. The can be due to the user selecting
246 	 * a different item from the list, or due to a
247 	 * call to gtk_combo_box_set_active_iter().
248 	 * It will also be emitted while typing into the entry of a combo box
249 	 * with an entry.
250 	 *
251 	 * Since: 2.4
252 	 */
253 	gulong addOnChanged(void delegate(ComboBoxText) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
254 	{
255 		auto wrapper = new OnChangedDelegateWrapper(dlg);
256 		wrapper.handlerId = Signals.connectData(
257 			this,
258 			"changed",
259 			cast(GCallback)&callBackChanged,
260 			cast(void*)wrapper,
261 			cast(GClosureNotify)&callBackChangedDestroy,
262 			connectFlags);
263 		return wrapper.handlerId;
264 	}
265 
266 	extern(C) static void callBackChanged(GtkComboBoxText* comboboxTextStruct, OnChangedDelegateWrapper wrapper)
267 	{
268 		wrapper.dlg(wrapper.outer);
269 	}
270 
271 	extern(C) static void callBackChangedDestroy(OnChangedDelegateWrapper wrapper, GClosure* closure)
272 	{
273 		wrapper.remove(wrapper);
274 	}
275 
276 	protected class OnFormatEntryTextDelegateWrapper
277 	{
278 		string delegate(string, ComboBoxText) dlg;
279 		gulong handlerId;
280 
281 		this(string delegate(string, ComboBoxText) dlg)
282 		{
283 			this.dlg = dlg;
284 			onFormatEntryTextListeners ~= this;
285 		}
286 
287 		void remove(OnFormatEntryTextDelegateWrapper source)
288 		{
289 			foreach(index, wrapper; onFormatEntryTextListeners)
290 			{
291 				if (wrapper.handlerId == source.handlerId)
292 				{
293 					onFormatEntryTextListeners[index] = null;
294 					onFormatEntryTextListeners = std.algorithm.remove(onFormatEntryTextListeners, index);
295 					break;
296 				}
297 			}
298 		}
299 	}
300 	OnFormatEntryTextDelegateWrapper[] onFormatEntryTextListeners;
301 
302 	/**
303 	 * For combo boxes that are created with an entry (See GtkComboBox:has-entry).
304 	 *
305 	 * A signal which allows you to change how the text displayed in a combo box's
306 	 * entry is displayed.
307 	 *
308 	 * Connect a signal handler which returns an allocated string representing
309 	 * @path. That string will then be used to set the text in the combo box's entry.
310 	 * The default signal handler uses the text from the GtkComboBox::entry-text-column
311 	 * model column.
312 	 *
313 	 * Here's an example signal handler which fetches data from the model and
314 	 * displays it in the entry.
315 	 * |[<!-- language="C" -->
316 	 * static gchar*
317 	 * format_entry_text_callback (GtkComboBox *combo,
318 	 * const gchar *path,
319 	 * gpointer     user_data)
320 	 * {
321 	 * GtkTreeIter iter;
322 	 * GtkTreeModel model;
323 	 * gdouble      value;
324 	 *
325 	 * model = gtk_combo_box_get_model (combo);
326 	 *
327 	 * gtk_tree_model_get_iter_from_string (model, &iter, path);
328 	 * gtk_tree_model_get (model, &iter,
329 	 * THE_DOUBLE_VALUE_COLUMN, &value,
330 	 * -1);
331 	 *
332 	 * return g_strdup_printf ("%g", value);
333 	 * }
334 	 * ]|
335 	 *
336 	 * Params:
337 	 *     path = the GtkTreePath string from the combo box's current model to format text for
338 	 *
339 	 * Return: a newly allocated string representing @path
340 	 *     for the current GtkComboBox model.
341 	 *
342 	 * Since: 3.4
343 	 */
344 	gulong addOnFormatEntryText(string delegate(string, ComboBoxText) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
345 	{
346 		auto wrapper = new OnFormatEntryTextDelegateWrapper(dlg);
347 		wrapper.handlerId = Signals.connectData(
348 			this,
349 			"format-entry-text",
350 			cast(GCallback)&callBackFormatEntryText,
351 			cast(void*)wrapper,
352 			cast(GClosureNotify)&callBackFormatEntryTextDestroy,
353 			connectFlags);
354 		return wrapper.handlerId;
355 	}
356 
357 	extern(C) static string callBackFormatEntryText(GtkComboBoxText* comboboxStructText, char* path,OnFormatEntryTextDelegateWrapper wrapper)
358 	{
359 		return wrapper.dlg(Str.toString(path), wrapper.outer);
360 	}
361 
362 	extern(C) static void callBackFormatEntryTextDestroy(OnFormatEntryTextDelegateWrapper wrapper, GClosure* closure)
363 	{
364 		wrapper.remove(wrapper);
365 	}
366 
367 	protected class OnMoveActiveDelegateWrapper
368 	{
369 		void delegate(GtkScrollType, ComboBoxText) dlg;
370 		gulong handlerId;
371 
372 		this(void delegate(GtkScrollType, ComboBoxText) dlg)
373 		{
374 			this.dlg = dlg;
375 			onMoveActiveListeners ~= this;
376 		}
377 
378 		void remove(OnMoveActiveDelegateWrapper source)
379 		{
380 			foreach(index, wrapper; onMoveActiveListeners)
381 			{
382 				if (wrapper.handlerId == source.handlerId)
383 				{
384 					onMoveActiveListeners[index] = null;
385 					onMoveActiveListeners = std.algorithm.remove(onMoveActiveListeners, index);
386 					break;
387 				}
388 			}
389 		}
390 	}
391 	OnMoveActiveDelegateWrapper[] onMoveActiveListeners;
392 
393 	/**
394 	 * The ::move-active signal is a
395 	 * [keybinding signal][GtkBindingSignal]
396 	 * which gets emitted to move the active selection.
397 	 *
398 	 * Params:
399 	 *     scrollType = a #GtkScrollType
400 	 *
401 	 * Since: 2.12
402 	 */
403 	gulong addOnMoveActive(void delegate(GtkScrollType, ComboBoxText) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
404 	{
405 		auto wrapper = new OnMoveActiveDelegateWrapper(dlg);
406 		wrapper.handlerId = Signals.connectData(
407 			this,
408 			"move-active",
409 			cast(GCallback)&callBackMoveActive,
410 			cast(void*)wrapper,
411 			cast(GClosureNotify)&callBackMoveActiveDestroy,
412 			connectFlags);
413 		return wrapper.handlerId;
414 	}
415 
416 	extern(C) static void callBackMoveActive(GtkComboBoxText* comboboxTextStruct, GtkScrollType scrollType,OnMoveActiveDelegateWrapper wrapper)
417 	{
418 		wrapper.dlg(scrollType, wrapper.outer);
419 	}
420 
421 	extern(C) static void callBackMoveActiveDestroy(OnMoveActiveDelegateWrapper wrapper, GClosure* closure)
422 	{
423 		wrapper.remove(wrapper);
424 	}
425 
426 	protected class OnPopdownDelegateWrapper
427 	{
428 		bool delegate(ComboBoxText) dlg;
429 		gulong handlerId;
430 
431 		this(bool delegate(ComboBoxText) dlg)
432 		{
433 			this.dlg = dlg;
434 			onPopdownListeners ~= this;
435 		}
436 
437 		void remove(OnPopdownDelegateWrapper source)
438 		{
439 			foreach(index, wrapper; onPopdownListeners)
440 			{
441 				if (wrapper.handlerId == source.handlerId)
442 				{
443 					onPopdownListeners[index] = null;
444 					onPopdownListeners = std.algorithm.remove(onPopdownListeners, index);
445 					break;
446 				}
447 			}
448 		}
449 	}
450 	OnPopdownDelegateWrapper[] onPopdownListeners;
451 
452 	/**
453 	 * The ::popdown signal is a
454 	 * [keybinding signal][GtkBindingSignal]
455 	 * which gets emitted to popdown the combo box list.
456 	 *
457 	 * The default bindings for this signal are Alt+Up and Escape.
458 	 *
459 	 * Since: 2.12
460 	 */
461 	gulong addOnPopdown(bool delegate(ComboBoxText) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
462 	{
463 		auto wrapper = new OnPopdownDelegateWrapper(dlg);
464 		wrapper.handlerId = Signals.connectData(
465 			this,
466 			"popdown",
467 			cast(GCallback)&callBackPopdown,
468 			cast(void*)wrapper,
469 			cast(GClosureNotify)&callBackPopdownDestroy,
470 			connectFlags);
471 		return wrapper.handlerId;
472 	}
473 
474 	extern(C) static int callBackPopdown(GtkComboBoxText* comboboxTextStruct,OnPopdownDelegateWrapper wrapper)
475 	{
476 		return wrapper.dlg(wrapper.outer);
477 	}
478 
479 	extern(C) static void callBackPopdownDestroy(OnPopdownDelegateWrapper wrapper, GClosure* closure)
480 	{
481 		wrapper.remove(wrapper);
482 	}
483 
484 	protected class OnPopupDelegateWrapper
485 	{
486 		void delegate(ComboBoxText) dlg;
487 		gulong handlerId;
488 
489 		this(void delegate(ComboBoxText) dlg)
490 		{
491 			this.dlg = dlg;
492 			onPopupListeners ~= this;
493 		}
494 
495 		void remove(OnPopupDelegateWrapper source)
496 		{
497 			foreach(index, wrapper; onPopupListeners)
498 			{
499 				if (wrapper.handlerId == source.handlerId)
500 				{
501 					onPopupListeners[index] = null;
502 					onPopupListeners = std.algorithm.remove(onPopupListeners, index);
503 					break;
504 				}
505 			}
506 		}
507 	}
508 	OnPopupDelegateWrapper[] onPopupListeners;
509 
510 	/**
511 	 * The ::popup signal is a
512 	 * [keybinding signal][GtkBindingSignal]
513 	 * which gets emitted to popup the combo box list.
514 	 *
515 	 * The default binding for this signal is Alt+Down.
516 	 *
517 	 * Since: 2.12
518 	 */
519 	gulong addOnPopup(void delegate(ComboBoxText) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
520 	{
521 		auto wrapper = new OnPopupDelegateWrapper(dlg);
522 		wrapper.handlerId = Signals.connectData(
523 			this,
524 			"popup",
525 			cast(GCallback)&callBackPopup,
526 			cast(void*)wrapper,
527 			cast(GClosureNotify)&callBackPopupDestroy,
528 			connectFlags);
529 		return wrapper.handlerId;
530 	}
531 
532 	extern(C) static void callBackPopup(GtkComboBoxText* comboboxTextStruct,OnPopupDelegateWrapper wrapper)
533 	{
534 		wrapper.dlg(wrapper.outer);
535 	}
536 
537 	extern(C) static void callBackPopupDestroy(OnPopupDelegateWrapper wrapper, GClosure* closure)
538 	{
539 		wrapper.remove(wrapper);
540 	}
541 
542 	/**
543 	 */
544 
545 	/** */
546 	public static GType getType()
547 	{
548 		return gtk_combo_box_text_get_type();
549 	}
550 
551 	/**
552 	 * Appends @text to the list of strings stored in @combo_box.
553 	 * If @id is non-%NULL then it is used as the ID of the row.
554 	 *
555 	 * This is the same as calling gtk_combo_box_text_insert() with a
556 	 * position of -1.
557 	 *
558 	 * Params:
559 	 *     id = a string ID for this value, or %NULL
560 	 *     text = A string
561 	 *
562 	 * Since: 2.24
563 	 */
564 	public void append(string id, string text)
565 	{
566 		gtk_combo_box_text_append(gtkComboBoxText, Str.toStringz(id), Str.toStringz(text));
567 	}
568 
569 	/**
570 	 * Appends @text to the list of strings stored in @combo_box.
571 	 *
572 	 * This is the same as calling gtk_combo_box_text_insert_text() with a
573 	 * position of -1.
574 	 *
575 	 * Params:
576 	 *     text = A string
577 	 *
578 	 * Since: 2.24
579 	 */
580 	public void appendText(string text)
581 	{
582 		gtk_combo_box_text_append_text(gtkComboBoxText, Str.toStringz(text));
583 	}
584 
585 	/**
586 	 * Returns the currently active string in @combo_box, or %NULL
587 	 * if none is selected. If @combo_box contains an entry, this
588 	 * function will return its contents (which will not necessarily
589 	 * be an item from the list).
590 	 *
591 	 * Returns: a newly allocated string containing the
592 	 *     currently active text. Must be freed with g_free().
593 	 *
594 	 * Since: 2.24
595 	 */
596 	public string getActiveText()
597 	{
598 		auto retStr = gtk_combo_box_text_get_active_text(gtkComboBoxText);
599 
600 		scope(exit) Str.freeString(retStr);
601 		return Str.toString(retStr);
602 	}
603 
604 	/**
605 	 * Inserts @text at @position in the list of strings stored in @combo_box.
606 	 * If @id is non-%NULL then it is used as the ID of the row.  See
607 	 * #GtkComboBox:id-column.
608 	 *
609 	 * If @position is negative then @text is appended.
610 	 *
611 	 * Params:
612 	 *     position = An index to insert @text
613 	 *     id = a string ID for this value, or %NULL
614 	 *     text = A string to display
615 	 *
616 	 * Since: 3.0
617 	 */
618 	public void insert(int position, string id, string text)
619 	{
620 		gtk_combo_box_text_insert(gtkComboBoxText, position, Str.toStringz(id), Str.toStringz(text));
621 	}
622 
623 	/**
624 	 * Inserts @text at @position in the list of strings stored in @combo_box.
625 	 *
626 	 * If @position is negative then @text is appended.
627 	 *
628 	 * This is the same as calling gtk_combo_box_text_insert() with a %NULL
629 	 * ID string.
630 	 *
631 	 * Params:
632 	 *     position = An index to insert @text
633 	 *     text = A string
634 	 *
635 	 * Since: 2.24
636 	 */
637 	public void insertText(int position, string text)
638 	{
639 		gtk_combo_box_text_insert_text(gtkComboBoxText, position, Str.toStringz(text));
640 	}
641 
642 	/**
643 	 * Prepends @text to the list of strings stored in @combo_box.
644 	 * If @id is non-%NULL then it is used as the ID of the row.
645 	 *
646 	 * This is the same as calling gtk_combo_box_text_insert() with a
647 	 * position of 0.
648 	 *
649 	 * Params:
650 	 *     id = a string ID for this value, or %NULL
651 	 *     text = a string
652 	 *
653 	 * Since: 2.24
654 	 */
655 	public void prepend(string id, string text)
656 	{
657 		gtk_combo_box_text_prepend(gtkComboBoxText, Str.toStringz(id), Str.toStringz(text));
658 	}
659 
660 	/**
661 	 * Prepends @text to the list of strings stored in @combo_box.
662 	 *
663 	 * This is the same as calling gtk_combo_box_text_insert_text() with a
664 	 * position of 0.
665 	 *
666 	 * Params:
667 	 *     text = A string
668 	 *
669 	 * Since: 2.24
670 	 */
671 	public void prependText(string text)
672 	{
673 		gtk_combo_box_text_prepend_text(gtkComboBoxText, Str.toStringz(text));
674 	}
675 
676 	/**
677 	 * Removes the string at @position from @combo_box.
678 	 *
679 	 * Params:
680 	 *     position = Index of the item to remove
681 	 *
682 	 * Since: 2.24
683 	 */
684 	public void remove(int position)
685 	{
686 		gtk_combo_box_text_remove(gtkComboBoxText, position);
687 	}
688 
689 	/**
690 	 * Removes all the text entries from the combo box.
691 	 *
692 	 * Since: 3.0
693 	 */
694 	public override void removeAll()
695 	{
696 		gtk_combo_box_text_remove_all(gtkComboBoxText);
697 	}
698 }