* 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/>.
*/
/**
#include "gtkassistant.h"
-#include "gtkaccessibleprivate.h"
#include "gtkbutton.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 "gtkintl.h"
#include "gtkprivate.h"
#include "gtkbuildable.h"
+#include "a11y/gtkwindowaccessible.h"
#define HEADER_SPACING 12
GValue *value,
GParamSpec *pspec);
-static AtkObject *gtk_assistant_get_accessible (GtkWidget *widget);
-static GType gtk_assistant_accessible_factory_get_type (void);
-
static void gtk_assistant_buildable_interface_init (GtkBuildableIface *iface);
static GObject *gtk_assistant_buildable_get_internal_child (GtkBuildable *buildable,
GtkBuilder *builder,
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
{
widget_class->map = gtk_assistant_map;
widget_class->unmap = gtk_assistant_unmap;
widget_class->delete_event = gtk_assistant_delete_event;
- 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;
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);
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)
{
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);
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);
- priv->back = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
+ 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_from_stock (GTK_STOCK_GOTO_LAST);
+ 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);
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), priv->apply, FALSE, FALSE, 0);
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,
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);
-
- if (gtk_widget_get_mapped (GTK_WIDGET (assistant)))
- {
- update_buttons_state (assistant);
- update_title_state (assistant);
- }
-}
-
-static void
-remove_page (GtkAssistant *assistant,
- GList *element)
-{
- GtkAssistantPrivate *priv = assistant->priv;
- GtkAssistantPage *page_info;
- GList *page_node;
-
- 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);
-
- gtk_notebook_remove_page (GTK_NOTEBOOK (priv->content), gtk_notebook_page_num (GTK_NOTEBOOK (priv->content), page_info->page));
- 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_destroy (GtkWidget *widget)
{
*/
priv->current_page = NULL;
- while (priv->pages)
- remove_page (assistant, priv->pages);
+ if (priv->content)
+ {
+ GtkNotebook *notebook;
+ GtkWidget *page;
+
+ /* 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);
+
+ /* Our GtkAssistantPage list should be empty now. */
+ g_warn_if_fail (priv->pages == NULL);
+
+ priv->content = NULL;
+ }
if (priv->sidebar)
priv->sidebar = NULL;
- if (priv->content)
- priv->content = NULL;
-
if (priv->action_area)
priv->action_area = NULL;
GtkWidget *page)
{
GtkAssistant *assistant = (GtkAssistant*) container;
- GList *element;
- element = find_page (assistant, page);
-
- if (element)
+ /* Forward this removal to the content notebook */
+ if (gtk_widget_get_parent (page) == assistant->priv->content)
{
- remove_page (assistant, element);
- gtk_widget_queue_resize ((GtkWidget *) container);
+ container = (GtkContainer *) assistant->priv->content;
+ gtk_container_remove (container, page);
}
}
page_info = g_slice_new0 (GtkAssistantPage);
page_info->page = page;
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);
- gtk_misc_set_alignment (GTK_MISC (page_info->regular_title), 0.,0.5);
+ /* 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);
- gtk_misc_set_alignment (GTK_MISC (page_info->current_title), 0.,0.5);
+ 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);
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
GtkWidget *page,
GdkPixbuf *pixbuf)
{
- 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));
+ 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);
GtkWidget *page,
GdkPixbuf *pixbuf)
{
- 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));
+ 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);
update_buttons_state (assistant);
}
-static AtkObject *
-gtk_assistant_get_accessible (GtkWidget *widget)
-{
- static gboolean first_time = TRUE;
-
- if (first_time)
- {
- _gtk_accessible_set_factory_type (GTK_TYPE_ASSISTANT,
- gtk_assistant_accessible_factory_get_type ());
-
- first_time = FALSE;
- }
-
- return GTK_WIDGET_CLASS (gtk_assistant_parent_class)->get_accessible (widget);
-}
-
/* accessible implementation */
/* dummy typedefs */
-typedef struct _GtkAssistantAccessible GtkAssistantAccessible;
-typedef struct _GtkAssistantAccessibleClass GtkAssistantAccessibleClass;
+typedef GtkWindowAccessible GtkAssistantAccessible;
+typedef GtkWindowAccessibleClass GtkAssistantAccessibleClass;
-ATK_DEFINE_TYPE (GtkAssistantAccessible, _gtk_assistant_accessible, GTK_TYPE_ASSISTANT);
+G_DEFINE_TYPE (GtkAssistantAccessible, _gtk_assistant_accessible, GTK_TYPE_WINDOW_ACCESSIBLE);
static gint
gtk_assistant_accessible_get_n_children (AtkObject *accessible)
{
}
-/* factory */
-typedef AtkObjectFactory GtkAssistantAccessibleFactory;
-typedef AtkObjectFactoryClass GtkAssistantAccessibleFactoryClass;
-
-G_DEFINE_TYPE (GtkAssistantAccessibleFactory,
- gtk_assistant_accessible_factory,
- ATK_TYPE_OBJECT_FACTORY);
-
-static GType
-gtk_assistant_accessible_factory_get_accessible_type (void)
-{
- return _gtk_assistant_accessible_get_type ();
-}
-
-static AtkObject*
-gtk_assistant_accessible_factory_create_accessible (GObject *obj)
-{
- AtkObject *accessible;
-
- accessible = g_object_new (_gtk_assistant_accessible_get_type (), NULL);
- atk_object_initialize (accessible, obj);
-
- return accessible;
-}
-
-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 void
-gtk_assistant_accessible_factory_init (AtkObjectFactory *factory)
-{
-}
-
/* buildable implementation */
static GtkBuildableIface *parent_buildable_iface;