[gtk/bin-removal: 10/44] viewport: Derive from GtkWidget



commit a5fb580ed62d13fa307d7f2606ba51a0e914cf3f
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri May 1 16:53:14 2020 -0400

    viewport: Derive from GtkWidget
    
    We want to remove GtkBin and GtkContainer as they don't
    provide much useful functionality anymore. This requires
    us to move get_request_mode and compute_expand down.
    
    We have to implement GtkBuildable in order to keep
    the <child> element working for viewports in ui files.
    See #2681

 gtk/gtkviewport.c | 135 +++++++++++++++++++++++++++++++++++++++++-------------
 gtk/gtkviewport.h |   2 +-
 2 files changed, 104 insertions(+), 33 deletions(-)
---
diff --git a/gtk/gtkviewport.c b/gtk/gtkviewport.c
index dea061ec2f..1cbd46aa65 100644
--- a/gtk/gtkviewport.c
+++ b/gtk/gtkviewport.c
@@ -34,6 +34,7 @@
 #include "gtkstylecontext.h"
 #include "gtktypebuiltins.h"
 #include "gtkwidgetprivate.h"
+#include "gtkbuildable.h"
 #include "gtktext.h"
 
 
@@ -69,7 +70,9 @@ typedef struct _GtkViewportClass         GtkViewportClass;
 
 struct _GtkViewport
 {
-  GtkBin parent_instance;
+  GtkWidget parent_instance;
+
+  GtkWidget *child;
 
   GtkAdjustment  *hadjustment;
   GtkAdjustment  *vadjustment;
@@ -85,7 +88,7 @@ struct _GtkViewport
 
 struct _GtkViewportClass
 {
-  GtkBinClass parent_class;
+  GtkWidgetClass parent_class;
 };
 
 enum {
@@ -107,11 +110,12 @@ static void gtk_viewport_get_property             (GObject         *object,
                                                    guint            prop_id,
                                                    GValue          *value,
                                                    GParamSpec      *pspec);
-static void gtk_viewport_destroy                  (GtkWidget        *widget);
-static void gtk_viewport_size_allocate            (GtkWidget        *widget,
-                                                   int               width,
-                                                   int               height,
-                                                   int               baseline);
+static void gtk_viewport_destroy                  (GtkWidget       *widget);
+static void gtk_viewport_size_allocate            (GtkWidget       *widget,
+                                                   int              width,
+                                                   int              height,
+                                                   int              baseline);
+
 static void gtk_viewport_adjustment_value_changed (GtkAdjustment    *adjustment,
                                                    gpointer          data);
 static void viewport_set_adjustment               (GtkViewport      *viewport,
@@ -121,19 +125,44 @@ static void viewport_set_adjustment               (GtkViewport      *viewport,
 static void setup_focus_change_handler (GtkViewport *viewport);
 static void clear_focus_change_handler (GtkViewport *viewport);
 
-G_DEFINE_TYPE_WITH_CODE (GtkViewport, gtk_viewport, GTK_TYPE_BIN,
+static void gtk_viewport_buildable_init (GtkBuildableIface *iface);
+
+
+G_DEFINE_TYPE_WITH_CODE (GtkViewport, gtk_viewport, GTK_TYPE_WIDGET,
+                         G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
+                                                gtk_viewport_buildable_init)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
 
+static GtkBuildableIface *parent_buildable_iface;
+
+static void
+gtk_viewport_buildable_add_child (GtkBuildable *buildable,
+                                  GtkBuilder   *builder,
+                                  GObject      *child,
+                                  const gchar  *type)
+{
+  if (GTK_IS_WIDGET (child))
+    gtk_viewport_set_child (GTK_VIEWPORT (buildable), GTK_WIDGET (child));
+  else
+    parent_buildable_iface->add_child (buildable, builder, child, type);
+}
+
+static void
+gtk_viewport_buildable_init (GtkBuildableIface *iface)
+{
+  parent_buildable_iface = g_type_interface_peek_parent (iface);
+
+  iface->add_child = gtk_viewport_buildable_add_child;
+}
+
 static void
 viewport_set_adjustment_values (GtkViewport    *viewport,
                                 GtkOrientation  orientation)
 {
-  GtkBin *bin = GTK_BIN (viewport);
   GtkAdjustment *adjustment;
   GtkScrollablePolicy scroll_policy;
   GtkScrollablePolicy other_scroll_policy;
   GtkOrientation other_orientation;
-  GtkWidget *child;
   gdouble upper, value;
   int viewport_size, other_viewport_size;
   int view_width, view_height;
@@ -161,20 +190,19 @@ viewport_set_adjustment_values (GtkViewport    *viewport,
     }
 
 
-  child = gtk_bin_get_child (bin);
-  if (child && gtk_widget_get_visible (child))
+  if (viewport->child && gtk_widget_get_visible (viewport->child))
     {
       int min_size, nat_size;
       int scroll_size;
 
       if (other_scroll_policy == GTK_SCROLL_MINIMUM)
-        gtk_widget_measure (child, other_orientation, -1,
+        gtk_widget_measure (viewport->child, other_orientation, -1,
                             &scroll_size, NULL, NULL, NULL);
       else
-        gtk_widget_measure (child, other_orientation, -1,
+        gtk_widget_measure (viewport->child, other_orientation, -1,
                             NULL, &scroll_size, NULL, NULL);
 
-      gtk_widget_measure (child, orientation,
+      gtk_widget_measure (viewport->child, orientation,
                           MAX (other_viewport_size, scroll_size),
                           &min_size, &nat_size, NULL, NULL);
 
@@ -219,23 +247,56 @@ gtk_viewport_measure (GtkWidget      *widget,
                       int            *minimum_baseline,
                       int            *natural_baseline)
 {
-  GtkWidget *child;
+  GtkViewport *viewport = GTK_VIEWPORT (widget);
 
   *minimum = *natural = 0;
 
-  child = gtk_bin_get_child (GTK_BIN (widget));
-  if (child && gtk_widget_get_visible (child))
-    gtk_widget_measure (child,
+  if (viewport->child && gtk_widget_get_visible (viewport->child))
+    gtk_widget_measure (viewport->child,
                         orientation,
                         for_size,
                         minimum, natural,
                         NULL, NULL);
 }
 
+static void
+gtk_viewport_compute_expand (GtkWidget *widget,
+                             gboolean  *hexpand,
+                             gboolean  *vexpand)
+{
+  GtkViewport *viewport = GTK_VIEWPORT (widget);
+
+  if (viewport->child)
+    {
+      *hexpand = gtk_widget_compute_expand (viewport->child, GTK_ORIENTATION_HORIZONTAL);
+      *vexpand = gtk_widget_compute_expand (viewport->child, GTK_ORIENTATION_VERTICAL);
+    }
+  else
+    {
+      *hexpand = FALSE;
+      *vexpand = FALSE;
+    }
+}
+
+static GtkSizeRequestMode
+gtk_viewport_get_request_mode (GtkWidget *widget)
+{
+  GtkViewport *viewport = GTK_VIEWPORT (widget);
+
+  if (viewport->child)
+    return gtk_widget_get_request_mode (viewport->child);
+  else
+    return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+}
+
 static void
 gtk_viewport_dispose (GObject *object)
 {
-  clear_focus_change_handler (GTK_VIEWPORT (object));
+  GtkViewport *viewport = GTK_VIEWPORT (object);
+
+  clear_focus_change_handler (viewport);
+
+  g_clear_pointer (&viewport->child, gtk_widget_unparent);
 
   G_OBJECT_CLASS (gtk_viewport_parent_class)->dispose (object);
 
@@ -281,7 +342,12 @@ gtk_viewport_class_init (GtkViewportClass *class)
   widget_class->measure = gtk_viewport_measure;
   widget_class->root = gtk_viewport_root;
   widget_class->unroot = gtk_viewport_unroot;
-  
+  widget_class->compute_expand = gtk_viewport_compute_expand;
+  widget_class->get_request_mode = gtk_viewport_get_request_mode;
+  widget_class->grab_focus = gtk_widget_grab_focus_none;
+  widget_class->focus = gtk_widget_focus_child;
+
+
   gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_VIEWPORT);
 
   /* GtkScrollable implementation */
@@ -494,7 +560,6 @@ gtk_viewport_size_allocate (GtkWidget *widget,
   GtkViewport *viewport = GTK_VIEWPORT (widget);
   GtkAdjustment *hadjustment = viewport->hadjustment;
   GtkAdjustment *vadjustment = viewport->vadjustment;
-  GtkWidget *child;
 
   g_object_freeze_notify (G_OBJECT (hadjustment));
   g_object_freeze_notify (G_OBJECT (vadjustment));
@@ -502,8 +567,7 @@ gtk_viewport_size_allocate (GtkWidget *widget,
   viewport_set_adjustment_values (viewport, GTK_ORIENTATION_HORIZONTAL);
   viewport_set_adjustment_values (viewport, GTK_ORIENTATION_VERTICAL);
 
-  child = gtk_bin_get_child (GTK_BIN (widget));
-  if (child && gtk_widget_get_visible (child))
+  if (viewport->child && gtk_widget_get_visible (viewport->child))
     {
       GtkAllocation child_allocation;
 
@@ -512,7 +576,7 @@ gtk_viewport_size_allocate (GtkWidget *widget,
       child_allocation.width = gtk_adjustment_get_upper (hadjustment);
       child_allocation.height = gtk_adjustment_get_upper (vadjustment);
 
-      gtk_widget_size_allocate (child, &child_allocation, -1);
+      gtk_widget_size_allocate (viewport->child, &child_allocation, -1);
     }
 
   g_object_thaw_notify (G_OBJECT (hadjustment));
@@ -595,7 +659,6 @@ focus_change_handler (GtkWidget *widget)
   GtkViewport *viewport = GTK_VIEWPORT (widget);
   GtkRoot *root;
   GtkWidget *focus_widget;
-  GtkWidget *child;
   graphene_rect_t rect;
   int x, y;
 
@@ -611,12 +674,10 @@ focus_change_handler (GtkWidget *widget)
   if (GTK_IS_TEXT (focus_widget))
     focus_widget = gtk_widget_get_parent (focus_widget);
 
-  child = gtk_bin_get_child (GTK_BIN (viewport));
-
-  if (!gtk_widget_compute_bounds (focus_widget, child, &rect))
+  if (!gtk_widget_compute_bounds (focus_widget, viewport->child, &rect))
     return;
 
-  gtk_widget_translate_coordinates (child, widget,
+  gtk_widget_translate_coordinates (viewport->child, widget,
                                     (int)rect.origin.x,
                                     (int)rect.origin.y,
                                      &x, &y);
@@ -664,7 +725,17 @@ gtk_viewport_set_child (GtkViewport *viewport,
   g_return_if_fail (GTK_IS_VIEWPORT (viewport));
   g_return_if_fail (child == NULL || GTK_IS_WIDGET (child));
 
-  _gtk_bin_set_child (GTK_BIN (viewport), child);
+  if (viewport->child == child)
+    return;
+
+  g_clear_pointer (&viewport->child, gtk_widget_unparent);
+
+  if (child)
+    {
+      viewport->child = child;
+      gtk_widget_set_parent (child, GTK_WIDGET (viewport));
+    }
+
   g_object_notify (G_OBJECT (viewport), "child");
 }
 
@@ -681,6 +752,6 @@ gtk_viewport_get_child (GtkViewport *viewport)
 {
   g_return_val_if_fail (GTK_IS_VIEWPORT (viewport), NULL);
 
-  return gtk_bin_get_child (GTK_BIN (viewport));
+  return viewport->child;
 }
 
diff --git a/gtk/gtkviewport.h b/gtk/gtkviewport.h
index d2b7d26384..5c34c6b887 100644
--- a/gtk/gtkviewport.h
+++ b/gtk/gtkviewport.h
@@ -30,7 +30,7 @@
 #error "Only <gtk/gtk.h> can be included directly."
 #endif
 
-#include <gtk/gtkbin.h>
+#include <gtk/gtkwidget.h>
 
 
 G_BEGIN_DECLS


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