[gnome-builder] libide-gui: port to AdwHeaderBar



commit 2aa9072641f08cd00229fdba85ef70ece2f1be01
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jul 11 21:48:45 2022 -0700

    libide-gui: port to AdwHeaderBar

 src/libide/gui/ide-header-bar.c  | 468 +++++++++++++++++++--------------------
 src/libide/gui/ide-header-bar.h  |  62 +++---
 src/libide/gui/ide-header-bar.ui |  91 +++-----
 3 files changed, 288 insertions(+), 333 deletions(-)
---
diff --git a/src/libide/gui/ide-header-bar.c b/src/libide/gui/ide-header-bar.c
index 19d361b09..6509655ae 100644
--- a/src/libide/gui/ide-header-bar.c
+++ b/src/libide/gui/ide-header-bar.c
@@ -22,70 +22,50 @@
 
 #include "config.h"
 
-#include <dazzle.h>
-
-#include "ide-gui-private.h"
+#include "ide-application.h"
 #include "ide-header-bar.h"
 
 typedef struct
 {
-  gchar              *menu_id;
-
-  GtkToggleButton    *fullscreen_button;
-  GtkImage           *fullscreen_image;
-  DzlShortcutTooltip *fullscreen_tooltip;
+  char *menu_id;
 
-  DzlMenuButton      *menu_button;
-  DzlShortcutTooltip *menu_tooltip;
-  GtkBox             *primary;
-  GtkBox             *secondary;
+  AdwHeaderBar *header_bar;
+  GtkMenuButton *menu_button;
+  GtkCenterBox *center_box;
+  GtkBox *left;
+  GtkBox *left_of_center;
+  GtkBox *right;
+  GtkBox *right_of_center;
 
-  guint               show_fullscreen_button : 1;
+  guint flat : 1;
 } IdeHeaderBarPrivate;
 
 enum {
   PROP_0,
+  PROP_FLAT,
   PROP_MENU_ID,
-  PROP_SHOW_FULLSCREEN_BUTTON,
   N_PROPS
 };
 
 static void buildable_iface_init (GtkBuildableIface *iface);
 
-G_DEFINE_TYPE_WITH_CODE (IdeHeaderBar, ide_header_bar, HDY_TYPE_HEADER_BAR,
+G_DEFINE_TYPE_WITH_CODE (IdeHeaderBar, ide_header_bar, GTK_TYPE_WIDGET,
                          G_ADD_PRIVATE (IdeHeaderBar)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, buildable_iface_init))
 
-static GParamSpec        *properties [N_PROPS];
-static GtkBuildableIface *buildable_parent;
+static GtkBuildableIface *buildable_parent_iface;
+static GParamSpec *properties [N_PROPS];
 
 static void
-on_fullscreen_toggled_cb (GtkToggleButton *button,
-                          GParamSpec      *pspec,
-                          GtkImage        *image)
-{
-  const gchar *icon_name;
-
-  g_assert (GTK_IS_TOGGLE_BUTTON (button));
-  g_assert (GTK_IS_IMAGE (image));
-
-  if (gtk_toggle_button_get_active (button))
-    icon_name = "view-restore-symbolic";
-  else
-    icon_name = "view-fullscreen-symbolic";
-
-  g_object_set (image, "icon-name", icon_name, NULL);
-}
-
-static void
-ide_header_bar_finalize (GObject *object)
+ide_header_bar_dispose (GObject *object)
 {
   IdeHeaderBar *self = (IdeHeaderBar *)object;
   IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
 
   g_clear_pointer (&priv->menu_id, g_free);
+  g_clear_pointer ((GtkWidget **)&priv->header_bar, gtk_widget_unparent);
 
-  G_OBJECT_CLASS (ide_header_bar_parent_class)->finalize (object);
+  G_OBJECT_CLASS (ide_header_bar_parent_class)->dispose (object);
 }
 
 static void
@@ -98,12 +78,12 @@ ide_header_bar_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_MENU_ID:
-      g_value_set_string (value, ide_header_bar_get_menu_id (self));
+    case PROP_FLAT:
+      g_value_set_boolean (value, ide_header_bar_get_flat (self));
       break;
 
-    case PROP_SHOW_FULLSCREEN_BUTTON:
-      g_value_set_boolean (value, ide_header_bar_get_show_fullscreen_button (self));
+    case PROP_MENU_ID:
+      g_value_set_string (value, ide_header_bar_get_menu_id (self));
       break;
 
     default:
@@ -121,12 +101,12 @@ ide_header_bar_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_MENU_ID:
-      ide_header_bar_set_menu_id (self, g_value_get_string (value));
+    case PROP_FLAT:
+      ide_header_bar_set_flat (self, g_value_get_boolean (value));
       break;
 
-    case PROP_SHOW_FULLSCREEN_BUTTON:
-      ide_header_bar_set_show_fullscreen_button (self, g_value_get_boolean (value));
+    case PROP_MENU_ID:
+      ide_header_bar_set_menu_id (self, g_value_get_string (value));
       break;
 
     default:
@@ -140,14 +120,12 @@ ide_header_bar_class_init (IdeHeaderBarClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  object_class->finalize = ide_header_bar_finalize;
+  object_class->dispose = ide_header_bar_dispose;
   object_class->get_property = ide_header_bar_get_property;
   object_class->set_property = ide_header_bar_set_property;
 
-  properties [PROP_SHOW_FULLSCREEN_BUTTON] =
-    g_param_spec_boolean ("show-fullscreen-button",
-                          "Show Fullscreen Button",
-                          "If the fullscreen button should be shown",
+  properties [PROP_FLAT] =
+    g_param_spec_boolean ("flat", NULL, NULL,
                           FALSE,
                           (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
 
@@ -160,33 +138,21 @@ ide_header_bar_class_init (IdeHeaderBarClass *klass)
 
   g_object_class_install_properties (object_class, N_PROPS, properties);
 
+  gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
   gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/libide-gui/ui/ide-header-bar.ui");
-  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, fullscreen_button);
-  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, fullscreen_image);
-  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, fullscreen_tooltip);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, center_box);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, header_bar);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, left);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, left_of_center);
   gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, menu_button);
-  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, menu_tooltip);
-  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, primary);
-  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, secondary);
-
-  g_type_ensure (DZL_TYPE_PRIORITY_BOX);
-  g_type_ensure (DZL_TYPE_SHORTCUT_TOOLTIP);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, right);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeHeaderBar, right_of_center);
 }
 
 static void
 ide_header_bar_init (IdeHeaderBar *self)
 {
-  IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
-
   gtk_widget_init_template (GTK_WIDGET (self));
-
-  g_signal_connect_object (priv->fullscreen_button,
-                           "notify::active",
-                           G_CALLBACK (on_fullscreen_toggled_cb),
-                           priv->fullscreen_image,
-                           0);
-
-  _ide_header_bar_init_shortcuts (self);
 }
 
 GtkWidget *
@@ -196,78 +162,48 @@ ide_header_bar_new (void)
 }
 
 /**
- * ide_header_bar_get_show_fullscreen_button:
+ * ide_header_bar_get_menu_id:
  * @self: a #IdeHeaderBar
  *
- * Gets if the fullscreen button should be displayed in the header bar.
- *
- * Returns: %TRUE if it should be displayed
+ * Gets the menu-id to show in the workspace window.
  *
- * Since: 3.32
+ * Returns: (nullable): a string containing the menu-id, or %NULL
  */
-gboolean
-ide_header_bar_get_show_fullscreen_button (IdeHeaderBar *self)
+const gchar *
+ide_header_bar_get_menu_id (IdeHeaderBar *self)
 {
   IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
 
-  g_return_val_if_fail (IDE_IS_HEADER_BAR (self), FALSE);
+  g_return_val_if_fail (IDE_IS_HEADER_BAR (self), NULL);
 
-  return priv->show_fullscreen_button;
+  return priv->menu_id;
 }
 
-/**
- * ide_header_bar_set_show_fullscreen_button:
- * @self: a #IdeHeaderBar
- * @show_fullscreen_button: if the fullscreen button should be displayed
- *
- * Changes the visibility of the fullscreen button.
- *
- * Since: 3.32
- */
-void
-ide_header_bar_set_show_fullscreen_button (IdeHeaderBar *self,
-                                           gboolean      show_fullscreen_button)
+static gboolean
+menu_has_custom (GMenuModel *model,
+                 const char *name)
 {
-  IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
-
-  g_return_if_fail (IDE_IS_HEADER_BAR (self));
+  guint n_items;
 
-  show_fullscreen_button = !!show_fullscreen_button;
+  if (model == NULL || name == NULL)
+    return FALSE;
 
-  if (show_fullscreen_button != priv->show_fullscreen_button)
+  n_items = g_menu_model_get_n_items (model);
+  for (int i = 0; i < n_items; i++)
     {
-      const gchar *session;
-
-      priv->show_fullscreen_button = show_fullscreen_button;
-
-      session = g_getenv ("DESKTOP_SESSION");
-      if (ide_str_equal0 (session, "pantheon"))
-        show_fullscreen_button = FALSE;
+      g_autofree char *custom = NULL;
+      g_autoptr(GMenuModel) section = NULL;
 
-      gtk_widget_set_visible (GTK_WIDGET (priv->fullscreen_button), show_fullscreen_button);
+      if (g_menu_model_get_item_attribute (model, i, "custom", "s", &custom) &&
+          g_strcmp0 (custom, name) == 0)
+        return TRUE;
 
-      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHOW_FULLSCREEN_BUTTON]);
+      if ((section = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION)) &&
+          menu_has_custom (section, name))
+        return TRUE;
     }
-}
-
-/**
- * ide_header_bar_get_menu_id:
- * @self: a #IdeHeaderBar
- *
- * Gets the menu-id to show in the workspace window.
- *
- * Returns: (nullable): a string containing the menu-id, or %NULL
- *
- * Since: 3.32
- */
-const gchar *
-ide_header_bar_get_menu_id (IdeHeaderBar *self)
-{
-  IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
-
-  g_return_val_if_fail (IDE_IS_HEADER_BAR (self), NULL);
 
-  return priv->menu_id;
+  return FALSE;
 }
 
 /**
@@ -277,12 +213,10 @@ ide_header_bar_get_menu_id (IdeHeaderBar *self)
  * Sets the menu-id to display in the window.
  *
  * Set to %NULL to hide the workspace menu.
- *
- * Since: 3.32
  */
 void
 ide_header_bar_set_menu_id (IdeHeaderBar *self,
-                            const gchar  *menu_id)
+                            const char   *menu_id)
 {
   IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
 
@@ -290,181 +224,229 @@ ide_header_bar_set_menu_id (IdeHeaderBar *self,
 
   if (!ide_str_equal0 (menu_id, priv->menu_id))
     {
+      GtkPopover *popover;
+      GMenu *menu = NULL;
+
       g_free (priv->menu_id);
       priv->menu_id = g_strdup (menu_id);
-      g_object_set (priv->menu_button, "menu-id", menu_id, NULL);
+
+      if (menu_id != NULL)
+        menu = ide_application_get_menu_by_id (IDE_APPLICATION_DEFAULT, menu_id);
+
+      g_object_set (priv->menu_button, "menu-model", menu, NULL);
       gtk_widget_set_visible (GTK_WIDGET (priv->menu_button), !ide_str_empty0 (menu_id));
+
+      popover = gtk_menu_button_get_popover (priv->menu_button);
+      if (menu_has_custom (G_MENU_MODEL (menu), "theme_selector"))
+        gtk_popover_menu_add_child (GTK_POPOVER_MENU (popover),
+                                    g_object_new (PANEL_TYPE_THEME_SELECTOR,
+                                                  "action-name", "app.style-variant",
+                                                  NULL),
+                                    "theme_selector");
+
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_MENU_ID]);
     }
 }
 
-/**
- * ide_header_bar_add_primary:
- * @self: a #IdeHeaderBar
- *
- * Adds a widget to the primary button section of the workspace header.
- * This is the left, for LTR languages.
- *
- * Since: 3.32
- */
-void
-ide_header_bar_add_primary (IdeHeaderBar *self,
-                            GtkWidget    *widget)
+static void
+ide_header_bar_add_child (GtkBuildable  *buildable,
+                          GtkBuilder    *builder,
+                          GObject       *child,
+                          const gchar   *type)
 {
+  IdeHeaderBar *self = (IdeHeaderBar *)buildable;
   IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
 
-  g_return_if_fail (IDE_IS_HEADER_BAR (self));
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_assert (IDE_IS_HEADER_BAR (self));
+  g_assert (GTK_IS_BUILDER (builder));
+  g_assert (G_IS_OBJECT (child));
+
+  if (ADW_IS_HEADER_BAR (child) && priv->header_bar == NULL)
+    {
+      buildable_parent_iface->add_child (buildable, builder, child, type);
+      return;
+    }
+
+  if (GTK_IS_WIDGET (child))
+    {
+      if (ide_str_equal0 (type, "title"))
+        gtk_center_box_set_center_widget (priv->center_box, GTK_WIDGET (child));
+      else if (ide_str_equal0 (type, "left"))
+        ide_header_bar_add (self, IDE_HEADER_BAR_POSITION_LEFT, 0, GTK_WIDGET (child));
+      else if (ide_str_equal0 (type, "right"))
+        ide_header_bar_add (self, IDE_HEADER_BAR_POSITION_RIGHT, 0, GTK_WIDGET (child));
+      else if (ide_str_equal0 (type, "left-of-center"))
+        ide_header_bar_add (self, IDE_HEADER_BAR_POSITION_LEFT_OF_CENTER, 0, GTK_WIDGET (child));
+      else if (ide_str_equal0 (type, "right-of-center"))
+        ide_header_bar_add (self, IDE_HEADER_BAR_POSITION_RIGHT_OF_CENTER, 0, GTK_WIDGET (child));
+      else
+        goto failure;
+
+      return;
+    }
+
+failure:
+  g_warning ("No such child \"%s\" for child of type %s",
+             type ? type : "NULL", G_OBJECT_TYPE_NAME (child));
 
-  gtk_container_add (GTK_CONTAINER (priv->primary), widget);
 }
 
-void
-ide_header_bar_add_center_left (IdeHeaderBar *self,
-                                GtkWidget    *child)
+static GObject *
+ide_header_bar_get_internal_child (GtkBuildable *buildable,
+                                   GtkBuilder   *builder,
+                                   const char   *name)
 {
+  IdeHeaderBar *self = (IdeHeaderBar *)buildable;
   IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
 
-  g_return_if_fail (IDE_IS_HEADER_BAR (self));
-  g_return_if_fail (GTK_IS_WIDGET (child));
+  if (g_strcmp0 (name, "headerbar") == 0)
+    return G_OBJECT (priv->header_bar);
 
-  gtk_container_add_with_properties (GTK_CONTAINER (priv->primary), child,
-                                     "pack-type", GTK_PACK_END,
-                                     NULL);
+  return buildable_parent_iface->get_internal_child (buildable, builder, name);
 }
 
-/**
- * ide_header_bar_add_secondary:
- * @self: a #IdeHeaderBar
- *
- * Adds a widget to the secondary button section of the workspace header.
- * This is the right, for LTR languages.
- *
- * Since: 3.32
- */
-void
-ide_header_bar_add_secondary (IdeHeaderBar *self,
-                              GtkWidget    *widget)
+static void
+buildable_iface_init (GtkBuildableIface *iface)
 {
-  IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
-
-  g_return_if_fail (IDE_IS_HEADER_BAR (self));
-  g_return_if_fail (GTK_IS_WIDGET (widget));
+  buildable_parent_iface = g_type_interface_peek_parent (iface);
 
-  gtk_container_add (GTK_CONTAINER (priv->secondary), widget);
+  iface->add_child = ide_header_bar_add_child;
+  iface->get_internal_child = ide_header_bar_get_internal_child;
 }
 
+#define GET_PRIORITY(w)   GPOINTER_TO_INT(g_object_get_data(G_OBJECT(w),"PRIORITY"))
+#define SET_PRIORITY(w,i) g_object_set_data(G_OBJECT(w),"PRIORITY",GINT_TO_POINTER(i))
+
 void
-_ide_header_bar_show_menu (IdeHeaderBar *self)
+ide_header_bar_add (IdeHeaderBar         *self,
+                    IdeHeaderBarPosition  position,
+                    int                   priority,
+                    GtkWidget            *widget)
 {
   IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
+  GtkBox *box;
+  gboolean append;
 
   g_return_if_fail (IDE_IS_HEADER_BAR (self));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (position < IDE_HEADER_BAR_POSITION_LAST);
 
-  gtk_widget_activate (GTK_WIDGET (priv->menu_button));
-}
+  SET_PRIORITY (widget, priority);
 
-static void
-ide_header_bar_add_child (GtkBuildable  *buildable,
-                          GtkBuilder    *builder,
-                          GObject       *child,
-                          const gchar   *type)
-{
-  IdeHeaderBar *self = (IdeHeaderBar *)buildable;
-  IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
+  switch (position)
+    {
+    case IDE_HEADER_BAR_POSITION_LEFT:
+      box = priv->left;
+      append = TRUE;
+      break;
 
-  g_assert (IDE_IS_HEADER_BAR (self));
-  g_assert (GTK_IS_BUILDER (builder));
-  g_assert (G_IS_OBJECT (child));
+    case IDE_HEADER_BAR_POSITION_RIGHT:
+      box = priv->right;
+      append = FALSE;
+      break;
 
-  if (ide_str_equal0 (type, "left-of-center"))
-    {
-      if (GTK_IS_WIDGET (child))
-        {
-          gtk_container_add_with_properties (GTK_CONTAINER (priv->primary), GTK_WIDGET (child),
-                                             "pack-type", GTK_PACK_END,
-                                             NULL);
-          return;
-        }
+    case IDE_HEADER_BAR_POSITION_LEFT_OF_CENTER:
+      box = priv->left_of_center;
+      append = FALSE;
+      break;
+
+    case IDE_HEADER_BAR_POSITION_RIGHT_OF_CENTER:
+      box = priv->right_of_center;
+      append = TRUE;
+      break;
 
-      goto warning;
+    case IDE_HEADER_BAR_POSITION_LAST:
+    default:
+      g_assert_not_reached ();
     }
 
-  if (ide_str_equal0 (type, "left") || ide_str_equal0 (type, "primary"))
+  if (append)
     {
-      if (GTK_IS_WIDGET (child))
+      GtkWidget *sibling = NULL;
+
+      for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (box));
+           child != NULL;
+           child = gtk_widget_get_next_sibling (child))
         {
-          gtk_container_add_with_properties (GTK_CONTAINER (priv->primary), GTK_WIDGET (child),
-                                             "pack-type", GTK_PACK_START,
-                                             NULL);
-          return;
+          if (priority < GET_PRIORITY (child))
+            break;
+          sibling = child;
         }
 
-      goto warning;
+      gtk_box_insert_child_after (box, widget, sibling);
     }
-
-  if (ide_str_equal0 (type, "right-of-center"))
+  else
     {
-      if (GTK_IS_WIDGET (child))
+      GtkWidget *sibling = NULL;
+
+      for (GtkWidget *child = gtk_widget_get_last_child (GTK_WIDGET (box));
+           child != NULL;
+           child = gtk_widget_get_prev_sibling (child))
         {
-          gtk_container_add_with_properties (GTK_CONTAINER (priv->secondary), GTK_WIDGET (child),
-                                             "pack-type", GTK_PACK_START,
-                                             NULL);
-          return;
+          if (priority < GET_PRIORITY (child))
+            break;
+          sibling = child;
         }
 
-      goto warning;
+      gtk_box_insert_child_after (box, widget, sibling);
     }
+}
 
-  if (ide_str_equal0 (type, "right") || ide_str_equal0 (type, "secondary"))
-    {
-      if (GTK_IS_WIDGET (child))
-        {
-          gtk_container_add_with_properties (GTK_CONTAINER (priv->secondary), GTK_WIDGET (child),
-                                             "pack-type", GTK_PACK_END,
-                                             NULL);
-          return;
-        }
+void
+ide_header_bar_remove (IdeHeaderBar *self,
+                       GtkWidget    *widget)
+{
+  IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
+  GtkBox *box;
 
-      goto warning;
-    }
+  g_return_if_fail (IDE_IS_HEADER_BAR (self));
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+  g_return_if_fail (gtk_widget_get_ancestor (widget, IDE_TYPE_HEADER_BAR) == GTK_WIDGET (self));
 
-  buildable_parent->add_child (buildable, builder, child, type);
+  box = GTK_BOX (gtk_widget_get_ancestor (widget, GTK_TYPE_BOX));
 
-  return;
+  if (box == priv->left ||
+      box == priv->right ||
+      box == priv->left_of_center ||
+      box == priv->right_of_center)
+    {
+      gtk_box_remove (box, widget);
+      return;
+    }
 
-warning:
-  g_warning ("'%s' child type must be a GtkWidget, not %s",
-             type, G_OBJECT_TYPE_NAME (child));
+  g_warning ("Failed to locate widget of type %s within headerbar",
+             G_OBJECT_TYPE_NAME (widget));
 }
 
-static GObject *
-ide_header_bar_get_internal_child (GtkBuildable *buildable,
-                                   GtkBuilder   *builder,
-                                   const gchar  *child_name)
+gboolean
+ide_header_bar_get_flat (IdeHeaderBar *self)
 {
-  IdeHeaderBar *self = (IdeHeaderBar *)buildable;
   IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
 
-  g_assert (IDE_IS_HEADER_BAR (self));
-  g_assert (GTK_IS_BUILDER (builder));
+  g_return_val_if_fail (IDE_IS_HEADER_BAR (self), FALSE);
 
-  if (ide_str_equal0 (child_name, "primary"))
-    return G_OBJECT (priv->primary);
+  return priv->flat;
+}
 
-  if (ide_str_equal0 (child_name, "secondary"))
-    return G_OBJECT (priv->secondary);
+void
+ide_header_bar_set_flat (IdeHeaderBar *self,
+                         gboolean      flat)
+{
+  IdeHeaderBarPrivate *priv = ide_header_bar_get_instance_private (self);
 
-  if (buildable_parent->get_internal_child)
-    return buildable_parent->get_internal_child (buildable, builder, child_name);
+  g_return_if_fail (IDE_IS_HEADER_BAR (self));
 
-  return NULL;
-}
+  flat = !!flat;
 
-static void
-buildable_iface_init (GtkBuildableIface *iface)
-{
-  buildable_parent = g_type_interface_peek_parent (iface);
-  iface->add_child = ide_header_bar_add_child;
-  iface->get_internal_child = ide_header_bar_get_internal_child;
+  if (priv->flat != flat)
+    {
+      priv->flat = flat;
+
+      if (flat)
+        gtk_widget_add_css_class (GTK_WIDGET (priv->header_bar), "flat");
+      else
+        gtk_widget_remove_css_class (GTK_WIDGET (priv->header_bar), "flat");
+
+      g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FLAT]);
+    }
 }
diff --git a/src/libide/gui/ide-header-bar.h b/src/libide/gui/ide-header-bar.h
index 0811a06a0..70d66915f 100644
--- a/src/libide/gui/ide-header-bar.h
+++ b/src/libide/gui/ide-header-bar.h
@@ -24,45 +24,49 @@
 # error "Only <libide-gui.h> can be included directly."
 #endif
 
-#include <gtk/gtk.h>
-#include <handy.h>
+#include <adwaita.h>
 #include <libide-core.h>
 
 G_BEGIN_DECLS
 
+typedef enum
+{
+  IDE_HEADER_BAR_POSITION_LEFT,
+  IDE_HEADER_BAR_POSITION_RIGHT,
+  IDE_HEADER_BAR_POSITION_LEFT_OF_CENTER,
+  IDE_HEADER_BAR_POSITION_RIGHT_OF_CENTER,
+  IDE_HEADER_BAR_POSITION_LAST,
+} IdeHeaderBarPosition;
+
 #define IDE_TYPE_HEADER_BAR (ide_header_bar_get_type())
 
-IDE_AVAILABLE_IN_3_32
-G_DECLARE_DERIVABLE_TYPE (IdeHeaderBar, ide_header_bar, IDE, HEADER_BAR, HdyHeaderBar)
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_DERIVABLE_TYPE (IdeHeaderBar, ide_header_bar, IDE, HEADER_BAR, GtkWidget)
 
 struct _IdeHeaderBarClass
 {
-  HdyHeaderBarClass parent_class;
-
-  /*< private >*/
-  gpointer _reserved[16];
+  GtkWidgetClass parent_class;
 };
 
-IDE_AVAILABLE_IN_3_32
-GtkWidget   *ide_header_bar_new                        (void);
-IDE_AVAILABLE_IN_3_32
-void         ide_header_bar_add_primary                (IdeHeaderBar *self,
-                                                        GtkWidget    *widget);
-IDE_AVAILABLE_IN_3_32
-void         ide_header_bar_add_center_left            (IdeHeaderBar *self,
-                                                        GtkWidget    *widget);
-IDE_AVAILABLE_IN_3_32
-void         ide_header_bar_add_secondary              (IdeHeaderBar *self,
-                                                        GtkWidget    *widget);
-IDE_AVAILABLE_IN_3_32
-const gchar *ide_header_bar_get_menu_id                (IdeHeaderBar *self);
-IDE_AVAILABLE_IN_3_32
-void         ide_header_bar_set_menu_id                (IdeHeaderBar *self,
-                                                        const gchar  *menu_id);
-IDE_AVAILABLE_IN_3_32
-gboolean     ide_header_bar_get_show_fullscreen_button (IdeHeaderBar *self);
-IDE_AVAILABLE_IN_3_32
-void         ide_header_bar_set_show_fullscreen_button (IdeHeaderBar *self,
-                                                        gboolean      show_fullscreen_button);
+IDE_AVAILABLE_IN_ALL
+GtkWidget  *ide_header_bar_new         (void);
+IDE_AVAILABLE_IN_ALL
+void        ide_header_bar_add         (IdeHeaderBar         *self,
+                                        IdeHeaderBarPosition  position,
+                                        int                   priority,
+                                        GtkWidget            *widget);
+IDE_AVAILABLE_IN_ALL
+void        ide_header_bar_remove      (IdeHeaderBar         *self,
+                                        GtkWidget            *widget);
+IDE_AVAILABLE_IN_ALL
+const char *ide_header_bar_get_menu_id (IdeHeaderBar *self);
+IDE_AVAILABLE_IN_ALL
+void        ide_header_bar_set_menu_id (IdeHeaderBar *self,
+                                        const char   *menu_id);
+IDE_AVAILABLE_IN_ALL
+gboolean    ide_header_bar_get_flat (IdeHeaderBar *self);
+IDE_AVAILABLE_IN_ALL
+void        ide_header_bar_set_flat    (IdeHeaderBar *self,
+                                        gboolean      flat);
 
 G_END_DECLS
diff --git a/src/libide/gui/ide-header-bar.ui b/src/libide/gui/ide-header-bar.ui
index 7cc625edc..4ee1de14e 100644
--- a/src/libide/gui/ide-header-bar.ui
+++ b/src/libide/gui/ide-header-bar.ui
@@ -1,76 +1,45 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
-  <!-- interface-requires gtk+ 3.24 -->
-  <template class="IdeHeaderBar" parent="HdyHeaderBar">
+  <requires lib="gtk" version="4.0"/>
+  <requires lib="Adw" version="1.0"/>
+  <template class="IdeHeaderBar" parent="GtkWidget">
     <child>
-      <object class="DzlPriorityBox" id="primary">
-        <property name="hexpand">true</property>
-        <property name="margin-end">6</property>
-        <property name="orientation">horizontal</property>
-        <property name="spacing">6</property>
-        <property name="visible">true</property>
-      </object>
-      <packing>
-        <property name="pack-type">start</property>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="DzlPriorityBox" id="secondary">
-        <property name="hexpand">true</property>
-        <property name="margin-start">6</property>
-        <property name="spacing">6</property>
-        <property name="visible">true</property>
-        <child>
-          <object class="GtkBox">
-            <property name="orientation">horizontal</property>
+      <object class="AdwHeaderBar" id="header_bar">
+        <child type="start">
+          <object class="GtkBox" id="left">
+            <property name="hexpand">true</property>
             <property name="spacing">6</property>
-            <property name="visible">true</property>
-            <child>
-              <object class="GtkToggleButton" id="fullscreen_button">
-                <property name="action-name">win.fullscreen</property>
-                <property name="focus-on-click">false</property>
-                <style>
-                  <class name="image-button"/>
-                </style>
-                <child>
-                  <object class="GtkImage" id="fullscreen_image">
-                    <property name="icon-name">view-fullscreen-symbolic</property>
-                    <property name="visible">true</property>
-                  </object>
-                </child>
+          </object>
+        </child>
+        <child type="title">
+          <object class="GtkCenterBox" id="center_box">
+            <child type="start">
+              <object class="GtkBox" id="left_of_center">
+                <property name="margin-start">6</property>
+                <property name="margin-end">6</property>
               </object>
             </child>
-            <child>
-              <object class="DzlMenuButton" id="menu_button">
-                <property name="icon-name">open-menu-symbolic</property>
-                <property name="show-accels">true</property>
-                <property name="show-icons">true</property>
-                <style>
-                  <class name="image-button"/>
-                </style>
+            <child type="end">
+              <object class="GtkBox" id="right_of_center">
+                <property name="margin-start">6</property>
+                <property name="margin-end">6</property>
               </object>
             </child>
           </object>
-          <packing>
-            <property name="pack-type">end</property>
-            <property name="priority">-1000000</property>
-          </packing>
+        </child>
+        <child type="end">
+          <object class="GtkMenuButton" id="menu_button">
+            <property name="icon-name">open-menu-symbolic</property>
+            <property name="primary">true</property>
+          </object>
+        </child>
+        <child type="end">
+          <object class="GtkBox" id="right">
+            <property name="hexpand">true</property>
+          </object>
         </child>
       </object>
-      <packing>
-        <property name="pack-type">end</property>
-        <property name="position">0</property>
-      </packing>
     </child>
   </template>
-  <object class="DzlShortcutTooltip" id="fullscreen_tooltip">
-    <property name="command-id">org.gnome.builder.workspace.fullscreen</property>
-    <property name="widget">fullscreen_button</property>
-  </object>
-  <object class="DzlShortcutTooltip" id="menu_tooltip">
-    <property name="command-id">org.gnome.builder.workspace.show-menu</property>
-    <property name="widget">menu_button</property>
-  </object>
 </interface>
 


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