[gtk/new-style-menu: 4/14] model button: Redo layout



commit 8ba39e7c7e724d56e6b736aaa49e4d4035023b63
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Jun 6 00:41:45 2019 +0000

    model button: Redo layout
    
    Move checks to the left, and introduce a size group
    to align things. The size group is provided by the
    parent, using the new ::indicator-size-group property.

 gtk/gtkmenusectionbox.c |  12 +-
 gtk/gtkmodelbutton.c    | 473 +++++++++++++++++++++++++-----------------------
 2 files changed, 262 insertions(+), 223 deletions(-)
---
diff --git a/gtk/gtkmenusectionbox.c b/gtk/gtkmenusectionbox.c
index f71108e42a..350455f417 100644
--- a/gtk/gtkmenusectionbox.c
+++ b/gtk/gtkmenusectionbox.c
@@ -46,6 +46,7 @@ struct _GtkMenuSectionBox
   guint              separator_sync_idle;
   gboolean           iconic;
   gint               depth;
+  GtkSizeGroup      *indicators;
 };
 
 typedef struct
@@ -297,6 +298,7 @@ gtk_menu_section_box_insert_func (GtkMenuTrackerItem *item,
 
       widget = g_object_new (GTK_TYPE_MODEL_BUTTON,
                              "menu-name", gtk_menu_tracker_item_get_label (item),
+                             "indicator-size-group", box->indicators,
                              NULL);
       g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
       g_object_bind_property (item, "icon", widget, "icon", G_BINDING_SYNC_CREATE);
@@ -309,7 +311,9 @@ gtk_menu_section_box_insert_func (GtkMenuTrackerItem *item,
     }
   else
     {
-      widget = gtk_model_button_new ();
+      widget = g_object_new (GTK_TYPE_MODEL_BUTTON,
+                             "indicator-size-group", box->indicators,
+                             NULL);
       g_object_bind_property (item, "label", widget, "text", G_BINDING_SYNC_CREATE);
 
       if (box->iconic)
@@ -383,6 +387,8 @@ gtk_menu_section_box_dispose (GObject *object)
       box->tracker = NULL;
     }
 
+  g_clear_object (&box->indicators);
+
   G_OBJECT_CLASS (gtk_menu_section_box_parent_class)->dispose (object);
 }
 
@@ -431,6 +437,8 @@ gtk_menu_section_box_new_toplevel (GtkStack    *stack,
   GtkMenuSectionBox *box;
 
   box = g_object_new (GTK_TYPE_MENU_SECTION_BOX,  NULL);
+  box->indicators = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
   gtk_stack_add_named (stack, GTK_WIDGET (box), "main");
 
   box->tracker = gtk_menu_tracker_new (GTK_ACTION_OBSERVABLE (_gtk_widget_get_action_muxer (GTK_WIDGET 
(box), TRUE)),
@@ -451,6 +459,7 @@ gtk_menu_section_box_new_submenu (GtkMenuTrackerItem *item,
   GtkWidget *button;
 
   box = g_object_new (GTK_TYPE_MENU_SECTION_BOX, NULL);
+  box->indicators = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
 
   button = g_object_new (GTK_TYPE_MODEL_BUTTON,
                          "menu-name", name,
@@ -487,6 +496,7 @@ gtk_menu_section_box_new_section (GtkMenuTrackerItem *item,
   const gchar *text_direction;
 
   box = g_object_new (GTK_TYPE_MENU_SECTION_BOX, NULL);
+  box->indicators = g_object_ref (parent->indicators);
   box->toplevel = parent->toplevel;
   box->depth = parent->depth + 1;
 
diff --git a/gtk/gtkmodelbutton.c b/gtk/gtkmodelbutton.c
index b277eab6aa..67a2988ebd 100644
--- a/gtk/gtkmodelbutton.c
+++ b/gtk/gtkmodelbutton.c
@@ -38,6 +38,7 @@
 #include "gtkstylecontextprivate.h"
 #include "gtkcontainerprivate.h"
 #include "gtkiconprivate.h"
+#include "gtksizegroup.h"
 
 /**
  * SECTION:gtkmodelbutton
@@ -152,13 +153,14 @@ struct _GtkModelButton
   GtkWidget *box;
   GtkWidget *image;
   GtkWidget *label;
-  GtkWidget *indicator_widget;
+  GtkWidget *start_indicator;
+  GtkWidget *end_indicator;
   gboolean active;
   gboolean centered;
-  gboolean inverted;
   gboolean iconic;
   gchar *menu_name;
   GtkButtonRole role;
+  GtkSizeGroup *indicators;
 };
 
 typedef GtkButtonClass GtkModelButtonClass;
@@ -175,45 +177,49 @@ enum
   PROP_ACTIVE,
   PROP_MENU_NAME,
   PROP_ICONIC,
+  PROP_INDICATOR_SIZE_GROUP,
   LAST_PROPERTY
 };
 
 static GParamSpec *properties[LAST_PROPERTY] = { NULL, };
 
-static gboolean
-indicator_is_left (GtkWidget *widget)
-{
-  GtkModelButton *button = GTK_MODEL_BUTTON (widget);
-
-  return ((gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL && !button->inverted) ||
-          (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR && button->inverted));
-}
-
 static void
 update_node_ordering (GtkModelButton *button)
 {
-  GtkStyleContext *indicator_context;
+  GtkStyleContext *start_indicator_context;
+  GtkStyleContext *end_indicator_context;
   GtkWidget *child;
 
-  indicator_context = gtk_widget_get_style_context (button->indicator_widget);
+  start_indicator_context = gtk_widget_get_style_context (button->start_indicator);
+  end_indicator_context = gtk_widget_get_style_context (button->end_indicator);
 
-  if (indicator_is_left (GTK_WIDGET (button)))
+  if (gtk_widget_get_direction (GTK_WIDGET (button)) == GTK_TEXT_DIR_LTR)
     {
-      gtk_style_context_add_class (indicator_context, GTK_STYLE_CLASS_LEFT);
-      gtk_style_context_remove_class (indicator_context, GTK_STYLE_CLASS_RIGHT);
+      gtk_style_context_add_class (start_indicator_context, GTK_STYLE_CLASS_LEFT);
+      gtk_style_context_remove_class (start_indicator_context, GTK_STYLE_CLASS_RIGHT);
+      gtk_style_context_add_class (end_indicator_context, GTK_STYLE_CLASS_RIGHT);
+      gtk_style_context_remove_class (end_indicator_context, GTK_STYLE_CLASS_LEFT);
 
       child = gtk_widget_get_first_child (GTK_WIDGET (button));
-      if (child != button->indicator_widget)
-        gtk_widget_insert_before (button->indicator_widget, GTK_WIDGET (button), child);
+      if (child != button->start_indicator)
+        gtk_widget_insert_before (button->start_indicator, GTK_WIDGET (button), child);
+      child = gtk_widget_get_last_child (GTK_WIDGET (button));
+      if (child != button->end_indicator)
+        gtk_widget_insert_after (button->end_indicator, GTK_WIDGET (button), child);
     }
   else
     {
-      gtk_style_context_add_class (indicator_context, GTK_STYLE_CLASS_RIGHT);
-      gtk_style_context_remove_class (indicator_context, GTK_STYLE_CLASS_LEFT);
+      gtk_style_context_add_class (start_indicator_context, GTK_STYLE_CLASS_RIGHT);
+      gtk_style_context_remove_class (start_indicator_context, GTK_STYLE_CLASS_LEFT);
+      gtk_style_context_add_class (end_indicator_context, GTK_STYLE_CLASS_LEFT);
+      gtk_style_context_remove_class (end_indicator_context, GTK_STYLE_CLASS_RIGHT);
 
       child = gtk_widget_get_first_child (GTK_WIDGET (button));
-      if (child != button->indicator_widget)
-        gtk_widget_insert_after (button->indicator_widget, GTK_WIDGET (button), child);
+      if (child != button->end_indicator)
+        gtk_widget_insert_before (button->end_indicator, GTK_WIDGET (button), child);
+      child = gtk_widget_get_last_child (GTK_WIDGET (button));
+      if (child != button->start_indicator)
+        gtk_widget_insert_after (button->start_indicator, GTK_WIDGET (button), child);
     }
 }
 
@@ -222,70 +228,55 @@ gtk_model_button_update_state (GtkModelButton *button)
 {
   GtkStateFlags state;
   GtkStateFlags indicator_state;
-  GtkCssImageBuiltinType image_type;
-  gboolean inverted;
+  GtkCssImageBuiltinType start_type;
+  GtkCssImageBuiltinType end_type;
   gboolean centered;
 
   state = gtk_widget_get_state_flags (GTK_WIDGET (button));
   indicator_state = state;
-  image_type = GTK_CSS_IMAGE_BUILTIN_NONE;
-  inverted = FALSE;
+  start_type = GTK_CSS_IMAGE_BUILTIN_NONE;
+  end_type = GTK_CSS_IMAGE_BUILTIN_NONE;
   centered = FALSE;
 
   switch (button->role)
     {
     case GTK_BUTTON_ROLE_CHECK:
-      if (button->active && !button->menu_name)
-        {
-          indicator_state |= GTK_STATE_FLAG_CHECKED;
-          image_type = GTK_CSS_IMAGE_BUILTIN_CHECK;
-        }
+      start_type = GTK_CSS_IMAGE_BUILTIN_CHECK;
+      end_type = GTK_CSS_IMAGE_BUILTIN_NONE;
+      if (button->active)
+        indicator_state |= GTK_STATE_FLAG_CHECKED;
       else
-        {
-          indicator_state &= ~GTK_STATE_FLAG_CHECKED;
-        }
+        indicator_state &= ~GTK_STATE_FLAG_CHECKED;
       break;
 
     case GTK_BUTTON_ROLE_RADIO:
-      if (button->active && !button->menu_name)
-        {
-          indicator_state |= GTK_STATE_FLAG_CHECKED;
-          image_type = GTK_CSS_IMAGE_BUILTIN_OPTION;
-        }
+      start_type = GTK_CSS_IMAGE_BUILTIN_OPTION;
+      end_type = GTK_CSS_IMAGE_BUILTIN_NONE;
+      if (button->active)
+        indicator_state |= GTK_STATE_FLAG_CHECKED;
       else
-        {
-          indicator_state &= ~GTK_STATE_FLAG_CHECKED;
-        }
+        indicator_state &= ~GTK_STATE_FLAG_CHECKED;
       break;
 
     case GTK_BUTTON_ROLE_TITLE:
-      inverted = TRUE;
       centered = TRUE;
-      /* fall through */
+      start_type = GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT;
+      end_type = GTK_CSS_IMAGE_BUILTIN_NONE;
+      break;
 
     case GTK_BUTTON_ROLE_NORMAL:
+      start_type = GTK_CSS_IMAGE_BUILTIN_NONE;
       if (button->menu_name != NULL)
-        {
-          if (indicator_is_left (GTK_WIDGET (button)))
-            image_type = GTK_CSS_IMAGE_BUILTIN_ARROW_LEFT;
-          else
-            image_type = GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT;
-        }
-      if (!centered)
-        centered = button->iconic;
+        end_type = GTK_CSS_IMAGE_BUILTIN_ARROW_RIGHT;
+      else
+        end_type = GTK_CSS_IMAGE_BUILTIN_NONE;
+      centered = button->iconic;
       break;
 
     default:
       g_assert_not_reached ();
     }
 
-  if (button->inverted != inverted)
-    {
-      button->inverted = inverted;
-      update_node_ordering (button);
-      gtk_widget_queue_draw (GTK_WIDGET (button));
-    }
-
   if (button->centered != centered)
     {
       button->centered = centered;
@@ -293,14 +284,15 @@ gtk_model_button_update_state (GtkModelButton *button)
       gtk_widget_queue_resize (GTK_WIDGET (button));
     }
 
-  gtk_icon_set_image (GTK_ICON (button->indicator_widget), image_type);
+  gtk_icon_set_image (GTK_ICON (button->start_indicator), start_type);
+  gtk_icon_set_image (GTK_ICON (button->end_indicator), end_type);
 
   if (button->iconic)
     gtk_widget_set_state_flags (GTK_WIDGET (button), indicator_state, TRUE);
   else
     gtk_widget_set_state_flags (GTK_WIDGET (button), state, TRUE);
 
-  gtk_widget_set_state_flags (button->indicator_widget, indicator_state, TRUE);
+  gtk_widget_set_state_flags (button->start_indicator, indicator_state, TRUE);
 }
 
 static void
@@ -329,37 +321,51 @@ update_node_name (GtkModelButton *button)
 {
   AtkObject *accessible;
   AtkRole a11y_role;
-  const gchar *indicator_name;
-  gboolean indicator_visible;
+  const gchar *start_name;
+  const gchar *end_name;
+  gboolean start_visible;
+  gboolean end_visible;
 
   accessible = gtk_widget_get_accessible (GTK_WIDGET (button));
   switch (button->role)
     {
-    case GTK_BUTTON_ROLE_NORMAL:
     case GTK_BUTTON_ROLE_TITLE:
       a11y_role = ATK_ROLE_PUSH_BUTTON;
+      start_name = I_("arrow");
+      start_visible = TRUE;
+      end_name = I_("none");
+      end_visible = FALSE;
+      break;
+    case GTK_BUTTON_ROLE_NORMAL:
+      a11y_role = ATK_ROLE_PUSH_BUTTON;
+      start_name = I_("none");
+      start_visible = TRUE;
       if (button->menu_name)
         {
-          indicator_name = I_("arrow");
-          indicator_visible = TRUE;
+          end_name = I_("arrow");
+          end_visible = TRUE;
         }
       else
         {
-          indicator_name = I_("check");
-          indicator_visible = FALSE;
+          end_name = I_("none");
+          end_visible = FALSE;
         }
       break;
 
     case GTK_BUTTON_ROLE_CHECK:
       a11y_role = ATK_ROLE_CHECK_BOX;
-      indicator_name = I_("check");
-      indicator_visible = TRUE;
+      start_name = I_("check");
+      start_visible = TRUE;
+      end_name = I_("none");
+      end_visible = FALSE;
       break;
 
     case GTK_BUTTON_ROLE_RADIO:
       a11y_role = ATK_ROLE_RADIO_BUTTON;
-      indicator_name = I_("radio");
-      indicator_visible = TRUE;
+      start_name = I_("radio");
+      start_visible = TRUE;
+      end_name = I_("none");
+      end_visible = FALSE;
       break;
 
     default:
@@ -367,12 +373,17 @@ update_node_name (GtkModelButton *button)
     }
 
   if (button->iconic)
-    indicator_visible = FALSE;
+    {
+      start_visible = FALSE;
+      end_visible = FALSE;
+    }
 
   atk_object_set_role (accessible, a11y_role);
 
-  gtk_icon_set_css_name (GTK_ICON (button->indicator_widget), indicator_name);
-  gtk_widget_set_visible (button->indicator_widget, indicator_visible);
+  gtk_icon_set_css_name (GTK_ICON (button->start_indicator), start_name);
+  gtk_widget_set_visible (button->start_indicator, start_visible);
+  gtk_icon_set_css_name (GTK_ICON (button->end_indicator), end_name);
+  gtk_widget_set_visible (button->end_indicator, end_visible);
 }
 
 static void
@@ -419,7 +430,8 @@ static void
 gtk_model_button_set_text (GtkModelButton *button,
                            const gchar    *text)
 {
-  gtk_label_set_text_with_mnemonic (GTK_LABEL (button->label), text);
+  gtk_label_set_text_with_mnemonic (GTK_LABEL (button->label),
+                                    text ? text : "");
   update_visibility (button);
   g_object_notify_by_pspec (G_OBJECT (button), properties[PROP_TEXT]);
 }
@@ -486,7 +498,6 @@ gtk_model_button_set_iconic (GtkModelButton *button,
       gtk_style_context_add_class (context, "model");
       gtk_style_context_add_class (context, "image-button");
       gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NORMAL);
-      gtk_widget_set_visible (button->indicator_widget, FALSE);
     }
   else
     {
@@ -494,15 +505,13 @@ gtk_model_button_set_iconic (GtkModelButton *button,
       gtk_style_context_remove_class (context, "model");
       gtk_style_context_remove_class (context, "image-button");
       gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
-      gtk_widget_set_visible (button->indicator_widget,
-                              button->role != GTK_BUTTON_ROLE_NORMAL ||
-                              button->menu_name == NULL);
     }
 
   button->centered = iconic;
 
   gtk_widget_set_halign (button->box, button->centered ? GTK_ALIGN_CENTER : GTK_ALIGN_FILL);
 
+  update_node_name (button);
   update_visibility (button);
   gtk_widget_queue_resize (GTK_WIDGET (button));
   g_object_notify_by_pspec (G_OBJECT (button), properties[PROP_ICONIC]);
@@ -546,6 +555,10 @@ gtk_model_button_get_property (GObject    *object,
       g_value_set_boolean (value, button->iconic);
       break;
 
+    case PROP_INDICATOR_SIZE_GROUP:
+      g_value_set_object (value, button->indicators);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -590,57 +603,20 @@ gtk_model_button_set_property (GObject      *object,
       gtk_model_button_set_iconic (button, g_value_get_boolean (value));
       break;
 
+    case PROP_INDICATOR_SIZE_GROUP:
+      if (button->indicators)
+        gtk_size_group_remove_widget (button->indicators, button->start_indicator);
+      button->indicators = GTK_SIZE_GROUP (g_value_get_object (value));
+      if (button->indicators)
+        gtk_size_group_add_widget (button->indicators, button->start_indicator);
+      break;
+
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
     }
 }
 
-static gboolean
-has_sibling_with_indicator (GtkWidget *button)
-{
-  GtkWidget *parent;
-  gboolean has_indicator;
-  GList *children, *l;
-  GtkModelButton *sibling;
-
-  has_indicator = FALSE;
-
-  parent = gtk_widget_get_parent (button);
-  children = gtk_container_get_children (GTK_CONTAINER (parent));
-
-  for (l = children; l; l = l->next)
-    {
-      sibling = l->data;
-
-      if (!GTK_IS_MODEL_BUTTON (sibling))
-        continue;
-
-      if (!gtk_widget_is_visible (GTK_WIDGET (sibling)))
-        continue;
-
-      if (!sibling->centered &&
-          (sibling->menu_name || sibling->role != GTK_BUTTON_ROLE_NORMAL))
-        {
-          has_indicator = TRUE;
-          break;
-        }
-    }
-
-  g_list_free (children);
-
-  return has_indicator;
-}
-
-static gboolean
-needs_indicator (GtkModelButton *button)
-{
-  if (button->role != GTK_BUTTON_ROLE_NORMAL)
-    return TRUE;
-
-  return has_sibling_with_indicator (GTK_WIDGET (button));
-}
-
 static void
 gtk_model_button_measure (GtkWidget      *widget,
                           GtkOrientation  orientation,
@@ -666,13 +642,34 @@ gtk_model_button_measure (GtkWidget      *widget,
 
       if (orientation == GTK_ORIENTATION_HORIZONTAL)
         {
-          gint check_min, check_nat;
+          int start_min, start_nat;
+          int end_min, end_nat;
 
-          gtk_widget_measure (button->indicator_widget,
-                              GTK_ORIENTATION_HORIZONTAL,
-                              -1,
-                              &check_min, &check_nat,
-                               NULL, NULL);
+          if (gtk_widget_get_visible (button->start_indicator))
+            {
+              gtk_widget_measure (button->start_indicator,
+                                  GTK_ORIENTATION_HORIZONTAL,
+                                  -1,
+                                  &start_min, &start_nat,
+                                  NULL, NULL);
+            }
+          else
+            {
+              start_min = start_nat = 0;
+            }
+
+          if (gtk_widget_get_visible (button->end_indicator))
+            {
+              gtk_widget_measure (button->end_indicator,
+                                  GTK_ORIENTATION_HORIZONTAL,
+                                  -1,
+                                  &end_min, &end_nat,
+                                  NULL, NULL);
+            }
+          else
+            {
+              end_min = end_nat = 0;
+            }
 
           if (child && gtk_widget_get_visible (child))
             {
@@ -690,24 +687,45 @@ gtk_model_button_measure (GtkWidget      *widget,
 
           if (button->centered)
             {
-              *minimum += 2 * check_min;
-              *natural += 2 * check_nat;
+              *minimum += 2 * MAX (start_min, end_min);
+              *natural += 2 * MAX (start_nat, end_nat);
             }
-          else if (needs_indicator (button))
+          else
             {
-              *minimum += check_min;
-              *natural += check_nat;
+              *minimum += start_min + end_min;
+              *natural += start_nat + end_nat;
             }
         }
       else
         {
-          gint check_min, check_nat;
+          int start_min, start_nat;
+          int end_min, end_nat;
 
-          gtk_widget_measure (button->indicator_widget,
-                              GTK_ORIENTATION_VERTICAL,
-                              -1,
-                              &check_min, &check_nat,
-                              NULL, NULL);
+          if (gtk_widget_get_visible (button->start_indicator))
+            {
+              gtk_widget_measure (button->start_indicator,
+                                  GTK_ORIENTATION_VERTICAL,
+                                  -1,
+                                  &start_min, &start_nat,
+                                  NULL, NULL);
+            }
+          else
+            {
+              start_min = start_nat = 0;
+            }
+
+          if (gtk_widget_get_visible (button->end_indicator))
+            {
+              gtk_widget_measure (button->end_indicator,
+                                  GTK_ORIENTATION_VERTICAL,
+                                  -1,
+                                  &end_min, &end_nat,
+                                  NULL, NULL);
+            }
+          else
+            {
+              end_min = end_nat = 0;
+            }
 
           if (child && gtk_widget_get_visible (child))
             {
@@ -715,33 +733,15 @@ gtk_model_button_measure (GtkWidget      *widget,
               gint child_min_baseline = -1, child_nat_baseline = -1;
 
               if (for_size > -1)
-                {
-                  if (button->centered)
-                    for_size -= 2 * check_nat;
-                  else if (needs_indicator (button))
-                    for_size -= check_nat;
-                }
+                for_size -= start_nat + end_nat;
 
               gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL,
                                   for_size,
                                   &child_min, &child_nat,
                                   &child_min_baseline, &child_nat_baseline);
 
-              if (button->centered)
-                {
-                  *minimum = MAX (2 * check_min, child_min);
-                  *natural = MAX (2 * check_nat, child_nat);
-                }
-              else if (needs_indicator (button))
-                {
-                  *minimum = MAX (check_min, child_min);
-                  *natural = MAX (check_nat, child_nat);
-                }
-              else
-                {
-                  *minimum = child_min;
-                  *natural = child_nat;
-                }
+              *minimum = MAX (child_min, MAX (start_min, end_min));
+              *natural = MAX (child_nat, MAX (start_nat, end_nat));
 
               if (minimum_baseline && child_min_baseline >= 0)
                 *minimum_baseline = child_min_baseline + (*minimum - child_min) / 2;
@@ -750,21 +750,8 @@ gtk_model_button_measure (GtkWidget      *widget,
             }
           else
             {
-              if (button->centered)
-                {
-                  *minimum = 2 * check_min;
-                  *natural = 2 * check_nat;
-                }
-              else if (needs_indicator (button))
-                {
-                  *minimum = check_min;
-                  *natural = check_nat;
-                }
-              else
-                {
-                  *minimum = 0;
-                  *natural = 0;
-                }
+              *minimum = 0;
+              *natural = 0;
             }
         }
     }
@@ -788,59 +775,83 @@ gtk_model_button_size_allocate (GtkWidget *widget,
       GtkModelButton *button;
       GtkAllocation child_allocation;
       GtkWidget *child;
-      gint check_min_width, check_nat_width;
-      gint check_min_height, check_nat_height;
+      int start_width, start_height;
+      int end_width, end_height;
 
       button = GTK_MODEL_BUTTON (widget);
       child = gtk_bin_get_child (GTK_BIN (widget));
 
+      if (gtk_widget_get_visible (button->start_indicator))
+        {
+          int min;
+          gtk_widget_measure (button->start_indicator,
+                              GTK_ORIENTATION_HORIZONTAL,
+                              -1,
+                              &min, &start_width,
+                              NULL, NULL);
+          gtk_widget_measure (button->start_indicator,
+                              GTK_ORIENTATION_VERTICAL,
+                              -1,
+                              &min, &start_height,
+                              NULL, NULL);
 
+          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+            child_allocation.x = width - start_width;
+          else
+            child_allocation.x = 0;
+          child_allocation.y = (height - start_height) / 2;
+          child_allocation.width = start_width;
+          child_allocation.height = start_height;
 
-      gtk_widget_measure (button->indicator_widget,
-                          GTK_ORIENTATION_HORIZONTAL,
-                          -1,
-                          &check_min_width, &check_nat_width,
-                          NULL, NULL);
-      gtk_widget_measure (button->indicator_widget,
-                          GTK_ORIENTATION_VERTICAL,
-                          -1,
-                          &check_min_height, &check_nat_height,
-                          NULL, NULL);
-
-      if (indicator_is_left (widget))
-        child_allocation.x = 0;
+          gtk_widget_size_allocate (button->start_indicator, &child_allocation, baseline);
+        }
       else
-        child_allocation.x = width - check_nat_width;
-      child_allocation.y = (height - check_nat_height) / 2;
-      child_allocation.width = check_nat_width;
-      child_allocation.height = check_nat_height;
+        {
+          start_width = start_height = 0;
+        }
 
-      gtk_widget_size_allocate (button->indicator_widget, &child_allocation, baseline);
 
-      if (child && gtk_widget_get_visible (child))
+      if (gtk_widget_get_visible (button->end_indicator))
         {
-          GtkBorder border = { 0, };
+          int min;
+          gtk_widget_measure (button->end_indicator,
+                              GTK_ORIENTATION_HORIZONTAL,
+                              -1,
+                              &min, &end_width,
+                              NULL, NULL);
+          gtk_widget_measure (button->end_indicator,
+                              GTK_ORIENTATION_VERTICAL,
+                              -1,
+                              &min, &end_height,
+                              NULL, NULL);
 
-          if (button->centered)
-            {
-              border.left = check_nat_width;
-              border.right = check_nat_width;
-            }
-          else if (needs_indicator (button))
-            {
-              if (indicator_is_left (widget))
-                border.left += check_nat_width;
-              else
-                border.right += check_nat_width;
-            }
+          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+            child_allocation.x = 0;
+          else
+            child_allocation.x = width - end_width;
+          child_allocation.y = (height - end_height) / 2;
+          child_allocation.width = end_width;
+          child_allocation.height = end_height;
 
-          child_allocation.x = border.left;
-          child_allocation.y = border.top;
-          child_allocation.width = width - border.left - border.right;
-          child_allocation.height = height - border.top - border.bottom;
+          gtk_widget_size_allocate (button->end_indicator, &child_allocation, baseline);
+        }
+      else
+        {
+          end_width = end_height = 0;
+        }
+
+      if (button->centered)
+        end_width = start_width = MAX (start_width, end_width);
 
-          if (baseline != -1)
-            baseline -= border.top;
+      if (child && gtk_widget_get_visible (child))
+        {
+          if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
+            child_allocation.x = end_width;
+          else
+            child_allocation.x = start_width;
+          child_allocation.y = 0;
+          child_allocation.width = width - start_width - end_width;
+          child_allocation.height = height;
 
           gtk_widget_size_allocate (child, &child_allocation, baseline);
         }
@@ -885,7 +896,8 @@ gtk_model_button_finalize (GObject *object)
 {
   GtkModelButton *button = GTK_MODEL_BUTTON (object);
 
-  gtk_widget_unparent (button->indicator_widget);
+  gtk_widget_unparent (button->start_indicator);
+  gtk_widget_unparent (button->end_indicator);
 
   G_OBJECT_CLASS (gtk_model_button_parent_class)->finalize (object);
 }
@@ -1002,6 +1014,20 @@ gtk_model_button_class_init (GtkModelButtonClass *class)
                           P_("Whether to prefer the icon over text"),
                           FALSE,
                           G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+  /**
+   * GtkModelButton:indicator-size-group:
+   *
+   * Containers like #GtkPopoverMenu can provide a size group
+   * in this property to align the checks and radios of all
+   * the model buttons in a menu.
+   */
+  properties[PROP_INDICATOR_SIZE_GROUP] =
+    g_param_spec_object ("indicator-size-group",
+                          P_("Size group"),
+                          P_("Size group for checks and radios"),
+                          GTK_TYPE_SIZE_GROUP,
+                          G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
   g_object_class_install_properties (object_class, LAST_PROPERTY, properties);
 
   gtk_widget_class_set_accessible_role (GTK_WIDGET_CLASS (class), ATK_ROLE_PUSH_BUTTON);
@@ -1023,9 +1049,12 @@ gtk_model_button_init (GtkModelButton *button)
   gtk_container_add (GTK_CONTAINER (button->box), button->label);
   gtk_container_add (GTK_CONTAINER (button), button->box);
 
-  button->indicator_widget = gtk_icon_new ("check");
-  gtk_widget_set_parent (button->indicator_widget, GTK_WIDGET (button));
-  gtk_widget_hide (button->indicator_widget);
+  button->start_indicator = gtk_icon_new ("none");
+  button->end_indicator = gtk_icon_new ("none");
+  gtk_widget_set_parent (button->start_indicator, GTK_WIDGET (button));
+  gtk_widget_set_parent (button->end_indicator, GTK_WIDGET (button));
+  gtk_widget_show (button->start_indicator);
+  gtk_widget_hide (button->end_indicator);
   update_node_ordering (button);
 }
 


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