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.SearchEntry;
26 
27 private import gdk.Event;
28 private import glib.ConstructionException;
29 private import gobject.ObjectG;
30 private import gobject.Signals;
31 private import gtk.Entry;
32 private import gtk.Widget;
33 public  import gtkc.gdktypes;
34 private import gtkc.gtk;
35 public  import gtkc.gtktypes;
36 private import std.algorithm;
37 
38 
39 /**
40  * #GtkSearchEntry is a subclass of #GtkEntry that has been
41  * tailored for use as a search entry.
42  * 
43  * It will show an inactive symbolic “find” icon when the search
44  * entry is empty, and a symbolic “clear” icon when there is text.
45  * Clicking on the “clear” icon will empty the search entry.
46  * 
47  * Note that the search/clear icon is shown using a secondary
48  * icon, and thus does not work if you are using the secondary
49  * icon position for some other purpose.
50  * 
51  * To make filtering appear more reactive, it is a good idea to
52  * not react to every change in the entry text immediately, but
53  * only after a short delay. To support this, #GtkSearchEntry
54  * emits the #GtkSearchEntry::search-changed signal which can
55  * be used instead of the #GtkEditable::changed signal.
56  * 
57  * The #GtkSearchEntry::previous-match, #GtkSearchEntry::next-match
58  * and #GtkSearchEntry::stop-search signals can be uesd to implement
59  * moving between search results and ending the search.
60  * 
61  * Often, GtkSearchEntry will be fed events by means of being
62  * placed inside a #GtkSearchBar. If that is not the case,
63  * you can use gtk_search_entry_handle_event() to pass events.
64  */
65 public class SearchEntry : Entry
66 {
67 	/** the main Gtk struct */
68 	protected GtkSearchEntry* gtkSearchEntry;
69 
70 	/** Get the main Gtk struct */
71 	public GtkSearchEntry* getSearchEntryStruct()
72 	{
73 		return gtkSearchEntry;
74 	}
75 
76 	/** the main Gtk struct as a void* */
77 	protected override void* getStruct()
78 	{
79 		return cast(void*)gtkSearchEntry;
80 	}
81 
82 	protected override void setStruct(GObject* obj)
83 	{
84 		gtkSearchEntry = cast(GtkSearchEntry*)obj;
85 		super.setStruct(obj);
86 	}
87 
88 	/**
89 	 * Sets our main struct and passes it to the parent class.
90 	 */
91 	public this (GtkSearchEntry* gtkSearchEntry, bool ownedRef = false)
92 	{
93 		this.gtkSearchEntry = gtkSearchEntry;
94 		super(cast(GtkEntry*)gtkSearchEntry, ownedRef);
95 	}
96 
97 
98 	/** */
99 	public static GType getType()
100 	{
101 		return gtk_search_entry_get_type();
102 	}
103 
104 	/**
105 	 * Creates a #GtkSearchEntry, with a find icon when the search field is
106 	 * empty, and a clear icon when it isn't.
107 	 *
108 	 * Return: a new #GtkSearchEntry
109 	 *
110 	 * Since: 3.6
111 	 *
112 	 * Throws: ConstructionException GTK+ fails to create the object.
113 	 */
114 	public this()
115 	{
116 		auto p = gtk_search_entry_new();
117 		
118 		if(p is null)
119 		{
120 			throw new ConstructionException("null returned by new");
121 		}
122 		
123 		this(cast(GtkSearchEntry*) p);
124 	}
125 
126 	/**
127 	 * This function should be called when the top-level window
128 	 * which contains the search entry received a key event. If
129 	 * the entry is part of a #GtkSearchBar, it is preferable
130 	 * to call gtk_search_bar_handle_event() instead, which will
131 	 * reveal the entry in addition to passing the event to this
132 	 * function.
133 	 *
134 	 * If the key event is handled by the search entry and starts
135 	 * or continues a search, %GDK_EVENT_STOP will be returned.
136 	 * The caller should ensure that the entry is shown in this
137 	 * case, and not propagate the event further.
138 	 *
139 	 * Params:
140 	 *     event = a key event
141 	 *
142 	 * Return: %GDK_EVENT_STOP if the key press event resulted
143 	 *     in a search beginning or continuing, %GDK_EVENT_PROPAGATE
144 	 *     otherwise.
145 	 *
146 	 * Since: 3.16
147 	 */
148 	public bool handleEvent(Event event)
149 	{
150 		return gtk_search_entry_handle_event(gtkSearchEntry, (event is null) ? null : event.getEventStruct()) != 0;
151 	}
152 
153 	protected class OnNextMatchDelegateWrapper
154 	{
155 		void delegate(SearchEntry) dlg;
156 		gulong handlerId;
157 		ConnectFlags flags;
158 		this(void delegate(SearchEntry) dlg, gulong handlerId, ConnectFlags flags)
159 		{
160 			this.dlg = dlg;
161 			this.handlerId = handlerId;
162 			this.flags = flags;
163 		}
164 	}
165 	protected OnNextMatchDelegateWrapper[] onNextMatchListeners;
166 
167 	/**
168 	 * The ::next-match signal is a [keybinding signal][GtkBindingSignal]
169 	 * which gets emitted when the user initiates a move to the next match
170 	 * for the current search string.
171 	 *
172 	 * Applications should connect to it, to implement moving between
173 	 * matches.
174 	 *
175 	 * The default bindings for this signal is Ctrl-g.
176 	 *
177 	 * Since: 3.16
178 	 */
179 	gulong addOnNextMatch(void delegate(SearchEntry) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
180 	{
181 		onNextMatchListeners ~= new OnNextMatchDelegateWrapper(dlg, 0, connectFlags);
182 		onNextMatchListeners[onNextMatchListeners.length - 1].handlerId = Signals.connectData(
183 			this,
184 			"next-match",
185 			cast(GCallback)&callBackNextMatch,
186 			cast(void*)onNextMatchListeners[onNextMatchListeners.length - 1],
187 			cast(GClosureNotify)&callBackNextMatchDestroy,
188 			connectFlags);
189 		return onNextMatchListeners[onNextMatchListeners.length - 1].handlerId;
190 	}
191 	
192 	extern(C) static void callBackNextMatch(GtkSearchEntry* searchentryStruct,OnNextMatchDelegateWrapper wrapper)
193 	{
194 		wrapper.dlg(wrapper.outer);
195 	}
196 	
197 	extern(C) static void callBackNextMatchDestroy(OnNextMatchDelegateWrapper wrapper, GClosure* closure)
198 	{
199 		wrapper.outer.internalRemoveOnNextMatch(wrapper);
200 	}
201 
202 	protected void internalRemoveOnNextMatch(OnNextMatchDelegateWrapper source)
203 	{
204 		foreach(index, wrapper; onNextMatchListeners)
205 		{
206 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
207 			{
208 				onNextMatchListeners[index] = null;
209 				onNextMatchListeners = std.algorithm.remove(onNextMatchListeners, index);
210 				break;
211 			}
212 		}
213 	}
214 	
215 
216 	protected class OnPreviousMatchDelegateWrapper
217 	{
218 		void delegate(SearchEntry) dlg;
219 		gulong handlerId;
220 		ConnectFlags flags;
221 		this(void delegate(SearchEntry) dlg, gulong handlerId, ConnectFlags flags)
222 		{
223 			this.dlg = dlg;
224 			this.handlerId = handlerId;
225 			this.flags = flags;
226 		}
227 	}
228 	protected OnPreviousMatchDelegateWrapper[] onPreviousMatchListeners;
229 
230 	/**
231 	 * The ::previous-match signal is a [keybinding signal][GtkBindingSignal]
232 	 * which gets emitted when the user initiates a move to the previous match
233 	 * for the current search string.
234 	 *
235 	 * Applications should connect to it, to implement moving between
236 	 * matches.
237 	 *
238 	 * The default bindings for this signal is Ctrl-Shift-g.
239 	 *
240 	 * Since: 3.16
241 	 */
242 	gulong addOnPreviousMatch(void delegate(SearchEntry) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
243 	{
244 		onPreviousMatchListeners ~= new OnPreviousMatchDelegateWrapper(dlg, 0, connectFlags);
245 		onPreviousMatchListeners[onPreviousMatchListeners.length - 1].handlerId = Signals.connectData(
246 			this,
247 			"previous-match",
248 			cast(GCallback)&callBackPreviousMatch,
249 			cast(void*)onPreviousMatchListeners[onPreviousMatchListeners.length - 1],
250 			cast(GClosureNotify)&callBackPreviousMatchDestroy,
251 			connectFlags);
252 		return onPreviousMatchListeners[onPreviousMatchListeners.length - 1].handlerId;
253 	}
254 	
255 	extern(C) static void callBackPreviousMatch(GtkSearchEntry* searchentryStruct,OnPreviousMatchDelegateWrapper wrapper)
256 	{
257 		wrapper.dlg(wrapper.outer);
258 	}
259 	
260 	extern(C) static void callBackPreviousMatchDestroy(OnPreviousMatchDelegateWrapper wrapper, GClosure* closure)
261 	{
262 		wrapper.outer.internalRemoveOnPreviousMatch(wrapper);
263 	}
264 
265 	protected void internalRemoveOnPreviousMatch(OnPreviousMatchDelegateWrapper source)
266 	{
267 		foreach(index, wrapper; onPreviousMatchListeners)
268 		{
269 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
270 			{
271 				onPreviousMatchListeners[index] = null;
272 				onPreviousMatchListeners = std.algorithm.remove(onPreviousMatchListeners, index);
273 				break;
274 			}
275 		}
276 	}
277 	
278 
279 	protected class OnSearchChangedDelegateWrapper
280 	{
281 		void delegate(SearchEntry) dlg;
282 		gulong handlerId;
283 		ConnectFlags flags;
284 		this(void delegate(SearchEntry) dlg, gulong handlerId, ConnectFlags flags)
285 		{
286 			this.dlg = dlg;
287 			this.handlerId = handlerId;
288 			this.flags = flags;
289 		}
290 	}
291 	protected OnSearchChangedDelegateWrapper[] onSearchChangedListeners;
292 
293 	/**
294 	 * The #GtkSearchEntry::search-changed signal is emitted with a short
295 	 * delay of 150 milliseconds after the last change to the entry text.
296 	 *
297 	 * Since: 3.10
298 	 */
299 	gulong addOnSearchChanged(void delegate(SearchEntry) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
300 	{
301 		onSearchChangedListeners ~= new OnSearchChangedDelegateWrapper(dlg, 0, connectFlags);
302 		onSearchChangedListeners[onSearchChangedListeners.length - 1].handlerId = Signals.connectData(
303 			this,
304 			"search-changed",
305 			cast(GCallback)&callBackSearchChanged,
306 			cast(void*)onSearchChangedListeners[onSearchChangedListeners.length - 1],
307 			cast(GClosureNotify)&callBackSearchChangedDestroy,
308 			connectFlags);
309 		return onSearchChangedListeners[onSearchChangedListeners.length - 1].handlerId;
310 	}
311 	
312 	extern(C) static void callBackSearchChanged(GtkSearchEntry* searchentryStruct,OnSearchChangedDelegateWrapper wrapper)
313 	{
314 		wrapper.dlg(wrapper.outer);
315 	}
316 	
317 	extern(C) static void callBackSearchChangedDestroy(OnSearchChangedDelegateWrapper wrapper, GClosure* closure)
318 	{
319 		wrapper.outer.internalRemoveOnSearchChanged(wrapper);
320 	}
321 
322 	protected void internalRemoveOnSearchChanged(OnSearchChangedDelegateWrapper source)
323 	{
324 		foreach(index, wrapper; onSearchChangedListeners)
325 		{
326 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
327 			{
328 				onSearchChangedListeners[index] = null;
329 				onSearchChangedListeners = std.algorithm.remove(onSearchChangedListeners, index);
330 				break;
331 			}
332 		}
333 	}
334 	
335 
336 	protected class OnStopSearchDelegateWrapper
337 	{
338 		void delegate(SearchEntry) dlg;
339 		gulong handlerId;
340 		ConnectFlags flags;
341 		this(void delegate(SearchEntry) dlg, gulong handlerId, ConnectFlags flags)
342 		{
343 			this.dlg = dlg;
344 			this.handlerId = handlerId;
345 			this.flags = flags;
346 		}
347 	}
348 	protected OnStopSearchDelegateWrapper[] onStopSearchListeners;
349 
350 	/**
351 	 * The ::stop-search signal is a [keybinding signal][GtkBindingSignal]
352 	 * which gets emitted when the user stops a search via keyboard input.
353 	 *
354 	 * Applications should connect to it, to implement hiding the search
355 	 * entry in this case.
356 	 *
357 	 * The default bindings for this signal is Escape.
358 	 *
359 	 * Since: 3.16
360 	 */
361 	gulong addOnStopSearch(void delegate(SearchEntry) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
362 	{
363 		onStopSearchListeners ~= new OnStopSearchDelegateWrapper(dlg, 0, connectFlags);
364 		onStopSearchListeners[onStopSearchListeners.length - 1].handlerId = Signals.connectData(
365 			this,
366 			"stop-search",
367 			cast(GCallback)&callBackStopSearch,
368 			cast(void*)onStopSearchListeners[onStopSearchListeners.length - 1],
369 			cast(GClosureNotify)&callBackStopSearchDestroy,
370 			connectFlags);
371 		return onStopSearchListeners[onStopSearchListeners.length - 1].handlerId;
372 	}
373 	
374 	extern(C) static void callBackStopSearch(GtkSearchEntry* searchentryStruct,OnStopSearchDelegateWrapper wrapper)
375 	{
376 		wrapper.dlg(wrapper.outer);
377 	}
378 	
379 	extern(C) static void callBackStopSearchDestroy(OnStopSearchDelegateWrapper wrapper, GClosure* closure)
380 	{
381 		wrapper.outer.internalRemoveOnStopSearch(wrapper);
382 	}
383 
384 	protected void internalRemoveOnStopSearch(OnStopSearchDelegateWrapper source)
385 	{
386 		foreach(index, wrapper; onStopSearchListeners)
387 		{
388 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
389 			{
390 				onStopSearchListeners[index] = null;
391 				onStopSearchListeners = std.algorithm.remove(onStopSearchListeners, index);
392 				break;
393 			}
394 		}
395 	}
396 	
397 }