[gtk+/resizegrips] Make GtkStatusbar avoid resize grips



commit 116dec9be113aa20d2d9022189c2f029a7d9fa88
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Oct 3 02:01:52 2010 -0400

    Make GtkStatusbar avoid resize grips
    
    This reinstates some of the earlier GtkStatusbar resize grip handling
    code, but now it works withe the GtkWindow resize grip.

 gtk/gtkstatusbar.c |  177 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 176 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkstatusbar.c b/gtk/gtkstatusbar.c
index f71dd83..704b3b6 100644
--- a/gtk/gtkstatusbar.c
+++ b/gtk/gtkstatusbar.c
@@ -107,6 +107,10 @@ static void     gtk_statusbar_update            (GtkStatusbar      *statusbar,
 						 guint              context_id,
 						 const gchar       *text);
 static void     gtk_statusbar_destroy           (GtkWidget         *widget);
+static void     gtk_statusbar_size_allocate     (GtkWidget         *widget,
+                                                 GtkAllocation     *allocation);
+static void     gtk_statusbar_hierarchy_changed (GtkWidget         *widget,
+                                                 GtkWidget         *previous_toplevel);
 
 
 static guint              statusbar_signals[SIGNAL_LAST] = { 0 };
@@ -125,7 +129,9 @@ gtk_statusbar_class_init (GtkStatusbarClass *class)
   widget_class = (GtkWidgetClass *) class;
 
   widget_class->destroy = gtk_statusbar_destroy;
-  
+  widget_class->size_allocate = gtk_statusbar_size_allocate;
+  widget_class->hierarchy_changed = gtk_statusbar_hierarchy_changed;
+
   class->text_pushed = gtk_statusbar_update;
   class->text_popped = gtk_statusbar_update;
 
@@ -578,3 +584,172 @@ gtk_statusbar_destroy (GtkWidget *widget)
 
   GTK_WIDGET_CLASS (gtk_statusbar_parent_class)->destroy (widget);
 }
+
+/* look for extra children between the frame containing
+ * the label and where we want to draw the resize grip
+ */
+static gboolean
+has_extra_children (GtkStatusbar *statusbar)
+{
+  GtkStatusbarPrivate *priv = statusbar->priv;
+  GtkPackType child_pack_type, frame_pack_type;
+  GtkWidget *child, *frame;
+  GList *l, *children;
+  gboolean retval = FALSE;
+
+  frame = NULL;
+  children = _gtk_box_get_children (GTK_BOX (statusbar));
+  for (l = children; l; l = l->next)
+    {
+      frame = l->data;
+
+      if (frame == priv->frame)
+        break;
+    }
+
+  gtk_box_query_child_packing (GTK_BOX (statusbar), frame,
+                               NULL, NULL, NULL, &frame_pack_type);
+
+  for (l = l->next; l; l = l->next)
+    {
+      child = l->data;
+
+      if (!gtk_widget_get_visible (child))
+        continue;
+
+      gtk_box_query_child_packing (GTK_BOX (statusbar), child,
+                                   NULL, NULL, NULL, &child_pack_type);
+
+      if (frame_pack_type == GTK_PACK_START || child_pack_type == GTK_PACK_END)
+        {
+          retval = TRUE;
+          break;
+        }
+    }
+
+  g_list_free (children);
+
+  return retval;
+}
+
+static void
+gtk_statusbar_size_allocate (GtkWidget     *widget,
+                             GtkAllocation *allocation)
+{
+  GtkStatusbar *statusbar = GTK_STATUSBAR (widget);
+  GtkStatusbarPrivate *priv = statusbar->priv;
+  gboolean extra_children = FALSE;
+  gboolean has_resize_grip = FALSE;
+  GdkRectangle rect;
+  GtkWidget *window;
+  gint x, y;
+  GdkRectangle translated_rect;
+
+  window = gtk_widget_get_toplevel (widget);
+  if (GTK_IS_WINDOW (window) &&
+      gtk_window_resize_grip_is_visible (GTK_WINDOW (window)))
+    {
+      gtk_window_get_resize_grip_area (GTK_WINDOW (window), &rect);
+
+      if (gtk_widget_translate_coordinates (gtk_widget_get_parent (widget),
+                                            window,
+                                            allocation->x,
+                                            allocation->y,
+                                            &x,
+                                            &y))
+        {
+          translated_rect.x = x;
+          translated_rect.y = y;
+          translated_rect.width = allocation->width;
+          translated_rect.height = allocation->height;
+
+          if (gdk_rectangle_intersect (&rect, &translated_rect, NULL))
+            {
+              has_resize_grip = TRUE;
+              extra_children = has_extra_children (statusbar);
+
+              /* If there are extra children, we don't want them to occupy
+               * the space where we draw the resize grip, so we temporarily
+               * shrink the allocation.
+               * If there are no extra children, we want the frame to get
+               * the full allocation, and we fix up the allocation of the
+               * label afterwards to make room for the grip.
+               */
+              if (extra_children)
+                {
+                  allocation->width -= rect.width;
+                  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+                    allocation->x += rect.width;
+                }
+            }
+        }
+    }
+
+  /* chain up normally */
+  GTK_WIDGET_CLASS (gtk_statusbar_parent_class)->size_allocate (widget, allocation);
+
+  if (has_resize_grip)
+    {
+      if (extra_children)
+        {
+          allocation->width += rect.width;
+          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+            allocation->x -= rect.width;
+
+          gtk_widget_set_allocation (widget, allocation);
+        }
+      else
+        {
+          GtkAllocation child_allocation, frame_allocation;
+          GtkWidget *child;
+
+          /* Use the frame's child instead of statusbar->label directly, in case
+           * the label has been replaced by a container as the frame's child
+           * (and the label reparented into that container).
+           */
+          child = gtk_bin_get_child (GTK_BIN (priv->frame));
+
+          gtk_widget_get_allocation (child, &child_allocation);
+          gtk_widget_get_allocation (priv->frame, &frame_allocation);
+          if (child_allocation.width + rect.width > frame_allocation.width)
+            {
+              /* shrink the label to make room for the grip */
+              *allocation = child_allocation;
+              allocation->width = MAX (1, allocation->width - rect.width);
+              if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+                allocation->x += child_allocation.width - allocation->width;
+
+              gtk_widget_size_allocate (child, allocation);
+            }
+        }
+    }
+}
+
+static void
+resize_grip_visible_changed (GObject    *object,
+                             GParamSpec *pspec,
+                             gpointer    user_data)
+{
+  GtkStatusbar *statusbar = GTK_STATUSBAR (user_data);
+  GtkStatusbarPrivate *priv = statusbar->priv;
+
+  gtk_widget_queue_resize (GTK_WIDGET (statusbar));
+  gtk_widget_queue_resize (priv->label);
+  gtk_widget_queue_resize (priv->frame);
+}
+
+static void
+gtk_statusbar_hierarchy_changed (GtkWidget *widget,
+                                 GtkWidget *previous_toplevel)
+{
+  GtkWidget *window;
+
+  if (previous_toplevel)
+    g_signal_handlers_disconnect_by_func (previous_toplevel,
+                                          G_CALLBACK (resize_grip_visible_changed),
+                                          widget);
+  window = gtk_widget_get_toplevel (widget);
+  if (GTK_IS_WINDOW (window))
+    g_signal_connect (window, "notify::resize-grip-visible",
+                      G_CALLBACK (resize_grip_visible_changed), widget);
+}



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