* 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.
+ *
* <refsect2 id="GtkAssistant-BUILDER-UI">
* <title>GtkAssistant as GtkBuildable</title>
* <para>
#include "gtkimage.h"
#include "gtklabel.h"
#include "gtksizegroup.h"
+#include "gtksizerequest.h"
#include "gtkstock.h"
#include "gtkintl.h"
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_destroy (GtkWidget *widget);
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_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural);
+static void gtk_assistant_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural);
static void gtk_assistant_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
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_draw (GtkWidget *widget,
+ cairo_t *cr);
static gboolean gtk_assistant_focus (GtkWidget *widget,
GtkDirectionType direction);
static void gtk_assistant_add (GtkContainer *container,
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->destroy = gtk_assistant_destroy;
widget_class->style_set = gtk_assistant_style_set;
- widget_class->size_request = gtk_assistant_size_request;
+ widget_class->get_preferred_width = gtk_assistant_get_preferred_width;
+ widget_class->get_preferred_height = gtk_assistant_get_preferred_height;
widget_class->size_allocate = gtk_assistant_size_allocate;
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->draw = gtk_assistant_draw;
widget_class->focus = gtk_assistant_focus;
widget_class->get_accessible = gtk_assistant_get_accessible;
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)
+ 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);
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_get_visible (page_info->page));
-
- set_current_page (assistant, page_info);
+ gtk_assistant_previous_page (assistant);
}
static void
gtk_widget_show (priv->sidebar_image);
/* Action area */
- priv->action_area = gtk_hbox_new (FALSE, 6);
-
+ priv->action_area = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+
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_from_stock (GTK_STOCK_GO_FORWARD);
}
static void
-gtk_assistant_destroy (GtkObject *object)
+gtk_assistant_destroy (GtkWidget *widget)
{
- GtkAssistant *assistant = GTK_ASSISTANT (object);
+ GtkAssistant *assistant = GTK_ASSISTANT (widget);
GtkAssistantPrivate *priv = assistant->priv;
if (priv->header_image)
priv->current_page = NULL;
while (priv->pages)
- remove_page (GTK_ASSISTANT (object), priv->pages);
-
- GTK_OBJECT_CLASS (gtk_assistant_parent_class)->destroy (object);
+ remove_page (assistant, priv->pages);
+
+ GTK_WIDGET_CLASS (gtk_assistant_parent_class)->destroy (widget);
}
static GList*
gint size;
desc = pango_font_description_new ();
- size = pango_font_description_get_size (assistant->style->font_desc);
+ size = pango_font_description_get_size (gtk_widget_get_style (assistant)->font_desc);
pango_font_description_set_weight (desc, PANGO_WEIGHT_ULTRABOLD);
pango_font_description_set_size (desc, size * PANGO_SCALE_XX_LARGE);
GtkRequisition child_requisition;
gint header_padding, content_padding;
gint width, height, header_width, header_height;
+ guint border_width;
GList *list;
gtk_widget_style_get (widget,
GtkAssistantPage *page = list->data;
gint w, h;
- gtk_widget_size_request (page->page, &child_requisition);
+ gtk_widget_get_preferred_size (page->page,
+ &child_requisition, NULL);
width = MAX (width, child_requisition.width);
height = MAX (height, child_requisition.height);
- gtk_widget_size_request (page->title, &child_requisition);
+ gtk_widget_get_preferred_size (page->title,
+ &child_requisition, NULL);
w = child_requisition.width;
h = child_requisition.height;
list = list->next;
}
- gtk_widget_size_request (priv->sidebar_image, &child_requisition);
+ gtk_widget_get_preferred_size (priv->sidebar_image,
+ &child_requisition, NULL);
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);
+ gtk_widget_get_preferred_size (priv->header_image,
+ &child_requisition, NULL);
width = MAX (width, header_width) + 2 * header_padding;
height += header_height + 2 * header_padding;
- gtk_widget_size_request (priv->action_area, &child_requisition);
+ gtk_widget_get_preferred_size (priv->action_area,
+ &child_requisition, NULL);
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;
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
+ width += border_width * 2 + content_padding * 2;
+ height += border_width * 2 + content_padding * 2;
requisition->width = width;
requisition->height = height;
}
+static void
+gtk_assistant_get_preferred_width (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkRequisition requisition;
+
+ gtk_assistant_size_request (widget, &requisition);
+
+ *minimum = *natural = requisition.width;
+}
+
+static void
+gtk_assistant_get_preferred_height (GtkWidget *widget,
+ gint *minimum,
+ gint *natural)
+{
+ GtkRequisition requisition;
+
+ gtk_assistant_size_request (widget, &requisition);
+
+ *minimum = *natural = requisition.height;
+}
static void
gtk_assistant_size_allocate (GtkWidget *widget,
GtkAssistantPrivate *priv = assistant->priv;
GtkRequisition header_requisition, action_requisition, sidebar_requisition;
GtkAllocation child_allocation, header_allocation;
+ GtkAllocation action_area_allocation, header_image_allocation;
gint header_padding, content_padding;
+ guint border_width;
gboolean rtl;
GList *pages;
"content-padding", &content_padding,
NULL);
- widget->allocation = *allocation;
+ gtk_widget_set_allocation (widget, allocation);
+ border_width = gtk_container_get_border_width (GTK_CONTAINER (widget));
/* Header */
- gtk_widget_get_child_requisition (priv->header_image, &header_requisition);
+ gtk_widget_get_preferred_size (priv->header_image,
+ &header_requisition, NULL);
- 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.x = border_width + header_padding;
+ header_allocation.y = border_width + header_padding;
+ header_allocation.width = allocation->width - 2 * border_width - 2 * header_padding;
header_allocation.height = header_requisition.height;
gtk_widget_size_allocate (priv->header_image, &header_allocation);
/* Action area */
- gtk_widget_get_child_requisition (priv->action_area, &action_requisition);
+ gtk_widget_get_preferred_size (priv->action_area,
+ &action_requisition, NULL);
- child_allocation.x = GTK_CONTAINER (widget)->border_width;
- child_allocation.y = allocation->height -
- GTK_CONTAINER (widget)->border_width - action_requisition.height;
- child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
+ child_allocation.x = border_width;
+ child_allocation.y = allocation->height - border_width - action_requisition.height;
+ child_allocation.width = allocation->width - 2 * border_width;
child_allocation.height = action_requisition.height;
gtk_widget_size_allocate (priv->action_area, &child_allocation);
+ gtk_widget_get_allocation (priv->header_image, &header_image_allocation);
+ gtk_widget_get_allocation (priv->action_area, &action_area_allocation);
+
/* Sidebar */
- gtk_widget_get_child_requisition (priv->sidebar_image, &sidebar_requisition);
+ gtk_widget_get_preferred_size (priv->sidebar_image,
+ &sidebar_requisition, NULL);
if (rtl)
- child_allocation.x = allocation->width -
- GTK_CONTAINER (widget)->border_width - sidebar_requisition.width;
+ child_allocation.x = allocation->width - border_width - sidebar_requisition.width;
else
- child_allocation.x = GTK_CONTAINER (widget)->border_width;
+ child_allocation.x = border_width;
- child_allocation.y = GTK_CONTAINER (widget)->border_width +
- priv->header_image->allocation.height + 2 * header_padding;
+ child_allocation.y = border_width + header_image_allocation.height + 2 * header_padding;
child_allocation.width = sidebar_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;
+ child_allocation.height = allocation->height - 2 * border_width -
+ header_image_allocation.height - 2 * header_padding - 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;
+ child_allocation.x = border_width + content_padding;
+ child_allocation.y = border_width +
+ header_image_allocation.height + 2 * header_padding + content_padding;
+ child_allocation.width = allocation->width - 2 * border_width - 2 * content_padding;
+ child_allocation.height = allocation->height - 2 * border_width -
+ header_image_allocation.height - 2 * header_padding - ACTION_AREA_SPACING - action_area_allocation.height - 2 * content_padding;
if (gtk_widget_get_visible (priv->sidebar_image))
{
+ GtkAllocation sidebar_image_allocation;
+
+ gtk_widget_get_allocation (priv->sidebar_image, &sidebar_image_allocation);
+
if (!rtl)
- child_allocation.x += priv->sidebar_image->allocation.width;
+ child_allocation.x += sidebar_image_allocation.width;
- child_allocation.width -= priv->sidebar_image->allocation.width;
+ child_allocation.width -= sidebar_image_allocation.width;
}
while (pages)
}
static void
-assistant_paint_colored_box (GtkWidget *widget)
+assistant_paint_colored_box (GtkWidget *widget,
+ cairo_t *cr)
{
GtkAssistant *assistant = GTK_ASSISTANT (widget);
GtkAssistantPrivate *priv = assistant->priv;
+ GtkAllocation allocation, action_area_allocation, header_image_allocation;
+ GtkStyle *style;
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));
"content-padding", &content_padding,
NULL);
+ style = gtk_widget_get_style (widget);
+ gtk_widget_get_allocation (widget, &allocation);
+ gtk_widget_get_allocation (priv->action_area, &action_area_allocation);
+ gtk_widget_get_allocation (priv->header_image, &header_image_allocation);
+
/* colored box */
- gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_SELECTED]);
+ gdk_cairo_set_source_color (cr, &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);
+ allocation.width - 2 * border_width,
+ allocation.height - 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;
+ content_width = allocation.width - 2 * content_padding - 2 * border_width;
if (gtk_widget_get_visible (priv->sidebar_image))
{
+ GtkAllocation sidebar_image_allocation;
+
+ gtk_widget_get_allocation (priv->sidebar_image, &sidebar_image_allocation);
+
if (!rtl)
- content_x += priv->sidebar_image->allocation.width;
- content_width -= priv->sidebar_image->allocation.width;
+ content_x += sidebar_image_allocation.width;
+ content_width -= sidebar_image_allocation.width;
}
-
- gdk_cairo_set_source_color (cr, &widget->style->bg[GTK_STATE_NORMAL]);
+
+ gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]);
cairo_rectangle (cr,
content_x,
- priv->header_image->allocation.height + content_padding + 2 * header_padding + border_width,
+ 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);
+ allocation.height - 2 * border_width - action_area_allocation.height -
+ 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)
+gtk_assistant_draw (GtkWidget *widget,
+ cairo_t *cr)
{
GtkAssistant *assistant = GTK_ASSISTANT (widget);
GtkAssistantPrivate *priv = assistant->priv;
- GtkContainer *container;
+ GtkContainer *container = GTK_CONTAINER (widget);
- if (gtk_widget_is_drawable (widget))
- {
- container = GTK_CONTAINER (widget);
+ if (GTK_WIDGET_CLASS (gtk_assistant_parent_class)->draw)
+ GTK_WIDGET_CLASS (gtk_assistant_parent_class)->draw (widget, cr);
- assistant_paint_colored_box (widget);
+ assistant_paint_colored_box (widget, cr);
- 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);
+ gtk_container_propagate_draw (container, priv->header_image, cr);
+ gtk_container_propagate_draw (container, priv->sidebar_image, cr);
+ gtk_container_propagate_draw (container, priv->action_area, cr);
- if (priv->current_page)
- {
- gtk_container_propagate_expose (container, priv->current_page->page, event);
- gtk_container_propagate_expose (container, priv->current_page->title, event);
- }
+ if (priv->current_page)
+ {
+ gtk_container_propagate_draw (container, priv->current_page->page, cr);
+ gtk_container_propagate_draw (container, priv->current_page->title, cr);
}
return FALSE;
priv = GTK_ASSISTANT (widget)->priv;
/* we only have to care about 2 widgets, action area and the current page */
- if (container->focus_child == priv->action_area)
+ if (gtk_container_get_focus_child (container) == priv->action_area)
{
if (!gtk_widget_child_focus (priv->action_area, direction) &&
(priv->current_page == NULL ||
set_current_page (assistant, page);
}
+/**
+ * gtk_assistant_next_page:
+ * @assistant: a #GtkAssistant
+ *
+ * Navigate to the next page. It is a programming
+ * error to call this function if 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)
+{
+ GtkAssistantPrivate *priv;
+
+ g_return_if_fail (GTK_IS_ASSISTANT (assistant));
+
+ priv = assistant->priv;
+
+ 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_previous_page:
+ * @assistant: a #GtkAssistant
+ *
+ * Navigate to the previous visited page. It is a programming
+ * error to call this function if 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_info);
+}
+
/**
* gtk_assistant_get_n_pages:
* @assistant: a #GtkAssistant
*
* 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
**/
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;
* 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
**/
* 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 header 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
**/