libegg r889 - in trunk: . libegg/toolpalette



Author: hasselmm
Date: Thu Jul 10 12:33:07 2008
New Revision: 889
URL: http://svn.gnome.org/viewvc/libegg?rev=889&view=rev

Log:
Scroll when focusing tool palette item.

* libegg/toolpalette/eggtoolitemgroup.c (EggToolItemGroupPrivate,
  egg_tool_item_group_dispose(), egg_tool_item_group_set_focus_cb(),
  egg_tool_item_group_realize(), egg_tool_item_group_unrealize(),
  egg_tool_item_group_set_toplevel_window()): Hook to parent window's
  set-focus signal to track focus changes and actually scroll to the
  focused widget when it is one of our items.

* libegg/toolpalette/eggtoolpalette.c
 (egg_tool_palette_get_hadjustment(),
  egg_tool_palette_get_vadjustment()):
* libegg/toolpalette/eggtoolpalette.h
 (egg_tool_palette_get_hadjustment(),
  egg_tool_palette_get_vadjustment()):
  Provide adjustment accessors. Fix some formatting issues.


Modified:
   trunk/ChangeLog
   trunk/libegg/toolpalette/eggtoolitemgroup.c
   trunk/libegg/toolpalette/eggtoolpalette.c
   trunk/libegg/toolpalette/eggtoolpalette.h
   trunk/libegg/toolpalette/testtoolpalette.c

Modified: trunk/libegg/toolpalette/eggtoolitemgroup.c
==============================================================================
--- trunk/libegg/toolpalette/eggtoolitemgroup.c	(original)
+++ trunk/libegg/toolpalette/eggtoolitemgroup.c	Thu Jul 10 12:33:07 2008
@@ -80,8 +80,10 @@
   gint               header_spacing;
   PangoEllipsizeMode ellipsize;
 
-  guint              collapsed : 1;
+  gulong             focus_set_id;
+  GtkWidget         *toplevel;
 
+  guint              collapsed : 1;
 };
 
 struct _EggToolItemGroupChild
@@ -444,6 +446,24 @@
 }
 
 static void
+egg_tool_item_group_dispose (GObject *object)
+{
+  EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (object);
+
+  if (group->priv->toplevel)
+    {
+      /* disconnect focus tracking handler */
+      g_signal_handler_disconnect (group->priv->toplevel,
+                                   group->priv->focus_set_id);
+
+      group->priv->focus_set_id = 0;
+      group->priv->toplevel = NULL;
+    }
+
+  G_OBJECT_CLASS (egg_tool_item_group_parent_class)->dispose (object);
+}
+
+static void
 egg_tool_item_group_get_item_size (EggToolItemGroup *group,
                                    GtkRequisition   *item_size,
                                    gboolean          homogeneous_only,
@@ -800,7 +820,7 @@
           child_allocation.width = child_requisition.width;
           child_allocation.height = allocation->height;
 
-	  if (GTK_TEXT_DIR_RTL == direction)
+          if (GTK_TEXT_DIR_RTL == direction)
             child_allocation.x = allocation->width - border_width - child_allocation.width;
         }
 
@@ -958,8 +978,116 @@
 }
 
 static void
+egg_tool_item_group_set_focus_cb (GtkWidget *window G_GNUC_UNUSED,
+                                  GtkWidget *widget,
+                                  gpointer   user_data)
+{
+  GtkAdjustment *adjustment;
+  GtkWidget *p;
+
+  /* Find this group's parent widget in the focused widget's anchestry. */
+  for (p = widget; p; p = gtk_widget_get_parent (p))
+    if (p == user_data)
+      {
+        p = gtk_widget_get_parent (p);
+        break;
+      }
+
+  if (EGG_IS_TOOL_PALETTE (p))
+    {
+      /* Check that the focused widgets is fully visible within
+       * the group's parent widget and make it visible otherwise. */
+
+      adjustment = egg_tool_palette_get_hadjustment (EGG_TOOL_PALETTE (p));
+      adjustment = egg_tool_palette_get_vadjustment (EGG_TOOL_PALETTE (p));
+
+      if (adjustment)
+        {
+          int y;
+
+          /* Handle vertical adjustment. */
+          if (gtk_widget_translate_coordinates
+                (widget, p, 0, 0, NULL, &y) && y < 0)
+            {
+              y += adjustment->value;
+              gtk_adjustment_clamp_page (adjustment, y, y + widget->allocation.height);
+            }
+          else if (gtk_widget_translate_coordinates
+                      (widget, p, 0, widget->allocation.height, NULL, &y) &&
+                   y > p->allocation.height)
+            {
+              y += adjustment->value;
+              gtk_adjustment_clamp_page (adjustment, y - widget->allocation.height, y);
+            }
+        }
+
+      adjustment = egg_tool_palette_get_hadjustment (EGG_TOOL_PALETTE (p));
+
+      if (adjustment)
+        {
+          int x;
+
+          /* Handle horizontal adjustment. */
+          if (gtk_widget_translate_coordinates
+                (widget, p, 0, 0, &x, NULL) && x < 0)
+            {
+              x += adjustment->value;
+              gtk_adjustment_clamp_page (adjustment, x, x + widget->allocation.width);
+            }
+          else if (gtk_widget_translate_coordinates
+                      (widget, p, widget->allocation.width, 0, &x, NULL) &&
+                   x > p->allocation.width)
+            {
+              x += adjustment->value;
+              gtk_adjustment_clamp_page (adjustment, x - widget->allocation.width, x);
+            }
+
+          return;
+        }
+    }
+}
+
+static void
+egg_tool_item_group_set_toplevel_window (EggToolItemGroup *group,
+                                         GtkWidget        *toplevel)
+{
+  if (toplevel != group->priv->toplevel)
+    {
+      if (group->priv->toplevel)
+        {
+          /* Disconnect focus tracking handler. */
+          g_signal_handler_disconnect (group->priv->toplevel,
+                                       group->priv->focus_set_id);
+
+          group->priv->focus_set_id = 0;
+          group->priv->toplevel = NULL;
+        }
+
+      if (toplevel)
+        {
+          /* Install focus tracking handler. We connect to the window's
+           * set-focus signal instead of connecting to the focus signal of
+           * each child to:
+           *
+           * 1) Reduce the number of signal handlers used.
+           * 2) Avoid special handling for group headers.
+           * 3) Catch focus grabs not only for direct children,
+           *    but also for nested widgets.
+           */
+          group->priv->focus_set_id =
+            g_signal_connect (toplevel, "set-focus",
+                              G_CALLBACK (egg_tool_item_group_set_focus_cb),
+                              group);
+
+          group->priv->toplevel = toplevel;
+        }
+    }
+}
+
+static void
 egg_tool_item_group_realize (GtkWidget *widget)
 {
+  GtkWidget *toplevel_window;
   const gint border_width = GTK_CONTAINER (widget)->border_width;
   gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
   GdkWindowAttr attributes;
@@ -995,6 +1123,17 @@
                         widget->window);
 
   gtk_widget_queue_resize_no_redraw (widget);
+
+  toplevel_window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
+  egg_tool_item_group_set_toplevel_window (EGG_TOOL_ITEM_GROUP (widget),
+                                           toplevel_window);
+}
+
+static void
+egg_tool_item_group_unrealize (GtkWidget *widget)
+{
+  egg_tool_item_group_set_toplevel_window (EGG_TOOL_ITEM_GROUP (widget), NULL);
+  GTK_WIDGET_CLASS (egg_tool_item_group_parent_class)->unrealize (widget);
 }
 
 static void
@@ -1305,10 +1444,12 @@
   oclass->set_property       = egg_tool_item_group_set_property;
   oclass->get_property       = egg_tool_item_group_get_property;
   oclass->finalize           = egg_tool_item_group_finalize;
+  oclass->dispose            = egg_tool_item_group_dispose;
 
   wclass->size_request       = egg_tool_item_group_size_request;
   wclass->size_allocate      = egg_tool_item_group_size_allocate;
   wclass->realize            = egg_tool_item_group_realize;
+  wclass->unrealize          = egg_tool_item_group_unrealize;
   wclass->style_set          = egg_tool_item_group_style_set;
 
   cclass->add                = egg_tool_item_group_add;
@@ -1467,19 +1608,37 @@
   EggToolItemGroup *group = EGG_TOOL_ITEM_GROUP (data);
   gint64 timestamp = egg_tool_item_group_get_animation_timestamp (group);
 
-  /* enque this early to reduce number of expose events */
+  /* Enque this early to reduce number of expose events. */
   gtk_widget_queue_resize_no_redraw (GTK_WIDGET (group));
 
+  /* Figure out current style of the expander arrow. */
+  if (group->priv->collapsed)
+    {
+      if (group->priv->expander_style == GTK_EXPANDER_EXPANDED)
+        group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
+      else
+        group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
+    }
+  else
+    {
+      if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED)
+        group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
+      else
+        group->priv->expander_style = GTK_EXPANDER_EXPANDED;
+    }
+
   if (GTK_WIDGET_REALIZED (group->priv->header))
     {
       GtkWidget *alignment = egg_tool_item_group_get_alignment (group);
       GdkRectangle area;
 
+      /* Find the header button's arrow area... */
       area.x = alignment->allocation.x;
       area.y = alignment->allocation.y + (alignment->allocation.height - group->priv->expander_size) / 2;
       area.height = group->priv->expander_size;
       area.width = group->priv->expander_size;
 
+      /* ... and invalidated it to get it animated. */
       gdk_window_invalidate_rect (group->priv->header->window, &area, TRUE);
     }
 
@@ -1487,10 +1646,11 @@
     {
       GtkWidget *widget = GTK_WIDGET (group);
       GtkWidget *parent = gtk_widget_get_parent (widget);
+      int x, y, width, height;
 
-      gint width = widget->allocation.width;
-      gint height = widget->allocation.height;
-      gint x, y;
+      /* Find the tool item area button's arrow area... */
+      width = widget->allocation.width;
+      height = widget->allocation.height;
 
       gtk_widget_translate_coordinates (widget, parent, 0, 0, &x, &y);
 
@@ -1500,24 +1660,11 @@
           y += group->priv->header->allocation.height;
         }
 
+      /* ... and invalidated it to get it animated. */
       gtk_widget_queue_draw_area (parent, x, y, width, height);
     }
 
-  if (group->priv->collapsed)
-    {
-      if (group->priv->expander_style == GTK_EXPANDER_EXPANDED)
-        group->priv->expander_style = GTK_EXPANDER_SEMI_COLLAPSED;
-      else
-        group->priv->expander_style = GTK_EXPANDER_COLLAPSED;
-    }
-  else
-    {
-      if (group->priv->expander_style == GTK_EXPANDER_COLLAPSED)
-        group->priv->expander_style = GTK_EXPANDER_SEMI_EXPANDED;
-      else
-        group->priv->expander_style = GTK_EXPANDER_EXPANDED;
-    }
-
+  /* Finish animation when done. */
   if (timestamp >= ANIMATION_DURATION)
     group->priv->animation_timeout = NULL;
 
@@ -1560,8 +1707,10 @@
       group->priv->animation_timeout = g_timeout_source_new (ANIMATION_TIMEOUT);
 
       parent = gtk_widget_get_parent (GTK_WIDGET (group));
+
       if (EGG_IS_TOOL_PALETTE (parent) && !collapsed)
-        _egg_tool_palette_set_expanding_child (EGG_TOOL_PALETTE (parent), GTK_WIDGET (group));
+        _egg_tool_palette_set_expanding_child (EGG_TOOL_PALETTE (parent),
+                                               GTK_WIDGET (group));
 
       g_source_set_callback (group->priv->animation_timeout,
                              egg_tool_item_group_animation_cb,

Modified: trunk/libegg/toolpalette/eggtoolpalette.c
==============================================================================
--- trunk/libegg/toolpalette/eggtoolpalette.c	(original)
+++ trunk/libegg/toolpalette/eggtoolpalette.c	Thu Jul 10 12:33:07 2008
@@ -451,21 +451,25 @@
        * widget as possible is calculated */
       if (widget == palette->priv->expanding_child)
         {
-          guint j;
+          gint limit =
+            GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
+            child_allocation.width : child_allocation.height;
+
           gint real_size;
-          gint limit = GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? child_allocation.width : child_allocation.height;
+          guint j;
 
           min_offset = 0;
+
           for (j = 0; j < i; ++j)
-            {
-              min_offset += group_sizes[j];
-            }
+            min_offset += group_sizes[j];
+
           max_offset = min_offset + group_sizes[i];
 
-          real_size = _egg_tool_item_group_get_size_for_limit (EGG_TOOL_ITEM_GROUP (widget),
-                                                               limit,
-                                                               GTK_ORIENTATION_VERTICAL == palette->priv->orientation,
-                                                               FALSE);
+          real_size = _egg_tool_item_group_get_size_for_limit
+            (EGG_TOOL_ITEM_GROUP (widget), limit,
+             GTK_ORIENTATION_VERTICAL == palette->priv->orientation,
+             FALSE);
+
           if (size == real_size)
             palette->priv->expanding_child = NULL;
         }
@@ -479,9 +483,11 @@
 
   if (max_offset != -1)
     {
-      gint limit = GTK_ORIENTATION_VERTICAL == palette->priv->orientation ? allocation->height : allocation->width;
+      gint limit =
+        GTK_ORIENTATION_VERTICAL == palette->priv->orientation ?
+        allocation->height : allocation->width;
 
-      offset = MIN(MAX (offset, max_offset - limit), min_offset);
+      offset = MIN (MAX (offset, max_offset - limit), min_offset);
     }
 
   if (remaining_space > 0)
@@ -562,18 +568,9 @@
       adjustment->page_increment = page_size * 0.9;
       adjustment->step_increment = page_size * 0.1;
       adjustment->page_size = page_size;
-      if (GTK_ORIENTATION_HORIZONTAL == palette->priv->orientation &&
-          GTK_TEXT_DIR_RTL == direction)
-        {
-          adjustment->lower = page_size - MAX (0, page_start);
-          adjustment->upper = page_size;
 
-          offset = -offset;
-
-          value = MAX(offset, adjustment->lower);
-          gtk_adjustment_clamp_page (adjustment, offset, value + page_size);
-        }
-      else
+      if (GTK_ORIENTATION_VERTICAL == palette->priv->orientation ||
+          GTK_TEXT_DIR_LTR == direction)
         {
           adjustment->lower = 0;
           adjustment->upper = MAX (0, page_start);
@@ -581,6 +578,16 @@
           value = MIN (offset, adjustment->upper - adjustment->page_size);
           gtk_adjustment_clamp_page (adjustment, value, offset + page_size);
         }
+      else
+        {
+          adjustment->lower = page_size - MAX (0, page_start);
+          adjustment->upper = page_size;
+
+          offset = -offset;
+
+          value = MAX (offset, adjustment->lower);
+          gtk_adjustment_clamp_page (adjustment, offset, value + page_size);
+        }
 
       gtk_adjustment_changed (adjustment);
     }
@@ -1597,15 +1604,29 @@
 }
 
 void
-_egg_tool_palette_set_expanding_child (EggToolPalette   *palette,
-                                       GtkWidget        *widget)
+_egg_tool_palette_set_expanding_child (EggToolPalette *palette,
+                                       GtkWidget      *widget)
 {
   g_return_if_fail (EGG_IS_TOOL_PALETTE (palette));
-
   palette->priv->expanding_child = widget;
 }
 
+GtkAdjustment*
+egg_tool_palette_get_hadjustment (EggToolPalette *palette)
+{
+  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (palette), NULL);
+  return palette->priv->hadjustment;
+}
+
+GtkAdjustment*
+egg_tool_palette_get_vadjustment (EggToolPalette *palette)
+{
+  g_return_val_if_fail (EGG_IS_TOOL_PALETTE (palette), NULL);
+  return palette->priv->vadjustment;
+}
+
 #ifdef HAVE_EXTENDED_TOOL_SHELL_SUPPORT_BUG_535090
+
 GtkSizeGroup *
 _egg_tool_palette_get_size_group (EggToolPalette *palette)
 {
@@ -1613,4 +1634,5 @@
 
   return palette->priv->text_size_group;
 }
+
 #endif

Modified: trunk/libegg/toolpalette/eggtoolpalette.h
==============================================================================
--- trunk/libegg/toolpalette/eggtoolpalette.h	(original)
+++ trunk/libegg/toolpalette/eggtoolpalette.h	Thu Jul 10 12:33:07 2008
@@ -121,6 +121,9 @@
                                                                        EggToolPaletteDragTargets  targets,
                                                                        GdkDragAction              actions);
 
+GtkAdjustment*                 egg_tool_palette_get_hadjustment       (EggToolPalette            *palette);
+GtkAdjustment*                 egg_tool_palette_get_vadjustment       (EggToolPalette            *palette);
+
 G_CONST_RETURN GtkTargetEntry* egg_tool_palette_get_drag_target_item  (void) G_GNUC_CONST;
 G_CONST_RETURN GtkTargetEntry* egg_tool_palette_get_drag_target_group (void) G_GNUC_CONST;
 

Modified: trunk/libegg/toolpalette/testtoolpalette.c
==============================================================================
--- trunk/libegg/toolpalette/testtoolpalette.c	(original)
+++ trunk/libegg/toolpalette/testtoolpalette.c	Thu Jul 10 12:33:07 2008
@@ -117,7 +117,7 @@
   if (EGG_TOOL_ITEM_GROUP (drag_group) != drop_group)
     {
       gboolean homogeneous, expand, fill, new_row;
-      
+
       g_object_ref (drag_item);
       gtk_container_child_get (GTK_CONTAINER (drag_group), GTK_WIDGET (drag_item),
                                "homogeneous", &homogeneous,
@@ -433,6 +433,30 @@
 }
 
 static void
+load_toggle_items (EggToolPalette *palette)
+{
+  GSList *toggle_group = NULL;
+  GtkToolItem *item;
+  GtkWidget *group;
+  char *label;
+  int i;
+
+  group = egg_tool_item_group_new (_("Radio Item"));
+  gtk_container_add (GTK_CONTAINER (palette), group);
+
+  for (i = 1; i <= 10; ++i)
+    {
+      label = g_strdup_printf ("#%d", i);
+      item = gtk_radio_tool_button_new (toggle_group);
+      gtk_tool_button_set_label (GTK_TOOL_BUTTON (item), label);
+      g_free (label);
+
+      egg_tool_item_group_insert (EGG_TOOL_ITEM_GROUP (group), item, -1);
+      toggle_group = gtk_radio_tool_button_get_group (GTK_RADIO_TOOL_BUTTON (item));
+    }
+}
+
+static void
 load_special_items (EggToolPalette *palette)
 {
   GtkToolItem *item;
@@ -720,6 +744,7 @@
   /* ===== palette ===== */
 
   load_stock_items (EGG_TOOL_PALETTE (palette));
+  load_toggle_items (EGG_TOOL_PALETTE (palette));
   load_special_items (EGG_TOOL_PALETTE (palette));
 
   g_signal_connect (palette, "notify::orientation",



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