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.Assistant;
26 
27 private import gdkpixbuf.Pixbuf;
28 private import glib.ConstructionException;
29 private import glib.Str;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 private import gtk.Widget;
33 private import gtk.Window;
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 #GtkAssistant is a widget used to represent a generally complex
42  * operation splitted in several steps, guiding the user through its
43  * pages and controlling the page flow to collect the necessary data.
44  * 
45  * The design of GtkAssistant is that it controls what buttons to show
46  * and to make sensitive, based on what it knows about the page sequence
47  * and the [type][GtkAssistantPageType] of each page,
48  * in addition to state information like the page
49  * [completion][gtk-assistant-set-page-complete]
50  * and [committed][gtk-assistant-commit] status.
51  * 
52  * If you have a case that doesn’t quite fit in #GtkAssistants way of
53  * handling buttons, you can use the #GTK_ASSISTANT_PAGE_CUSTOM page
54  * type and handle buttons yourself.
55  * 
56  * # GtkAssistant as GtkBuildable
57  * 
58  * The GtkAssistant implementation of the #GtkBuildable interface
59  * exposes the @action_area as internal children with the name
60  * “action_area”.
61  * 
62  * To add pages to an assistant in #GtkBuilder, simply add it as a
63  * child to the GtkAssistant object, and set its child properties
64  * as necessary.
65  * 
66  * # CSS nodes
67  * 
68  * GtkAssistant has a single CSS node with the name assistant.
69  */
70 public class Assistant : Window
71 {
72 	/** the main Gtk struct */
73 	protected GtkAssistant* gtkAssistant;
74 
75 	/** Get the main Gtk struct */
76 	public GtkAssistant* getAssistantStruct(bool transferOwnership = false)
77 	{
78 		if (transferOwnership)
79 			ownedRef = false;
80 		return gtkAssistant;
81 	}
82 
83 	/** the main Gtk struct as a void* */
84 	protected override void* getStruct()
85 	{
86 		return cast(void*)gtkAssistant;
87 	}
88 
89 	protected override void setStruct(GObject* obj)
90 	{
91 		gtkAssistant = cast(GtkAssistant*)obj;
92 		super.setStruct(obj);
93 	}
94 
95 	/**
96 	 * Sets our main struct and passes it to the parent class.
97 	 */
98 	public this (GtkAssistant* gtkAssistant, bool ownedRef = false)
99 	{
100 		this.gtkAssistant = gtkAssistant;
101 		super(cast(GtkWindow*)gtkAssistant, ownedRef);
102 	}
103 
104 
105 	/** */
106 	public static GType getType()
107 	{
108 		return gtk_assistant_get_type();
109 	}
110 
111 	/**
112 	 * Creates a new #GtkAssistant.
113 	 *
114 	 * Returns: a newly created #GtkAssistant
115 	 *
116 	 * Since: 2.10
117 	 *
118 	 * Throws: ConstructionException GTK+ fails to create the object.
119 	 */
120 	public this()
121 	{
122 		auto p = gtk_assistant_new();
123 
124 		if(p is null)
125 		{
126 			throw new ConstructionException("null returned by new");
127 		}
128 
129 		this(cast(GtkAssistant*) p);
130 	}
131 
132 	/**
133 	 * Adds a widget to the action area of a #GtkAssistant.
134 	 *
135 	 * Params:
136 	 *     child = a #GtkWidget
137 	 *
138 	 * Since: 2.10
139 	 */
140 	public void addActionWidget(Widget child)
141 	{
142 		gtk_assistant_add_action_widget(gtkAssistant, (child is null) ? null : child.getWidgetStruct());
143 	}
144 
145 	/**
146 	 * Appends a page to the @assistant.
147 	 *
148 	 * Params:
149 	 *     page = a #GtkWidget
150 	 *
151 	 * Returns: the index (starting at 0) of the inserted page
152 	 *
153 	 * Since: 2.10
154 	 */
155 	public int appendPage(Widget page)
156 	{
157 		return gtk_assistant_append_page(gtkAssistant, (page is null) ? null : page.getWidgetStruct());
158 	}
159 
160 	/**
161 	 * Erases the visited page history so the back button is not
162 	 * shown on the current page, and removes the cancel button
163 	 * from subsequent pages.
164 	 *
165 	 * Use this when the information provided up to the current
166 	 * page is hereafter deemed permanent and cannot be modified
167 	 * or undone. For example, showing a progress page to track
168 	 * a long-running, unreversible operation after the user has
169 	 * clicked apply on a confirmation page.
170 	 *
171 	 * Since: 2.22
172 	 */
173 	public void commit()
174 	{
175 		gtk_assistant_commit(gtkAssistant);
176 	}
177 
178 	/**
179 	 * Returns the page number of the current page.
180 	 *
181 	 * Returns: The index (starting from 0) of the current
182 	 *     page in the @assistant, or -1 if the @assistant has no pages,
183 	 *     or no current page.
184 	 *
185 	 * Since: 2.10
186 	 */
187 	public int getCurrentPage()
188 	{
189 		return gtk_assistant_get_current_page(gtkAssistant);
190 	}
191 
192 	/**
193 	 * Returns the number of pages in the @assistant
194 	 *
195 	 * Returns: the number of pages in the @assistant
196 	 *
197 	 * Since: 2.10
198 	 */
199 	public int getNPages()
200 	{
201 		return gtk_assistant_get_n_pages(gtkAssistant);
202 	}
203 
204 	/**
205 	 * Returns the child widget contained in page number @page_num.
206 	 *
207 	 * Params:
208 	 *     pageNum = the index of a page in the @assistant,
209 	 *         or -1 to get the last page
210 	 *
211 	 * Returns: the child widget, or %NULL
212 	 *     if @page_num is out of bounds
213 	 *
214 	 * Since: 2.10
215 	 */
216 	public Widget getNthPage(int pageNum)
217 	{
218 		auto p = gtk_assistant_get_nth_page(gtkAssistant, pageNum);
219 
220 		if(p is null)
221 		{
222 			return null;
223 		}
224 
225 		return ObjectG.getDObject!(Widget)(cast(GtkWidget*) p);
226 	}
227 
228 	/**
229 	 * Gets whether @page is complete.
230 	 *
231 	 * Params:
232 	 *     page = a page of @assistant
233 	 *
234 	 * Returns: %TRUE if @page is complete.
235 	 *
236 	 * Since: 2.10
237 	 */
238 	public bool getPageComplete(Widget page)
239 	{
240 		return gtk_assistant_get_page_complete(gtkAssistant, (page is null) ? null : page.getWidgetStruct()) != 0;
241 	}
242 
243 	/**
244 	 * Gets whether page has padding.
245 	 *
246 	 * Params:
247 	 *     page = a page of @assistant
248 	 *
249 	 * Returns: %TRUE if @page has padding
250 	 *
251 	 * Since: 3.18
252 	 */
253 	public bool getPageHasPadding(Widget page)
254 	{
255 		return gtk_assistant_get_page_has_padding(gtkAssistant, (page is null) ? null : page.getWidgetStruct()) != 0;
256 	}
257 
258 	/**
259 	 * Gets the header image for @page.
260 	 *
261 	 * Deprecated: Since GTK+ 3.2, a header is no longer shown;
262 	 * add your header decoration to the page content instead.
263 	 *
264 	 * Params:
265 	 *     page = a page of @assistant
266 	 *
267 	 * Returns: the header image for @page,
268 	 *     or %NULL if there’s no header image for the page
269 	 *
270 	 * Since: 2.10
271 	 */
272 	public Pixbuf getPageHeaderImage(Widget page)
273 	{
274 		auto p = gtk_assistant_get_page_header_image(gtkAssistant, (page is null) ? null : page.getWidgetStruct());
275 
276 		if(p is null)
277 		{
278 			return null;
279 		}
280 
281 		return ObjectG.getDObject!(Pixbuf)(cast(GdkPixbuf*) p);
282 	}
283 
284 	/**
285 	 * Gets the side image for @page.
286 	 *
287 	 * Deprecated: Since GTK+ 3.2, sidebar images are not
288 	 * shown anymore.
289 	 *
290 	 * Params:
291 	 *     page = a page of @assistant
292 	 *
293 	 * Returns: the side image for @page,
294 	 *     or %NULL if there’s no side image for the page
295 	 *
296 	 * Since: 2.10
297 	 */
298 	public Pixbuf getPageSideImage(Widget page)
299 	{
300 		auto p = gtk_assistant_get_page_side_image(gtkAssistant, (page is null) ? null : page.getWidgetStruct());
301 
302 		if(p is null)
303 		{
304 			return null;
305 		}
306 
307 		return ObjectG.getDObject!(Pixbuf)(cast(GdkPixbuf*) p);
308 	}
309 
310 	/**
311 	 * Gets the title for @page.
312 	 *
313 	 * Params:
314 	 *     page = a page of @assistant
315 	 *
316 	 * Returns: the title for @page
317 	 *
318 	 * Since: 2.10
319 	 */
320 	public string getPageTitle(Widget page)
321 	{
322 		return Str.toString(gtk_assistant_get_page_title(gtkAssistant, (page is null) ? null : page.getWidgetStruct()));
323 	}
324 
325 	/**
326 	 * Gets the page type of @page.
327 	 *
328 	 * Params:
329 	 *     page = a page of @assistant
330 	 *
331 	 * Returns: the page type of @page
332 	 *
333 	 * Since: 2.10
334 	 */
335 	public GtkAssistantPageType getPageType(Widget page)
336 	{
337 		return gtk_assistant_get_page_type(gtkAssistant, (page is null) ? null : page.getWidgetStruct());
338 	}
339 
340 	/**
341 	 * Inserts a page in the @assistant at a given position.
342 	 *
343 	 * Params:
344 	 *     page = a #GtkWidget
345 	 *     position = the index (starting at 0) at which to insert the page,
346 	 *         or -1 to append the page to the @assistant
347 	 *
348 	 * Returns: the index (starting from 0) of the inserted page
349 	 *
350 	 * Since: 2.10
351 	 */
352 	public int insertPage(Widget page, int position)
353 	{
354 		return gtk_assistant_insert_page(gtkAssistant, (page is null) ? null : page.getWidgetStruct(), position);
355 	}
356 
357 	/**
358 	 * Navigate to the next page.
359 	 *
360 	 * It is a programming error to call this function when
361 	 * there is no next page.
362 	 *
363 	 * This function is for use when creating pages of the
364 	 * #GTK_ASSISTANT_PAGE_CUSTOM type.
365 	 *
366 	 * Since: 3.0
367 	 */
368 	public void nextPage()
369 	{
370 		gtk_assistant_next_page(gtkAssistant);
371 	}
372 
373 	/**
374 	 * Prepends a page to the @assistant.
375 	 *
376 	 * Params:
377 	 *     page = a #GtkWidget
378 	 *
379 	 * Returns: the index (starting at 0) of the inserted page
380 	 *
381 	 * Since: 2.10
382 	 */
383 	public int prependPage(Widget page)
384 	{
385 		return gtk_assistant_prepend_page(gtkAssistant, (page is null) ? null : page.getWidgetStruct());
386 	}
387 
388 	/**
389 	 * Navigate to the previous visited page.
390 	 *
391 	 * It is a programming error to call this function when
392 	 * no previous page is available.
393 	 *
394 	 * This function is for use when creating pages of the
395 	 * #GTK_ASSISTANT_PAGE_CUSTOM type.
396 	 *
397 	 * Since: 3.0
398 	 */
399 	public void previousPage()
400 	{
401 		gtk_assistant_previous_page(gtkAssistant);
402 	}
403 
404 	/**
405 	 * Removes a widget from the action area of a #GtkAssistant.
406 	 *
407 	 * Params:
408 	 *     child = a #GtkWidget
409 	 *
410 	 * Since: 2.10
411 	 */
412 	public void removeActionWidget(Widget child)
413 	{
414 		gtk_assistant_remove_action_widget(gtkAssistant, (child is null) ? null : child.getWidgetStruct());
415 	}
416 
417 	/**
418 	 * Removes the @page_num’s page from @assistant.
419 	 *
420 	 * Params:
421 	 *     pageNum = the index of a page in the @assistant,
422 	 *         or -1 to remove the last page
423 	 *
424 	 * Since: 3.2
425 	 */
426 	public void removePage(int pageNum)
427 	{
428 		gtk_assistant_remove_page(gtkAssistant, pageNum);
429 	}
430 
431 	/**
432 	 * Switches the page to @page_num.
433 	 *
434 	 * Note that this will only be necessary in custom buttons,
435 	 * as the @assistant flow can be set with
436 	 * gtk_assistant_set_forward_page_func().
437 	 *
438 	 * Params:
439 	 *     pageNum = index of the page to switch to, starting from 0.
440 	 *         If negative, the last page will be used. If greater
441 	 *         than the number of pages in the @assistant, nothing
442 	 *         will be done.
443 	 *
444 	 * Since: 2.10
445 	 */
446 	public void setCurrentPage(int pageNum)
447 	{
448 		gtk_assistant_set_current_page(gtkAssistant, pageNum);
449 	}
450 
451 	/**
452 	 * Sets the page forwarding function to be @page_func.
453 	 *
454 	 * This function will be used to determine what will be
455 	 * the next page when the user presses the forward button.
456 	 * Setting @page_func to %NULL will make the assistant to
457 	 * use the default forward function, which just goes to the
458 	 * next visible page.
459 	 *
460 	 * Params:
461 	 *     pageFunc = the #GtkAssistantPageFunc, or %NULL
462 	 *         to use the default one
463 	 *     data = user data for @page_func
464 	 *     destroy = destroy notifier for @data
465 	 *
466 	 * Since: 2.10
467 	 */
468 	public void setForwardPageFunc(GtkAssistantPageFunc pageFunc, void* data, GDestroyNotify destroy)
469 	{
470 		gtk_assistant_set_forward_page_func(gtkAssistant, pageFunc, data, destroy);
471 	}
472 
473 	/**
474 	 * Sets whether @page contents are complete.
475 	 *
476 	 * This will make @assistant update the buttons state
477 	 * to be able to continue the task.
478 	 *
479 	 * Params:
480 	 *     page = a page of @assistant
481 	 *     complete = the completeness status of the page
482 	 *
483 	 * Since: 2.10
484 	 */
485 	public void setPageComplete(Widget page, bool complete)
486 	{
487 		gtk_assistant_set_page_complete(gtkAssistant, (page is null) ? null : page.getWidgetStruct(), complete);
488 	}
489 
490 	/**
491 	 * Sets whether the assistant is adding padding around
492 	 * the page.
493 	 *
494 	 * Params:
495 	 *     page = a page of @assistant
496 	 *     hasPadding = whether this page has padding
497 	 *
498 	 * Since: 3.18
499 	 */
500 	public void setPageHasPadding(Widget page, bool hasPadding)
501 	{
502 		gtk_assistant_set_page_has_padding(gtkAssistant, (page is null) ? null : page.getWidgetStruct(), hasPadding);
503 	}
504 
505 	/**
506 	 * Sets a header image for @page.
507 	 *
508 	 * Deprecated: Since GTK+ 3.2, a header is no longer shown;
509 	 * add your header decoration to the page content instead.
510 	 *
511 	 * Params:
512 	 *     page = a page of @assistant
513 	 *     pixbuf = the new header image @page
514 	 *
515 	 * Since: 2.10
516 	 */
517 	public void setPageHeaderImage(Widget page, Pixbuf pixbuf)
518 	{
519 		gtk_assistant_set_page_header_image(gtkAssistant, (page is null) ? null : page.getWidgetStruct(), (pixbuf is null) ? null : pixbuf.getPixbufStruct());
520 	}
521 
522 	/**
523 	 * Sets a side image for @page.
524 	 *
525 	 * This image used to be displayed in the side area of the assistant
526 	 * when @page is the current page.
527 	 *
528 	 * Deprecated: Since GTK+ 3.2, sidebar images are not
529 	 * shown anymore.
530 	 *
531 	 * Params:
532 	 *     page = a page of @assistant
533 	 *     pixbuf = the new side image @page
534 	 *
535 	 * Since: 2.10
536 	 */
537 	public void setPageSideImage(Widget page, Pixbuf pixbuf)
538 	{
539 		gtk_assistant_set_page_side_image(gtkAssistant, (page is null) ? null : page.getWidgetStruct(), (pixbuf is null) ? null : pixbuf.getPixbufStruct());
540 	}
541 
542 	/**
543 	 * Sets a title for @page.
544 	 *
545 	 * The title is displayed in the header area of the assistant
546 	 * when @page is the current page.
547 	 *
548 	 * Params:
549 	 *     page = a page of @assistant
550 	 *     title = the new title for @page
551 	 *
552 	 * Since: 2.10
553 	 */
554 	public void setPageTitle(Widget page, string title)
555 	{
556 		gtk_assistant_set_page_title(gtkAssistant, (page is null) ? null : page.getWidgetStruct(), Str.toStringz(title));
557 	}
558 
559 	/**
560 	 * Sets the page type for @page.
561 	 *
562 	 * The page type determines the page behavior in the @assistant.
563 	 *
564 	 * Params:
565 	 *     page = a page of @assistant
566 	 *     type = the new type for @page
567 	 *
568 	 * Since: 2.10
569 	 */
570 	public void setPageType(Widget page, GtkAssistantPageType type)
571 	{
572 		gtk_assistant_set_page_type(gtkAssistant, (page is null) ? null : page.getWidgetStruct(), type);
573 	}
574 
575 	/**
576 	 * Forces @assistant to recompute the buttons state.
577 	 *
578 	 * GTK+ automatically takes care of this in most situations,
579 	 * e.g. when the user goes to a different page, or when the
580 	 * visibility or completeness of a page changes.
581 	 *
582 	 * One situation where it can be necessary to call this
583 	 * function is when changing a value on the current page
584 	 * affects the future page flow of the assistant.
585 	 *
586 	 * Since: 2.10
587 	 */
588 	public void updateButtonsState()
589 	{
590 		gtk_assistant_update_buttons_state(gtkAssistant);
591 	}
592 
593 	protected class OnApplyDelegateWrapper
594 	{
595 		void delegate(Assistant) dlg;
596 		gulong handlerId;
597 
598 		this(void delegate(Assistant) dlg)
599 		{
600 			this.dlg = dlg;
601 			onApplyListeners ~= this;
602 		}
603 
604 		void remove(OnApplyDelegateWrapper source)
605 		{
606 			foreach(index, wrapper; onApplyListeners)
607 			{
608 				if (wrapper.handlerId == source.handlerId)
609 				{
610 					onApplyListeners[index] = null;
611 					onApplyListeners = std.algorithm.remove(onApplyListeners, index);
612 					break;
613 				}
614 			}
615 		}
616 	}
617 	OnApplyDelegateWrapper[] onApplyListeners;
618 
619 	/**
620 	 * The ::apply signal is emitted when the apply button is clicked.
621 	 *
622 	 * The default behavior of the #GtkAssistant is to switch to the page
623 	 * after the current page, unless the current page is the last one.
624 	 *
625 	 * A handler for the ::apply signal should carry out the actions for
626 	 * which the wizard has collected data. If the action takes a long time
627 	 * to complete, you might consider putting a page of type
628 	 * %GTK_ASSISTANT_PAGE_PROGRESS after the confirmation page and handle
629 	 * this operation within the #GtkAssistant::prepare signal of the progress
630 	 * page.
631 	 *
632 	 * Since: 2.10
633 	 */
634 	gulong addOnApply(void delegate(Assistant) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
635 	{
636 		auto wrapper = new OnApplyDelegateWrapper(dlg);
637 		wrapper.handlerId = Signals.connectData(
638 			this,
639 			"apply",
640 			cast(GCallback)&callBackApply,
641 			cast(void*)wrapper,
642 			cast(GClosureNotify)&callBackApplyDestroy,
643 			connectFlags);
644 		return wrapper.handlerId;
645 	}
646 
647 	extern(C) static void callBackApply(GtkAssistant* assistantStruct, OnApplyDelegateWrapper wrapper)
648 	{
649 		wrapper.dlg(wrapper.outer);
650 	}
651 
652 	extern(C) static void callBackApplyDestroy(OnApplyDelegateWrapper wrapper, GClosure* closure)
653 	{
654 		wrapper.remove(wrapper);
655 	}
656 
657 	protected class OnCancelDelegateWrapper
658 	{
659 		void delegate(Assistant) dlg;
660 		gulong handlerId;
661 
662 		this(void delegate(Assistant) dlg)
663 		{
664 			this.dlg = dlg;
665 			onCancelListeners ~= this;
666 		}
667 
668 		void remove(OnCancelDelegateWrapper source)
669 		{
670 			foreach(index, wrapper; onCancelListeners)
671 			{
672 				if (wrapper.handlerId == source.handlerId)
673 				{
674 					onCancelListeners[index] = null;
675 					onCancelListeners = std.algorithm.remove(onCancelListeners, index);
676 					break;
677 				}
678 			}
679 		}
680 	}
681 	OnCancelDelegateWrapper[] onCancelListeners;
682 
683 	/**
684 	 * The ::cancel signal is emitted when then the cancel button is clicked.
685 	 *
686 	 * Since: 2.10
687 	 */
688 	gulong addOnCancel(void delegate(Assistant) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
689 	{
690 		auto wrapper = new OnCancelDelegateWrapper(dlg);
691 		wrapper.handlerId = Signals.connectData(
692 			this,
693 			"cancel",
694 			cast(GCallback)&callBackCancel,
695 			cast(void*)wrapper,
696 			cast(GClosureNotify)&callBackCancelDestroy,
697 			connectFlags);
698 		return wrapper.handlerId;
699 	}
700 
701 	extern(C) static void callBackCancel(GtkAssistant* assistantStruct, OnCancelDelegateWrapper wrapper)
702 	{
703 		wrapper.dlg(wrapper.outer);
704 	}
705 
706 	extern(C) static void callBackCancelDestroy(OnCancelDelegateWrapper wrapper, GClosure* closure)
707 	{
708 		wrapper.remove(wrapper);
709 	}
710 
711 	protected class OnCloseDelegateWrapper
712 	{
713 		void delegate(Assistant) dlg;
714 		gulong handlerId;
715 
716 		this(void delegate(Assistant) dlg)
717 		{
718 			this.dlg = dlg;
719 			onCloseListeners ~= this;
720 		}
721 
722 		void remove(OnCloseDelegateWrapper source)
723 		{
724 			foreach(index, wrapper; onCloseListeners)
725 			{
726 				if (wrapper.handlerId == source.handlerId)
727 				{
728 					onCloseListeners[index] = null;
729 					onCloseListeners = std.algorithm.remove(onCloseListeners, index);
730 					break;
731 				}
732 			}
733 		}
734 	}
735 	OnCloseDelegateWrapper[] onCloseListeners;
736 
737 	/**
738 	 * The ::close signal is emitted either when the close button of
739 	 * a summary page is clicked, or when the apply button in the last
740 	 * page in the flow (of type %GTK_ASSISTANT_PAGE_CONFIRM) is clicked.
741 	 *
742 	 * Since: 2.10
743 	 */
744 	gulong addOnClose(void delegate(Assistant) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
745 	{
746 		auto wrapper = new OnCloseDelegateWrapper(dlg);
747 		wrapper.handlerId = Signals.connectData(
748 			this,
749 			"close",
750 			cast(GCallback)&callBackClose,
751 			cast(void*)wrapper,
752 			cast(GClosureNotify)&callBackCloseDestroy,
753 			connectFlags);
754 		return wrapper.handlerId;
755 	}
756 
757 	extern(C) static void callBackClose(GtkAssistant* assistantStruct, OnCloseDelegateWrapper wrapper)
758 	{
759 		wrapper.dlg(wrapper.outer);
760 	}
761 
762 	extern(C) static void callBackCloseDestroy(OnCloseDelegateWrapper wrapper, GClosure* closure)
763 	{
764 		wrapper.remove(wrapper);
765 	}
766 
767 	protected class OnEscapeDelegateWrapper
768 	{
769 		void delegate(Assistant) dlg;
770 		gulong handlerId;
771 
772 		this(void delegate(Assistant) dlg)
773 		{
774 			this.dlg = dlg;
775 			onEscapeListeners ~= this;
776 		}
777 
778 		void remove(OnEscapeDelegateWrapper source)
779 		{
780 			foreach(index, wrapper; onEscapeListeners)
781 			{
782 				if (wrapper.handlerId == source.handlerId)
783 				{
784 					onEscapeListeners[index] = null;
785 					onEscapeListeners = std.algorithm.remove(onEscapeListeners, index);
786 					break;
787 				}
788 			}
789 		}
790 	}
791 	OnEscapeDelegateWrapper[] onEscapeListeners;
792 
793 	/** */
794 	gulong addOnEscape(void delegate(Assistant) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
795 	{
796 		auto wrapper = new OnEscapeDelegateWrapper(dlg);
797 		wrapper.handlerId = Signals.connectData(
798 			this,
799 			"escape",
800 			cast(GCallback)&callBackEscape,
801 			cast(void*)wrapper,
802 			cast(GClosureNotify)&callBackEscapeDestroy,
803 			connectFlags);
804 		return wrapper.handlerId;
805 	}
806 
807 	extern(C) static void callBackEscape(GtkAssistant* assistantStruct, OnEscapeDelegateWrapper wrapper)
808 	{
809 		wrapper.dlg(wrapper.outer);
810 	}
811 
812 	extern(C) static void callBackEscapeDestroy(OnEscapeDelegateWrapper wrapper, GClosure* closure)
813 	{
814 		wrapper.remove(wrapper);
815 	}
816 
817 	protected class OnPrepareDelegateWrapper
818 	{
819 		void delegate(Widget, Assistant) dlg;
820 		gulong handlerId;
821 
822 		this(void delegate(Widget, Assistant) dlg)
823 		{
824 			this.dlg = dlg;
825 			onPrepareListeners ~= this;
826 		}
827 
828 		void remove(OnPrepareDelegateWrapper source)
829 		{
830 			foreach(index, wrapper; onPrepareListeners)
831 			{
832 				if (wrapper.handlerId == source.handlerId)
833 				{
834 					onPrepareListeners[index] = null;
835 					onPrepareListeners = std.algorithm.remove(onPrepareListeners, index);
836 					break;
837 				}
838 			}
839 		}
840 	}
841 	OnPrepareDelegateWrapper[] onPrepareListeners;
842 
843 	/**
844 	 * The ::prepare signal is emitted when a new page is set as the
845 	 * assistant's current page, before making the new page visible.
846 	 *
847 	 * A handler for this signal can do any preparations which are
848 	 * necessary before showing @page.
849 	 *
850 	 * Params:
851 	 *     page = the current page
852 	 *
853 	 * Since: 2.10
854 	 */
855 	gulong addOnPrepare(void delegate(Widget, Assistant) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
856 	{
857 		auto wrapper = new OnPrepareDelegateWrapper(dlg);
858 		wrapper.handlerId = Signals.connectData(
859 			this,
860 			"prepare",
861 			cast(GCallback)&callBackPrepare,
862 			cast(void*)wrapper,
863 			cast(GClosureNotify)&callBackPrepareDestroy,
864 			connectFlags);
865 		return wrapper.handlerId;
866 	}
867 
868 	extern(C) static void callBackPrepare(GtkAssistant* assistantStruct, GtkWidget* page, OnPrepareDelegateWrapper wrapper)
869 	{
870 		wrapper.dlg(ObjectG.getDObject!(Widget)(page), wrapper.outer);
871 	}
872 
873 	extern(C) static void callBackPrepareDestroy(OnPrepareDelegateWrapper wrapper, GClosure* closure)
874 	{
875 		wrapper.remove(wrapper);
876 	}
877 }