Re: GtkNotebook accelerators.



On 28 Feb 2001, Owen Taylor wrote:

>  * I think we probably should avoid adding more append/prepend
>    variants and simply stick to the convention that to prepend you
>    insert with an index of 0, to append, you insert with and index of
>    -1.
>
>  * gtk_notebook_insert_page_label() should almost certainly
>    be gtk_notebook_insert_page_accel() to correspond
>    to gtk_button_new_accel()
>
>  * But, more importantly, I'm not very happy with the way this
>    works altogether - it's fiddly to set up, not flexible,
>    and just more entry points than I like.
>
>    I'm sort of coming to the conclusion here that we need
>    to make some more changes to the way accelerators work in GTK+
>    for 2.0 - it's something we've discussed some here, but
>    were figuring we'd be able to punt to 2.2.
>
>    Two issues in this area, that if we address, may provide some better
>    resolution of this are:
>
>     - If we use the scheme for label properties I suggested (or
>       any scheme that allows setting of the underline), then how
>       do you find out the accelerator? How is that accelerator
>       hooked up.
>
>       It probably at least necessary to store the accelerator
>       for the label in some place that can be retrieved.
>
>     - We need some way of indicating what widget a label is "for"
>       both for accelerators, and for accessibility applications.
>
>    So, perhaps it is best to hold off on this patch until we think
>    about these things some more.

Do you thing there is enough time for this?

I made the changes you commented on, and added a way to block the
accelgroups of non-visible notebook pages. I've appended the patch.

I think this is good enough for 2.0. I've thought a bit about
generic handling of label accelerators, but i think we should punt that
work to 2.2.

/ Alex

Index: gtkaccelgroup.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkaccelgroup.c,v
retrieving revision 1.20
diff -u -p -r1.20 gtkaccelgroup.c
--- gtkaccelgroup.c	2000/10/25 22:34:11	1.20
+++ gtkaccelgroup.c	2001/03/13 12:48:56
@@ -118,6 +118,7 @@ gtk_accel_group_new (void)
   accel_group->lock_count = 0;
   accel_group->modifier_mask = gtk_accelerator_get_default_mod_mask ();
   accel_group->attach_objects = NULL;
+  accel_group->blocked = FALSE;

   return accel_group;
 }
@@ -238,6 +239,23 @@ gtk_accel_group_unlock (GtkAccelGroup  *
     accel_group->lock_count -= 1;
 }

+void
+gtk_accel_group_block (GtkAccelGroup  *accel_group,
+		       gboolean        blocked)
+{
+  g_return_if_fail (accel_group != NULL);
+
+  accel_group->blocked = blocked;
+}
+
+gboolean
+gtk_accel_group_is_blocked (GtkAccelGroup  *accel_group)
+{
+  g_return_if_fail (accel_group != NULL);
+
+  return accel_group->blocked;
+}
+
 static GtkAccelEntry*
 gtk_accel_group_lookup (GtkAccelGroup	*accel_group,
 			guint		 accel_key,
@@ -260,6 +278,9 @@ gtk_accel_group_activate (GtkAccelGroup
   GtkAccelEntry *entry;

   g_return_val_if_fail (accel_group != NULL, FALSE);
+
+  if (accel_group->blocked)
+    return FALSE;

   entry = gtk_accel_group_lookup (accel_group, accel_key, accel_mods);
   if (entry && entry->signal_id &&
Index: gtkaccelgroup.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkaccelgroup.h,v
retrieving revision 1.9
diff -u -p -r1.9 gtkaccelgroup.h
--- gtkaccelgroup.h	2000/08/30 00:33:36	1.9
+++ gtkaccelgroup.h	2001/03/13 12:48:56
@@ -67,6 +67,7 @@ struct _GtkAccelGroup
   guint	          lock_count;
   GdkModifierType modifier_mask;
   GSList         *attach_objects;
+  guint           blocked : 1;
 };

 struct _GtkAccelEntry
@@ -107,6 +108,10 @@ void		gtk_accel_group_unlock		(GtkAccelG
 gboolean        gtk_accel_groups_activate      	(GtkObject	*object,
 						 guint		 accel_key,
 						 GdkModifierType accel_mods);
+void            gtk_accel_group_block      	(GtkAccelGroup	*accel_group,
+						 gboolean        blocked);
+gboolean        gtk_accel_group_is_blocked    	(GtkAccelGroup	*accel_group);
+

 /* internal functions
  */
Index: gtknotebook.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.c,v
retrieving revision 1.82
diff -u -p -r1.82 gtknotebook.c
--- gtknotebook.c	2001/03/09 13:28:25	1.82
+++ gtknotebook.c	2001/03/13 12:48:56
@@ -86,6 +86,8 @@ struct _GtkNotebookPage
   GtkWidget *tab_label;
   GtkWidget *menu_label;

+  GtkAccelGroup *accel_group;
+
   guint default_menu : 1;	/* If true, we create the menu label ourself */
   guint default_tab  : 1;	/* If true, we create the tab label ourself */
   guint expand       : 1;
@@ -3264,7 +3266,10 @@ gtk_notebook_real_switch_page (GtkNotebo

   if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
     gtk_widget_unmap (notebook->cur_page->child);
-
+
+  if (notebook->cur_page && notebook->cur_page->accel_group)
+      gtk_accel_group_block (notebook->cur_page->accel_group, TRUE);
+
   notebook->cur_page = page;

   if (!notebook->focus_tab ||
@@ -3275,6 +3280,9 @@ gtk_notebook_real_switch_page (GtkNotebo
   if (GTK_WIDGET_MAPPED (notebook))
     gtk_widget_map (notebook->cur_page->child);

+  if (notebook->cur_page && notebook->cur_page->accel_group)
+      gtk_accel_group_block (notebook->cur_page->accel_group, FALSE);
+
   gtk_widget_queue_resize (GTK_WIDGET (notebook));
 }

@@ -3550,7 +3558,7 @@ gtk_notebook_append_page_menu (GtkNotebo
  * @tab_label: the #GtkWidget to be used as the label for the page,
  *             or %NULL to use the default label, 'page N'.
  *
- * Prepends a page to @noteobook.
+ * Prepends a page to @notebook.
  **/
 void
 gtk_notebook_prepend_page (GtkNotebook *notebook,
@@ -3619,6 +3627,48 @@ gtk_notebook_insert_page (GtkNotebook *n
 }

 /**
+ * gtk_notebook_insert_page_accel:
+ * @notebook: a #GtkNotebook
+ * @child: the #GtkWidget to use as the contents of the page.
+ * @uline_label: the text of the label, use underscore to make
+ *               keyboard accelerators.
+ * @accel_group: the accel group to place the keyboard accelerators
+ *               in. May be null.
+ * @position: the index (starting at 0) at which to insert the page,
+ *            or -1 to append the page after all other pages.
+ *
+ * Inserts a page to @notebook, with the specified label text.
+ **/
+void
+gtk_notebook_insert_page_accel (GtkNotebook *notebook,
+				GtkWidget   *child,
+				const gchar *uline_label,
+				GtkAccelGroup *accel_group,
+				gint         position)
+{
+  GtkWidget *tab_label;
+  guint keyval;
+
+  g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+  g_return_if_fail (uline_label != NULL);
+
+  tab_label = gtk_label_new (uline_label);
+  keyval = gtk_label_parse_uline (GTK_LABEL (tab_label),
+				  uline_label);
+
+  gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
+
+  if (accel_group)
+    gtk_notebook_set_tab_accel (notebook,
+				child,
+				keyval,
+				GDK_MOD1_MASK,
+				accel_group);
+
+}
+
+/**
  * gtk_notebook_insert_page_menu:
  * @notebook: a #GtkNotebook
  * @child: the #GtkWidget to use as the contents of the page.
@@ -3661,6 +3711,7 @@ gtk_notebook_insert_page_menu (GtkNotebo
   page->allocation.height = 0;
   page->default_menu = FALSE;
   page->default_tab = FALSE;
+  page->accel_group = NULL;

   nchildren = g_list_length (notebook->children);
   if ((position < 0) || (position > nchildren))
@@ -4360,6 +4411,138 @@ gtk_notebook_set_tab_label_text (GtkNote

   if (tab_text)
     tab_label = gtk_label_new (tab_text);
+  gtk_notebook_set_tab_label (notebook, child, tab_label);
+}
+
+static gboolean
+grab_focus_callback (GtkWidget *child, gpointer data)
+{
+  GtkNotebook *notebook = GTK_NOTEBOOK (data);
+  GtkNotebookPage *page;
+  GList *list;
+
+  list = CHECK_FIND_CHILD (notebook, child);
+  if (!list)
+    return TRUE;
+
+  page = list->data;
+
+  gtk_notebook_switch_page (notebook, page,  -1);
+  return TRUE;
+}
+
+/**
+ * gtk_notebook_set_tab_accel_group:
+ * @notebook: a #GtkNotebook
+ * @child: the page
+ * @accel_group: an acceleration group
+ *
+ * This call binds an acceleration group to a particular notebook page.
+ * Only the acceleration group that belongs to the visible page is active,
+ * all the others are blocked.
+ **/
+void
+gtk_notebook_set_tab_accel_group (GtkNotebook   *notebook,
+				  GtkWidget     *child,
+				  GtkAccelGroup *accel_group)
+{
+  GtkNotebookPage *page;
+  GList *list;
+
+  g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+  g_return_if_fail (child != NULL);
+
+  list = CHECK_FIND_CHILD (notebook, child);
+  if (!list)
+    return;
+
+  page = list->data;
+
+  gtk_accel_group_ref (accel_group);
+
+  if (page->accel_group)
+    gtk_accel_group_unref (page->accel_group);
+
+  page->accel_group = accel_group;
+
+  gtk_accel_group_block (accel_group,
+			 page != notebook->cur_page);
+}
+
+void
+gtk_notebook_set_tab_accel (GtkNotebook   *notebook,
+			    GtkWidget     *child,
+			    guint          keyval,
+			    guint          modifiers,
+			    GtkAccelGroup *accel_group)
+{
+  GList *list;
+  GtkNotebookPage *page;
+
+  g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+  g_return_if_fail (child != NULL);
+
+  list = CHECK_FIND_CHILD (notebook, child);
+  if (!list)
+    return;
+
+  page = list->data;
+
+  /* Since we cannot add arguments to the signal emitted
+   * by the accelerator we misuse grab_focus of the child
+   * widget to get the child pointer.
+   */
+
+  gtk_widget_add_accelerator (child,
+			      "grab_focus",
+			      accel_group,
+			      keyval,
+			      modifiers,
+			      GTK_ACCEL_LOCKED);
+
+  gtk_signal_connect (GTK_OBJECT (child),
+		      "grab_focus",
+		      (GtkSignalFunc) grab_focus_callback,
+		      notebook);
+}
+
+/**
+ * gtk_notebook_set_tab_label_text_accel:
+ * @notebook: a #GtkNotebook
+ * @child: the page
+ * @uline_text: the label text, with underline
+ * @accel_group: The acceleration group to set the accelerator in
+ *
+ * Creates a new label and sets it as the tab label for the page
+ * containing @child. The label text is parsed looking for
+ * an underscore, and an accelerator <ALT>key is added that
+ * shows the page.
+ **/
+void
+gtk_notebook_set_tab_label_text_accel (GtkNotebook *notebook,
+				       GtkWidget   *child,
+				       const gchar   *uline_text,
+				       GtkAccelGroup *accel_group)
+{
+  GtkWidget *tab_label = NULL;
+  guint keyval;
+
+  g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
+
+  if (uline_text)
+    {
+      tab_label = gtk_label_new (uline_text);
+      keyval = gtk_label_parse_uline (GTK_LABEL (tab_label),
+                                      uline_text);
+
+      if (accel_group)
+	gtk_notebook_set_tab_accel (notebook,
+				    child,
+				    keyval,
+				    GDK_MOD1_MASK,
+				    accel_group);
+
+    }
   gtk_notebook_set_tab_label (notebook, child, tab_label);
 }

Index: gtknotebook.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtknotebook.h,v
retrieving revision 1.23
diff -u -p -r1.23 gtknotebook.h
--- gtknotebook.h	2000/12/11 17:47:24	1.23
+++ gtknotebook.h	2001/03/13 12:48:57
@@ -92,34 +92,40 @@ struct _GtkNotebookClass
  *           Creation, insertion, deletion                 *
  ***********************************************************/

-GtkType gtk_notebook_get_type       (void) G_GNUC_CONST;
-GtkWidget * gtk_notebook_new        (void);
-void gtk_notebook_append_page       (GtkNotebook *notebook,
-				     GtkWidget   *child,
-				     GtkWidget   *tab_label);
-void gtk_notebook_append_page_menu  (GtkNotebook *notebook,
-				     GtkWidget   *child,
-				     GtkWidget   *tab_label,
-				     GtkWidget   *menu_label);
-void gtk_notebook_prepend_page      (GtkNotebook *notebook,
-				     GtkWidget   *child,
-				     GtkWidget   *tab_label);
-void gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
-				     GtkWidget   *child,
-				     GtkWidget   *tab_label,
-				     GtkWidget   *menu_label);
-void gtk_notebook_insert_page       (GtkNotebook *notebook,
-				     GtkWidget   *child,
-				     GtkWidget   *tab_label,
-				     gint         position);
-void gtk_notebook_insert_page_menu  (GtkNotebook *notebook,
-				     GtkWidget   *child,
-				     GtkWidget   *tab_label,
-				     GtkWidget   *menu_label,
-				     gint         position);
-void gtk_notebook_remove_page       (GtkNotebook *notebook,
-				     gint         page_num);
+GtkType    gtk_notebook_get_type           (void) G_GNUC_CONST;
+GtkWidget *gtk_notebook_new                (void);
+void       gtk_notebook_append_page        (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    GtkWidget     *tab_label);
+void       gtk_notebook_append_page_menu   (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    GtkWidget     *tab_label,
+					    GtkWidget     *menu_label);
+void       gtk_notebook_prepend_page       (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    GtkWidget     *tab_label);
+void       gtk_notebook_prepend_page_menu  (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    GtkWidget     *tab_label,
+					    GtkWidget     *menu_label);
+void       gtk_notebook_insert_page        (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    GtkWidget     *tab_label,
+					    gint           position);
+void       gtk_notebook_insert_page_accel  (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    const gchar   *uline_label,
+					    GtkAccelGroup *accel_group,
+					    gint           position);
+void       gtk_notebook_insert_page_menu   (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    GtkWidget     *tab_label,
+					    GtkWidget     *menu_label,
+					    gint           position);
+void       gtk_notebook_remove_page        (GtkNotebook   *notebook,
+					    gint           page_num);

+
 /***********************************************************
  *            query, set current NoteebookPage             *
  ***********************************************************/
@@ -174,6 +180,18 @@ void gtk_notebook_set_tab_label
 void gtk_notebook_set_tab_label_text      (GtkNotebook *notebook,
 					   GtkWidget   *child,
 					   const gchar *tab_text);
+void gtk_notebook_set_tab_label_text_accel (GtkNotebook   *notebook,
+					    GtkWidget     *child,
+					    const gchar   *uline_text,
+					    GtkAccelGroup *accel_group);
+void gtk_notebook_set_tab_accel           (GtkNotebook   *notebook,
+					   GtkWidget     *child,
+					   guint          keyval,
+					   guint          modifiers,
+					   GtkAccelGroup *accel_group);
+void gtk_notebook_set_tab_accel_group     (GtkNotebook   *notebook,
+					   GtkWidget     *child,
+					   GtkAccelGroup *accel_group);
 GtkWidget * gtk_notebook_get_menu_label   (GtkNotebook *notebook,
 					   GtkWidget   *child);
 void gtk_notebook_set_menu_label          (GtkNotebook *notebook,





[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]