X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkassistant.c;h=3ba9f227be5abc7934d793a7877a92be13638a2d;hb=a97178af65072e98605b2ce168ee4cc36f684ca2;hp=69fc67e1d01a650d792fbbc2d3049cb23e8220d5;hpb=bf0d8402f5382fadd32a9748d00a4bcd715ea07a;p=~andy%2Fgtk diff --git a/gtk/gtkassistant.c b/gtk/gtkassistant.c index 69fc67e1d..3ba9f227b 100644 --- a/gtk/gtkassistant.c +++ b/gtk/gtkassistant.c @@ -18,9 +18,7 @@ * 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 . */ /** @@ -62,13 +60,13 @@ #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" @@ -76,6 +74,7 @@ #include "gtkintl.h" #include "gtkprivate.h" #include "gtkbuildable.h" +#include "a11y/gtkwindowaccessible.h" #define HEADER_SPACING 12 @@ -149,9 +148,6 @@ static void gtk_assistant_get_child_property (GtkContainer *container, 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, @@ -170,6 +166,14 @@ static void gtk_assistant_buildable_custom_finished (GtkBuildable *bui 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 { @@ -213,7 +217,8 @@ gtk_assistant_class_init (GtkAssistantClass *class) 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; @@ -714,6 +719,10 @@ set_current_page (GtkAssistant *assistant, 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); @@ -863,6 +872,83 @@ assistant_sidebar_draw_cb (GtkWidget *widget, 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) { @@ -902,6 +988,9 @@ 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); @@ -916,10 +1005,16 @@ gtk_assistant_init (GtkAssistant *assistant) 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); @@ -932,6 +1027,13 @@ gtk_assistant_init (GtkAssistant *assistant) 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); @@ -1000,12 +1102,12 @@ gtk_assistant_set_child_property (GtkContainer *container, 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, @@ -1024,27 +1126,29 @@ gtk_assistant_get_child_property (GtkContainer *container, 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); @@ -1052,78 +1156,6 @@ gtk_assistant_get_child_property (GtkContainer *container, } } -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) { @@ -1135,15 +1167,25 @@ 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; @@ -1275,14 +1317,12 @@ gtk_assistant_remove (GtkContainer *container, 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); } } @@ -1586,12 +1626,19 @@ gtk_assistant_insert_page (GtkAssistant *assistant, 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); @@ -1626,6 +1673,30 @@ gtk_assistant_insert_page (GtkAssistant *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 @@ -1909,13 +1980,21 @@ gtk_assistant_set_page_header_image (GtkAssistant *assistant, 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); @@ -1992,13 +2071,21 @@ gtk_assistant_set_page_side_image (GtkAssistant *assistant, 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); @@ -2181,29 +2268,13 @@ gtk_assistant_commit (GtkAssistant *assistant) 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) @@ -2275,43 +2346,6 @@ _gtk_assistant_accessible_init (GtkAssistantAccessible *self) { } -/* 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;