-/*
+/*
* GTK - The GIMP Toolkit
* Copyright (C) 1999 Red Hat, Inc.
* Copyright (C) 2002 Anders Carlsson <andersca@gnu.org>
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * SECTION:gtkassistant
+ * @Short_description: A widget used to guide users through multi-step operations
+ * @Title: GtkAssistant
+ *
+ * A #GtkAssistant is a widget used to represent a generally complex
+ * operation splitted in several steps, guiding the user through its pages
+ * and controlling the page flow to collect the necessary data.
+ *
+ * The design of GtkAssistant is that it controls what buttons to show and
+ * to make sensitive, based on what it knows about the page sequence and
+ * the <link linkend="GtkAssistantPageType">type</link> of each page, in
+ * addition to state information like the page
+ * <link linkend="gtk-assistant-set-page-complete">completion</link> and
+ * <link linkend="gtk-assistant-commit">committed</link> status.
+ *
+ * If you have a case that doesn't quite fit in #GtkAssistants way of
+ * handling buttons, you can use the #GTK_ASSISTANT_PAGE_CUSTOM page type
+ * and handle buttons yourself.
+ *
+ * <refsect2 id="GtkAssistant-BUILDER-UI">
+ * <title>GtkAssistant as GtkBuildable</title>
+ * <para>
+ * The GtkAssistant implementation of the GtkBuildable interface exposes the
+ * @action_area as internal children with the name "action_area".
+ *
+ * To add pages to an assistant in GtkBuilder, simply add it as a
+ * <child> to the GtkAssistant object, and set its child properties
+ * as necessary.
+ * </para>
+ * </refsect2>
*/
#include "config.h"
#include "gtkassistant.h"
-#include "gtkaccessible.h"
#include "gtkbutton.h"
-#include "gtkhbox.h"
-#include "gtkhbbox.h"
+#include "gtkbox.h"
+#include "gtkframe.h"
+#include "gtknotebook.h"
#include "gtkimage.h"
#include "gtklabel.h"
+#include "gtksettings.h"
#include "gtksizegroup.h"
+#include "gtksizerequest.h"
#include "gtkstock.h"
-
+#include "gtktypebuiltins.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkbuildable.h"
+#include "a11y/gtkwindowaccessible.h"
-#include "gtkalias.h"
-
-#define GTK_ASSISTANT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTK_TYPE_ASSISTANT, GtkAssistantPrivate))
#define HEADER_SPACING 12
#define ACTION_AREA_SPACING 12
struct _GtkAssistantPage
{
- GtkWidget *page;
GtkAssistantPageType type;
- guint complete : 1;
+ guint complete : 1;
guint complete_set : 1;
- GtkWidget *title;
+ gchar *title;
+
+ GtkWidget *page;
+ GtkWidget *regular_title;
+ GtkWidget *current_title;
GdkPixbuf *header_image;
GdkPixbuf *sidebar_image;
};
struct _GtkAssistantPrivate
{
- GtkWidget *header_image;
- GtkWidget *sidebar_image;
+ GtkWidget *cancel;
+ GtkWidget *forward;
+ GtkWidget *back;
+ GtkWidget *apply;
+ GtkWidget *close;
+ GtkWidget *last;
+ GtkWidget *sidebar;
+ GtkWidget *content;
GtkWidget *action_area;
GList *pages;
-
- GtkAssistantPage *current_page;
-
GSList *visited_pages;
+ GtkAssistantPage *current_page;
- GtkSizeGroup *size_group;
+ GtkSizeGroup *button_size_group;
+ GtkSizeGroup *title_size_group;
GtkAssistantPageFunc forward_function;
gpointer forward_function_data;
GDestroyNotify forward_data_destroy;
+
+ gint extra_buttons;
+
+ guint committed : 1;
};
static void gtk_assistant_class_init (GtkAssistantClass *class);
static void gtk_assistant_init (GtkAssistant *assistant);
-static void gtk_assistant_destroy (GtkObject *object);
-static void gtk_assistant_style_set (GtkWidget *widget,
- GtkStyle *old_style);
-static void gtk_assistant_size_request (GtkWidget *widget,
- GtkRequisition *requisition);
-static void gtk_assistant_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
+static void gtk_assistant_destroy (GtkWidget *widget);
static void gtk_assistant_map (GtkWidget *widget);
static void gtk_assistant_unmap (GtkWidget *widget);
static gboolean gtk_assistant_delete_event (GtkWidget *widget,
- GdkEventAny *event);
-static gboolean gtk_assistant_expose (GtkWidget *widget,
- GdkEventExpose *event);
-static gboolean gtk_assistant_focus (GtkWidget *widget,
- GtkDirectionType direction);
+ GdkEventAny *event);
static void gtk_assistant_add (GtkContainer *container,
- GtkWidget *page);
+ GtkWidget *page);
static void gtk_assistant_remove (GtkContainer *container,
- GtkWidget *page);
-static void gtk_assistant_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data);
+ GtkWidget *page);
static void gtk_assistant_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec);
+ GtkWidget *child,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
static void gtk_assistant_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint property_id,
- GValue *value,
- GParamSpec *pspec);
-
-static AtkObject *gtk_assistant_get_accessible (GtkWidget *widget);
+ GtkWidget *child,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
static void gtk_assistant_buildable_interface_init (GtkBuildableIface *iface);
static GObject *gtk_assistant_buildable_get_internal_child (GtkBuildable *buildable,
static GList* find_page (GtkAssistant *assistant,
GtkWidget *page);
+static void gtk_assistant_do_set_page_header_image (GtkAssistant *assistant,
+ GtkWidget *page,
+ GdkPixbuf *pixbuf);
+static void gtk_assistant_do_set_page_side_image (GtkAssistant *assistant,
+ GtkWidget *page,
+ GdkPixbuf *pixbuf);
+
+GType _gtk_assistant_accessible_get_type (void);
enum
{
gtk_assistant_class_init (GtkAssistantClass *class)
{
GObjectClass *gobject_class;
- GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkContainerClass *container_class;
gobject_class = (GObjectClass *) class;
- object_class = (GtkObjectClass *) class;
widget_class = (GtkWidgetClass *) class;
container_class = (GtkContainerClass *) class;
- object_class->destroy = gtk_assistant_destroy;
-
- widget_class->style_set = gtk_assistant_style_set;
- widget_class->size_request = gtk_assistant_size_request;
- widget_class->size_allocate = gtk_assistant_size_allocate;
+ widget_class->destroy = gtk_assistant_destroy;
widget_class->map = gtk_assistant_map;
widget_class->unmap = gtk_assistant_unmap;
widget_class->delete_event = gtk_assistant_delete_event;
- widget_class->expose_event = gtk_assistant_expose;
- widget_class->focus = gtk_assistant_focus;
- widget_class->get_accessible = gtk_assistant_get_accessible;
+
+ gtk_widget_class_set_accessible_type (widget_class, _gtk_assistant_accessible_get_type ());
container_class->add = gtk_assistant_add;
container_class->remove = gtk_assistant_remove;
- container_class->forall = gtk_assistant_forall;
container_class->set_child_property = gtk_assistant_set_child_property;
container_class->get_child_property = gtk_assistant_get_child_property;
*/
signals[CANCEL] =
g_signal_new (I_("cancel"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkAssistantClass, cancel),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkAssistantClass, cancel),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
/**
* GtkAssistant::prepare:
* @assistant: the #GtkAssistant
* @page: the current page
*
- * The ::prepare signal is emitted when a new page is set as the assistant's
- * current page, before making the new page visible. A handler for this signal
- * can do any preparation which are necessary before showing @page.
+ * The ::prepare signal is emitted when a new page is set as the
+ * assistant's current page, before making the new page visible.
+ *
+ * A handler for this signal can do any preparations which are
+ * necessary before showing @page.
*
* Since: 2.10
*/
signals[PREPARE] =
g_signal_new (I_("prepare"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkAssistantClass, prepare),
- NULL, NULL,
- g_cclosure_marshal_VOID__OBJECT,
- G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkAssistantClass, prepare),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, GTK_TYPE_WIDGET);
/**
* GtkAssistant::apply:
- * @assistant: the @GtkAssistant
+ * @assistant: the #GtkAssistant
*
- * The ::apply signal is emitted when the apply button is clicked. The default
- * behavior of the #GtkAssistant is to switch to the page after the current
- * page, unless the current page is the last one.
+ * The ::apply signal is emitted when the apply button is clicked.
*
- * A handler for the ::apply signal should carry out the actions for which
- * the wizard has collected data. If the action takes a long time to complete,
- * you might consider to put a page of type %GTK_ASSISTANT_PAGE_PROGRESS
- * after the confirmation page and handle this operation within the
- * #GtkAssistant::prepare signal of the progress page.
+ * The default behavior of the #GtkAssistant is to switch to the page
+ * after the current page, unless the current page is the last one.
+ *
+ * A handler for the ::apply signal should carry out the actions for
+ * which the wizard has collected data. If the action takes a long time
+ * to complete, you might consider putting a page of type
+ * %GTK_ASSISTANT_PAGE_PROGRESS after the confirmation page and handle
+ * this operation within the #GtkAssistant::prepare signal of the progress
+ * page.
*
* Since: 2.10
*/
signals[APPLY] =
g_signal_new (I_("apply"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkAssistantClass, apply),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkAssistantClass, apply),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
/**
* GtkAssistant::close:
*/
signals[CLOSE] =
g_signal_new (I_("close"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GtkAssistantClass, close),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GtkAssistantClass, close),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
gtk_widget_class_install_style_property (widget_class,
- g_param_spec_int ("header-padding",
- P_("Header Padding"),
- P_("Number of pixels around the header."),
- 0,
- G_MAXINT,
- 6,
- GTK_PARAM_READABLE));
+ g_param_spec_int ("header-padding",
+ P_("Header Padding"),
+ P_("Number of pixels around the header."),
+ 0,
+ G_MAXINT,
+ 6,
+ GTK_PARAM_READABLE));
gtk_widget_class_install_style_property (widget_class,
- g_param_spec_int ("content-padding",
- P_("Content Padding"),
- P_("Number of pixels around the content pages."),
- 0,
- G_MAXINT,
- 1,
- GTK_PARAM_READABLE));
+ g_param_spec_int ("content-padding",
+ P_("Content Padding"),
+ P_("Number of pixels around the content pages."),
+ 0,
+ G_MAXINT,
+ 1,
+ GTK_PARAM_READABLE));
/**
* GtkAssistant:page-type:
* Since: 2.10
*/
gtk_container_class_install_child_property (container_class,
- CHILD_PROP_PAGE_TYPE,
- g_param_spec_enum ("page-type",
- P_("Page type"),
- P_("The type of the assistant page"),
- GTK_TYPE_ASSISTANT_PAGE_TYPE,
- GTK_ASSISTANT_PAGE_CONTENT,
- GTK_PARAM_READWRITE));
+ CHILD_PROP_PAGE_TYPE,
+ g_param_spec_enum ("page-type",
+ P_("Page type"),
+ P_("The type of the assistant page"),
+ GTK_TYPE_ASSISTANT_PAGE_TYPE,
+ GTK_ASSISTANT_PAGE_CONTENT,
+ GTK_PARAM_READWRITE));
/**
* GtkAssistant:title:
*
- * The title that is displayed in the page header.
- *
- * If title and header-image are both %NULL, no header is displayed.
+ * The title of the page.
*
* Since: 2.10
*/
gtk_container_class_install_child_property (container_class,
- CHILD_PROP_PAGE_TITLE,
- g_param_spec_string ("title",
- P_("Page title"),
- P_("The title of the assistant page"),
- NULL,
- GTK_PARAM_READWRITE));
+ CHILD_PROP_PAGE_TITLE,
+ g_param_spec_string ("title",
+ P_("Page title"),
+ P_("The title of the assistant page"),
+ NULL,
+ GTK_PARAM_READWRITE));
/**
* GtkAssistant:header-image:
*
- * The image that is displayed next to the title in the page header.
- *
- * If title and header-image are both %NULL, no header is displayed.
+ * This image used to be displayed in the page header.
*
* Since: 2.10
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, a header is no longer shown;
+ * add your header decoration to the page content instead.
*/
gtk_container_class_install_child_property (container_class,
- CHILD_PROP_PAGE_HEADER_IMAGE,
- g_param_spec_object ("header-image",
- P_("Header image"),
- P_("Header image for the assistant page"),
- GDK_TYPE_PIXBUF,
- GTK_PARAM_READWRITE));
+ CHILD_PROP_PAGE_HEADER_IMAGE,
+ g_param_spec_object ("header-image",
+ P_("Header image"),
+ P_("Header image for the assistant page"),
+ GDK_TYPE_PIXBUF,
+ GTK_PARAM_READWRITE));
/**
- * GtkAssistant:header-image:
- *
- * The image that is displayed next to the page.
+ * GtkAssistant:sidebar-image:
*
- * Set this to %NULL to make the sidebar disappear.
+ * This image used to be displayed in the 'sidebar'.
*
* Since: 2.10
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, the sidebar image is no longer shown.
*/
gtk_container_class_install_child_property (container_class,
- CHILD_PROP_PAGE_SIDEBAR_IMAGE,
- g_param_spec_object ("sidebar-image",
- P_("Sidebar image"),
- P_("Sidebar image for the assistant page"),
- GDK_TYPE_PIXBUF,
- GTK_PARAM_READWRITE));
+ CHILD_PROP_PAGE_SIDEBAR_IMAGE,
+ g_param_spec_object ("sidebar-image",
+ P_("Sidebar image"),
+ P_("Sidebar image for the assistant page"),
+ GDK_TYPE_PIXBUF,
+ GTK_PARAM_READWRITE));
+
/**
* GtkAssistant:complete:
*
- * Setting the "complete" child property to %TRUE marks a page as complete
- * (i.e.: all the required fields are filled out). GTK+ uses this information
- * to control the sensitivity of the navigation buttons.
+ * Setting the "complete" child property to %TRUE marks a page as
+ * complete (i.e.: all the required fields are filled out). GTK+ uses
+ * this information to control the sensitivity of the navigation buttons.
*
* Since: 2.10
- **/
+ */
gtk_container_class_install_child_property (container_class,
- CHILD_PROP_PAGE_COMPLETE,
- g_param_spec_boolean ("complete",
- P_("Page complete"),
- P_("Whether all required fields on the page have been filled out"),
- FALSE,
- G_PARAM_READWRITE));
+ CHILD_PROP_PAGE_COMPLETE,
+ g_param_spec_boolean ("complete",
+ P_("Page complete"),
+ P_("Whether all required fields on the page have been filled out"),
+ FALSE,
+ G_PARAM_READWRITE));
g_type_class_add_private (gobject_class, sizeof (GtkAssistantPrivate));
}
page_info = (GtkAssistantPage *) page_node->data;
- while (page_node && !GTK_WIDGET_VISIBLE (page_info->page))
+ while (page_node && !gtk_widget_get_visible (page_info->page))
{
page_node = page_node->next;
current_page++;
if (page_node)
- page_info = (GtkAssistantPage *) page_node->data;
+ page_info = (GtkAssistantPage *) page_node->data;
}
return current_page;
}
-static void
-compute_last_button_state (GtkAssistant *assistant)
+static gboolean
+last_button_visible (GtkAssistant *assistant, GtkAssistantPage *page)
{
GtkAssistantPrivate *priv = assistant->priv;
- GtkAssistantPage *page_info, *current_page_info;
+ GtkAssistantPage *page_info;
gint count, page_num, n_pages;
+ if (page == NULL)
+ return FALSE;
+
+ if (page->type != GTK_ASSISTANT_PAGE_CONTENT)
+ return FALSE;
+
count = 0;
- page_num = gtk_assistant_get_current_page (assistant);
- n_pages = gtk_assistant_get_n_pages (assistant);
- current_page_info = page_info = g_list_nth_data (priv->pages, page_num);
+ page_num = g_list_index (priv->pages, page);
+ n_pages = g_list_length (priv->pages);
+ page_info = page;
while (page_num >= 0 && page_num < n_pages &&
- page_info->type == GTK_ASSISTANT_PAGE_CONTENT &&
- (count == 0 || page_info->complete) &&
- count < n_pages)
+ page_info->type == GTK_ASSISTANT_PAGE_CONTENT &&
+ (count == 0 || page_info->complete) &&
+ count < n_pages)
{
page_num = (priv->forward_function) (page_num, priv->forward_function_data);
page_info = g_list_nth_data (priv->pages, page_num);
count++;
}
- /* make the last button visible if we can skip multiple
+ /* Make the last button visible if we can skip multiple
* pages and end on a confirmation or summary page
*/
if (count > 1 && page_info &&
(page_info->type == GTK_ASSISTANT_PAGE_CONFIRM ||
page_info->type == GTK_ASSISTANT_PAGE_SUMMARY))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+update_actions_size (GtkAssistant *assistant)
+{
+ GtkAssistantPrivate *priv = assistant->priv;
+ GList *l;
+ GtkAssistantPage *page;
+ gint buttons, page_buttons;
+
+ if (!priv->current_page)
+ return;
+
+ /* Some heuristics to find out how many buttons we should
+ * reserve space for. It is possible to trick this code
+ * with page forward functions and invisible pages, etc.
+ */
+ buttons = 0;
+ for (l = priv->pages; l; l = l->next)
{
- gtk_widget_show (assistant->last);
- gtk_widget_set_sensitive (assistant->last,
- current_page_info->complete);
+ page = l->data;
+
+ if (!gtk_widget_get_visible (page->page))
+ continue;
+
+ page_buttons = 2; /* cancel, forward/apply/close */
+ if (l != priv->pages)
+ page_buttons += 1; /* back */
+ if (last_button_visible (assistant, page))
+ page_buttons += 1; /* last */
+
+ buttons = MAX (buttons, page_buttons);
}
- else
- gtk_widget_hide (assistant->last);
+
+ buttons += priv->extra_buttons;
+
+ gtk_widget_set_size_request (priv->action_area,
+ buttons * gtk_widget_get_allocated_width (priv->cancel) + (buttons - 1) * 6,
+ -1);
}
static void
-set_assistant_header_image (GtkAssistant *assistant)
+compute_last_button_state (GtkAssistant *assistant)
{
GtkAssistantPrivate *priv = assistant->priv;
- gtk_image_set_from_pixbuf (GTK_IMAGE (priv->header_image),
- priv->current_page->header_image);
+ gtk_widget_set_sensitive (priv->last, priv->current_page->complete);
+ if (last_button_visible (assistant, priv->current_page))
+ gtk_widget_show (priv->last);
+ else
+ gtk_widget_hide (priv->last);
}
static void
-set_assistant_sidebar_image (GtkAssistant *assistant)
+compute_progress_state (GtkAssistant *assistant)
{
GtkAssistantPrivate *priv = assistant->priv;
+ gint page_num, n_pages;
- gtk_image_set_from_pixbuf (GTK_IMAGE (priv->sidebar_image),
- priv->current_page->sidebar_image);
+ n_pages = gtk_assistant_get_n_pages (assistant);
+ page_num = gtk_assistant_get_current_page (assistant);
- if (priv->current_page->sidebar_image)
- gtk_widget_show (priv->sidebar_image);
+ page_num = (priv->forward_function) (page_num, priv->forward_function_data);
+
+ if (page_num >= 0 && page_num < n_pages)
+ gtk_widget_show (priv->forward);
else
- gtk_widget_hide (priv->sidebar_image);
+ gtk_widget_hide (priv->forward);
}
static void
-set_assistant_buttons_state (GtkAssistant *assistant)
+update_buttons_state (GtkAssistant *assistant)
{
GtkAssistantPrivate *priv = assistant->priv;
if (!priv->current_page)
return;
-
+
switch (priv->current_page->type)
{
case GTK_ASSISTANT_PAGE_INTRO:
- gtk_widget_set_sensitive (assistant->cancel, TRUE);
- gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
- gtk_widget_grab_default (assistant->forward);
- gtk_widget_show (assistant->cancel);
- gtk_widget_show (assistant->forward);
- gtk_widget_hide (assistant->back);
- gtk_widget_hide (assistant->apply);
- gtk_widget_hide (assistant->close);
+ gtk_widget_set_sensitive (priv->cancel, TRUE);
+ gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
+ gtk_widget_grab_default (priv->forward);
+ gtk_widget_show (priv->forward);
+ gtk_widget_hide (priv->back);
+ gtk_widget_hide (priv->apply);
+ gtk_widget_hide (priv->close);
compute_last_button_state (assistant);
break;
case GTK_ASSISTANT_PAGE_CONFIRM:
- gtk_widget_set_sensitive (assistant->cancel, TRUE);
- gtk_widget_set_sensitive (assistant->back, TRUE);
- gtk_widget_set_sensitive (assistant->apply, priv->current_page->complete);
- gtk_widget_grab_default (assistant->apply);
- gtk_widget_show (assistant->cancel);
- gtk_widget_show (assistant->back);
- gtk_widget_show (assistant->apply);
- gtk_widget_hide (assistant->forward);
- gtk_widget_hide (assistant->close);
- gtk_widget_hide (assistant->last);
+ gtk_widget_set_sensitive (priv->cancel, TRUE);
+ gtk_widget_set_sensitive (priv->back, TRUE);
+ gtk_widget_set_sensitive (priv->apply, priv->current_page->complete);
+ gtk_widget_grab_default (priv->apply);
+ gtk_widget_show (priv->back);
+ gtk_widget_show (priv->apply);
+ gtk_widget_hide (priv->forward);
+ gtk_widget_hide (priv->close);
+ gtk_widget_hide (priv->last);
break;
case GTK_ASSISTANT_PAGE_CONTENT:
- gtk_widget_set_sensitive (assistant->cancel, TRUE);
- gtk_widget_set_sensitive (assistant->back, TRUE);
- gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
- gtk_widget_grab_default (assistant->forward);
- gtk_widget_show (assistant->cancel);
- gtk_widget_show (assistant->back);
- gtk_widget_show (assistant->forward);
- gtk_widget_hide (assistant->apply);
- gtk_widget_hide (assistant->close);
+ gtk_widget_set_sensitive (priv->cancel, TRUE);
+ gtk_widget_set_sensitive (priv->back, TRUE);
+ gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
+ gtk_widget_grab_default (priv->forward);
+ gtk_widget_show (priv->back);
+ gtk_widget_show (priv->forward);
+ gtk_widget_hide (priv->apply);
+ gtk_widget_hide (priv->close);
compute_last_button_state (assistant);
break;
case GTK_ASSISTANT_PAGE_SUMMARY:
- gtk_widget_set_sensitive (assistant->close, priv->current_page->complete);
- gtk_widget_grab_default (assistant->close);
- gtk_widget_show (assistant->close);
- gtk_widget_hide (assistant->cancel);
- gtk_widget_hide (assistant->back);
- gtk_widget_hide (assistant->forward);
- gtk_widget_hide (assistant->apply);
- gtk_widget_hide (assistant->last);
+ gtk_widget_set_sensitive (priv->close, priv->current_page->complete);
+ gtk_widget_grab_default (priv->close);
+ gtk_widget_show (priv->close);
+ gtk_widget_hide (priv->back);
+ gtk_widget_hide (priv->forward);
+ gtk_widget_hide (priv->apply);
+ gtk_widget_hide (priv->last);
break;
case GTK_ASSISTANT_PAGE_PROGRESS:
- gtk_widget_set_sensitive (assistant->cancel, priv->current_page->complete);
- gtk_widget_set_sensitive (assistant->back, priv->current_page->complete);
- gtk_widget_set_sensitive (assistant->forward, priv->current_page->complete);
- gtk_widget_grab_default (assistant->forward);
- gtk_widget_show (assistant->cancel);
- gtk_widget_show (assistant->back);
- gtk_widget_show (assistant->forward);
- gtk_widget_hide (assistant->apply);
- gtk_widget_hide (assistant->close);
- gtk_widget_hide (assistant->last);
+ gtk_widget_set_sensitive (priv->cancel, priv->current_page->complete);
+ gtk_widget_set_sensitive (priv->back, priv->current_page->complete);
+ gtk_widget_set_sensitive (priv->forward, priv->current_page->complete);
+ gtk_widget_grab_default (priv->forward);
+ gtk_widget_show (priv->back);
+ gtk_widget_hide (priv->apply);
+ gtk_widget_hide (priv->close);
+ gtk_widget_hide (priv->last);
+ compute_progress_state (assistant);
+ break;
+ case GTK_ASSISTANT_PAGE_CUSTOM:
+ gtk_widget_hide (priv->cancel);
+ gtk_widget_hide (priv->back);
+ gtk_widget_hide (priv->forward);
+ gtk_widget_hide (priv->apply);
+ gtk_widget_hide (priv->last);
+ gtk_widget_hide (priv->close);
break;
default:
g_assert_not_reached ();
}
+ if (priv->committed)
+ gtk_widget_hide (priv->cancel);
+ else if (priv->current_page->type == GTK_ASSISTANT_PAGE_SUMMARY ||
+ priv->current_page->type == GTK_ASSISTANT_PAGE_CUSTOM)
+ gtk_widget_hide (priv->cancel);
+ else
+ gtk_widget_show (priv->cancel);
+
/* this is quite general, we don't want to
- * go back if it's the first page */
+ * go back if it's the first page
+ */
if (!priv->visited_pages)
- gtk_widget_hide (assistant->back);
+ gtk_widget_hide (priv->back);
}
-static void
-set_current_page (GtkAssistant *assistant,
- GtkAssistantPage *page)
+static gboolean
+update_page_title_state (GtkAssistant *assistant, GList *list)
{
+ GtkAssistantPage *page, *other;
GtkAssistantPrivate *priv = assistant->priv;
- GtkAssistantPage *old_page;
+ gboolean visible;
+ GList *l;
- if (priv->current_page &&
- GTK_WIDGET_DRAWABLE (priv->current_page->page))
- old_page = priv->current_page;
- else
- old_page = NULL;
+ page = list->data;
- priv->current_page = page;
+ if (page->title == NULL || page->title[0] == 0)
+ visible = FALSE;
+ else
+ visible = gtk_widget_get_visible (page->page);
- set_assistant_buttons_state (assistant);
- set_assistant_header_image (assistant);
- set_assistant_sidebar_image (assistant);
+ if (page == priv->current_page)
+ {
+ gtk_widget_set_visible (page->regular_title, FALSE);
+ gtk_widget_set_visible (page->current_title, visible);
+ }
+ else
+ {
+ /* If multiple consecutive pages have the same title,
+ * we only show it once, since it would otherwise look
+ * silly. We have to be a little careful, since we
+ * _always_ show the title of the current page.
+ */
+ if (list->prev)
+ {
+ other = list->prev->data;
+ if (g_strcmp0 (page->title, other->title) == 0)
+ visible = FALSE;
+ }
+ for (l = list->next; l; l = l->next)
+ {
+ other = l->data;
+ if (g_strcmp0 (page->title, other->title) != 0)
+ break;
- g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
+ if (other == priv->current_page)
+ {
+ visible = FALSE;
+ break;
+ }
+ }
- if (GTK_WIDGET_VISIBLE (priv->current_page->page) && GTK_WIDGET_MAPPED (assistant))
- {
- gtk_widget_set_child_visible (priv->current_page->page, TRUE);
- gtk_widget_map (priv->current_page->page);
- gtk_widget_map (priv->current_page->title);
+ gtk_widget_set_visible (page->regular_title, visible);
+ gtk_widget_set_visible (page->current_title, FALSE);
}
-
- if (old_page && GTK_WIDGET_MAPPED (old_page->page))
+
+ return visible;
+}
+
+static void
+update_title_state (GtkAssistant *assistant)
+{
+ GtkAssistantPrivate *priv = assistant->priv;
+ GList *l;
+ gboolean show_titles;
+
+ show_titles = FALSE;
+ for (l = priv->pages; l != NULL; l = l->next)
{
- gtk_widget_set_child_visible (old_page->page, FALSE);
- gtk_widget_unmap (old_page->page);
- gtk_widget_unmap (old_page->title);
+ if (update_page_title_state (assistant, l))
+ show_titles = TRUE;
}
+ gtk_widget_set_visible (priv->sidebar, show_titles);
+}
+
+static void
+set_current_page (GtkAssistant *assistant,
+ gint page_num)
+{
+ GtkAssistantPrivate *priv = assistant->priv;
+
+ priv->current_page = (GtkAssistantPage *)g_list_nth_data (priv->pages, page_num);
+
+ g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
+ /* do not continue if the prepare signal handler has already changed the
+ * current page */
+ if (priv->current_page != (GtkAssistantPage *)g_list_nth_data (priv->pages, page_num))
+ return;
+
+ update_title_state (assistant);
+
+ gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->content), page_num);
+
+ /* update buttons state, flow may have changed */
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+ update_buttons_state (assistant);
+
if (!gtk_widget_child_focus (priv->current_page->page, GTK_DIR_TAB_FORWARD))
{
GtkWidget *button[6];
gint i;
/* find the best button to focus */
- button[0] = assistant->apply;
- button[1] = assistant->close;
- button[2] = assistant->forward;
- button[3] = assistant->back;
- button[4] = assistant->cancel;
- button[5] = assistant->last;
+ button[0] = priv->apply;
+ button[1] = priv->close;
+ button[2] = priv->forward;
+ button[3] = priv->back;
+ button[4] = priv->cancel;
+ button[5] = priv->last;
for (i = 0; i < 6; i++)
{
- if (GTK_WIDGET_VISIBLE (button[i]) && GTK_WIDGET_SENSITIVE (button[i]))
+ if (gtk_widget_get_visible (button[i]) &&
+ gtk_widget_get_sensitive (button[i]))
{
gtk_widget_grab_focus (button[i]);
break;
n_pages = gtk_assistant_get_n_pages (assistant);
next_page = (priv->forward_function) (current_page,
- priv->forward_function_data);
+ priv->forward_function_data);
if (next_page >= 0 && next_page < n_pages)
{
priv->visited_pages = g_slist_prepend (priv->visited_pages, page_info);
- set_current_page (assistant, g_list_nth_data (priv->pages, next_page));
+ set_current_page (assistant, next_page);
return TRUE;
}
on_assistant_forward (GtkWidget *widget,
GtkAssistant *assistant)
{
- if (!compute_next_step (assistant))
- g_critical ("Page flow is broken, you may want to end it with a page of "
- "type GTK_ASSISTANT_PAGE_CONFIRM or GTK_ASSISTANT_PAGE_SUMMARY");
+ gtk_assistant_next_page (assistant);
}
static void
on_assistant_back (GtkWidget *widget,
GtkAssistant *assistant)
{
- GtkAssistantPrivate *priv = assistant->priv;
- GtkAssistantPage *page_info;
- GSList *page_node;
-
- /* skip the progress pages when going back */
- do
- {
- page_node = priv->visited_pages;
-
- g_return_if_fail (page_node != NULL);
-
- priv->visited_pages = priv->visited_pages->next;
- page_info = (GtkAssistantPage *) page_node->data;
- g_slist_free_1 (page_node);
- }
- while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
- !GTK_WIDGET_VISIBLE (page_info->page));
-
- set_current_page (assistant, page_info);
+ gtk_assistant_previous_page (assistant);
}
static void
GtkAssistantPrivate *priv = assistant->priv;
while (priv->current_page->type == GTK_ASSISTANT_PAGE_CONTENT &&
- priv->current_page->complete)
+ priv->current_page->complete)
compute_next_step (assistant);
}
settings = gtk_settings_get_for_screen (screen);
g_object_get (settings,
- "gtk-alternative-button-order", &result,
- NULL);
+ "gtk-alternative-button-order", &result,
+ NULL);
return result;
}
+static gboolean
+assistant_sidebar_draw_cb (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer user_data)
+{
+ gint width, height;
+ GtkStyleContext *context;
+
+ width = gtk_widget_get_allocated_width (widget);
+ height = gtk_widget_get_allocated_height (widget);
+ context = gtk_widget_get_style_context (widget);
+
+ gtk_render_background (context, cr, 0, 0, width, height);
+
+ return FALSE;
+}
+
+static void
+on_page_notify_visibility (GtkWidget *widget,
+ GParamSpec *arg,
+ gpointer data)
+{
+ GtkAssistant *assistant = GTK_ASSISTANT (data);
+
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+ {
+ update_buttons_state (assistant);
+ update_title_state (assistant);
+ }
+}
+
+static void
+assistant_remove_page_cb (GtkNotebook *notebook,
+ GtkWidget *page,
+ GtkAssistant *assistant)
+{
+ GtkAssistantPrivate *priv = assistant->priv;
+ GtkAssistantPage *page_info;
+ GList *page_node;
+ GList *element;
+
+ element = find_page (assistant, page);
+ if (!element)
+ return;
+
+ page_info = element->data;
+
+ /* If this is the current page, we need to switch away. */
+ if (page_info == priv->current_page)
+ {
+ if (!compute_next_step (assistant))
+ {
+ /* The best we can do at this point is probably to pick
+ * the first visible page.
+ */
+ page_node = priv->pages;
+
+ while (page_node &&
+ !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
+ page_node = page_node->next;
+
+ if (page_node == element)
+ page_node = page_node->next;
+
+ if (page_node)
+ priv->current_page = page_node->data;
+ else
+ priv->current_page = NULL;
+ }
+ }
+
+ g_signal_handlers_disconnect_by_func (page_info->page, on_page_notify_visibility, assistant);
+
+ gtk_size_group_remove_widget (priv->title_size_group, page_info->regular_title);
+ gtk_size_group_remove_widget (priv->title_size_group, page_info->current_title);
+
+ gtk_container_remove (GTK_CONTAINER (priv->sidebar), page_info->regular_title);
+ gtk_container_remove (GTK_CONTAINER (priv->sidebar), page_info->current_title);
+
+ priv->pages = g_list_remove_link (priv->pages, element);
+ priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
+
+ g_free (page_info->title);
+
+ g_slice_free (GtkAssistantPage, page_info);
+ g_list_free_1 (element);
+
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+ {
+ update_buttons_state (assistant);
+ update_actions_size (assistant);
+ }
+}
+
static void
gtk_assistant_init (GtkAssistant *assistant)
{
GtkAssistantPrivate *priv;
+ GtkStyleContext *context;
+ GtkWidget *main_box;
+ GtkWidget *content_box;
+ GtkWidget *sidebar_frame;
+
+ assistant->priv = G_TYPE_INSTANCE_GET_PRIVATE (assistant,
+ GTK_TYPE_ASSISTANT,
+ GtkAssistantPrivate);
+ priv = assistant->priv;
- priv = assistant->priv = GTK_ASSISTANT_GET_PRIVATE (assistant);
-
- gtk_container_set_reallocate_redraws (GTK_CONTAINER (assistant), TRUE);
- gtk_container_set_border_width (GTK_CONTAINER (assistant), 12);
+ /* use border on inner panes instead */
+ gtk_container_set_border_width (GTK_CONTAINER (assistant), 0);
gtk_widget_push_composite_child ();
- /* Header */
- priv->header_image = gtk_image_new ();
- gtk_misc_set_alignment (GTK_MISC (priv->header_image), 1., 0.5);
- gtk_widget_set_parent (priv->header_image, GTK_WIDGET (assistant));
- gtk_widget_show (priv->header_image);
-
- /* Sidebar */
- priv->sidebar_image = gtk_image_new ();
- gtk_misc_set_alignment (GTK_MISC (priv->sidebar_image), 0., 0.);
- gtk_widget_set_parent (priv->sidebar_image, GTK_WIDGET (assistant));
- gtk_widget_show (priv->sidebar_image);
-
- /* Action area */
- priv->action_area = gtk_hbox_new (FALSE, 6);
-
- assistant->close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
- assistant->apply = gtk_button_new_from_stock (GTK_STOCK_APPLY);
- assistant->forward = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
- assistant->back = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
- assistant->cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
- assistant->last = gtk_button_new_from_stock (GTK_STOCK_GOTO_LAST);
- GTK_WIDGET_SET_FLAGS (assistant->close, GTK_CAN_DEFAULT);
- GTK_WIDGET_SET_FLAGS (assistant->apply, GTK_CAN_DEFAULT);
- GTK_WIDGET_SET_FLAGS (assistant->forward, GTK_CAN_DEFAULT);
-
- priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
- gtk_size_group_add_widget (priv->size_group, assistant->close);
- gtk_size_group_add_widget (priv->size_group, assistant->apply);
- gtk_size_group_add_widget (priv->size_group, assistant->forward);
- gtk_size_group_add_widget (priv->size_group, assistant->back);
- gtk_size_group_add_widget (priv->size_group, assistant->cancel);
- gtk_size_group_add_widget (priv->size_group, assistant->last);
+ main_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+ priv->sidebar = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6);
+
+ /* use a frame for the sidebar, and manually render a background
+ * in it. GtkFrame also gives us padding support for free.
+ */
+ sidebar_frame = gtk_frame_new (NULL);
+ context = gtk_widget_get_style_context (sidebar_frame);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_SIDEBAR);
+
+ g_signal_connect (sidebar_frame, "draw",
+ G_CALLBACK (assistant_sidebar_draw_cb), assistant);
+
+ content_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ gtk_container_set_border_width (GTK_CONTAINER (content_box), 12);
+ priv->content = gtk_notebook_new ();
+ gtk_notebook_set_show_border (GTK_NOTEBOOK (priv->content), FALSE);
+ gtk_notebook_set_show_tabs (GTK_NOTEBOOK (priv->content), FALSE);
+ priv->action_area = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
+ g_signal_connect (priv->content, "remove",
+ G_CALLBACK (assistant_remove_page_cb), assistant);
+
+ gtk_container_add (GTK_CONTAINER (sidebar_frame), priv->sidebar);
+ gtk_box_pack_start (GTK_BOX (main_box), sidebar_frame, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (main_box), content_box, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (content_box), priv->content, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (content_box), priv->action_area, FALSE, TRUE, 0);
+ gtk_widget_set_halign (priv->action_area, GTK_ALIGN_END);
+
+ gtk_widget_show_all (main_box);
+
+ gtk_widget_set_parent (main_box, GTK_WIDGET (assistant));
+ _gtk_bin_set_child (GTK_BIN (assistant), main_box);
+
+ priv->close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+ priv->apply = gtk_button_new_from_stock (GTK_STOCK_APPLY);
+ priv->forward = gtk_button_new_with_mnemonic (_("C_ontinue"));
+ gtk_button_set_image (GTK_BUTTON (priv->forward),
+ gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD, GTK_ICON_SIZE_BUTTON));
+ priv->back = gtk_button_new_with_mnemonic (_("Go _Back"));
+ gtk_button_set_image (GTK_BUTTON (priv->back),
+ gtk_image_new_from_stock (GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON));
+ priv->cancel = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
+ priv->last = gtk_button_new_with_mnemonic (_("_Finish"));
+ gtk_button_set_image (GTK_BUTTON (priv->last),
+ gtk_image_new_from_stock (GTK_STOCK_GOTO_LAST, GTK_ICON_SIZE_BUTTON));
+ gtk_widget_set_can_default (priv->close, TRUE);
+ gtk_widget_set_can_default (priv->apply, TRUE);
+ gtk_widget_set_can_default (priv->forward, TRUE);
+
+ priv->button_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+ gtk_size_group_add_widget (priv->button_size_group, priv->close);
+ gtk_size_group_add_widget (priv->button_size_group, priv->apply);
+ gtk_size_group_add_widget (priv->button_size_group, priv->forward);
+ gtk_size_group_add_widget (priv->button_size_group, priv->back);
+ gtk_size_group_add_widget (priv->button_size_group, priv->cancel);
+ gtk_size_group_add_widget (priv->button_size_group, priv->last);
+
+ gtk_widget_set_no_show_all (priv->close, TRUE);
+ gtk_widget_set_no_show_all (priv->apply, TRUE);
+ gtk_widget_set_no_show_all (priv->forward, TRUE);
+ gtk_widget_set_no_show_all (priv->back, TRUE);
+ gtk_widget_set_no_show_all (priv->cancel, TRUE);
+ gtk_widget_set_no_show_all (priv->last, TRUE);
if (!alternative_button_order (assistant))
{
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->apply, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->forward, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->back, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->last, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->cancel, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->close, FALSE, FALSE, 0);
}
else
{
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->close, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->cancel, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->apply, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->forward, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->back, FALSE, FALSE, 0);
- gtk_box_pack_end (GTK_BOX (priv->action_area), assistant->last, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->close, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->cancel, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->apply, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->forward, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->back, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (priv->action_area), priv->last, FALSE, FALSE, 0);
}
- gtk_widget_set_parent (priv->action_area, GTK_WIDGET (assistant));
- gtk_widget_show (assistant->forward);
- gtk_widget_show (assistant->back);
- gtk_widget_show (assistant->cancel);
+ gtk_widget_show (priv->forward);
+ gtk_widget_show (priv->back);
+ gtk_widget_show (priv->cancel);
gtk_widget_show (priv->action_area);
gtk_widget_pop_composite_child ();
+ priv->title_size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
priv->pages = NULL;
priv->current_page = NULL;
priv->visited_pages = NULL;
priv->forward_function_data = assistant;
priv->forward_data_destroy = NULL;
- g_signal_connect (G_OBJECT (assistant->close), "clicked",
- G_CALLBACK (on_assistant_close), assistant);
- g_signal_connect (G_OBJECT (assistant->apply), "clicked",
- G_CALLBACK (on_assistant_apply), assistant);
- g_signal_connect (G_OBJECT (assistant->forward), "clicked",
- G_CALLBACK (on_assistant_forward), assistant);
- g_signal_connect (G_OBJECT (assistant->back), "clicked",
- G_CALLBACK (on_assistant_back), assistant);
- g_signal_connect (G_OBJECT (assistant->cancel), "clicked",
- G_CALLBACK (on_assistant_cancel), assistant);
- g_signal_connect (G_OBJECT (assistant->last), "clicked",
- G_CALLBACK (on_assistant_last), assistant);
+ g_signal_connect (G_OBJECT (priv->close), "clicked",
+ G_CALLBACK (on_assistant_close), assistant);
+ g_signal_connect (G_OBJECT (priv->apply), "clicked",
+ G_CALLBACK (on_assistant_apply), assistant);
+ g_signal_connect (G_OBJECT (priv->forward), "clicked",
+ G_CALLBACK (on_assistant_forward), assistant);
+ g_signal_connect (G_OBJECT (priv->back), "clicked",
+ G_CALLBACK (on_assistant_back), assistant);
+ g_signal_connect (G_OBJECT (priv->cancel), "clicked",
+ G_CALLBACK (on_assistant_cancel), assistant);
+ g_signal_connect (G_OBJECT (priv->last), "clicked",
+ G_CALLBACK (on_assistant_last), assistant);
}
static void
-gtk_assistant_set_child_property (GtkContainer *container,
- GtkWidget *child,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+gtk_assistant_set_child_property (GtkContainer *container,
+ GtkWidget *child,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
switch (property_id)
{
case CHILD_PROP_PAGE_TYPE:
gtk_assistant_set_page_type (GTK_ASSISTANT (container), child,
- g_value_get_enum (value));
+ g_value_get_enum (value));
break;
case CHILD_PROP_PAGE_TITLE:
gtk_assistant_set_page_title (GTK_ASSISTANT (container), child,
- g_value_get_string (value));
+ g_value_get_string (value));
break;
case CHILD_PROP_PAGE_HEADER_IMAGE:
- gtk_assistant_set_page_header_image (GTK_ASSISTANT (container), child,
- g_value_get_object (value));
+ gtk_assistant_do_set_page_header_image (GTK_ASSISTANT (container), child,
+ g_value_get_object (value));
break;
case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
- gtk_assistant_set_page_side_image (GTK_ASSISTANT (container), child,
- g_value_get_object (value));
+ gtk_assistant_do_set_page_side_image (GTK_ASSISTANT (container), child,
+ g_value_get_object (value));
break;
case CHILD_PROP_PAGE_COMPLETE:
gtk_assistant_set_page_complete (GTK_ASSISTANT (container), child,
- g_value_get_boolean (value));
+ g_value_get_boolean (value));
break;
default:
GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
static void
gtk_assistant_get_child_property (GtkContainer *container,
- GtkWidget *child,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ GtkWidget *child,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
+ GtkAssistant *assistant = GTK_ASSISTANT (container);
+
switch (property_id)
{
case CHILD_PROP_PAGE_TYPE:
g_value_set_enum (value,
- gtk_assistant_get_page_type (GTK_ASSISTANT (container), child));
+ gtk_assistant_get_page_type (assistant, child));
break;
case CHILD_PROP_PAGE_TITLE:
g_value_set_string (value,
- gtk_assistant_get_page_title (GTK_ASSISTANT (container), child));
+ gtk_assistant_get_page_title (assistant, child));
break;
case CHILD_PROP_PAGE_HEADER_IMAGE:
g_value_set_object (value,
- gtk_assistant_get_page_header_image (GTK_ASSISTANT (container), child));
+ ((GtkAssistantPage*) find_page (assistant, child))->header_image);
break;
case CHILD_PROP_PAGE_SIDEBAR_IMAGE:
g_value_set_object (value,
- gtk_assistant_get_page_side_image (GTK_ASSISTANT (container), child));
+ ((GtkAssistantPage*) find_page (assistant, child))->sidebar_image);
break;
case CHILD_PROP_PAGE_COMPLETE:
g_value_set_boolean (value,
- gtk_assistant_get_page_complete (GTK_ASSISTANT (container), child));
+ gtk_assistant_get_page_complete (assistant, child));
break;
default:
GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
}
static void
-on_page_notify_visibility (GtkWidget *widget,
- GParamSpec *arg,
- gpointer data)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (data);
-
- /* update buttons state, flow may have changed */
- if (GTK_WIDGET_MAPPED (assistant))
- set_assistant_buttons_state (assistant);
-}
-
-static void
-remove_page (GtkAssistant *assistant,
- GList *element)
+gtk_assistant_destroy (GtkWidget *widget)
{
+ GtkAssistant *assistant = GTK_ASSISTANT (widget);
GtkAssistantPrivate *priv = assistant->priv;
- GtkAssistantPage *page_info;
- GList *page_node;
- page_info = element->data;
+ /* We set current to NULL so that the remove code doesn't try
+ * to do anything funny
+ */
+ priv->current_page = NULL;
- /* If this is the current page, we need to switch away. */
- if (page_info == priv->current_page)
+ if (priv->content)
{
- if (!compute_next_step (assistant))
- {
- /* The best we can do at this point is probably to pick the first
- * visible page.
- */
- page_node = priv->pages;
+ GtkNotebook *notebook;
+ GtkWidget *page;
- while (page_node && !GTK_WIDGET_VISIBLE (((GtkAssistantPage *) page_node->data)->page))
- page_node = page_node->next;
+ /* Remove all pages from the content notebook. */
+ notebook = (GtkNotebook *) priv->content;
+ while ((page = gtk_notebook_get_nth_page (notebook, 0)) != NULL)
+ gtk_container_remove ((GtkContainer *) notebook, page);
- if (page_node == element)
- page_node = page_node->next;
+ /* Our GtkAssistantPage list should be empty now. */
+ g_warn_if_fail (priv->pages == NULL);
- if (page_node)
- priv->current_page = page_node->data;
- else
- priv->current_page = NULL;
- }
+ priv->content = NULL;
}
- priv->pages = g_list_remove_link (priv->pages, element);
- priv->visited_pages = g_slist_remove_all (priv->visited_pages, page_info);
-
- g_signal_handlers_disconnect_by_func (page_info->page, on_page_notify_visibility, assistant);
- gtk_widget_unparent (page_info->page);
-
- if (page_info->header_image)
- g_object_unref (page_info->header_image);
-
- if (page_info->sidebar_image)
- g_object_unref (page_info->sidebar_image);
-
- gtk_widget_destroy (page_info->title);
- g_slice_free (GtkAssistantPage, page_info);
- g_list_free_1 (element);
-}
-
-static void
-gtk_assistant_destroy (GtkObject *object)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (object);
- GtkAssistantPrivate *priv = assistant->priv;
-
- if (priv->header_image)
- {
- gtk_widget_destroy (priv->header_image);
- priv->header_image = NULL;
- }
-
- if (priv->sidebar_image)
- {
- gtk_widget_destroy (priv->sidebar_image);
- priv->sidebar_image = NULL;
- }
+ if (priv->sidebar)
+ priv->sidebar = NULL;
if (priv->action_area)
+ priv->action_area = NULL;
+
+ if (priv->button_size_group)
{
- gtk_widget_destroy (priv->action_area);
- priv->action_area = NULL;
+ g_object_unref (priv->button_size_group);
+ priv->button_size_group = NULL;
}
- if (priv->size_group)
+ if (priv->title_size_group)
{
- g_object_unref (priv->size_group);
- priv->size_group = NULL;
+ g_object_unref (priv->title_size_group);
+ priv->title_size_group = NULL;
}
if (priv->forward_function)
{
if (priv->forward_function_data &&
- priv->forward_data_destroy)
- priv->forward_data_destroy (priv->forward_function_data);
+ priv->forward_data_destroy)
+ priv->forward_data_destroy (priv->forward_function_data);
priv->forward_function = NULL;
priv->forward_function_data = NULL;
priv->visited_pages = NULL;
}
- /* We set current to NULL so that the remove code doesn't try
- * to do anything funny */
- priv->current_page = NULL;
-
- while (priv->pages)
- remove_page (GTK_ASSISTANT (object), priv->pages);
-
- GTK_OBJECT_CLASS (gtk_assistant_parent_class)->destroy (object);
+ GTK_WIDGET_CLASS (gtk_assistant_parent_class)->destroy (widget);
}
static GList*
find_page (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
GtkAssistantPrivate *priv = assistant->priv;
GList *child = priv->pages;
-
+
while (child)
{
GtkAssistantPage *page_info = child->data;
if (page_info->page == page)
- return child;
+ return child;
child = child->next;
}
-
- return NULL;
-}
-
-static void
-set_title_colors (GtkWidget *assistant,
- GtkWidget *title_label)
-{
- GtkStyle *style;
-
- gtk_widget_ensure_style (assistant);
- style = gtk_widget_get_style (assistant);
-
- /* change colors schema, for making the header text visible */
- gtk_widget_modify_bg (title_label, GTK_STATE_NORMAL, &style->bg[GTK_STATE_SELECTED]);
- gtk_widget_modify_fg (title_label, GTK_STATE_NORMAL, &style->fg[GTK_STATE_SELECTED]);
-}
-
-static void
-set_title_font (GtkWidget *assistant,
- GtkWidget *title_label)
-{
- PangoFontDescription *desc;
- gint size;
-
- desc = pango_font_description_new ();
- size = pango_font_description_get_size (assistant->style->font_desc);
-
- pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
- pango_font_description_set_size (desc, size * PANGO_SCALE_XX_LARGE);
-
- gtk_widget_modify_font (title_label, desc);
- pango_font_description_free (desc);
-}
-
-static void
-gtk_assistant_style_set (GtkWidget *widget,
- GtkStyle *old_style)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (widget);
- GtkAssistantPrivate *priv = assistant->priv;
- GList *list;
-
- list = priv->pages;
-
- while (list)
- {
- GtkAssistantPage *page = list->data;
-
- set_title_colors (widget, page->title);
- set_title_font (widget, page->title);
-
- list = list->next;
- }
-}
-
-static void
-gtk_assistant_size_request (GtkWidget *widget,
- GtkRequisition *requisition)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (widget);
- GtkAssistantPrivate *priv = assistant->priv;
- GtkRequisition child_requisition;
- gint header_padding, content_padding;
- gint width, height, header_width, header_height;
- GList *list;
-
- gtk_widget_style_get (widget,
- "header-padding", &header_padding,
- "content-padding", &content_padding,
- NULL);
- width = height = 0;
- header_width = header_height = 0;
- list = priv->pages;
-
- while (list)
- {
- GtkAssistantPage *page = list->data;
- gint w, h;
- gtk_widget_size_request (page->page, &child_requisition);
- width = MAX (width, child_requisition.width);
- height = MAX (height, child_requisition.height);
-
- gtk_widget_size_request (page->title, &child_requisition);
- w = child_requisition.width;
- h = child_requisition.height;
-
- if (page->header_image)
- {
- w += gdk_pixbuf_get_width (page->header_image) + HEADER_SPACING;
- h = MAX (h, gdk_pixbuf_get_height (page->header_image));
- }
-
- header_width = MAX (header_width, w);
- header_height = MAX (header_height, h);
-
- list = list->next;
- }
-
- gtk_widget_size_request (priv->sidebar_image, &child_requisition);
- width += child_requisition.width;
- height = MAX (height, child_requisition.height);
-
- gtk_widget_set_size_request (priv->header_image, header_width, header_height);
- gtk_widget_size_request (priv->header_image, &child_requisition);
- width = MAX (width, header_width) + 2 * header_padding;
- height += header_height + 2 * header_padding;
-
- gtk_widget_size_request (priv->action_area, &child_requisition);
- width = MAX (width, child_requisition.width);
- height += child_requisition.height + ACTION_AREA_SPACING;
-
- width += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
- height += GTK_CONTAINER (widget)->border_width * 2 + content_padding * 2;
-
- requisition->width = width;
- requisition->height = height;
-}
-
-static void
-gtk_assistant_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (widget);
- GtkAssistantPrivate *priv = assistant->priv;
- GtkRequisition header_requisition;
- GtkAllocation child_allocation, header_allocation;
- gint header_padding, content_padding;
- gboolean rtl;
- GList *pages;
-
- rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
- pages = priv->pages;
-
- gtk_widget_style_get (widget,
- "header-padding", &header_padding,
- "content-padding", &content_padding,
- NULL);
-
- widget->allocation = *allocation;
-
- /* Header */
- gtk_widget_get_child_requisition (priv->header_image, &header_requisition);
-
- header_allocation.x = GTK_CONTAINER (widget)->border_width + header_padding;
- header_allocation.y = GTK_CONTAINER (widget)->border_width + header_padding;
- header_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * header_padding;
- header_allocation.height = header_requisition.height;
-
- gtk_widget_size_allocate (priv->header_image, &header_allocation);
-
- /* Action area */
- child_allocation.x = GTK_CONTAINER (widget)->border_width;
- child_allocation.y = allocation->height -
- GTK_CONTAINER (widget)->border_width - priv->action_area->requisition.height;
- child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
- child_allocation.height = priv->action_area->requisition.height;
-
- gtk_widget_size_allocate (priv->action_area, &child_allocation);
-
- /* Sidebar */
- if (rtl)
- child_allocation.x = allocation->width -
- GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
- else
- child_allocation.x = GTK_CONTAINER (widget)->border_width;
-
- child_allocation.y = GTK_CONTAINER (widget)->border_width +
- priv->header_image->allocation.height + 2 * header_padding;
- child_allocation.width = priv->sidebar_image->requisition.width;
- child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
- priv->header_image->allocation.height - 2 * header_padding - priv->action_area->allocation.height;
-
- gtk_widget_size_allocate (priv->sidebar_image, &child_allocation);
-
- /* Pages */
- child_allocation.x = GTK_CONTAINER (widget)->border_width + content_padding;
- child_allocation.y = GTK_CONTAINER (widget)->border_width +
- priv->header_image->allocation.height + 2 * header_padding + content_padding;
- child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width - 2 * content_padding;
- child_allocation.height = allocation->height - 2 * GTK_CONTAINER (widget)->border_width -
- priv->header_image->allocation.height - 2 * header_padding - ACTION_AREA_SPACING - priv->action_area->allocation.height - 2 * content_padding;
-
- if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
- {
- if (!rtl)
- child_allocation.x += priv->sidebar_image->allocation.width;
-
- child_allocation.width -= priv->sidebar_image->allocation.width;
- }
-
- while (pages)
- {
- GtkAssistantPage *page = pages->data;
-
- gtk_widget_size_allocate (page->page, &child_allocation);
- gtk_widget_size_allocate (page->title, &header_allocation);
- pages = pages->next;
- }
+ return NULL;
}
static void
GtkAssistantPrivate *priv = assistant->priv;
GList *page_node;
GtkAssistantPage *page;
-
- GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
-
- gtk_widget_map (priv->header_image);
- gtk_widget_map (priv->action_area);
-
- if (GTK_WIDGET_VISIBLE (priv->sidebar_image) &&
- !GTK_WIDGET_MAPPED (priv->sidebar_image))
- gtk_widget_map (priv->sidebar_image);
+ gint page_num;
/* if there's no default page, pick the first one */
page = NULL;
+ page_num = 0;
if (!priv->current_page)
{
page_node = priv->pages;
- while (page_node && !GTK_WIDGET_VISIBLE (((GtkAssistantPage *) page_node->data)->page))
- page_node = page_node->next;
+ while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
+ {
+ page_node = page_node->next;
+ page_num++;
+ }
if (page_node)
- page = page_node->data;
+ page = page_node->data;
}
- if (page &&
- GTK_WIDGET_VISIBLE (page->page) &&
- !GTK_WIDGET_MAPPED (page->page))
- set_current_page (assistant, page);
+ if (page && gtk_widget_get_visible (page->page))
+ set_current_page (assistant, page_num);
+
+ update_buttons_state (assistant);
+ update_actions_size (assistant);
+ update_title_state (assistant);
GTK_WIDGET_CLASS (gtk_assistant_parent_class)->map (widget);
}
GtkAssistant *assistant = GTK_ASSISTANT (widget);
GtkAssistantPrivate *priv = assistant->priv;
- GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
-
- gtk_widget_unmap (priv->header_image);
- gtk_widget_unmap (priv->action_area);
-
- if (GTK_WIDGET_DRAWABLE (priv->sidebar_image))
- gtk_widget_unmap (priv->sidebar_image);
-
- if (priv->current_page &&
- GTK_WIDGET_DRAWABLE (priv->current_page->page))
- gtk_widget_unmap (priv->current_page->page);
-
g_slist_free (priv->visited_pages);
- priv->visited_pages = NULL;
- priv->current_page = NULL;
-
- GTK_WIDGET_CLASS (gtk_assistant_parent_class)->unmap (widget);
-}
-
-static gboolean
-gtk_assistant_delete_event (GtkWidget *widget,
- GdkEventAny *event)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (widget);
- GtkAssistantPrivate *priv = assistant->priv;
-
- /* Do not allow cancelling in the middle of a progress page */
- if (priv->current_page &&
- (priv->current_page->type != GTK_ASSISTANT_PAGE_PROGRESS ||
- priv->current_page->complete))
- g_signal_emit (widget, signals [CANCEL], 0, NULL);
-
- return TRUE;
-}
-
-static void
-assistant_paint_colored_box (GtkWidget *widget)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (widget);
- GtkAssistantPrivate *priv = assistant->priv;
- gint border_width, header_padding, content_padding;
- cairo_t *cr;
- gint content_x, content_width;
- gboolean rtl;
-
- cr = gdk_cairo_create (widget->window);
- rtl = (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL);
- border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
-
- gtk_widget_style_get (widget,
- "header-padding", &header_padding,
- "content-padding", &content_padding,
- NULL);
-
- /* colored box */
- gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]);
- cairo_rectangle (cr,
- border_width,
- border_width,
- widget->allocation.width - 2 * border_width,
- widget->allocation.height - priv->action_area->allocation.height - 2 * border_width - ACTION_AREA_SPACING);
- cairo_fill (cr);
-
- /* content box */
- content_x = content_padding + border_width;
- content_width = widget->allocation.width - 2 * content_padding - 2 * border_width;
-
- if (GTK_WIDGET_VISIBLE (priv->sidebar_image))
- {
- if (!rtl)
- content_x += priv->sidebar_image->allocation.width;
- content_width -= priv->sidebar_image->allocation.width;
- }
-
- gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]);
-
- cairo_rectangle (cr,
- content_x,
- priv->header_image->allocation.height + content_padding + 2 * header_padding + border_width,
- content_width,
- widget->allocation.height - 2 * border_width - priv->action_area->allocation.height -
- priv->header_image->allocation.height - 2 * content_padding - 2 * header_padding - ACTION_AREA_SPACING);
- cairo_fill (cr);
-
- cairo_destroy (cr);
-}
-
-static gboolean
-gtk_assistant_expose (GtkWidget *widget,
- GdkEventExpose *event)
-{
- GtkAssistant *assistant = GTK_ASSISTANT (widget);
- GtkAssistantPrivate *priv = assistant->priv;
- GtkContainer *container;
-
- if (GTK_WIDGET_DRAWABLE (widget))
- {
- container = GTK_CONTAINER (widget);
-
- assistant_paint_colored_box (widget);
-
- gtk_container_propagate_expose (container, priv->header_image, event);
- gtk_container_propagate_expose (container, priv->sidebar_image, event);
- gtk_container_propagate_expose (container, priv->action_area, event);
-
- if (priv->current_page)
- {
- gtk_container_propagate_expose (container, priv->current_page->page, event);
- gtk_container_propagate_expose (container, priv->current_page->title, event);
- }
- }
+ priv->visited_pages = NULL;
+ priv->current_page = NULL;
- return FALSE;
+ GTK_WIDGET_CLASS (gtk_assistant_parent_class)->unmap (widget);
}
static gboolean
-gtk_assistant_focus (GtkWidget *widget,
- GtkDirectionType direction)
+gtk_assistant_delete_event (GtkWidget *widget,
+ GdkEventAny *event)
{
- GtkAssistantPrivate *priv;
- GtkContainer *container;
-
- container = GTK_CONTAINER (widget);
- priv = GTK_ASSISTANT (widget)->priv;
+ GtkAssistant *assistant = GTK_ASSISTANT (widget);
+ GtkAssistantPrivate *priv = assistant->priv;
- /* we only have to care about 2 widgets, action area and the current page */
- if (container->focus_child == priv->action_area)
- {
- if (!gtk_widget_child_focus (priv->action_area, direction) &&
- (priv->current_page == NULL ||
- !gtk_widget_child_focus (priv->current_page->page, direction)))
- {
- /* if we're leaving the action area and the current page hasn't
- any focusable widget, clear focus and go back to the action area */
- gtk_container_set_focus_child (GTK_CONTAINER (priv->action_area), NULL);
- gtk_widget_child_focus (priv->action_area, direction);
- }
- }
- else
- {
- if ((priv->current_page == NULL ||
- !gtk_widget_child_focus (priv->current_page->page, direction)) &&
- !gtk_widget_child_focus (priv->action_area, direction))
- {
- /* if we're leaving the current page and there isn't nothing focusable
- in the action area, try to clear focus and go back to the page */
- gtk_window_set_focus (GTK_WINDOW (widget), NULL);
- if (priv->current_page != NULL)
- gtk_widget_child_focus (priv->current_page->page, direction);
- }
- }
+ /* Do not allow cancelling in the middle of a progress page */
+ if (priv->current_page &&
+ (priv->current_page->type != GTK_ASSISTANT_PAGE_PROGRESS ||
+ priv->current_page->complete))
+ g_signal_emit (widget, signals [CANCEL], 0, NULL);
return TRUE;
}
static void
gtk_assistant_add (GtkContainer *container,
- GtkWidget *page)
+ GtkWidget *page)
{
gtk_assistant_append_page (GTK_ASSISTANT (container), page);
}
static void
gtk_assistant_remove (GtkContainer *container,
- GtkWidget *page)
-{
- GtkAssistant *assistant = (GtkAssistant*) container;
- GList *element;
-
- element = find_page (assistant, page);
-
- if (element)
- {
- remove_page (assistant, element);
- gtk_widget_queue_resize ((GtkWidget *) container);
- }
-}
-
-static void
-gtk_assistant_forall (GtkContainer *container,
- gboolean include_internals,
- GtkCallback callback,
- gpointer callback_data)
+ GtkWidget *page)
{
GtkAssistant *assistant = (GtkAssistant*) container;
- GtkAssistantPrivate *priv = assistant->priv;
- GList *pages;
-
- if (include_internals)
- {
- (*callback) (priv->header_image, callback_data);
- (*callback) (priv->sidebar_image, callback_data);
- (*callback) (priv->action_area, callback_data);
- }
- pages = priv->pages;
-
- while (pages)
+ /* Forward this removal to the content notebook */
+ if (gtk_widget_get_parent (page) == assistant->priv->content)
{
- GtkAssistantPage *page = (GtkAssistantPage *) pages->data;
-
- (*callback) (page->page, callback_data);
-
- if (include_internals)
- (*callback) (page->title, callback_data);
-
- pages = pages->next;
+ container = (GtkContainer *) assistant->priv->content;
+ gtk_container_remove (container, page);
}
}
/**
* gtk_assistant_new:
- *
+ *
* Creates a new #GtkAssistant.
*
* Return value: a newly created #GtkAssistant
*
* Since: 2.10
- **/
+ */
GtkWidget*
gtk_assistant_new (void)
{
* gtk_assistant_get_current_page:
* @assistant: a #GtkAssistant
*
- * Returns the page number of the current page
+ * Returns the page number of the current page.
*
- * Return value: The index (starting from 0) of the current page in
- * the @assistant, if the @assistant has no pages, -1 will be returned
+ * Return value: The index (starting from 0) of the current
+ * page in the @assistant, or -1 if the @assistant has no pages,
+ * or no current page.
*
* Since: 2.10
- **/
+ */
gint
gtk_assistant_get_current_page (GtkAssistant *assistant)
{
* gtk_assistant_set_current_page:
* @assistant: a #GtkAssistant
* @page_num: index of the page to switch to, starting from 0.
- * If negative, the last page will be used. If greater
- * than the number of pages in the @assistant, nothing
- * will be done.
+ * If negative, the last page will be used. If greater
+ * than the number of pages in the @assistant, nothing
+ * will be done.
+ *
+ * Switches the page to @page_num.
*
- * Switches the page to @page_num. Note that this will only be necessary
- * in custom buttons, as the @assistant flow can be set with
+ * Note that this will only be necessary in custom buttons,
+ * as the @assistant flow can be set with
* gtk_assistant_set_forward_page_func().
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_set_current_page (GtkAssistant *assistant,
- gint page_num)
+ gint page_num)
{
GtkAssistantPrivate *priv;
GtkAssistantPage *page;
if (page_num >= 0)
page = (GtkAssistantPage *) g_list_nth_data (priv->pages, page_num);
else
- page = (GtkAssistantPage *) g_list_last (priv->pages);
+ {
+ page = (GtkAssistantPage *) g_list_last (priv->pages)->data;
+ page_num = g_list_length (priv->pages);
+ }
g_return_if_fail (page != NULL);
if (priv->current_page == page)
return;
- /* only add the page to the visited list if the
- * assistant is mapped, if not, just use it as an
- * initial page setting, for the cases where the
- * initial page is != to 0
+ /* only add the page to the visited list if the assistant is mapped,
+ * if not, just use it as an initial page setting, for the cases where
+ * the initial page is != to 0
*/
- if (GTK_WIDGET_MAPPED (assistant))
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
priv->visited_pages = g_slist_prepend (priv->visited_pages,
- priv->current_page);
+ priv->current_page);
+
+ set_current_page (assistant, page_num);
+}
+
+/**
+ * gtk_assistant_next_page:
+ * @assistant: a #GtkAssistant
+ *
+ * Navigate to the next page.
+ *
+ * It is a programming error to call this function when
+ * there is no next page.
+ *
+ * This function is for use when creating pages of the
+ * #GTK_ASSISTANT_PAGE_CUSTOM type.
+ *
+ * Since: 3.0
+ */
+void
+gtk_assistant_next_page (GtkAssistant *assistant)
+{
+ g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+ if (!compute_next_step (assistant))
+ g_critical ("Page flow is broken.\n"
+ "You may want to end it with a page of type\n"
+ "GTK_ASSISTANT_PAGE_CONFIRM or GTK_ASSISTANT_PAGE_SUMMARY");
+}
+
+/**
+ * gtk_assistant_previous_page:
+ * @assistant: a #GtkAssistant
+ *
+ * Navigate to the previous visited page.
+ *
+ * It is a programming error to call this function when
+ * no previous page is available.
+ *
+ * This function is for use when creating pages of the
+ * #GTK_ASSISTANT_PAGE_CUSTOM type.
+ *
+ * Since: 3.0
+ */
+void
+gtk_assistant_previous_page (GtkAssistant *assistant)
+{
+ GtkAssistantPrivate *priv;
+ GtkAssistantPage *page_info;
+ GSList *page_node;
+
+ g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+ priv = assistant->priv;
+
+ /* skip the progress pages when going back */
+ do
+ {
+ page_node = priv->visited_pages;
+
+ g_return_if_fail (page_node != NULL);
+
+ priv->visited_pages = priv->visited_pages->next;
+ page_info = (GtkAssistantPage *) page_node->data;
+ g_slist_free_1 (page_node);
+ }
+ while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
+ !gtk_widget_get_visible (page_info->page));
- set_current_page (assistant, page);
+ set_current_page (assistant, g_list_index (priv->pages, page_info));
}
/**
*
* Returns the number of pages in the @assistant
*
- * Return value: The number of pages in the @assistant.
+ * Return value: the number of pages in the @assistant
*
* Since: 2.10
- **/
+ */
gint
gtk_assistant_get_n_pages (GtkAssistant *assistant)
{
/**
* gtk_assistant_get_nth_page:
* @assistant: a #GtkAssistant
- * @page_num: The index of a page in the @assistant, or -1 to get the last page;
+ * @page_num: the index of a page in the @assistant,
+ * or -1 to get the last page
*
* Returns the child widget contained in page number @page_num.
*
- * Return value: The child widget, or %NULL if @page_num is out of bounds.
+ * Return value: (transfer none): the child widget, or %NULL
+ * if @page_num is out of bounds
*
* Since: 2.10
- **/
+ */
GtkWidget*
gtk_assistant_get_nth_page (GtkAssistant *assistant,
- gint page_num)
+ gint page_num)
{
GtkAssistantPrivate *priv;
GtkAssistantPage *page;
GList *elem;
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), NULL);
+ g_return_val_if_fail (page_num >= -1, NULL);
priv = assistant->priv;
- elem = g_list_nth (priv->pages, page_num);
+ if (page_num == -1)
+ elem = g_list_last (priv->pages);
+ else
+ elem = g_list_nth (priv->pages, page_num);
if (!elem)
return NULL;
* Return value: the index (starting at 0) of the inserted page
*
* Since: 2.10
- **/
+ */
gint
gtk_assistant_prepend_page (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
* Return value: the index (starting at 0) of the inserted page
*
* Since: 2.10
- **/
+ */
gint
gtk_assistant_append_page (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
* @assistant: a #GtkAssistant
* @page: a #GtkWidget
* @position: the index (starting at 0) at which to insert the page,
- * or -1 to append the page to the @assistant
+ * or -1 to append the page to the @assistant
*
* Inserts a page in the @assistant at a given position.
*
* Return value: the index (starting from 0) of the inserted page
*
* Since: 2.10
- **/
+ */
gint
gtk_assistant_insert_page (GtkAssistant *assistant,
- GtkWidget *page,
- gint position)
+ GtkWidget *page,
+ gint position)
{
GtkAssistantPrivate *priv;
GtkAssistantPage *page_info;
gint n_pages;
+ GtkStyleContext *context;
g_return_val_if_fail (GTK_IS_ASSISTANT (assistant), 0);
g_return_val_if_fail (GTK_IS_WIDGET (page), 0);
- g_return_val_if_fail (page->parent == NULL, 0);
+ g_return_val_if_fail (gtk_widget_get_parent (page) == NULL, 0);
g_return_val_if_fail (!gtk_widget_is_toplevel (page), 0);
priv = assistant->priv;
page_info = g_slice_new0 (GtkAssistantPage);
page_info->page = page;
- page_info->title = gtk_label_new (NULL);
+ page_info->regular_title = gtk_label_new (NULL);
+ gtk_widget_set_no_show_all (page_info->regular_title, TRUE);
+ page_info->current_title = gtk_label_new (NULL);
+ gtk_widget_set_no_show_all (page_info->current_title, TRUE);
+
+ /* Note: we need to use misc alignment here as long as GtkLabel
+ * pays attention to it. GtkWiget::halign is ineffective, since
+ * all the labels are getting the same size anyway, due to the
+ * size group.
+ */
+ gtk_misc_set_alignment (GTK_MISC (page_info->regular_title), 0, 0.5);
+ gtk_widget_show (page_info->regular_title);
- g_signal_connect (G_OBJECT (page), "notify::visible",
- G_CALLBACK (on_page_notify_visibility), assistant);
+ gtk_misc_set_alignment (GTK_MISC (page_info->current_title), 0, 0.5);
+ gtk_widget_hide (page_info->current_title);
+
+ context = gtk_widget_get_style_context (page_info->current_title);
+ gtk_style_context_add_class (context, GTK_STYLE_CLASS_HIGHLIGHT);
- gtk_misc_set_alignment (GTK_MISC (page_info->title), 0.,0.5);
- set_title_colors (GTK_WIDGET (assistant), page_info->title);
- set_title_font (GTK_WIDGET (assistant), page_info->title);
- gtk_widget_show (page_info->title);
+ gtk_size_group_add_widget (priv->title_size_group, page_info->regular_title);
+ gtk_size_group_add_widget (priv->title_size_group, page_info->current_title);
+
+ g_signal_connect (G_OBJECT (page), "notify::visible",
+ G_CALLBACK (on_page_notify_visibility), assistant);
n_pages = g_list_length (priv->pages);
priv->pages = g_list_insert (priv->pages, page_info, position);
- gtk_widget_set_child_visible (page_info->page, FALSE);
- gtk_widget_set_parent (page_info->page, GTK_WIDGET (assistant));
- gtk_widget_set_parent (page_info->title, GTK_WIDGET (assistant));
+ gtk_box_pack_start (GTK_BOX (priv->sidebar), page_info->regular_title, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (priv->sidebar), page_info->current_title, FALSE, FALSE, 0);
+ gtk_box_reorder_child (GTK_BOX (priv->sidebar), page_info->regular_title, 2 * position);
+ gtk_box_reorder_child (GTK_BOX (priv->sidebar), page_info->current_title, 2 * position + 1);
- if (GTK_WIDGET_REALIZED (GTK_WIDGET (assistant)))
+ gtk_notebook_insert_page (GTK_NOTEBOOK (priv->content), page, NULL, position);
+
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
{
- gtk_widget_realize (page_info->page);
- gtk_widget_realize (page_info->title);
+ update_buttons_state (assistant);
+ update_actions_size (assistant);
}
- gtk_widget_queue_resize (GTK_WIDGET (assistant));
-
return position;
}
+/**
+ * gtk_assistant_remove_page:
+ * @assistant: a #GtkAssistant
+ * @page_num: the index of a page in the @assistant,
+ * or -1 to remove the last page
+ *
+ * Removes the @page_num's page from @assistant.
+ *
+ * Since: 3.2
+ */
+void
+gtk_assistant_remove_page (GtkAssistant *assistant,
+ gint page_num)
+{
+ GtkWidget *page;
+
+ g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+ page = gtk_assistant_get_nth_page (assistant, page_num);
+
+ if (page)
+ gtk_container_remove (GTK_CONTAINER (assistant), page);
+}
+
/**
* gtk_assistant_set_forward_page_func:
* @assistant: a #GtkAssistant
- * @page_func: (allow-none): the #GtkAssistantPageFunc, or %NULL to use the default one
+ * @page_func: (allow-none): the #GtkAssistantPageFunc, or %NULL
+ * to use the default one
* @data: user data for @page_func
* @destroy: destroy notifier for @data
*
- * Sets the page forwarding function to be @page_func, this function will
- * be used to determine what will be the next page when the user presses
- * the forward button. Setting @page_func to %NULL will make the assistant
- * to use the default forward function, which just goes to the next visible
- * page.
+ * Sets the page forwarding function to be @page_func.
+ *
+ * This function will be used to determine what will be
+ * the next page when the user presses the forward button.
+ * Setting @page_func to %NULL will make the assistant to
+ * use the default forward function, which just goes to the
+ * next visible page.
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_set_forward_page_func (GtkAssistant *assistant,
- GtkAssistantPageFunc page_func,
- gpointer data,
- GDestroyNotify destroy)
+ GtkAssistantPageFunc page_func,
+ gpointer data,
+ GDestroyNotify destroy)
{
GtkAssistantPrivate *priv;
}
/* Page flow has possibly changed, so the
- buttons state might need to change too */
- set_assistant_buttons_state (assistant);
+ * buttons state might need to change too
+ */
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+ update_buttons_state (assistant);
}
/**
* gtk_assistant_add_action_widget:
* @assistant: a #GtkAssistant
* @child: a #GtkWidget
- *
+ *
* Adds a widget to the action area of a #GtkAssistant.
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_add_action_widget (GtkAssistant *assistant,
- GtkWidget *child)
+ GtkWidget *child)
{
GtkAssistantPrivate *priv;
priv = assistant->priv;
if (GTK_IS_BUTTON (child))
- gtk_size_group_add_widget (priv->size_group, child);
+ {
+ gtk_size_group_add_widget (priv->button_size_group, child);
+ priv->extra_buttons += 1;
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+ update_actions_size (assistant);
+ }
gtk_box_pack_end (GTK_BOX (priv->action_area), child, FALSE, FALSE, 0);
}
* Removes a widget from the action area of a #GtkAssistant.
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_remove_action_widget (GtkAssistant *assistant,
- GtkWidget *child)
+ GtkWidget *child)
{
GtkAssistantPrivate *priv;
priv = assistant->priv;
if (GTK_IS_BUTTON (child))
- gtk_size_group_remove_widget (priv->size_group, child);
+ {
+ gtk_size_group_remove_widget (priv->button_size_group, child);
+ priv->extra_buttons -= 1;
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
+ update_actions_size (assistant);
+ }
gtk_container_remove (GTK_CONTAINER (priv->action_area), child);
}
* @assistant: a #GtkAssistant
* @page: a page of @assistant
* @title: the new title for @page
- *
- * Sets a title for @page. The title is displayed in the header
- * area of the assistant when @page is the current page.
+ *
+ * Sets a title for @page.
+ *
+ * The title is displayed in the header area of the assistant
+ * when @page is the current page.
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_set_page_title (GtkAssistant *assistant,
- GtkWidget *page,
- const gchar *title)
+ GtkWidget *page,
+ const gchar *title)
{
GtkAssistantPage *page_info;
GList *child;
page_info = (GtkAssistantPage*) child->data;
- gtk_label_set_text ((GtkLabel*) page_info->title, title);
+ g_free (page_info->title);
+ page_info->title = g_strdup (title);
+
+ gtk_label_set_text ((GtkLabel*) page_info->regular_title, title);
+ gtk_label_set_text ((GtkLabel*) page_info->current_title, title);
+
gtk_widget_queue_resize (GTK_WIDGET (assistant));
- gtk_widget_child_notify (page, "title");
+ gtk_container_child_notify (GTK_CONTAINER (assistant), page, "title");
}
/**
* gtk_assistant_get_page_title:
* @assistant: a #GtkAssistant
* @page: a page of @assistant
- *
- * Gets the title for @page.
- *
- * Return value: the title for @page.
+ *
+ * Gets the title for @page.
+ *
+ * Return value: the title for @page
*
* Since: 2.10
- **/
-G_CONST_RETURN gchar*
+ */
+const gchar*
gtk_assistant_get_page_title (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
GtkAssistantPage *page_info;
GList *child;
page_info = (GtkAssistantPage*) child->data;
- return gtk_label_get_text ((GtkLabel*) page_info->title);
+ return page_info->title;
}
/**
* @assistant: a #GtkAssistant
* @page: a page of @assistant
* @type: the new type for @page
- *
- * Sets the page type for @page. The page type determines the page
- * behavior in the @assistant.
+ *
+ * Sets the page type for @page.
+ *
+ * The page type determines the page behavior in the @assistant.
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_set_page_type (GtkAssistant *assistant,
- GtkWidget *page,
- GtkAssistantPageType type)
+ GtkWidget *page,
+ GtkAssistantPageType type)
{
- GtkAssistantPrivate *priv;
GtkAssistantPage *page_info;
GList *child;
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
g_return_if_fail (GTK_IS_WIDGET (page));
- priv = assistant->priv;
child = find_page (assistant, page);
g_return_if_fail (child != NULL);
}
/* Always set buttons state, a change in a future page
- might change current page buttons */
- set_assistant_buttons_state (assistant);
+ * might change current page buttons
+ */
+ update_buttons_state (assistant);
- gtk_widget_child_notify (page, "page-type");
+ gtk_container_child_notify (GTK_CONTAINER (assistant), page, "page-type");
}
}
*
* Gets the page type of @page.
*
- * Return value: the page type of @page.
+ * Return value: the page type of @page
*
* Since: 2.10
- **/
+ */
GtkAssistantPageType
gtk_assistant_get_page_type (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
GtkAssistantPage *page_info;
GList *child;
* @page: a page of @assistant
* @pixbuf: (allow-none): the new header image @page
*
- * Sets a header image for @page. This image is displayed in the header
- * area of the assistant when @page is the current page.
+ * Sets a header image for @page.
*
* Since: 2.10
- **/
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, a header is no longer shown;
+ * add your header decoration to the page content instead.
+ */
void
gtk_assistant_set_page_header_image (GtkAssistant *assistant,
- GtkWidget *page,
- GdkPixbuf *pixbuf)
+ GtkWidget *page,
+ GdkPixbuf *pixbuf)
{
- GtkAssistantPrivate *priv;
- GtkAssistantPage *page_info;
- GList *child;
-
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
g_return_if_fail (GTK_IS_WIDGET (page));
g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
- priv = assistant->priv;
+ gtk_assistant_do_set_page_header_image (assistant, page, pixbuf);
+}
+
+static void
+gtk_assistant_do_set_page_header_image (GtkAssistant *assistant,
+ GtkWidget *page,
+ GdkPixbuf *pixbuf)
+{
+ GtkAssistantPage *page_info;
+ GList *child;
+
child = find_page (assistant, page);
g_return_if_fail (child != NULL);
if (pixbuf != page_info->header_image)
{
if (page_info->header_image)
- {
- g_object_unref (page_info->header_image);
- page_info->header_image = NULL;
- }
+ {
+ g_object_unref (page_info->header_image);
+ page_info->header_image = NULL;
+ }
if (pixbuf)
- page_info->header_image = g_object_ref (pixbuf);
+ page_info->header_image = g_object_ref (pixbuf);
- if (page_info == priv->current_page)
- set_assistant_header_image (assistant);
-
- gtk_widget_child_notify (page, "header-image");
+ gtk_container_child_notify (GTK_CONTAINER (assistant), page, "header-image");
}
}
* gtk_assistant_get_page_header_image:
* @assistant: a #GtkAssistant
* @page: a page of @assistant
- *
- * Gets the header image for @page.
- *
- * Return value: the header image for @page, or %NULL
- * if there's no header image for the page.
+ *
+ * Gets the header image for @page.
+ *
+ * Return value: (transfer none): the header image for @page,
+ * or %NULL if there's no header image for the page
*
* Since: 2.10
- **/
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, a header is no longer shown;
+ * add your header decoration to the page content instead.
+ */
GdkPixbuf*
gtk_assistant_get_page_header_image (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
GtkAssistantPage *page_info;
GList *child;
* gtk_assistant_set_page_side_image:
* @assistant: a #GtkAssistant
* @page: a page of @assistant
- * @pixbuf: (allow-none): the new header image @page
+ * @pixbuf: (allow-none): the new side image @page
*
- * Sets a header image for @page. This image is displayed in the side
- * area of the assistant when @page is the current page.
+ * Sets a side image for @page.
+ *
+ * This image used to be displayed in the side area of the assistant
+ * when @page is the current page.
*
* Since: 2.10
- **/
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, sidebar images are not
+ * shown anymore.
+ */
void
gtk_assistant_set_page_side_image (GtkAssistant *assistant,
- GtkWidget *page,
- GdkPixbuf *pixbuf)
+ GtkWidget *page,
+ GdkPixbuf *pixbuf)
{
- GtkAssistantPrivate *priv;
- GtkAssistantPage *page_info;
- GList *child;
-
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
g_return_if_fail (GTK_IS_WIDGET (page));
g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
- priv = assistant->priv;
+ gtk_assistant_do_set_page_side_image (assistant, page, pixbuf);
+}
+
+static void
+gtk_assistant_do_set_page_side_image (GtkAssistant *assistant,
+ GtkWidget *page,
+ GdkPixbuf *pixbuf)
+{
+ GtkAssistantPage *page_info;
+ GList *child;
+
child = find_page (assistant, page);
g_return_if_fail (child != NULL);
if (pixbuf != page_info->sidebar_image)
{
if (page_info->sidebar_image)
- {
- g_object_unref (page_info->sidebar_image);
- page_info->sidebar_image = NULL;
- }
+ {
+ g_object_unref (page_info->sidebar_image);
+ page_info->sidebar_image = NULL;
+ }
if (pixbuf)
- page_info->sidebar_image = g_object_ref (pixbuf);
-
- if (page_info == priv->current_page)
- set_assistant_sidebar_image (assistant);
+ page_info->sidebar_image = g_object_ref (pixbuf);
- gtk_widget_child_notify (page, "sidebar-image");
+ gtk_container_child_notify (GTK_CONTAINER (assistant), page, "sidebar-image");
}
}
* gtk_assistant_get_page_side_image:
* @assistant: a #GtkAssistant
* @page: a page of @assistant
- *
- * Gets the header image for @page.
- *
- * Return value: the side image for @page, or %NULL
- * if there's no side image for the page.
+ *
+ * Gets the side image for @page.
+ *
+ * Return value: (transfer none): the side image for @page,
+ * or %NULL if there's no side image for the page
*
* Since: 2.10
- **/
+ *
+ * Deprecated: 3.2: Since GTK+ 3.2, sidebar images are not
+ * shown anymore.
+ */
GdkPixbuf*
gtk_assistant_get_page_side_image (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
GtkAssistantPage *page_info;
GList *child;
* @assistant: a #GtkAssistant
* @page: a page of @assistant
* @complete: the completeness status of the page
- *
- * Sets whether @page contents are complete. This will make
- * @assistant update the buttons state to be able to continue the task.
+ *
+ * Sets whether @page contents are complete.
+ *
+ * This will make @assistant update the buttons state
+ * to be able to continue the task.
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_set_page_complete (GtkAssistant *assistant,
- GtkWidget *page,
- gboolean complete)
+ GtkWidget *page,
+ gboolean complete)
{
- GtkAssistantPrivate *priv;
GtkAssistantPage *page_info;
GList *child;
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
g_return_if_fail (GTK_IS_WIDGET (page));
- priv = assistant->priv;
child = find_page (assistant, page);
g_return_if_fail (child != NULL);
page_info->complete_set = TRUE;
/* Always set buttons state, a change in a future page
- might change current page buttons */
- set_assistant_buttons_state (assistant);
+ * might change current page buttons
+ */
+ update_buttons_state (assistant);
- gtk_widget_child_notify (page, "complete");
+ gtk_container_child_notify (GTK_CONTAINER (assistant), page, "complete");
}
}
* gtk_assistant_get_page_complete:
* @assistant: a #GtkAssistant
* @page: a page of @assistant
- *
+ *
* Gets whether @page is complete.
- *
+ *
* Return value: %TRUE if @page is complete.
*
* Since: 2.10
- **/
+ */
gboolean
gtk_assistant_get_page_complete (GtkAssistant *assistant,
- GtkWidget *page)
+ GtkWidget *page)
{
GtkAssistantPage *page_info;
GList *child;
/**
* gtk_assistant_update_buttons_state:
* @assistant: a #GtkAssistant
- *
+ *
* Forces @assistant to recompute the buttons state.
- *
- * GTK+ automatically takes care of this in most situations,
+ *
+ * GTK+ automatically takes care of this in most situations,
* e.g. when the user goes to a different page, or when the
* visibility or completeness of a page changes.
*
* affects the future page flow of the assistant.
*
* Since: 2.10
- **/
+ */
void
gtk_assistant_update_buttons_state (GtkAssistant *assistant)
{
g_return_if_fail (GTK_IS_ASSISTANT (assistant));
- set_assistant_buttons_state (assistant);
+ update_buttons_state (assistant);
}
+/**
+ * gtk_assistant_commit:
+ * @assistant: a #GtkAssistant
+ *
+ * Erases the visited page history so the back button is not
+ * shown on the current page, and removes the cancel button
+ * from subsequent pages.
+ *
+ * Use this when the information provided up to the current
+ * page is hereafter deemed permanent and cannot be modified
+ * or undone. For example, showing a progress page to track
+ * a long-running, unreversible operation after the user has
+ * clicked apply on a confirmation page.
+ *
+ * Since: 2.22
+ */
+void
+gtk_assistant_commit (GtkAssistant *assistant)
+{
+ g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+ g_slist_free (assistant->priv->visited_pages);
+ assistant->priv->visited_pages = NULL;
+ assistant->priv->committed = TRUE;
+
+ update_buttons_state (assistant);
+}
/* accessible implementation */
+/* dummy typedefs */
+typedef GtkWindowAccessible GtkAssistantAccessible;
+typedef GtkWindowAccessibleClass GtkAssistantAccessibleClass;
+
+G_DEFINE_TYPE (GtkAssistantAccessible, _gtk_assistant_accessible, GTK_TYPE_WINDOW_ACCESSIBLE);
+
static gint
gtk_assistant_accessible_get_n_children (AtkObject *accessible)
{
- GtkAssistant *assistant;
GtkWidget *widget;
- widget = GTK_ACCESSIBLE (accessible)->widget;
-
- if (!widget)
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+ if (widget == NULL)
return 0;
- assistant = GTK_ASSISTANT (widget);
-
- return g_list_length (assistant->priv->pages) + 1;
+ return g_list_length (GTK_ASSISTANT (widget)->priv->pages) + 1;
}
-
static AtkObject *
gtk_assistant_accessible_ref_child (AtkObject *accessible,
- gint index)
+ gint index)
{
GtkAssistant *assistant;
GtkAssistantPrivate *priv;
AtkObject *obj;
const gchar *title;
- widget = GTK_ACCESSIBLE (accessible)->widget;
- if (!widget)
+ widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (accessible));
+ if (widget == NULL)
return NULL;
assistant = GTK_ASSISTANT (widget);
}
else
return NULL;
-
+
obj = gtk_widget_get_accessible (child);
if (title)
}
static void
-gtk_assistant_accessible_class_init (AtkObjectClass *class)
-{
- class->get_n_children = gtk_assistant_accessible_get_n_children;
- class->ref_child = gtk_assistant_accessible_ref_child;
-}
-
-static GType
-gtk_assistant_accessible_get_type (void)
-{
- static GType type = 0;
-
- if (!type)
- {
- /*
- * Figure out the size of the class and instance
- * we are deriving from
- */
- AtkObjectFactory *factory;
- GType derived_type;
- GTypeQuery query;
- GType derived_atk_type;
-
- derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
- factory = atk_registry_get_factory (atk_get_default_registry (),
- derived_type);
- derived_atk_type = atk_object_factory_get_accessible_type (factory);
- g_type_query (derived_atk_type, &query);
-
- type = g_type_register_static_simple (derived_atk_type,
- I_("GtkAssistantAccessible"),
- query.class_size,
- (GClassInitFunc) gtk_assistant_accessible_class_init,
- query.instance_size,
- NULL, 0);
- }
-
- return type;
-}
-
-static AtkObject *
-gtk_assistant_accessible_new (GObject *obj)
-{
- AtkObject *accessible;
-
- g_return_val_if_fail (GTK_IS_ASSISTANT (obj), NULL);
-
- accessible = g_object_new (gtk_assistant_accessible_get_type (), NULL);
- atk_object_initialize (accessible, obj);
-
- return accessible;
-}
-
-static GType
-gtk_assistant_accessible_factory_get_accessible_type (void)
+_gtk_assistant_accessible_class_init (GtkAssistantAccessibleClass *klass)
{
- return gtk_assistant_accessible_get_type ();
-}
+ AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass);
-static AtkObject*
-gtk_assistant_accessible_factory_create_accessible (GObject *obj)
-{
- return gtk_assistant_accessible_new (obj);
+ atk_class->get_n_children = gtk_assistant_accessible_get_n_children;
+ atk_class->ref_child = gtk_assistant_accessible_ref_child;
}
static void
-gtk_assistant_accessible_factory_class_init (AtkObjectFactoryClass *class)
-{
- class->create_accessible = gtk_assistant_accessible_factory_create_accessible;
- class->get_accessible_type = gtk_assistant_accessible_factory_get_accessible_type;
-}
-
-static GType
-gtk_assistant_accessible_factory_get_type (void)
-{
- static GType type = 0;
-
- if (!type)
- {
- type = g_type_register_static_simple (ATK_TYPE_OBJECT_FACTORY,
- I_("GtkAssistantAccessibleFactory"),
- sizeof (AtkObjectFactoryClass),
- (GClassInitFunc) gtk_assistant_accessible_factory_class_init,
- sizeof (AtkObjectFactory),
- NULL, 0);
- }
-
- return type;
-}
-
-static AtkObject *
-gtk_assistant_get_accessible (GtkWidget *widget)
+_gtk_assistant_accessible_init (GtkAssistantAccessible *self)
{
- static gboolean first_time = TRUE;
-
- if (first_time)
- {
- AtkObjectFactory *factory;
- AtkRegistry *registry;
- GType derived_type;
- GType derived_atk_type;
-
- /*
- * Figure out whether accessibility is enabled by looking at the
- * type of the accessible object which would be created for
- * the parent type of GtkAssistant.
- */
- derived_type = g_type_parent (GTK_TYPE_ASSISTANT);
-
- registry = atk_get_default_registry ();
- factory = atk_registry_get_factory (registry,
- derived_type);
- derived_atk_type = atk_object_factory_get_accessible_type (factory);
- if (g_type_is_a (derived_atk_type, GTK_TYPE_ACCESSIBLE))
- {
- atk_registry_set_factory_type (registry,
- GTK_TYPE_ASSISTANT,
- gtk_assistant_accessible_factory_get_type ());
- }
- first_time = FALSE;
- }
-
- return GTK_WIDGET_CLASS (gtk_assistant_parent_class)->get_accessible (widget);
}
+/* buildable implementation */
static GtkBuildableIface *parent_buildable_iface;
parent_buildable_iface->custom_finished (buildable, builder, child,
tagname, user_data);
}
-
-
-#define __GTK_ASSISTANT_C__
-#include "gtkaliasdef.c"