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.EntryCompletion;
26 
27 private import glib.ConstructionException;
28 private import glib.Str;
29 private import gobject.ObjectG;
30 private import gobject.Signals;
31 private import gtk.BuildableIF;
32 private import gtk.BuildableT;
33 private import gtk.CellArea;
34 private import gtk.CellLayoutIF;
35 private import gtk.CellLayoutT;
36 private import gtk.TreeIter;
37 private import gtk.TreeModel;
38 private import gtk.TreeModelIF;
39 private import gtk.Widget;
40 public  import gtkc.gdktypes;
41 private import gtkc.gtk;
42 public  import gtkc.gtktypes;
43 private import std.algorithm;
44 
45 
46 /**
47  * #GtkEntryCompletion is an auxiliary object to be used in conjunction with
48  * #GtkEntry to provide the completion functionality. It implements the
49  * #GtkCellLayout interface, to allow the user to add extra cells to the
50  * #GtkTreeView with completion matches.
51  * 
52  * “Completion functionality” means that when the user modifies the text
53  * in the entry, #GtkEntryCompletion checks which rows in the model match
54  * the current content of the entry, and displays a list of matches.
55  * By default, the matching is done by comparing the entry text
56  * case-insensitively against the text column of the model (see
57  * gtk_entry_completion_set_text_column()), but this can be overridden
58  * with a custom match function (see gtk_entry_completion_set_match_func()).
59  * 
60  * When the user selects a completion, the content of the entry is
61  * updated. By default, the content of the entry is replaced by the
62  * text column of the model, but this can be overridden by connecting
63  * to the #GtkEntryCompletion::match-selected signal and updating the
64  * entry in the signal handler. Note that you should return %TRUE from
65  * the signal handler to suppress the default behaviour.
66  * 
67  * To add completion functionality to an entry, use gtk_entry_set_completion().
68  * 
69  * In addition to regular completion matches, which will be inserted into the
70  * entry when they are selected, #GtkEntryCompletion also allows to display
71  * “actions” in the popup window. Their appearance is similar to menuitems,
72  * to differentiate them clearly from completion strings. When an action is
73  * selected, the #GtkEntryCompletion::action-activated signal is emitted.
74  * 
75  * GtkEntryCompletion uses a #GtkTreeModelFilter model to represent the
76  * subset of the entire model that is currently matching. While the
77  * GtkEntryCompletion signals #GtkEntryCompletion::match-selected and
78  * #GtkEntryCompletion::cursor-on-match take the original model and an
79  * iter pointing to that model as arguments, other callbacks and signals
80  * (such as #GtkCellLayoutDataFuncs or #GtkCellArea::apply-attributes)
81  * will generally take the filter model as argument. As long as you are
82  * only calling gtk_tree_model_get(), this will make no difference to
83  * you. If for some reason, you need the original model, use
84  * gtk_tree_model_filter_get_model(). Don’t forget to use
85  * gtk_tree_model_filter_convert_iter_to_child_iter() to obtain a
86  * matching iter.
87  */
88 public class EntryCompletion : ObjectG, BuildableIF, CellLayoutIF
89 {
90 	/** the main Gtk struct */
91 	protected GtkEntryCompletion* gtkEntryCompletion;
92 
93 	/** Get the main Gtk struct */
94 	public GtkEntryCompletion* getEntryCompletionStruct()
95 	{
96 		return gtkEntryCompletion;
97 	}
98 
99 	/** the main Gtk struct as a void* */
100 	protected override void* getStruct()
101 	{
102 		return cast(void*)gtkEntryCompletion;
103 	}
104 
105 	protected override void setStruct(GObject* obj)
106 	{
107 		gtkEntryCompletion = cast(GtkEntryCompletion*)obj;
108 		super.setStruct(obj);
109 	}
110 
111 	/**
112 	 * Sets our main struct and passes it to the parent class.
113 	 */
114 	public this (GtkEntryCompletion* gtkEntryCompletion, bool ownedRef = false)
115 	{
116 		this.gtkEntryCompletion = gtkEntryCompletion;
117 		super(cast(GObject*)gtkEntryCompletion, ownedRef);
118 	}
119 
120 	// add the Buildable capabilities
121 	mixin BuildableT!(GtkEntryCompletion);
122 
123 	// add the CellLayout capabilities
124 	mixin CellLayoutT!(GtkEntryCompletion);
125 
126 
127 	/** */
128 	public static GType getType()
129 	{
130 		return gtk_entry_completion_get_type();
131 	}
132 
133 	/**
134 	 * Creates a new #GtkEntryCompletion object.
135 	 *
136 	 * Return: A newly created #GtkEntryCompletion object
137 	 *
138 	 * Since: 2.4
139 	 *
140 	 * Throws: ConstructionException GTK+ fails to create the object.
141 	 */
142 	public this()
143 	{
144 		auto p = gtk_entry_completion_new();
145 		
146 		if(p is null)
147 		{
148 			throw new ConstructionException("null returned by new");
149 		}
150 		
151 		this(cast(GtkEntryCompletion*) p, true);
152 	}
153 
154 	/**
155 	 * Creates a new #GtkEntryCompletion object using the
156 	 * specified @area to layout cells in the underlying
157 	 * #GtkTreeViewColumn for the drop-down menu.
158 	 *
159 	 * Params:
160 	 *     area = the #GtkCellArea used to layout cells
161 	 *
162 	 * Return: A newly created #GtkEntryCompletion object
163 	 *
164 	 * Since: 3.0
165 	 *
166 	 * Throws: ConstructionException GTK+ fails to create the object.
167 	 */
168 	public this(CellArea area)
169 	{
170 		auto p = gtk_entry_completion_new_with_area((area is null) ? null : area.getCellAreaStruct());
171 		
172 		if(p is null)
173 		{
174 			throw new ConstructionException("null returned by new_with_area");
175 		}
176 		
177 		this(cast(GtkEntryCompletion*) p, true);
178 	}
179 
180 	/**
181 	 * Requests a completion operation, or in other words a refiltering of the
182 	 * current list with completions, using the current key. The completion list
183 	 * view will be updated accordingly.
184 	 *
185 	 * Since: 2.4
186 	 */
187 	public void complete()
188 	{
189 		gtk_entry_completion_complete(gtkEntryCompletion);
190 	}
191 
192 	/**
193 	 * Computes the common prefix that is shared by all rows in @completion
194 	 * that start with @key. If no row matches @key, %NULL will be returned.
195 	 * Note that a text column must have been set for this function to work,
196 	 * see gtk_entry_completion_set_text_column() for details.
197 	 *
198 	 * Params:
199 	 *     key = The text to complete for
200 	 *
201 	 * Return: The common prefix all rows starting with
202 	 *     @key or %NULL if no row matches @key.
203 	 *
204 	 * Since: 3.4
205 	 */
206 	public string computePrefix(string key)
207 	{
208 		auto retStr = gtk_entry_completion_compute_prefix(gtkEntryCompletion, Str.toStringz(key));
209 		
210 		scope(exit) Str.freeString(retStr);
211 		return Str.toString(retStr);
212 	}
213 
214 	/**
215 	 * Deletes the action at @index_ from @completion’s action list.
216 	 *
217 	 * Note that @index_ is a relative position and the position of an
218 	 * action may have changed since it was inserted.
219 	 *
220 	 * Params:
221 	 *     index = the index of the item to delete
222 	 *
223 	 * Since: 2.4
224 	 */
225 	public void deleteAction(int index)
226 	{
227 		gtk_entry_completion_delete_action(gtkEntryCompletion, index);
228 	}
229 
230 	/**
231 	 * Get the original text entered by the user that triggered
232 	 * the completion or %NULL if there’s no completion ongoing.
233 	 *
234 	 * Return: the prefix for the current completion
235 	 *
236 	 * Since: 2.12
237 	 */
238 	public string getCompletionPrefix()
239 	{
240 		return Str.toString(gtk_entry_completion_get_completion_prefix(gtkEntryCompletion));
241 	}
242 
243 	/**
244 	 * Gets the entry @completion has been attached to.
245 	 *
246 	 * Return: The entry @completion has been attached to
247 	 *
248 	 * Since: 2.4
249 	 */
250 	public Widget getEntry()
251 	{
252 		auto p = gtk_entry_completion_get_entry(gtkEntryCompletion);
253 		
254 		if(p is null)
255 		{
256 			return null;
257 		}
258 		
259 		return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p);
260 	}
261 
262 	/**
263 	 * Returns whether the common prefix of the possible completions should
264 	 * be automatically inserted in the entry.
265 	 *
266 	 * Return: %TRUE if inline completion is turned on
267 	 *
268 	 * Since: 2.6
269 	 */
270 	public bool getInlineCompletion()
271 	{
272 		return gtk_entry_completion_get_inline_completion(gtkEntryCompletion) != 0;
273 	}
274 
275 	/**
276 	 * Returns %TRUE if inline-selection mode is turned on.
277 	 *
278 	 * Return: %TRUE if inline-selection mode is on
279 	 *
280 	 * Since: 2.12
281 	 */
282 	public bool getInlineSelection()
283 	{
284 		return gtk_entry_completion_get_inline_selection(gtkEntryCompletion) != 0;
285 	}
286 
287 	/**
288 	 * Returns the minimum key length as set for @completion.
289 	 *
290 	 * Return: The currently used minimum key length
291 	 *
292 	 * Since: 2.4
293 	 */
294 	public int getMinimumKeyLength()
295 	{
296 		return gtk_entry_completion_get_minimum_key_length(gtkEntryCompletion);
297 	}
298 
299 	/**
300 	 * Returns the model the #GtkEntryCompletion is using as data source.
301 	 * Returns %NULL if the model is unset.
302 	 *
303 	 * Return: A #GtkTreeModel, or %NULL if none
304 	 *     is currently being used
305 	 *
306 	 * Since: 2.4
307 	 */
308 	public TreeModelIF getModel()
309 	{
310 		auto p = gtk_entry_completion_get_model(gtkEntryCompletion);
311 		
312 		if(p is null)
313 		{
314 			return null;
315 		}
316 		
317 		return ObjectG.getDObject!(TreeModel, TreeModelIF)(cast(GtkTreeModel*) p);
318 	}
319 
320 	/**
321 	 * Returns whether the completions should be presented in a popup window.
322 	 *
323 	 * Return: %TRUE if popup completion is turned on
324 	 *
325 	 * Since: 2.6
326 	 */
327 	public bool getPopupCompletion()
328 	{
329 		return gtk_entry_completion_get_popup_completion(gtkEntryCompletion) != 0;
330 	}
331 
332 	/**
333 	 * Returns whether the  completion popup window will be resized to the
334 	 * width of the entry.
335 	 *
336 	 * Return: %TRUE if the popup window will be resized to the width of
337 	 *     the entry
338 	 *
339 	 * Since: 2.8
340 	 */
341 	public bool getPopupSetWidth()
342 	{
343 		return gtk_entry_completion_get_popup_set_width(gtkEntryCompletion) != 0;
344 	}
345 
346 	/**
347 	 * Returns whether the completion popup window will appear even if there is
348 	 * only a single match.
349 	 *
350 	 * Return: %TRUE if the popup window will appear regardless of the
351 	 *     number of matches
352 	 *
353 	 * Since: 2.8
354 	 */
355 	public bool getPopupSingleMatch()
356 	{
357 		return gtk_entry_completion_get_popup_single_match(gtkEntryCompletion) != 0;
358 	}
359 
360 	/**
361 	 * Returns the column in the model of @completion to get strings from.
362 	 *
363 	 * Return: the column containing the strings
364 	 *
365 	 * Since: 2.6
366 	 */
367 	public int getTextColumn()
368 	{
369 		return gtk_entry_completion_get_text_column(gtkEntryCompletion);
370 	}
371 
372 	/**
373 	 * Inserts an action in @completion’s action item list at position @index_
374 	 * with markup @markup.
375 	 *
376 	 * Params:
377 	 *     index = the index of the item to insert
378 	 *     markup = markup of the item to insert
379 	 *
380 	 * Since: 2.4
381 	 */
382 	public void insertActionMarkup(int index, string markup)
383 	{
384 		gtk_entry_completion_insert_action_markup(gtkEntryCompletion, index, Str.toStringz(markup));
385 	}
386 
387 	/**
388 	 * Inserts an action in @completion’s action item list at position @index_
389 	 * with text @text. If you want the action item to have markup, use
390 	 * gtk_entry_completion_insert_action_markup().
391 	 *
392 	 * Note that @index_ is a relative position in the list of actions and
393 	 * the position of an action can change when deleting a different action.
394 	 *
395 	 * Params:
396 	 *     index = the index of the item to insert
397 	 *     text = text of the item to insert
398 	 *
399 	 * Since: 2.4
400 	 */
401 	public void insertActionText(int index, string text)
402 	{
403 		gtk_entry_completion_insert_action_text(gtkEntryCompletion, index, Str.toStringz(text));
404 	}
405 
406 	/**
407 	 * Requests a prefix insertion.
408 	 *
409 	 * Since: 2.6
410 	 */
411 	public void insertPrefix()
412 	{
413 		gtk_entry_completion_insert_prefix(gtkEntryCompletion);
414 	}
415 
416 	/**
417 	 * Sets whether the common prefix of the possible completions should
418 	 * be automatically inserted in the entry.
419 	 *
420 	 * Params:
421 	 *     inlineCompletion = %TRUE to do inline completion
422 	 *
423 	 * Since: 2.6
424 	 */
425 	public void setInlineCompletion(bool inlineCompletion)
426 	{
427 		gtk_entry_completion_set_inline_completion(gtkEntryCompletion, inlineCompletion);
428 	}
429 
430 	/**
431 	 * Sets whether it is possible to cycle through the possible completions
432 	 * inside the entry.
433 	 *
434 	 * Params:
435 	 *     inlineSelection = %TRUE to do inline selection
436 	 *
437 	 * Since: 2.12
438 	 */
439 	public void setInlineSelection(bool inlineSelection)
440 	{
441 		gtk_entry_completion_set_inline_selection(gtkEntryCompletion, inlineSelection);
442 	}
443 
444 	/**
445 	 * Sets the match function for @completion to be @func. The match function
446 	 * is used to determine if a row should or should not be in the completion
447 	 * list.
448 	 *
449 	 * Params:
450 	 *     func = the #GtkEntryCompletionMatchFunc to use
451 	 *     funcData = user data for @func
452 	 *     funcNotify = destroy notify for @func_data.
453 	 *
454 	 * Since: 2.4
455 	 */
456 	public void setMatchFunc(GtkEntryCompletionMatchFunc func, void* funcData, GDestroyNotify funcNotify)
457 	{
458 		gtk_entry_completion_set_match_func(gtkEntryCompletion, func, funcData, funcNotify);
459 	}
460 
461 	/**
462 	 * Requires the length of the search key for @completion to be at least
463 	 * @length. This is useful for long lists, where completing using a small
464 	 * key takes a lot of time and will come up with meaningless results anyway
465 	 * (ie, a too large dataset).
466 	 *
467 	 * Params:
468 	 *     length = the minimum length of the key in order to start completing
469 	 *
470 	 * Since: 2.4
471 	 */
472 	public void setMinimumKeyLength(int length)
473 	{
474 		gtk_entry_completion_set_minimum_key_length(gtkEntryCompletion, length);
475 	}
476 
477 	/**
478 	 * Sets the model for a #GtkEntryCompletion. If @completion already has
479 	 * a model set, it will remove it before setting the new model.
480 	 * If model is %NULL, then it will unset the model.
481 	 *
482 	 * Params:
483 	 *     model = the #GtkTreeModel
484 	 *
485 	 * Since: 2.4
486 	 */
487 	public void setModel(TreeModelIF model)
488 	{
489 		gtk_entry_completion_set_model(gtkEntryCompletion, (model is null) ? null : model.getTreeModelStruct());
490 	}
491 
492 	/**
493 	 * Sets whether the completions should be presented in a popup window.
494 	 *
495 	 * Params:
496 	 *     popupCompletion = %TRUE to do popup completion
497 	 *
498 	 * Since: 2.6
499 	 */
500 	public void setPopupCompletion(bool popupCompletion)
501 	{
502 		gtk_entry_completion_set_popup_completion(gtkEntryCompletion, popupCompletion);
503 	}
504 
505 	/**
506 	 * Sets whether the completion popup window will be resized to be the same
507 	 * width as the entry.
508 	 *
509 	 * Params:
510 	 *     popupSetWidth = %TRUE to make the width of the popup the same as the entry
511 	 *
512 	 * Since: 2.8
513 	 */
514 	public void setPopupSetWidth(bool popupSetWidth)
515 	{
516 		gtk_entry_completion_set_popup_set_width(gtkEntryCompletion, popupSetWidth);
517 	}
518 
519 	/**
520 	 * Sets whether the completion popup window will appear even if there is
521 	 * only a single match. You may want to set this to %FALSE if you
522 	 * are using [inline completion][GtkEntryCompletion--inline-completion].
523 	 *
524 	 * Params:
525 	 *     popupSingleMatch = %TRUE if the popup should appear even for a single
526 	 *         match
527 	 *
528 	 * Since: 2.8
529 	 */
530 	public void setPopupSingleMatch(bool popupSingleMatch)
531 	{
532 		gtk_entry_completion_set_popup_single_match(gtkEntryCompletion, popupSingleMatch);
533 	}
534 
535 	/**
536 	 * Convenience function for setting up the most used case of this code: a
537 	 * completion list with just strings. This function will set up @completion
538 	 * to have a list displaying all (and just) strings in the completion list,
539 	 * and to get those strings from @column in the model of @completion.
540 	 *
541 	 * This functions creates and adds a #GtkCellRendererText for the selected
542 	 * column. If you need to set the text column, but don't want the cell
543 	 * renderer, use g_object_set() to set the #GtkEntryCompletion:text-column
544 	 * property directly.
545 	 *
546 	 * Params:
547 	 *     column = the column in the model of @completion to get strings from
548 	 *
549 	 * Since: 2.4
550 	 */
551 	public void setTextColumn(int column)
552 	{
553 		gtk_entry_completion_set_text_column(gtkEntryCompletion, column);
554 	}
555 
556 	protected class OnActionActivatedDelegateWrapper
557 	{
558 		void delegate(int, EntryCompletion) dlg;
559 		gulong handlerId;
560 		ConnectFlags flags;
561 		this(void delegate(int, EntryCompletion) dlg, gulong handlerId, ConnectFlags flags)
562 		{
563 			this.dlg = dlg;
564 			this.handlerId = handlerId;
565 			this.flags = flags;
566 		}
567 	}
568 	protected OnActionActivatedDelegateWrapper[] onActionActivatedListeners;
569 
570 	/**
571 	 * Gets emitted when an action is activated.
572 	 *
573 	 * Params:
574 	 *     index = the index of the activated action
575 	 *
576 	 * Since: 2.4
577 	 */
578 	gulong addOnActionActivated(void delegate(int, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
579 	{
580 		onActionActivatedListeners ~= new OnActionActivatedDelegateWrapper(dlg, 0, connectFlags);
581 		onActionActivatedListeners[onActionActivatedListeners.length - 1].handlerId = Signals.connectData(
582 			this,
583 			"action-activated",
584 			cast(GCallback)&callBackActionActivated,
585 			cast(void*)onActionActivatedListeners[onActionActivatedListeners.length - 1],
586 			cast(GClosureNotify)&callBackActionActivatedDestroy,
587 			connectFlags);
588 		return onActionActivatedListeners[onActionActivatedListeners.length - 1].handlerId;
589 	}
590 	
591 	extern(C) static void callBackActionActivated(GtkEntryCompletion* entrycompletionStruct, int index,OnActionActivatedDelegateWrapper wrapper)
592 	{
593 		wrapper.dlg(index, wrapper.outer);
594 	}
595 	
596 	extern(C) static void callBackActionActivatedDestroy(OnActionActivatedDelegateWrapper wrapper, GClosure* closure)
597 	{
598 		wrapper.outer.internalRemoveOnActionActivated(wrapper);
599 	}
600 
601 	protected void internalRemoveOnActionActivated(OnActionActivatedDelegateWrapper source)
602 	{
603 		foreach(index, wrapper; onActionActivatedListeners)
604 		{
605 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
606 			{
607 				onActionActivatedListeners[index] = null;
608 				onActionActivatedListeners = std.algorithm.remove(onActionActivatedListeners, index);
609 				break;
610 			}
611 		}
612 	}
613 	
614 
615 	protected class OnCursorOnMatchDelegateWrapper
616 	{
617 		bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg;
618 		gulong handlerId;
619 		ConnectFlags flags;
620 		this(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg, gulong handlerId, ConnectFlags flags)
621 		{
622 			this.dlg = dlg;
623 			this.handlerId = handlerId;
624 			this.flags = flags;
625 		}
626 	}
627 	protected OnCursorOnMatchDelegateWrapper[] onCursorOnMatchListeners;
628 
629 	/**
630 	 * Gets emitted when a match from the cursor is on a match
631 	 * of the list. The default behaviour is to replace the contents
632 	 * of the entry with the contents of the text column in the row
633 	 * pointed to by @iter.
634 	 *
635 	 * Note that @model is the model that was passed to
636 	 * gtk_entry_completion_set_model().
637 	 *
638 	 * Params:
639 	 *     model = the #GtkTreeModel containing the matches
640 	 *     iter = a #GtkTreeIter positioned at the selected match
641 	 *
642 	 * Return: %TRUE if the signal has been handled
643 	 *
644 	 * Since: 2.12
645 	 */
646 	gulong addOnCursorOnMatch(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
647 	{
648 		onCursorOnMatchListeners ~= new OnCursorOnMatchDelegateWrapper(dlg, 0, connectFlags);
649 		onCursorOnMatchListeners[onCursorOnMatchListeners.length - 1].handlerId = Signals.connectData(
650 			this,
651 			"cursor-on-match",
652 			cast(GCallback)&callBackCursorOnMatch,
653 			cast(void*)onCursorOnMatchListeners[onCursorOnMatchListeners.length - 1],
654 			cast(GClosureNotify)&callBackCursorOnMatchDestroy,
655 			connectFlags);
656 		return onCursorOnMatchListeners[onCursorOnMatchListeners.length - 1].handlerId;
657 	}
658 	
659 	extern(C) static int callBackCursorOnMatch(GtkEntryCompletion* entrycompletionStruct, GtkTreeModel* model, GtkTreeIter* iter,OnCursorOnMatchDelegateWrapper wrapper)
660 	{
661 		return wrapper.dlg(ObjectG.getDObject!(TreeModel, TreeModelIF)(model), ObjectG.getDObject!(TreeIter)(iter), wrapper.outer);
662 	}
663 	
664 	extern(C) static void callBackCursorOnMatchDestroy(OnCursorOnMatchDelegateWrapper wrapper, GClosure* closure)
665 	{
666 		wrapper.outer.internalRemoveOnCursorOnMatch(wrapper);
667 	}
668 
669 	protected void internalRemoveOnCursorOnMatch(OnCursorOnMatchDelegateWrapper source)
670 	{
671 		foreach(index, wrapper; onCursorOnMatchListeners)
672 		{
673 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
674 			{
675 				onCursorOnMatchListeners[index] = null;
676 				onCursorOnMatchListeners = std.algorithm.remove(onCursorOnMatchListeners, index);
677 				break;
678 			}
679 		}
680 	}
681 	
682 
683 	protected class OnInsertPrefixDelegateWrapper
684 	{
685 		bool delegate(string, EntryCompletion) dlg;
686 		gulong handlerId;
687 		ConnectFlags flags;
688 		this(bool delegate(string, EntryCompletion) dlg, gulong handlerId, ConnectFlags flags)
689 		{
690 			this.dlg = dlg;
691 			this.handlerId = handlerId;
692 			this.flags = flags;
693 		}
694 	}
695 	protected OnInsertPrefixDelegateWrapper[] onInsertPrefixListeners;
696 
697 	/**
698 	 * Gets emitted when the inline autocompletion is triggered.
699 	 * The default behaviour is to make the entry display the
700 	 * whole prefix and select the newly inserted part.
701 	 *
702 	 * Applications may connect to this signal in order to insert only a
703 	 * smaller part of the @prefix into the entry - e.g. the entry used in
704 	 * the #GtkFileChooser inserts only the part of the prefix up to the
705 	 * next '/'.
706 	 *
707 	 * Params:
708 	 *     prefix = the common prefix of all possible completions
709 	 *
710 	 * Return: %TRUE if the signal has been handled
711 	 *
712 	 * Since: 2.6
713 	 */
714 	gulong addOnInsertPrefix(bool delegate(string, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
715 	{
716 		onInsertPrefixListeners ~= new OnInsertPrefixDelegateWrapper(dlg, 0, connectFlags);
717 		onInsertPrefixListeners[onInsertPrefixListeners.length - 1].handlerId = Signals.connectData(
718 			this,
719 			"insert-prefix",
720 			cast(GCallback)&callBackInsertPrefix,
721 			cast(void*)onInsertPrefixListeners[onInsertPrefixListeners.length - 1],
722 			cast(GClosureNotify)&callBackInsertPrefixDestroy,
723 			connectFlags);
724 		return onInsertPrefixListeners[onInsertPrefixListeners.length - 1].handlerId;
725 	}
726 	
727 	extern(C) static int callBackInsertPrefix(GtkEntryCompletion* entrycompletionStruct, char* prefix,OnInsertPrefixDelegateWrapper wrapper)
728 	{
729 		return wrapper.dlg(Str.toString(prefix), wrapper.outer);
730 	}
731 	
732 	extern(C) static void callBackInsertPrefixDestroy(OnInsertPrefixDelegateWrapper wrapper, GClosure* closure)
733 	{
734 		wrapper.outer.internalRemoveOnInsertPrefix(wrapper);
735 	}
736 
737 	protected void internalRemoveOnInsertPrefix(OnInsertPrefixDelegateWrapper source)
738 	{
739 		foreach(index, wrapper; onInsertPrefixListeners)
740 		{
741 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
742 			{
743 				onInsertPrefixListeners[index] = null;
744 				onInsertPrefixListeners = std.algorithm.remove(onInsertPrefixListeners, index);
745 				break;
746 			}
747 		}
748 	}
749 	
750 
751 	protected class OnMatchSelectedDelegateWrapper
752 	{
753 		bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg;
754 		gulong handlerId;
755 		ConnectFlags flags;
756 		this(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg, gulong handlerId, ConnectFlags flags)
757 		{
758 			this.dlg = dlg;
759 			this.handlerId = handlerId;
760 			this.flags = flags;
761 		}
762 	}
763 	protected OnMatchSelectedDelegateWrapper[] onMatchSelectedListeners;
764 
765 	/**
766 	 * Gets emitted when a match from the list is selected.
767 	 * The default behaviour is to replace the contents of the
768 	 * entry with the contents of the text column in the row
769 	 * pointed to by @iter.
770 	 *
771 	 * Note that @model is the model that was passed to
772 	 * gtk_entry_completion_set_model().
773 	 *
774 	 * Params:
775 	 *     model = the #GtkTreeModel containing the matches
776 	 *     iter = a #GtkTreeIter positioned at the selected match
777 	 *
778 	 * Return: %TRUE if the signal has been handled
779 	 *
780 	 * Since: 2.4
781 	 */
782 	gulong addOnMatchSelected(bool delegate(TreeModelIF, TreeIter, EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
783 	{
784 		onMatchSelectedListeners ~= new OnMatchSelectedDelegateWrapper(dlg, 0, connectFlags);
785 		onMatchSelectedListeners[onMatchSelectedListeners.length - 1].handlerId = Signals.connectData(
786 			this,
787 			"match-selected",
788 			cast(GCallback)&callBackMatchSelected,
789 			cast(void*)onMatchSelectedListeners[onMatchSelectedListeners.length - 1],
790 			cast(GClosureNotify)&callBackMatchSelectedDestroy,
791 			connectFlags);
792 		return onMatchSelectedListeners[onMatchSelectedListeners.length - 1].handlerId;
793 	}
794 	
795 	extern(C) static int callBackMatchSelected(GtkEntryCompletion* entrycompletionStruct, GtkTreeModel* model, GtkTreeIter* iter,OnMatchSelectedDelegateWrapper wrapper)
796 	{
797 		return wrapper.dlg(ObjectG.getDObject!(TreeModel, TreeModelIF)(model), ObjectG.getDObject!(TreeIter)(iter), wrapper.outer);
798 	}
799 	
800 	extern(C) static void callBackMatchSelectedDestroy(OnMatchSelectedDelegateWrapper wrapper, GClosure* closure)
801 	{
802 		wrapper.outer.internalRemoveOnMatchSelected(wrapper);
803 	}
804 
805 	protected void internalRemoveOnMatchSelected(OnMatchSelectedDelegateWrapper source)
806 	{
807 		foreach(index, wrapper; onMatchSelectedListeners)
808 		{
809 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
810 			{
811 				onMatchSelectedListeners[index] = null;
812 				onMatchSelectedListeners = std.algorithm.remove(onMatchSelectedListeners, index);
813 				break;
814 			}
815 		}
816 	}
817 	
818 
819 	protected class OnNoMatchesDelegateWrapper
820 	{
821 		void delegate(EntryCompletion) dlg;
822 		gulong handlerId;
823 		ConnectFlags flags;
824 		this(void delegate(EntryCompletion) dlg, gulong handlerId, ConnectFlags flags)
825 		{
826 			this.dlg = dlg;
827 			this.handlerId = handlerId;
828 			this.flags = flags;
829 		}
830 	}
831 	protected OnNoMatchesDelegateWrapper[] onNoMatchesListeners;
832 
833 	/**
834 	 * Gets emitted when the filter model has zero
835 	 * number of rows in completion_complete method.
836 	 * (In other words when GtkEntryCompletion is out of
837 	 * suggestions)
838 	 *
839 	 * Since: 3.14
840 	 */
841 	gulong addOnNoMatches(void delegate(EntryCompletion) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
842 	{
843 		onNoMatchesListeners ~= new OnNoMatchesDelegateWrapper(dlg, 0, connectFlags);
844 		onNoMatchesListeners[onNoMatchesListeners.length - 1].handlerId = Signals.connectData(
845 			this,
846 			"no-matches",
847 			cast(GCallback)&callBackNoMatches,
848 			cast(void*)onNoMatchesListeners[onNoMatchesListeners.length - 1],
849 			cast(GClosureNotify)&callBackNoMatchesDestroy,
850 			connectFlags);
851 		return onNoMatchesListeners[onNoMatchesListeners.length - 1].handlerId;
852 	}
853 	
854 	extern(C) static void callBackNoMatches(GtkEntryCompletion* entrycompletionStruct,OnNoMatchesDelegateWrapper wrapper)
855 	{
856 		wrapper.dlg(wrapper.outer);
857 	}
858 	
859 	extern(C) static void callBackNoMatchesDestroy(OnNoMatchesDelegateWrapper wrapper, GClosure* closure)
860 	{
861 		wrapper.outer.internalRemoveOnNoMatches(wrapper);
862 	}
863 
864 	protected void internalRemoveOnNoMatches(OnNoMatchesDelegateWrapper source)
865 	{
866 		foreach(index, wrapper; onNoMatchesListeners)
867 		{
868 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
869 			{
870 				onNoMatchesListeners[index] = null;
871 				onNoMatchesListeners = std.algorithm.remove(onNoMatchesListeners, index);
872 				break;
873 			}
874 		}
875 	}
876 	
877 }