* Boston, MA 02111-1307, USA.
*/
+/**
+ * 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.
+ *
+ * <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 <atk/atk.h>
{
GtkWidget *page;
GtkAssistantPageType type;
- gboolean complete;
+ guint complete : 1;
+ guint complete_set : 1;
GtkWidget *title;
GdkPixbuf *header_image;
const gchar *tagname,
gpointer user_data);
+static GList* find_page (GtkAssistant *assistant,
+ GtkWidget *page);
enum
{
/**
* 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_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++;
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_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_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);
compute_last_button_state (assistant);
break;
case GTK_ASSISTANT_PAGE_SUMMARY:
- gtk_widget_set_sensitive (assistant->close, TRUE);
+ 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_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);
GtkAssistantPage *old_page;
if (priv->current_page &&
- GTK_WIDGET_DRAWABLE (priv->current_page->page))
+ gtk_widget_is_drawable (priv->current_page->page))
old_page = priv->current_page;
else
old_page = NULL;
g_signal_emit (assistant, signals [PREPARE], 0, priv->current_page->page);
- if (GTK_WIDGET_VISIBLE (priv->current_page->page) && GTK_WIDGET_MAPPED (assistant))
+ if (gtk_widget_get_visible (priv->current_page->page) && gtk_widget_get_mapped (GTK_WIDGET (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);
}
- if (old_page && GTK_WIDGET_MAPPED (old_page->page))
+ if (old_page && gtk_widget_get_mapped (old_page->page))
{
gtk_widget_set_child_visible (old_page->page, FALSE);
gtk_widget_unmap (old_page->page);
button[5] = assistant->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;
{
gboolean success;
- success = compute_next_step (assistant);
-
g_signal_emit (assistant, signals [APPLY], 0);
+ success = compute_next_step (assistant);
+
/* if the assistant hasn't switched to another page, just emit
* the CLOSE signal, it't the last page in the assistant flow
*/
g_slist_free_1 (page_node);
}
while (page_info->type == GTK_ASSISTANT_PAGE_PROGRESS ||
- !GTK_WIDGET_VISIBLE (page_info->page));
+ !gtk_widget_get_visible (page_info->page));
set_current_page (assistant, page_info);
}
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_can_default (assistant->close, TRUE);
+ gtk_widget_set_can_default (assistant->apply, TRUE);
+ gtk_widget_set_can_default (assistant->forward, TRUE);
priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
gtk_size_group_add_widget (priv->size_group, assistant->close);
GtkAssistant *assistant = GTK_ASSISTANT (data);
/* update buttons state, flow may have changed */
- if (GTK_WIDGET_MAPPED (assistant))
+ if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
set_assistant_buttons_state (assistant);
}
*/
page_node = priv->pages;
- while (page_node && !GTK_WIDGET_VISIBLE (((GtkAssistantPage *) page_node->data)->page))
+ while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
page_node = page_node->next;
if (page_node == element)
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;
+ GtkRequisition header_requisition, action_requisition, sidebar_requisition;
GtkAllocation child_allocation, header_allocation;
gint header_padding, content_padding;
gboolean rtl;
gtk_widget_size_allocate (priv->header_image, &header_allocation);
/* Action area */
+ gtk_widget_get_child_requisition (priv->action_area, &action_requisition);
+
child_allocation.x = GTK_CONTAINER (widget)->border_width;
child_allocation.y = allocation->height -
- GTK_CONTAINER (widget)->border_width - priv->action_area->requisition.height;
+ GTK_CONTAINER (widget)->border_width - action_requisition.height;
child_allocation.width = allocation->width - 2 * GTK_CONTAINER (widget)->border_width;
- child_allocation.height = priv->action_area->requisition.height;
+ child_allocation.height = action_requisition.height;
gtk_widget_size_allocate (priv->action_area, &child_allocation);
/* Sidebar */
+ gtk_widget_get_child_requisition (priv->sidebar_image, &sidebar_requisition);
+
if (rtl)
child_allocation.x = allocation->width -
- GTK_CONTAINER (widget)->border_width - priv->sidebar_image->requisition.width;
+ GTK_CONTAINER (widget)->border_width - sidebar_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.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 * 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 (gtk_widget_get_visible (priv->sidebar_image))
{
if (!rtl)
child_allocation.x += priv->sidebar_image->allocation.width;
GtkAssistant *assistant = GTK_ASSISTANT (widget);
GtkAssistantPrivate *priv = assistant->priv;
GList *page_node;
+ GtkAssistantPage *page;
- GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
+ gtk_widget_set_mapped (widget, TRUE);
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))
+ if (gtk_widget_get_visible (priv->sidebar_image) &&
+ !gtk_widget_get_mapped (priv->sidebar_image))
gtk_widget_map (priv->sidebar_image);
/* if there's no default page, pick the first one */
- if (!priv->current_page && priv->pages)
+ page = NULL;
+ if (!priv->current_page)
{
page_node = priv->pages;
- while (page_node && !GTK_WIDGET_VISIBLE (((GtkAssistantPage *) page_node->data)->page))
+ while (page_node && !gtk_widget_get_visible (((GtkAssistantPage *) page_node->data)->page))
page_node = page_node->next;
if (page_node)
- priv->current_page = page_node->data;
+ page = page_node->data;
}
- if (priv->current_page &&
- GTK_WIDGET_VISIBLE (priv->current_page->page) &&
- !GTK_WIDGET_MAPPED (priv->current_page->page))
- {
- set_assistant_buttons_state ((GtkAssistant *) widget);
- set_assistant_header_image ((GtkAssistant*) widget);
- set_assistant_sidebar_image ((GtkAssistant*) widget);
-
- g_signal_emit (widget, signals [PREPARE], 0, priv->current_page->page);
- gtk_widget_set_child_visible (priv->current_page->page, TRUE);
- gtk_widget_map (priv->current_page->page);
- gtk_widget_map (priv->current_page->title);
- }
+ if (page &&
+ gtk_widget_get_visible (page->page) &&
+ !gtk_widget_get_mapped (page->page))
+ set_current_page (assistant, page);
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_set_mapped (widget, FALSE);
gtk_widget_unmap (priv->header_image);
gtk_widget_unmap (priv->action_area);
- if (GTK_WIDGET_DRAWABLE (priv->sidebar_image))
+ if (gtk_widget_is_drawable (priv->sidebar_image))
gtk_widget_unmap (priv->sidebar_image);
if (priv->current_page &&
- GTK_WIDGET_DRAWABLE (priv->current_page->page))
+ gtk_widget_is_drawable (priv->current_page->page))
gtk_widget_unmap (priv->current_page->page);
g_slist_free (priv->visited_pages);
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 (gtk_widget_get_visible (priv->sidebar_image))
{
if (!rtl)
content_x += priv->sidebar_image->allocation.width;
GtkAssistantPrivate *priv = assistant->priv;
GtkContainer *container;
- if (GTK_WIDGET_DRAWABLE (widget))
+ if (gtk_widget_is_drawable (widget))
{
container = GTK_CONTAINER (widget);
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;
g_return_if_fail (page != NULL);
* 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);
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;
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_TOPLEVEL (page), 0);
+ g_return_val_if_fail (!gtk_widget_is_toplevel (page), 0);
priv = assistant->priv;
gtk_widget_set_parent (page_info->page, GTK_WIDGET (assistant));
gtk_widget_set_parent (page_info->title, GTK_WIDGET (assistant));
- if (GTK_WIDGET_REALIZED (GTK_WIDGET (assistant)))
+ if (gtk_widget_get_realized (GTK_WIDGET (assistant)))
{
gtk_widget_realize (page_info->page);
gtk_widget_realize (page_info->title);
/**
* gtk_assistant_set_forward_page_func:
* @assistant: a #GtkAssistant
- * @page_func: 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
*
{
page_info->type = type;
+ /* backwards compatibility to the era before fixing bug 604289 */
+ if (type == GTK_ASSISTANT_PAGE_SUMMARY && !page_info->complete_set)
+ {
+ gtk_assistant_set_page_complete (assistant, page, TRUE);
+ page_info->complete_set = FALSE;
+ }
+
/* Always set buttons state, a change in a future page
might change current page buttons */
set_assistant_buttons_state (assistant);
* gtk_assistant_set_page_header_image:
* @assistant: a #GtkAssistant
* @page: a page of @assistant
- * @pixbuf: the new header image @page
- *
+ * @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.
*
* gtk_assistant_set_page_side_image:
* @assistant: a #GtkAssistant
* @page: a page of @assistant
- * @pixbuf: the new header image @page
- *
+ * @pixbuf: (allow-none): the new header 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.
*
if (complete != page_info->complete)
{
page_info->complete = complete;
+ page_info->complete_set = TRUE;
/* Always set buttons state, a change in a future page
might change current page buttons */