diff --git a/src/gnome-software.gresource.xml b/src/gnome-software.gresource.xml
index 6b58f2e616c9a01675ce22a577430062dda2710a..60277a60022aaf572053e058c8547815c175c628 100644
--- a/src/gnome-software.gresource.xml
+++ b/src/gnome-software.gresource.xml
@@ -24,6 +24,7 @@
gs-installed-page.ui
gs-license-tile.ui
gs-loading-page.ui
+ gs-lozenge.ui
gs-metered-data-dialog.ui
gs-moderate-page.ui
gs-overview-page.ui
diff --git a/src/gs-age-rating-context-dialog.c b/src/gs-age-rating-context-dialog.c
index 090c0b542615307cf9762d49471133ff839f4ab5..52a617e7d34dbd2a62f21ea9ec1765fbf636059e 100644
--- a/src/gs-age-rating-context-dialog.c
+++ b/src/gs-age-rating-context-dialog.c
@@ -70,8 +70,7 @@ struct _GsAgeRatingContextDialog
GsContextDialogRow *rows[GS_AGE_RATING_GROUP_TYPE_COUNT]; /* (unowned) */
GList *attributes[GS_AGE_RATING_GROUP_TYPE_COUNT]; /* (element-type GsAgeRatingAttribute) */
- GtkLabel *age;
- GtkWidget *lozenge;
+ GsLozenge *lozenge;
GtkLabel *title;
GtkListBox *attributes_list; /* (element-type GsContextDialogRow) */
};
@@ -878,15 +877,13 @@ gs_age_rating_context_dialog_format_age_short (AsContentRatingSystem system,
/**
* gs_age_rating_context_dialog_update_lozenge:
* @app: the #GsApp to rate
- * @lozenge: lozenge widget
- * @lozenge_content: label within the lozenge widget
+ * @lozenge: a #GsLozenge widget
* @is_unknown_out: (out caller-allocates) (not optional): return location for
* a boolean indicating whether the age rating is unknown, rather than a
* specific age
*
- * Update the @lozenge and @lozenge_content widgets to indicate the overall
- * age rating for @app. This involves changing their CSS class and label
- * content.
+ * Update the @lozenge widget to indicate the overall age rating for @app.
+ * This involves changing its CSS class and label content.
*
* If the overall age rating for @app is unknown (because the app doesn’t
* provide a complete `` element in its appdata), the lozenge is
@@ -896,8 +893,7 @@ gs_age_rating_context_dialog_format_age_short (AsContentRatingSystem system,
*/
void
gs_age_rating_context_dialog_update_lozenge (GsApp *app,
- GtkWidget *lozenge,
- GtkLabel *lozenge_content,
+ GsLozenge *lozenge,
gboolean *is_unknown_out)
{
const gchar *css_class;
@@ -916,8 +912,7 @@ gs_age_rating_context_dialog_update_lozenge (GsApp *app,
g_autofree gchar *age_text = NULL;
g_return_if_fail (GS_IS_APP (app));
- g_return_if_fail (GTK_IS_WIDGET (lozenge));
- g_return_if_fail (GTK_IS_LABEL (lozenge_content));
+ g_return_if_fail (GS_IS_LOZENGE (lozenge));
g_return_if_fail (is_unknown_out != NULL);
/* get the content rating system from the locale */
@@ -971,9 +966,9 @@ gs_age_rating_context_dialog_update_lozenge (GsApp *app,
}
/* Update the UI. */
- gtk_label_set_text (lozenge_content, age_text);
+ gs_lozenge_set_text (lozenge, age_text);
- context = gtk_widget_get_style_context (lozenge);
+ context = gtk_widget_get_style_context (GTK_WIDGET (lozenge));
for (gsize i = 0; i < G_N_ELEMENTS (css_age_classes); i++)
gtk_style_context_remove_class (context, css_age_classes[i]);
@@ -1008,7 +1003,6 @@ update_attributes_list (GsAgeRatingContextDialog *self)
content_rating = gs_app_dup_content_rating (self->app);
gs_age_rating_context_dialog_update_lozenge (self->app,
self->lozenge,
- self->age,
&is_unknown);
/* Title */
@@ -1052,7 +1046,7 @@ update_attributes_list (GsAgeRatingContextDialog *self)
* for a specified age group. The first placeholder is the app name, the second
* is the age group. */
title = g_strdup_printf (_("%s is suitable for %s"), gs_app_get_name (self->app),
- gtk_label_get_text (self->age));
+ gs_lozenge_get_text (self->lozenge));
}
gtk_label_set_text (self->title, title);
@@ -1180,7 +1174,6 @@ gs_age_rating_context_dialog_class_init (GsAgeRatingContextDialogClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-age-rating-context-dialog.ui");
- gtk_widget_class_bind_template_child (widget_class, GsAgeRatingContextDialog, age);
gtk_widget_class_bind_template_child (widget_class, GsAgeRatingContextDialog, lozenge);
gtk_widget_class_bind_template_child (widget_class, GsAgeRatingContextDialog, title);
gtk_widget_class_bind_template_child (widget_class, GsAgeRatingContextDialog, attributes_list);
diff --git a/src/gs-age-rating-context-dialog.h b/src/gs-age-rating-context-dialog.h
index 38902f83b870b0b2ad37650a39047d6cd092ab57..f619004161e2801bc04e9eaf28e004f8dda7fd18 100644
--- a/src/gs-age-rating-context-dialog.h
+++ b/src/gs-age-rating-context-dialog.h
@@ -16,6 +16,7 @@
#include "gs-app.h"
#include "gs-info-window.h"
+#include "gs-lozenge.h"
G_BEGIN_DECLS
@@ -32,8 +33,7 @@ void gs_age_rating_context_dialog_set_app (GsAgeRatingContextDialog *self,
gchar *gs_age_rating_context_dialog_format_age_short (AsContentRatingSystem system,
guint age);
void gs_age_rating_context_dialog_update_lozenge (GsApp *app,
- GtkWidget *lozenge,
- GtkLabel *lozenge_content,
+ GsLozenge *lozenge,
gboolean *is_unknown_out);
diff --git a/src/gs-age-rating-context-dialog.ui b/src/gs-age-rating-context-dialog.ui
index 9ac2b705fb14f25d73e423de6dd09078290be6b6..0572fc45e78b083b4bc051cbddacf74a0b71572c 100644
--- a/src/gs-age-rating-context-dialog.ui
+++ b/src/gs-age-rating-context-dialog.ui
@@ -23,25 +23,15 @@
12
-
diff --git a/src/gs-app-context-bar.c b/src/gs-app-context-bar.c
index d7ea20449b53672bf2de92df34aa63e29760898f..9b9cad5cac147bb3855614b9ab07cbfad860ac7d 100644
--- a/src/gs-app-context-bar.c
+++ b/src/gs-app-context-bar.c
@@ -38,6 +38,7 @@
#include "gs-app-context-bar.h"
#include "gs-common.h"
#include "gs-hardware-support-context-dialog.h"
+#include "gs-lozenge.h"
#include "gs-safety-context-dialog.h"
#include "gs-storage-context-dialog.h"
@@ -45,7 +46,6 @@ typedef struct
{
GtkWidget *tile;
GtkWidget *lozenge;
- GtkWidget *lozenge_content;
GtkLabel *title;
GtkLabel *description;
} GsAppContextTile;
@@ -215,9 +215,9 @@ update_storage_tile (GsAppContextBar *self)
}
if (lozenge_text_is_markup)
- gtk_label_set_markup (GTK_LABEL (self->tiles[STORAGE_TILE].lozenge_content), lozenge_text);
+ gs_lozenge_set_markup (GS_LOZENGE (self->tiles[STORAGE_TILE].lozenge), lozenge_text);
else
- gtk_label_set_text (GTK_LABEL (self->tiles[STORAGE_TILE].lozenge_content), lozenge_text);
+ gs_lozenge_set_text (GS_LOZENGE (self->tiles[STORAGE_TILE].lozenge), lozenge_text);
gtk_label_set_text (self->tiles[STORAGE_TILE].title, title);
gtk_label_set_text (self->tiles[STORAGE_TILE].description, description);
}
@@ -482,7 +482,7 @@ update_safety_tile (GsAppContextBar *self)
g_assert_not_reached ();
}
- gtk_image_set_from_icon_name (GTK_IMAGE (self->tiles[SAFETY_TILE].lozenge_content), icon_name);
+ gs_lozenge_set_icon_name (GS_LOZENGE (self->tiles[SAFETY_TILE].lozenge), icon_name);
gtk_label_set_text (self->tiles[SAFETY_TILE].title, title);
gtk_label_set_text (self->tiles[SAFETY_TILE].description, description);
@@ -654,8 +654,8 @@ update_hardware_support_tile (GsAppContextBar *self)
/* Update the UI. The `adaptive-symbolic` icon needs a special size to
* be set, as it is wider than it is tall. Setting the size ensures it’s
* rendered at the right height. */
- gtk_image_set_from_icon_name (GTK_IMAGE (self->tiles[HARDWARE_SUPPORT_TILE].lozenge_content), icon_name);
- gtk_image_set_pixel_size (GTK_IMAGE (self->tiles[HARDWARE_SUPPORT_TILE].lozenge_content), g_str_equal (icon_name, "adaptive-symbolic") ? 56 : -1);
+ gs_lozenge_set_icon_name (GS_LOZENGE (self->tiles[HARDWARE_SUPPORT_TILE].lozenge), icon_name);
+ gs_lozenge_set_pixel_size (GS_LOZENGE (self->tiles[HARDWARE_SUPPORT_TILE].lozenge), g_str_equal (icon_name, "adaptive-symbolic") ? 56 : -1);
gtk_label_set_text (self->tiles[HARDWARE_SUPPORT_TILE].title, title);
gtk_label_set_text (self->tiles[HARDWARE_SUPPORT_TILE].description, description);
@@ -732,8 +732,7 @@ update_age_rating_tile (GsAppContextBar *self)
content_rating = gs_app_dup_content_rating (self->app);
gs_age_rating_context_dialog_update_lozenge (self->app,
- self->tiles[AGE_RATING_TILE].lozenge,
- GTK_LABEL (self->tiles[AGE_RATING_TILE].lozenge_content),
+ GS_LOZENGE (self->tiles[AGE_RATING_TILE].lozenge),
&is_unknown);
/* Description */
@@ -885,22 +884,18 @@ gs_app_context_bar_class_init (GsAppContextBarClass *klass)
gtk_widget_class_bind_template_child_full (widget_class, "storage_tile", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[STORAGE_TILE].tile));
gtk_widget_class_bind_template_child_full (widget_class, "storage_tile_lozenge", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[STORAGE_TILE].lozenge));
- gtk_widget_class_bind_template_child_full (widget_class, "storage_tile_lozenge_content", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[STORAGE_TILE].lozenge_content));
gtk_widget_class_bind_template_child_full (widget_class, "storage_tile_title", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[STORAGE_TILE].title));
gtk_widget_class_bind_template_child_full (widget_class, "storage_tile_description", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[STORAGE_TILE].description));
gtk_widget_class_bind_template_child_full (widget_class, "safety_tile", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[SAFETY_TILE].tile));
gtk_widget_class_bind_template_child_full (widget_class, "safety_tile_lozenge", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[SAFETY_TILE].lozenge));
- gtk_widget_class_bind_template_child_full (widget_class, "safety_tile_lozenge_content", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[SAFETY_TILE].lozenge_content));
gtk_widget_class_bind_template_child_full (widget_class, "safety_tile_title", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[SAFETY_TILE].title));
gtk_widget_class_bind_template_child_full (widget_class, "safety_tile_description", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[SAFETY_TILE].description));
gtk_widget_class_bind_template_child_full (widget_class, "hardware_support_tile", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[HARDWARE_SUPPORT_TILE].tile));
gtk_widget_class_bind_template_child_full (widget_class, "hardware_support_tile_lozenge", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[HARDWARE_SUPPORT_TILE].lozenge));
- gtk_widget_class_bind_template_child_full (widget_class, "hardware_support_tile_lozenge_content", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[HARDWARE_SUPPORT_TILE].lozenge_content));
gtk_widget_class_bind_template_child_full (widget_class, "hardware_support_tile_title", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[HARDWARE_SUPPORT_TILE].title));
gtk_widget_class_bind_template_child_full (widget_class, "hardware_support_tile_description", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[HARDWARE_SUPPORT_TILE].description));
gtk_widget_class_bind_template_child_full (widget_class, "age_rating_tile", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[AGE_RATING_TILE].tile));
gtk_widget_class_bind_template_child_full (widget_class, "age_rating_tile_lozenge", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[AGE_RATING_TILE].lozenge));
- gtk_widget_class_bind_template_child_full (widget_class, "age_rating_tile_lozenge_content", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[AGE_RATING_TILE].lozenge_content));
gtk_widget_class_bind_template_child_full (widget_class, "age_rating_tile_title", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[AGE_RATING_TILE].title));
gtk_widget_class_bind_template_child_full (widget_class, "age_rating_tile_description", FALSE, G_STRUCT_OFFSET (GsAppContextBar, tiles[AGE_RATING_TILE].description));
gtk_widget_class_bind_template_callback (widget_class, tile_clicked_cb);
diff --git a/src/gs-app-context-bar.ui b/src/gs-app-context-bar.ui
index 705d7dcdb3b0cd1d54a538980efd6face5bf4ceb..db7091283b9c121cfdb860c6960d47eff432d91f 100644
--- a/src/gs-app-context-bar.ui
+++ b/src/gs-app-context-bar.ui
@@ -24,25 +24,15 @@
vertical
8
-
- center
+
+ False
-
-
- center
- True
-
- 20 MB
- 0.5
-
- storage_tile_title
- storage_tile_description
-
-
-
+
+ storage_tile_title
+ storage_tile_description
+
@@ -86,24 +76,17 @@
vertical
8
-
- center
+
+ True
+
+ safety-symbolic
-
-
- center
- True
-
- safety-symbolic
-
- safety_tile_title
- safety_tile_description
-
-
-
+
+ safety_tile_title
+ safety_tile_description
+
@@ -154,26 +137,19 @@
vertical
8
-
- center
+
+ False
+
+ adaptive-symbolic
+ 56
-
-
- center
- True
-
- adaptive-symbolic
- 56
-
- hardware_support_tile_title
- hardware_support_tile_description
-
-
-
+
+ hardware_support_tile_title
+ hardware_support_tile_description
+
@@ -217,25 +193,15 @@
vertical
8
-
- center
+
+ True
-
-
- center
- True
-
- 18+
- 0.5
-
- age_rating_tile_title
- age_rating_tile_description
-
-
-
+
+ age_rating_tile_title
+ age_rating_tile_description
+
diff --git a/src/gs-app-translation-dialog.ui b/src/gs-app-translation-dialog.ui
index 18b608ccfd38d8ca1c310efd3aa8e5859e807665..4b5b41f31e9f6bfab5ec3dac96f903485721a6c5 100644
--- a/src/gs-app-translation-dialog.ui
+++ b/src/gs-app-translation-dialog.ui
@@ -27,24 +27,17 @@
12
-
- center
+
+ True
+ flag-outline-thin-symbolic
+ 24
-
-
- center
- True
- flag-outline-thin-symbolic
- 24
-
- title
-
-
-
+
+ title
+
diff --git a/src/gs-context-dialog-row.c b/src/gs-context-dialog-row.c
index 11c9f382264e7db9ce03d98c442799f4dfee022b..73f8fcbfc2203f5bbd7e850a2e7f851ef187ee89 100644
--- a/src/gs-context-dialog-row.c
+++ b/src/gs-context-dialog-row.c
@@ -30,6 +30,7 @@
#include
#include "gs-context-dialog-row.h"
+#include "gs-lozenge.h"
#include "gs-enums.h"
struct _GsContextDialogRow
@@ -38,9 +39,7 @@ struct _GsContextDialogRow
GsContextDialogRowImportance importance;
- GtkWidget *lozenge; /* (unowned) */
- GtkImage *lozenge_content_image; /* (unowned) */
- GtkLabel *lozenge_content_text; /* (unowned) */
+ GsLozenge *lozenge; /* (unowned) */
};
G_DEFINE_TYPE (GsContextDialogRow, gs_context_dialog_row, ADW_TYPE_ACTION_ROW)
@@ -111,14 +110,10 @@ gs_context_dialog_row_set_property (GObject *object,
switch ((GsContextDialogRowProperty) prop_id) {
case PROP_ICON_NAME:
- gtk_image_set_from_icon_name (self->lozenge_content_image, g_value_get_string (value));
- gtk_widget_set_visible (GTK_WIDGET (self->lozenge_content_image), TRUE);
- gtk_widget_set_visible (GTK_WIDGET (self->lozenge_content_text), FALSE);
+ gs_lozenge_set_icon_name (self->lozenge, g_value_get_string (value));
break;
case PROP_CONTENT:
- gtk_label_set_text (self->lozenge_content_text, g_value_get_string (value));
- gtk_widget_set_visible (GTK_WIDGET (self->lozenge_content_image), FALSE);
- gtk_widget_set_visible (GTK_WIDGET (self->lozenge_content_text), TRUE);
+ gs_lozenge_set_text (self->lozenge, g_value_get_string (value));
break;
case PROP_IMPORTANCE: {
GtkStyleContext *context;
@@ -127,7 +122,7 @@ gs_context_dialog_row_set_property (GObject *object,
self->importance = g_value_get_enum (value);
css_class = css_class_for_importance (self->importance);
- context = gtk_widget_get_style_context (self->lozenge);
+ context = gtk_widget_get_style_context (GTK_WIDGET (self->lozenge));
gtk_style_context_remove_class (context, "green");
gtk_style_context_remove_class (context, "yellow");
@@ -204,8 +199,6 @@ gs_context_dialog_row_class_init (GsContextDialogRowClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-context-dialog-row.ui");
gtk_widget_class_bind_template_child (widget_class, GsContextDialogRow, lozenge);
- gtk_widget_class_bind_template_child (widget_class, GsContextDialogRow, lozenge_content_image);
- gtk_widget_class_bind_template_child (widget_class, GsContextDialogRow, lozenge_content_text);
}
/**
@@ -282,7 +275,7 @@ gs_context_dialog_row_get_icon_name (GsContextDialogRow *self)
{
g_return_val_if_fail (GS_IS_CONTEXT_DIALOG_ROW (self), NULL);
- return gtk_image_get_icon_name (self->lozenge_content_image);
+ return gs_lozenge_get_icon_name (self->lozenge);
}
/**
@@ -299,7 +292,7 @@ gs_context_dialog_row_get_content (GsContextDialogRow *self)
{
g_return_val_if_fail (GS_IS_CONTEXT_DIALOG_ROW (self), NULL);
- return gtk_label_get_text (self->lozenge_content_text);
+ return gs_lozenge_get_text (self->lozenge);
}
/**
@@ -316,25 +309,25 @@ gs_context_dialog_row_get_content_is_markup (GsContextDialogRow *self)
{
g_return_val_if_fail (GS_IS_CONTEXT_DIALOG_ROW (self), FALSE);
- return gtk_label_get_use_markup (self->lozenge_content_text);
+ return gs_lozenge_get_use_markup (self->lozenge);
}
/**
- * gs_context_dialog_row_set_content_is_markup:
+ * gs_context_dialog_row_set_content_markup:
* @self: a #GsContextDialogRow
- * @is_markup: value to set
+ * @markup: markup to set
*
- * Set to %TRUE, when the #GsContextDialogRow:content is markup.
+ * Set the @markup content as markup.
*
* Since: 43
*/
void
-gs_context_dialog_row_set_content_is_markup (GsContextDialogRow *self,
- gboolean is_markup)
+gs_context_dialog_row_set_content_markup (GsContextDialogRow *self,
+ const gchar *markup)
{
g_return_if_fail (GS_IS_CONTEXT_DIALOG_ROW (self));
- gtk_label_set_use_markup (self->lozenge_content_text, is_markup);
+ gs_lozenge_set_markup (self->lozenge, markup);
}
/**
@@ -378,5 +371,5 @@ gs_context_dialog_row_set_size_groups (GsContextDialogRow *self,
g_return_if_fail (description == NULL || GTK_IS_SIZE_GROUP (description));
if (lozenge != NULL)
- gtk_size_group_add_widget (lozenge, self->lozenge);
+ gtk_size_group_add_widget (lozenge, GTK_WIDGET (self->lozenge));
}
diff --git a/src/gs-context-dialog-row.h b/src/gs-context-dialog-row.h
index 74c805918cb2c19d0d00a8b98205618bf55a7f2a..d5d68fd25debc0bf7365819e0b00b6fc48a97262 100644
--- a/src/gs-context-dialog-row.h
+++ b/src/gs-context-dialog-row.h
@@ -57,9 +57,9 @@ const gchar *gs_context_dialog_row_get_content (GsContextDialogRow *self);
GsContextDialogRowImportance gs_context_dialog_row_get_importance (GsContextDialogRow *self);
gboolean gs_context_dialog_row_get_content_is_markup
(GsContextDialogRow *self);
-void gs_context_dialog_row_set_content_is_markup
+void gs_context_dialog_row_set_content_markup
(GsContextDialogRow *self,
- gboolean is_markup);
+ const gchar *markup);
void gs_context_dialog_row_set_size_groups (GsContextDialogRow *self,
GtkSizeGroup *lozenge,
diff --git a/src/gs-context-dialog-row.ui b/src/gs-context-dialog-row.ui
index f759f9bf1d6e83235ff3cb293e1aca0837931c63..47a78dff1432ebb3aa766c7941782bbe3b79f713 100644
--- a/src/gs-context-dialog-row.ui
+++ b/src/gs-context-dialog-row.ui
@@ -6,35 +6,14 @@
False
-
- center
- center
- False
+
+ True
+ 16
8
8
-
-
- center
- True
-
- safety-symbolic
- 16
-
-
-
-
- center
- True
-
- 20 MB
- False
- 0.5
-
-
diff --git a/src/gs-feature-tile.c b/src/gs-feature-tile.c
index cff5a50679c8d024c3cfd4cab485828a8c28805c..bb8bed438f7ac6e22a879ef45eacab9cb46281b2 100644
--- a/src/gs-feature-tile.c
+++ b/src/gs-feature-tile.c
@@ -13,9 +13,74 @@
#include
#include "gs-feature-tile.h"
+#include "gs-layout-manager.h"
#include "gs-common.h"
#include "gs-css.h"
+#define GS_TYPE_FEATURE_TILE_LAYOUT (gs_feature_tile_layout_get_type ())
+G_DECLARE_FINAL_TYPE (GsFeatureTileLayout, gs_feature_tile_layout, GS, FEATURE_TILE_LAYOUT, GsLayoutManager)
+
+struct _GsFeatureTileLayout
+{
+ GsLayoutManager parent_instance;
+
+ gboolean narrow_mode;
+};
+
+G_DEFINE_TYPE (GsFeatureTileLayout, gs_feature_tile_layout, GS_TYPE_LAYOUT_MANAGER)
+
+enum {
+ SIGNAL_NARROW_MODE_CHANGED,
+ SIGNAL_LAST
+};
+
+static guint signals [SIGNAL_LAST] = { 0 };
+
+static void
+gs_feature_tile_layout_allocate (GtkLayoutManager *layout_manager,
+ GtkWidget *widget,
+ gint width,
+ gint height,
+ gint baseline)
+{
+ GsFeatureTileLayout *self = GS_FEATURE_TILE_LAYOUT (layout_manager);
+ gboolean narrow_mode;
+
+ GTK_LAYOUT_MANAGER_CLASS (gs_feature_tile_layout_parent_class)->allocate (layout_manager,
+ widget, width, height, baseline);
+
+ /* Engage ‘narrow mode’ if the allocation becomes too narrow. The exact
+ * choice of width is arbitrary here. */
+ narrow_mode = (width < 600);
+ if (self->narrow_mode != narrow_mode) {
+ self->narrow_mode = narrow_mode;
+ g_signal_emit (self, signals[SIGNAL_NARROW_MODE_CHANGED], 0, self->narrow_mode);
+ }
+}
+
+static void
+gs_feature_tile_layout_class_init (GsFeatureTileLayoutClass *klass)
+{
+ GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ layout_manager_class->allocate = gs_feature_tile_layout_allocate;
+
+ signals [SIGNAL_NARROW_MODE_CHANGED] =
+ g_signal_new ("narrow-mode-changed",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, g_cclosure_marshal_generic,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+static void
+gs_feature_tile_layout_init (GsFeatureTileLayout *self)
+{
+}
+
+/* ********************************************************************* */
+
struct _GsFeatureTile
{
GsAppTile parent_instance;
@@ -32,54 +97,6 @@ struct _GsFeatureTile
guint refresh_id;
};
-#define GS_TYPE_FEATURE_TILE_LAYOUT (gs_feature_tile_layout_get_type ())
-
-G_DECLARE_FINAL_TYPE (GsFeatureTileLayout, gs_feature_tile_layout, GS, FEATURE_TILE_LAYOUT, GtkLayoutManager)
-
-/* This is a copy of GtkBinLayout, because cannot derive from it */
-struct _GsFeatureTileLayout
-{
- GtkLayoutManager parent_instance;
-};
-
-G_DEFINE_TYPE (GsFeatureTileLayout, gs_feature_tile_layout, GTK_TYPE_LAYOUT_MANAGER)
-
-static void
-gs_feature_tile_layout_measure (GtkLayoutManager *layout_manager,
- GtkWidget *widget,
- GtkOrientation orientation,
- int for_size,
- int *minimum,
- int *natural,
- int *minimum_baseline,
- int *natural_baseline)
-{
- GtkWidget *child;
-
- for (child = gtk_widget_get_first_child (widget);
- child != NULL;
- child = gtk_widget_get_next_sibling (child)) {
- if (gtk_widget_should_layout (child)) {
- int child_min = 0;
- int child_nat = 0;
- int child_min_baseline = -1;
- int child_nat_baseline = -1;
-
- gtk_widget_measure (child, orientation, for_size,
- &child_min, &child_nat,
- &child_min_baseline, &child_nat_baseline);
-
- *minimum = MAX (*minimum, child_min);
- *natural = MAX (*natural, child_nat);
-
- if (child_min_baseline > -1)
- *minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
- if (child_nat_baseline > -1)
- *natural_baseline = MAX (*natural_baseline, child_nat_baseline);
- }
- }
-}
-
static void gs_feature_tile_refresh (GsAppTile *self);
static gboolean
@@ -95,47 +112,18 @@ gs_feature_tile_refresh_idle_cb (gpointer user_data)
}
static void
-gs_feature_tile_layout_allocate (GtkLayoutManager *layout_manager,
- GtkWidget *widget,
- int width,
- int height,
- int baseline)
+gs_feature_tile_layout_narrow_mode_changed_cb (GtkLayoutManager *layout_manager,
+ gboolean narrow_mode,
+ gpointer user_data)
{
- GsFeatureTile *tile = GS_FEATURE_TILE (widget);
- GtkWidget *child;
- gboolean narrow_mode;
+ GsFeatureTile *self = GS_FEATURE_TILE (user_data);
- for (child = gtk_widget_get_first_child (widget);
- child != NULL;
- child = gtk_widget_get_next_sibling (child)) {
- if (child && gtk_widget_should_layout (child))
- gtk_widget_allocate (child, width, height, baseline, NULL);
- }
-
- /* Engage ‘narrow mode’ if the allocation becomes too narrow. The exact
- * choice of width is arbitrary here. */
- narrow_mode = (width < 600);
- if (tile->narrow_mode != narrow_mode) {
- tile->narrow_mode = narrow_mode;
- if (!tile->refresh_id)
- tile->refresh_id = g_idle_add (gs_feature_tile_refresh_idle_cb, tile);
+ if (self->narrow_mode != narrow_mode && !self->refresh_id) {
+ self->narrow_mode = narrow_mode;
+ self->refresh_id = g_idle_add (gs_feature_tile_refresh_idle_cb, self);
}
}
-static void
-gs_feature_tile_layout_class_init (GsFeatureTileLayoutClass *klass)
-{
- GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
-
- layout_manager_class->measure = gs_feature_tile_layout_measure;
- layout_manager_class->allocate = gs_feature_tile_layout_allocate;
-}
-
-static void
-gs_feature_tile_layout_init (GsFeatureTileLayout *layout)
-{
-}
-
/* A colour represented in hue, saturation, brightness form; with an additional
* field for its contrast calculated with respect to some external colour.
*
@@ -588,7 +576,14 @@ gs_feature_tile_css_changed (GtkWidget *widget,
static void
gs_feature_tile_init (GsFeatureTile *tile)
{
+ GtkLayoutManager *layout_manager;
+
gtk_widget_init_template (GTK_WIDGET (tile));
+
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (tile));
+ g_warn_if_fail (layout_manager != NULL);
+ g_signal_connect_object (layout_manager, "narrow-mode-changed",
+ G_CALLBACK (gs_feature_tile_layout_narrow_mode_changed_cb), tile, 0);
}
static void
diff --git a/src/gs-hardware-support-context-dialog.c b/src/gs-hardware-support-context-dialog.c
index e10d0c49a822aee7aee849ff79a5cca2a7f388a9..c1a4d60c5ca492bb9eadbf9aae18561530f65a10 100644
--- a/src/gs-hardware-support-context-dialog.c
+++ b/src/gs-hardware-support-context-dialog.c
@@ -40,6 +40,7 @@
#include "gs-common.h"
#include "gs-context-dialog-row.h"
#include "gs-hardware-support-context-dialog.h"
+#include "gs-lozenge.h"
struct _GsHardwareSupportContextDialog
{
@@ -49,7 +50,6 @@ struct _GsHardwareSupportContextDialog
gulong app_notify_handler_relations;
gulong app_notify_handler_name;
- GtkImage *icon;
GtkWidget *lozenge;
GtkLabel *title;
GtkListBox *relations_list;
@@ -722,7 +722,7 @@ update_relations_list (GsHardwareSupportContextDialog *self)
g_assert_not_reached ();
}
- gtk_image_set_from_icon_name (GTK_IMAGE (self->icon), icon_name);
+ gs_lozenge_set_icon_name (GS_LOZENGE (self->lozenge), icon_name);
gtk_label_set_text (self->title, title);
context = gtk_widget_get_style_context (self->lozenge);
@@ -826,7 +826,6 @@ gs_hardware_support_context_dialog_class_init (GsHardwareSupportContextDialogCla
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-hardware-support-context-dialog.ui");
- gtk_widget_class_bind_template_child (widget_class, GsHardwareSupportContextDialog, icon);
gtk_widget_class_bind_template_child (widget_class, GsHardwareSupportContextDialog, lozenge);
gtk_widget_class_bind_template_child (widget_class, GsHardwareSupportContextDialog, title);
gtk_widget_class_bind_template_child (widget_class, GsHardwareSupportContextDialog, relations_list);
diff --git a/src/gs-hardware-support-context-dialog.ui b/src/gs-hardware-support-context-dialog.ui
index 65fa0ee4d4b257e0f9e542ac5f072d2ff369dbd8..5ce7a72b0d43b4a4af92960bab2107417e84c9c8 100644
--- a/src/gs-hardware-support-context-dialog.ui
+++ b/src/gs-hardware-support-context-dialog.ui
@@ -23,25 +23,18 @@
12
-
- center
+
+ False
+
+ safety-symbolic
+ 24
-
-
- center
- True
-
- safety-symbolic
- 24
-
- title
-
-
-
+
+ title
+
diff --git a/src/gs-layout-manager.c b/src/gs-layout-manager.c
new file mode 100644
index 0000000000000000000000000000000000000000..37fcf49855039fe52e8c88a9285dd3f115e39ba4
--- /dev/null
+++ b/src/gs-layout-manager.c
@@ -0,0 +1,110 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2021 Endless OS Foundation LLC
+ *
+ * Author: Georges Basile Stavracas Neto
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include "gs-layout-manager.h"
+
+/*
+ * The GsLayoutManager is a copy of the GtkBoxLayout, only
+ * declared as a derivable class, to avoid code duplication.
+ */
+
+G_DEFINE_TYPE (GsLayoutManager, gs_layout_manager, GTK_TYPE_LAYOUT_MANAGER)
+
+static void
+gs_layout_manager_measure (GtkLayoutManager *layout_manager,
+ GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GtkWidget *child;
+ gint min = 0;
+ gint nat = 0;
+
+ for (child = gtk_widget_get_first_child (widget);
+ child != NULL;
+ child = gtk_widget_get_next_sibling (child)) {
+ gint child_min_baseline = -1;
+ gint child_nat_baseline = -1;
+ gint child_min = 0;
+ gint child_nat = 0;
+
+ if (!gtk_widget_should_layout (child))
+ continue;
+
+ gtk_widget_measure (child, orientation,
+ for_size,
+ &child_min, &child_nat,
+ &child_min_baseline,
+ &child_nat_baseline);
+
+ min = MAX (min, child_min);
+ nat = MAX (nat, child_nat);
+
+ if (child_min_baseline > -1)
+ *minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
+ if (child_nat_baseline > -1)
+ *natural_baseline = MAX (*natural_baseline, child_nat_baseline);
+ }
+
+ *minimum = min;
+ *natural = nat;
+}
+
+static void
+gs_layout_manager_allocate (GtkLayoutManager *layout_manager,
+ GtkWidget *widget,
+ gint width,
+ gint height,
+ gint baseline)
+{
+ GtkWidget *child;
+
+ for (child = gtk_widget_get_first_child (widget);
+ child != NULL;
+ child = gtk_widget_get_next_sibling (child)) {
+ if (child && gtk_widget_should_layout (child))
+ gtk_widget_allocate (child, width, height, baseline, NULL);
+ }
+}
+
+static void
+gs_layout_manager_class_init (GsLayoutManagerClass *klass)
+{
+ GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
+
+ layout_manager_class->measure = gs_layout_manager_measure;
+ layout_manager_class->allocate = gs_layout_manager_allocate;
+}
+
+static void
+gs_layout_manager_init (GsLayoutManager *self)
+{
+}
+
+/**
+ * gs_layout_manager_new:
+ *
+ * Create a new #GsLayoutManager.
+ *
+ * Returns: (transfer full): a new #GsLayoutManager
+ *
+ * Since: 43
+ **/
+GtkLayoutManager *
+gs_layout_manager_new (void)
+{
+ return g_object_new (GS_TYPE_LAYOUT_MANAGER, NULL);
+}
diff --git a/src/gs-summary-tile-layout.h b/src/gs-layout-manager.h
similarity index 56%
rename from src/gs-summary-tile-layout.h
rename to src/gs-layout-manager.h
index 55d3c1be2b56660f01d45ad20f01d84384105166..bbb661ff479158368c97b4fb8687c37d1796c24c 100644
--- a/src/gs-summary-tile-layout.h
+++ b/src/gs-layout-manager.h
@@ -16,10 +16,14 @@
G_BEGIN_DECLS
-#define GS_TYPE_SUMMARY_TILE_LAYOUT (gs_summary_tile_layout_get_type ())
-G_DECLARE_FINAL_TYPE (GsSummaryTileLayout, gs_summary_tile_layout, GS, SUMMARY_TILE_LAYOUT, GtkLayoutManager)
+#define GS_TYPE_LAYOUT_MANAGER (gs_layout_manager_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GsLayoutManager, gs_layout_manager, GS, LAYOUT_MANAGER, GtkLayoutManager)
-void gs_summary_tile_layout_set_preferred_width (GsSummaryTileLayout *self,
- gint preferred_width);
+struct _GsLayoutManagerClass {
+ GtkLayoutManagerClass parent_class;
+};
+
+GtkLayoutManager *
+ gs_layout_manager_new (void);
G_END_DECLS
diff --git a/src/gs-license-tile.c b/src/gs-license-tile.c
index a5fb8e9942d309b03342edc513c8a0fb49f90c74..a68326573be131e23d2158a733d5262028cb4773 100644
--- a/src/gs-license-tile.c
+++ b/src/gs-license-tile.c
@@ -30,6 +30,7 @@
#include "gs-common.h"
#include "gs-license-tile.h"
+#include "gs-lozenge.h"
struct _GsLicenseTile
{
@@ -40,7 +41,6 @@ struct _GsLicenseTile
gulong notify_urls_handler;
GtkWidget *lozenges[3];
- GtkImage *lozenge_images[3];
GtkLabel *title_label;
GtkLabel *description_label;
GtkListBoxRow *get_involved_row;
@@ -125,11 +125,9 @@ gs_license_tile_refresh (GsLicenseTile *self)
gtk_style_context_remove_class (context, "green");
gtk_style_context_remove_class (context, "grey");
gtk_style_context_add_class (context, css_class);
+ gs_lozenge_set_icon_name (GS_LOZENGE (self->lozenges[i]), lozenge_icon_names[i]);
}
- for (gsize i = 0; i < G_N_ELEMENTS (self->lozenge_images); i++)
- gtk_image_set_from_icon_name (self->lozenge_images[i], lozenge_icon_names[i]);
-
gtk_label_set_label (self->title_label, title);
gtk_label_set_label (self->description_label, description);
gtk_widget_set_visible (GTK_WIDGET (self->get_involved_row), get_involved_visible);
@@ -236,11 +234,8 @@ gs_license_tile_class_init (GsLicenseTileClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-license-tile.ui");
gtk_widget_class_bind_template_child_full (widget_class, "lozenge0", FALSE, G_STRUCT_OFFSET (GsLicenseTile, lozenges[0]));
- gtk_widget_class_bind_template_child_full (widget_class, "lozenge0_image", FALSE, G_STRUCT_OFFSET (GsLicenseTile, lozenge_images[0]));
gtk_widget_class_bind_template_child_full (widget_class, "lozenge1", FALSE, G_STRUCT_OFFSET (GsLicenseTile, lozenges[1]));
- gtk_widget_class_bind_template_child_full (widget_class, "lozenge1_image", FALSE, G_STRUCT_OFFSET (GsLicenseTile, lozenge_images[1]));
gtk_widget_class_bind_template_child_full (widget_class, "lozenge2", FALSE, G_STRUCT_OFFSET (GsLicenseTile, lozenges[2]));
- gtk_widget_class_bind_template_child_full (widget_class, "lozenge2_image", FALSE, G_STRUCT_OFFSET (GsLicenseTile, lozenge_images[2]));
gtk_widget_class_bind_template_child (widget_class, GsLicenseTile, title_label);
gtk_widget_class_bind_template_child (widget_class, GsLicenseTile, description_label);
gtk_widget_class_bind_template_child (widget_class, GsLicenseTile, get_involved_row);
diff --git a/src/gs-license-tile.ui b/src/gs-license-tile.ui
index ec8a43c9c102f6a113ba68f656e7086362ca5aaf..3ef3075d47c0ce5f63a6ad59e8e121d7dd172d94 100644
--- a/src/gs-license-tile.ui
+++ b/src/gs-license-tile.ui
@@ -31,51 +31,30 @@
8
-
- center
+
+ True
+ heart-filled-symbolic
-
-
- center
- True
- heart-filled-symbolic
-
-
-
- center
+
+ True
+ community-symbolic
-
-
- center
- True
- community-symbolic
-
-
-
- center
+
+ True
+ sign-language-symbolic
-
-
- center
- True
- sign-language-symbolic
-
-
diff --git a/src/gs-lozenge-layout.c b/src/gs-lozenge-layout.c
new file mode 100644
index 0000000000000000000000000000000000000000..037f71aef57075bc2a04f850288884d0dfb2cf34
--- /dev/null
+++ b/src/gs-lozenge-layout.c
@@ -0,0 +1,179 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2022 Red Hat (www.redhat.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include "gs-lozenge-layout.h"
+
+struct _GsLozengeLayout
+{
+ GsLayoutManager parent_instance;
+
+ gboolean circular;
+};
+
+G_DEFINE_TYPE (GsLozengeLayout, gs_lozenge_layout, GS_TYPE_LAYOUT_MANAGER)
+
+typedef enum {
+ PROP_CIRCULAR = 1,
+} GsLozengeLayoutProperty;
+
+static GParamSpec *obj_props[PROP_CIRCULAR + 1] = { NULL, };
+
+static void
+gs_lozenge_layout_measure (GtkLayoutManager *layout_manager,
+ GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GsLozengeLayout *self = GS_LOZENGE_LAYOUT (layout_manager);
+
+ GTK_LAYOUT_MANAGER_CLASS (gs_lozenge_layout_parent_class)->measure (layout_manager,
+ widget, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
+
+ if (self->circular) {
+ *minimum = MAX (for_size, *minimum);
+ *natural = *minimum;
+ *natural_baseline = *minimum_baseline;
+ }
+
+ if (*natural_baseline > *natural)
+ *natural_baseline = *natural;
+ if (*minimum_baseline > *minimum)
+ *minimum_baseline = *minimum;
+}
+
+static void
+gs_lozenge_layout_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsLozengeLayout *self = GS_LOZENGE_LAYOUT (object);
+
+ switch ((GsLozengeLayoutProperty) prop_id) {
+ case PROP_CIRCULAR:
+ g_value_set_boolean (value, gs_lozenge_layout_get_circular (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_lozenge_layout_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsLozengeLayout *self = GS_LOZENGE_LAYOUT (object);
+
+ switch ((GsLozengeLayoutProperty) prop_id) {
+ case PROP_CIRCULAR:
+ gs_lozenge_layout_set_circular (self, g_value_get_boolean (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_lozenge_layout_class_init (GsLozengeLayoutClass *klass)
+{
+ GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ layout_manager_class->measure = gs_lozenge_layout_measure;
+
+ object_class->get_property = gs_lozenge_layout_get_property;
+ object_class->set_property = gs_lozenge_layout_set_property;
+
+ /**
+ * GsLozengeLayout:circular:
+ *
+ * Whether the lozenge should be circular, thus its size square.
+ *
+ * The default is %FALSE.
+ *
+ * Since: 43
+ */
+ obj_props[PROP_CIRCULAR] =
+ g_param_spec_boolean ("circular", NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
+}
+
+static void
+gs_lozenge_layout_init (GsLozengeLayout *self)
+{
+}
+
+/**
+ * gs_lozenge_layout_new:
+ *
+ * Create a new #GsLozengeLayout.
+ *
+ * Returns: (transfer full): a new #GsLozengeLayout
+ *
+ * Since: 43
+ **/
+GsLozengeLayout *
+gs_lozenge_layout_new (void)
+{
+ return g_object_new (GS_TYPE_LOZENGE_LAYOUT, NULL);
+}
+
+/**
+ * gs_lozenge_layout_get_circular:
+ * @self: a #GsLozengeLayout
+ *
+ * Get the value of #GsLozengeLayout:circular.
+ *
+ * Returns: %TRUE if the lozenge has to be circular, %FALSE otherwise
+ * Since: 43
+ */
+gboolean
+gs_lozenge_layout_get_circular (GsLozengeLayout *self)
+{
+ g_return_val_if_fail (GS_IS_LOZENGE_LAYOUT (self), FALSE);
+
+ return self->circular;
+}
+
+/**
+ * gs_lozenge_layout_set_circular:
+ * @self: a #GsLozengeLayout
+ * @value: %TRUE if the lozenge should be circular, %FALSE otherwise
+ *
+ * Set the value of #GsLozengeLayout:circular to @value.
+ *
+ * Since: 43
+ */
+void
+gs_lozenge_layout_set_circular (GsLozengeLayout *self,
+ gboolean value)
+{
+ g_return_if_fail (GS_IS_LOZENGE_LAYOUT (self));
+
+ if ((!self->circular) == (!value))
+ return;
+
+ self->circular = value;
+
+ gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (self));
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CIRCULAR]);
+}
diff --git a/src/gs-lozenge-layout.h b/src/gs-lozenge-layout.h
new file mode 100644
index 0000000000000000000000000000000000000000..e731819bdd26e738d6c14c58143096b560a30d6f
--- /dev/null
+++ b/src/gs-lozenge-layout.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2022 Red Hat (www.redhat.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+#include "gs-layout-manager.h"
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_LOZENGE_LAYOUT (gs_lozenge_layout_get_type ())
+G_DECLARE_FINAL_TYPE (GsLozengeLayout, gs_lozenge_layout, GS, LOZENGE_LAYOUT, GsLayoutManager)
+
+GsLozengeLayout *
+ gs_lozenge_layout_new (void);
+gboolean gs_lozenge_layout_get_circular (GsLozengeLayout *self);
+void gs_lozenge_layout_set_circular (GsLozengeLayout *self,
+ gboolean value);
+
+G_END_DECLS
diff --git a/src/gs-lozenge.c b/src/gs-lozenge.c
new file mode 100644
index 0000000000000000000000000000000000000000..39886cf73381c56a49cf5c5ed6ed48bc1820ce93
--- /dev/null
+++ b/src/gs-lozenge.c
@@ -0,0 +1,415 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2022 Red Hat (www.redhat.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include "config.h"
+
+#include "gs-lozenge.h"
+#include "gs-lozenge-layout.h"
+
+struct _GsLozenge
+{
+ GtkBox parent_instance;
+
+ GtkWidget *image; /* (unowned) */
+ GtkWidget *label; /* (unowned) */
+
+ gchar *icon_name;
+ gchar *text;
+ gchar *markup;
+ gboolean circular;
+ gint pixel_size;
+};
+
+G_DEFINE_TYPE (GsLozenge, gs_lozenge, GTK_TYPE_BOX)
+
+typedef enum {
+ PROP_CIRCULAR = 1,
+ PROP_ICON_NAME,
+ PROP_PIXEL_SIZE,
+ PROP_TEXT,
+ PROP_MARKUP
+} GsLozengeProperty;
+
+static GParamSpec *obj_props[PROP_MARKUP + 1] = { NULL, };
+
+static void
+gs_lozenge_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GsLozenge *self = GS_LOZENGE (object);
+
+ switch ((GsLozengeProperty) prop_id) {
+ case PROP_CIRCULAR:
+ g_value_set_boolean (value, gs_lozenge_get_circular (self));
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value, gs_lozenge_get_icon_name (self));
+ break;
+ case PROP_PIXEL_SIZE:
+ g_value_set_int (value, gs_lozenge_get_pixel_size (self));
+ break;
+ case PROP_TEXT:
+ g_value_set_string (value, gs_lozenge_get_text (self));
+ break;
+ case PROP_MARKUP:
+ g_value_set_string (value, gs_lozenge_get_markup (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_lozenge_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GsLozenge *self = GS_LOZENGE (object);
+
+ switch ((GsLozengeProperty) prop_id) {
+ case PROP_CIRCULAR:
+ gs_lozenge_set_circular (self, g_value_get_boolean (value));
+ break;
+ case PROP_ICON_NAME:
+ gs_lozenge_set_icon_name (self, g_value_get_string (value));
+ break;
+ case PROP_PIXEL_SIZE:
+ gs_lozenge_set_pixel_size (self, g_value_get_int (value));
+ break;
+ case PROP_TEXT:
+ gs_lozenge_set_text (self, g_value_get_string (value));
+ break;
+ case PROP_MARKUP:
+ gs_lozenge_set_markup (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gs_lozenge_dispose (GObject *object)
+{
+ GsLozenge *self = GS_LOZENGE (object);
+
+ g_clear_pointer (&self->icon_name, g_free);
+ g_clear_pointer (&self->text, g_free);
+ g_clear_pointer (&self->markup, g_free);
+
+ G_OBJECT_CLASS (gs_lozenge_parent_class)->dispose (object);
+}
+
+static void
+gs_lozenge_class_init (GsLozengeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ object_class->get_property = gs_lozenge_get_property;
+ object_class->set_property = gs_lozenge_set_property;
+ object_class->dispose = gs_lozenge_dispose;
+
+ /**
+ * GsLozenge:circular:
+ *
+ * Whether the lozenge should be circular/square widget.
+ *
+ * Since: 43
+ */
+ obj_props[PROP_CIRCULAR] =
+ g_param_spec_boolean ("circular", NULL, NULL,
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GsLozenge:icon-name:
+ *
+ * An icon name for the lozenge. Setting this property turns
+ * the lozenge into the icon mode, which mean showing the icon,
+ * not the markup.
+ *
+ * Since: 43
+ */
+ obj_props[PROP_ICON_NAME] =
+ g_param_spec_string ("icon-name", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GsLozenge:pixel-size:
+ *
+ * An icon pixel size for the lozenge.
+ *
+ * Since: 43
+ */
+ obj_props[PROP_PIXEL_SIZE] =
+ g_param_spec_int ("pixel-size", NULL, NULL,
+ 0, G_MAXINT, 16,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GsLozenge:text:
+ *
+ * A plain text for the lozenge. Setting this property turns
+ * the lozenge into the text mode, which mean showing the text,
+ * not the icon.
+ *
+ * Since: 43
+ */
+ obj_props[PROP_TEXT] =
+ g_param_spec_string ("text", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * GsLozenge:markup:
+ *
+ * A markup text for the lozenge. Setting this property turns
+ * the lozenge into the text mode, which mean showing the markup,
+ * not the icon.
+ *
+ * Since: 43
+ */
+ obj_props[PROP_MARKUP] =
+ g_param_spec_string ("markup", NULL, NULL,
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, G_N_ELEMENTS (obj_props), obj_props);
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GS_TYPE_LOZENGE_LAYOUT);
+ gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-lozenge.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, GsLozenge, image);
+ gtk_widget_class_bind_template_child (widget_class, GsLozenge, label);
+}
+
+static void
+gs_lozenge_init (GsLozenge *self)
+{
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->pixel_size = 16;
+}
+
+/**
+ * gs_lozenge_new:
+ *
+ * Returns: (transfer full): a new #GsLozenge
+ *
+ * Since: 43
+ **/
+GtkWidget *
+gs_lozenge_new (void)
+{
+ return g_object_new (GS_TYPE_LOZENGE, NULL);
+}
+
+const gchar *
+gs_lozenge_get_icon_name (GsLozenge *self)
+{
+ g_return_val_if_fail (GS_IS_LOZENGE (self), NULL);
+
+ return self->icon_name;
+}
+
+gboolean
+gs_lozenge_get_circular (GsLozenge *self)
+{
+ g_return_val_if_fail (GS_IS_LOZENGE (self), FALSE);
+
+ return self->circular;
+}
+
+void
+gs_lozenge_set_circular (GsLozenge *self,
+ gboolean value)
+{
+ GtkLayoutManager *layout_manager;
+
+ g_return_if_fail (GS_IS_LOZENGE (self));
+
+ if ((!self->circular) == (!value))
+ return;
+
+ self->circular = value;
+
+ layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (self));
+ gs_lozenge_layout_set_circular (GS_LOZENGE_LAYOUT (layout_manager), self->circular);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_CIRCULAR]);
+}
+
+void
+gs_lozenge_set_icon_name (GsLozenge *self,
+ const gchar *value)
+{
+ g_return_if_fail (GS_IS_LOZENGE (self));
+
+ if (value != NULL && *value == '\0')
+ value = NULL;
+
+ if (g_strcmp0 (self->icon_name, value) == 0)
+ return;
+
+ g_clear_pointer (&self->icon_name, g_free);
+ self->icon_name = g_strdup (value);
+
+ if (self->icon_name == NULL) {
+ gtk_widget_hide (self->image);
+ gtk_widget_show (self->label);
+ } else {
+ gtk_image_set_from_icon_name (GTK_IMAGE (self->image), self->icon_name);
+ gtk_widget_hide (self->label);
+ gtk_widget_show (self->image);
+ }
+
+ /* Clean up the other properties before notifying of the changed property name */
+
+ if (self->text != NULL) {
+ g_clear_pointer (&self->text, g_free);
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]);
+ }
+
+ if (self->markup != NULL) {
+ g_clear_pointer (&self->markup, g_free);
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MARKUP]);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ICON_NAME]);
+}
+
+gint
+gs_lozenge_get_pixel_size (GsLozenge *self)
+{
+ g_return_val_if_fail (GS_IS_LOZENGE (self), 0);
+
+ return self->pixel_size;
+}
+
+void
+gs_lozenge_set_pixel_size (GsLozenge *self,
+ gint value)
+{
+ g_return_if_fail (GS_IS_LOZENGE (self));
+
+ if (self->pixel_size == value)
+ return;
+
+ self->pixel_size = value;
+
+ gtk_image_set_pixel_size (GTK_IMAGE (self->image), self->pixel_size);
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_PIXEL_SIZE]);
+}
+
+gboolean
+gs_lozenge_get_use_markup (GsLozenge *self)
+{
+ g_return_val_if_fail (GS_IS_LOZENGE (self), FALSE);
+ return gtk_label_get_use_markup (GTK_LABEL (self->label));
+}
+
+const gchar *
+gs_lozenge_get_text (GsLozenge *self)
+{
+ g_return_val_if_fail (GS_IS_LOZENGE (self), NULL);
+
+ return self->text;
+}
+
+void
+gs_lozenge_set_text (GsLozenge *self,
+ const gchar *value)
+{
+ g_return_if_fail (GS_IS_LOZENGE (self));
+
+ if (value != NULL && *value == '\0')
+ value = NULL;
+
+ if (g_strcmp0 (self->text, value) == 0)
+ return;
+
+ g_clear_pointer (&self->text, g_free);
+ self->text = g_strdup (value);
+
+ if (self->text == NULL) {
+ gtk_widget_hide (self->label);
+ gtk_widget_show (self->image);
+ } else {
+ gtk_label_set_text (GTK_LABEL (self->label), self->text);
+ gtk_widget_hide (self->image);
+ gtk_widget_show (self->label);
+ }
+
+ /* Clean up the other properties before notifying of the changed property name */
+
+ if (self->icon_name != NULL) {
+ g_clear_pointer (&self->icon_name, g_free);
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ICON_NAME]);
+ }
+
+ if (self->markup != NULL) {
+ g_clear_pointer (&self->markup, g_free);
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MARKUP]);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]);
+}
+
+const gchar *
+gs_lozenge_get_markup (GsLozenge *self)
+{
+ g_return_val_if_fail (GS_IS_LOZENGE (self), NULL);
+
+ return self->markup;
+}
+
+void
+gs_lozenge_set_markup (GsLozenge *self,
+ const gchar *value)
+{
+ g_return_if_fail (GS_IS_LOZENGE (self));
+
+ if (value != NULL && *value == '\0')
+ value = NULL;
+
+ if (g_strcmp0 (self->markup, value) == 0)
+ return;
+
+ g_clear_pointer (&self->markup, g_free);
+ self->markup = g_strdup (value);
+
+ if (self->markup == NULL) {
+ gtk_widget_hide (self->label);
+ gtk_widget_show (self->image);
+ } else {
+ gtk_label_set_markup (GTK_LABEL (self->label), self->markup);
+ gtk_widget_hide (self->image);
+ gtk_widget_show (self->label);
+ }
+
+ /* Clean up the other properties before notifying of the changed property name */
+
+ if (self->icon_name != NULL) {
+ g_clear_pointer (&self->icon_name, g_free);
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ICON_NAME]);
+ }
+
+ if (self->text != NULL) {
+ g_clear_pointer (&self->text, g_free);
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_TEXT]);
+ }
+
+ g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_MARKUP]);
+}
diff --git a/src/gs-lozenge.h b/src/gs-lozenge.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3319767267df318b55440d2e64f41ef006069a8
--- /dev/null
+++ b/src/gs-lozenge.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ * vi:set noexpandtab tabstop=8 shiftwidth=8:
+ *
+ * Copyright (C) 2022 Red Hat (www.redhat.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#pragma once
+
+#include
+#include
+#include
+
+G_BEGIN_DECLS
+
+#define GS_TYPE_LOZENGE (gs_lozenge_get_type ())
+G_DECLARE_FINAL_TYPE (GsLozenge, gs_lozenge, GS, LOZENGE, GtkBox)
+
+GtkWidget * gs_lozenge_new (void);
+gboolean gs_lozenge_get_circular (GsLozenge *self);
+void gs_lozenge_set_circular (GsLozenge *self,
+ gboolean value);
+const gchar * gs_lozenge_get_icon_name (GsLozenge *self);
+void gs_lozenge_set_icon_name (GsLozenge *self,
+ const gchar *value);
+gint gs_lozenge_get_pixel_size (GsLozenge *self);
+void gs_lozenge_set_pixel_size (GsLozenge *self,
+ gint value);
+gboolean gs_lozenge_get_use_markup (GsLozenge *self);
+const gchar * gs_lozenge_get_text (GsLozenge *self);
+void gs_lozenge_set_text (GsLozenge *self,
+ const gchar *value);
+const gchar * gs_lozenge_get_markup (GsLozenge *self);
+void gs_lozenge_set_markup (GsLozenge *self,
+ const gchar *value);
+
+G_END_DECLS
diff --git a/src/gs-lozenge.ui b/src/gs-lozenge.ui
new file mode 100644
index 0000000000000000000000000000000000000000..545d803f407ddc73f2f5999ece66b17b0b609a79
--- /dev/null
+++ b/src/gs-lozenge.ui
@@ -0,0 +1,33 @@
+
+
+
+
+ center
+ False
+ center
+
+
+
+ center
+ True
+
+ safety-symbolic
+ 16
+ False
+
+
+
+
+ center
+ True
+
+ 20 MB
+ False
+ 0.5
+ False
+
+
+
+
diff --git a/src/gs-safety-context-dialog.c b/src/gs-safety-context-dialog.c
index 1cb955f1c5a76212ac77f36974fea7de432bb3a5..a05a3543b736154a5d340d9ba2189a38fa9d2f06 100644
--- a/src/gs-safety-context-dialog.c
+++ b/src/gs-safety-context-dialog.c
@@ -38,6 +38,7 @@
#include "gs-app.h"
#include "gs-common.h"
#include "gs-context-dialog-row.h"
+#include "gs-lozenge.h"
#include "gs-safety-context-dialog.h"
struct _GsSafetyContextDialog
@@ -51,7 +52,6 @@ struct _GsSafetyContextDialog
gulong app_notify_handler_license;
gulong app_notify_handler_related;
- GtkImage *icon;
GtkWidget *lozenge;
GtkLabel *title;
GtkListBox *permissions_list;
@@ -374,7 +374,7 @@ update_permissions_list (GsSafetyContextDialog *self)
g_assert_not_reached ();
}
- gtk_image_set_from_icon_name (GTK_IMAGE (self->icon), icon_name);
+ gs_lozenge_set_icon_name (GS_LOZENGE (self->lozenge), icon_name);
gtk_label_set_text (self->title, title);
context = gtk_widget_get_style_context (self->lozenge);
@@ -533,7 +533,6 @@ gs_safety_context_dialog_class_init (GsSafetyContextDialogClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-safety-context-dialog.ui");
- gtk_widget_class_bind_template_child (widget_class, GsSafetyContextDialog, icon);
gtk_widget_class_bind_template_child (widget_class, GsSafetyContextDialog, lozenge);
gtk_widget_class_bind_template_child (widget_class, GsSafetyContextDialog, title);
gtk_widget_class_bind_template_child (widget_class, GsSafetyContextDialog, permissions_list);
diff --git a/src/gs-safety-context-dialog.ui b/src/gs-safety-context-dialog.ui
index 6d35151c146953dbd7544aa638ca8839cf3f0d67..836a7c49db1ba277395e22ed173121c116387817 100644
--- a/src/gs-safety-context-dialog.ui
+++ b/src/gs-safety-context-dialog.ui
@@ -23,25 +23,18 @@
12
-
- center
+
+ True
+
+ safety-symbolic
+ 24
-
-
- center
- True
-
- safety-symbolic
- 24
-
- title
-
-
-
+
+ title
+
diff --git a/src/gs-storage-context-dialog.c b/src/gs-storage-context-dialog.c
index 7ca2e29d9d8976274fd32297af9747d72fdce1b9..e0ca3778999d8f01f8d8a384aeffb4853873905f 100644
--- a/src/gs-storage-context-dialog.c
+++ b/src/gs-storage-context-dialog.c
@@ -38,6 +38,7 @@
#include "gs-app.h"
#include "gs-common.h"
#include "gs-context-dialog-row.h"
+#include "gs-lozenge.h"
#include "gs-storage-context-dialog.h"
struct _GsStorageContextDialog
@@ -48,7 +49,6 @@ struct _GsStorageContextDialog
gulong app_notify_handler;
GtkSizeGroup *lozenge_size_group;
- GtkLabel *lozenge_content;
GtkWidget *lozenge;
GtkLabel *title;
GtkListBox *sizes_list;
@@ -98,7 +98,8 @@ add_size_row (GtkListBox *list_box,
row = gs_context_dialog_row_new_text (size_bytes_str, GS_CONTEXT_DIALOG_ROW_IMPORTANCE_NEUTRAL,
title, description);
- gs_context_dialog_row_set_content_is_markup (GS_CONTEXT_DIALOG_ROW (row), is_markup);
+ if (is_markup)
+ gs_context_dialog_row_set_content_markup (GS_CONTEXT_DIALOG_ROW (row), size_bytes_str);
gs_context_dialog_row_set_size_groups (GS_CONTEXT_DIALOG_ROW (row), lozenge_size_group, NULL, NULL);
gtk_list_box_append (list_box, GTK_WIDGET (row));
}
@@ -187,9 +188,9 @@ update_sizes_list (GsStorageContextDialog *self)
title_size_bytes_str = g_strdup (C_("Download size", "Unknown"));
if (is_markup)
- gtk_label_set_markup (self->lozenge_content, title_size_bytes_str);
+ gs_lozenge_set_markup (GS_LOZENGE (self->lozenge), title_size_bytes_str);
else
- gtk_label_set_text (self->lozenge_content, title_size_bytes_str);
+ gs_lozenge_set_text (GS_LOZENGE (self->lozenge), title_size_bytes_str);
gtk_label_set_text (self->title, title);
@@ -332,7 +333,6 @@ gs_storage_context_dialog_class_init (GsStorageContextDialogClass *klass)
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/Software/gs-storage-context-dialog.ui");
gtk_widget_class_bind_template_child (widget_class, GsStorageContextDialog, lozenge_size_group);
- gtk_widget_class_bind_template_child (widget_class, GsStorageContextDialog, lozenge_content);
gtk_widget_class_bind_template_child (widget_class, GsStorageContextDialog, lozenge);
gtk_widget_class_bind_template_child (widget_class, GsStorageContextDialog, title);
gtk_widget_class_bind_template_child (widget_class, GsStorageContextDialog, sizes_list);
diff --git a/src/gs-storage-context-dialog.ui b/src/gs-storage-context-dialog.ui
index 4b3de96c02e7f9a3b714ba67b367b829504e0511..de2f589c84dc5b4fd18af244a39cbe3ebf3cfad0 100644
--- a/src/gs-storage-context-dialog.ui
+++ b/src/gs-storage-context-dialog.ui
@@ -23,25 +23,15 @@
12
-
- center
+
+ False
-
-
- center
- True
-
- 20 MB
- 0.5
-
- title
-
-
-
+
+ title
+
diff --git a/src/gs-summary-tile-layout.c b/src/gs-summary-tile-layout.c
deleted file mode 100644
index 5e738f16cc3127917ff859fb7d36da10fcc10209..0000000000000000000000000000000000000000
--- a/src/gs-summary-tile-layout.c
+++ /dev/null
@@ -1,114 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
- * vi:set noexpandtab tabstop=8 shiftwidth=8:
- *
- * Copyright (C) 2021 Endless OS Foundation LLC
- *
- * Author: Georges Basile Stavracas Neto
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include "gs-summary-tile-layout.h"
-
-struct _GsSummaryTileLayout
-{
- GtkLayoutManager parent_instance;
-
- gint preferred_width;
-};
-
-G_DEFINE_TYPE (GsSummaryTileLayout, gs_summary_tile_layout, GTK_TYPE_LAYOUT_MANAGER)
-
-static void
-gs_summary_tile_layout_layout_measure (GtkLayoutManager *layout_manager,
- GtkWidget *widget,
- GtkOrientation orientation,
- gint for_size,
- gint *minimum,
- gint *natural,
- gint *minimum_baseline,
- gint *natural_baseline)
-{
- GsSummaryTileLayout *self = GS_SUMMARY_TILE_LAYOUT (layout_manager);
- GtkWidget *child;
- gint min = 0;
- gint nat = 0;
-
- for (child = gtk_widget_get_first_child (widget);
- child != NULL;
- child = gtk_widget_get_next_sibling (child)) {
- gint child_min_baseline = -1;
- gint child_nat_baseline = -1;
- gint child_min = 0;
- gint child_nat = 0;
-
- if (!gtk_widget_should_layout (child))
- continue;
-
- gtk_widget_measure (child, orientation,
- for_size,
- &child_min, &child_nat,
- &child_min_baseline,
- &child_nat_baseline);
-
- min = MAX (min, child_min);
- nat = MAX (nat, child_nat);
-
- if (child_min_baseline > -1)
- *minimum_baseline = MAX (*minimum_baseline, child_min_baseline);
- if (child_nat_baseline > -1)
- *natural_baseline = MAX (*natural_baseline, child_nat_baseline);
- }
-
- *minimum = min;
- *natural = nat;
-
- /* Limit the natural width */
- if (self->preferred_width > 0 && orientation == GTK_ORIENTATION_HORIZONTAL)
- *natural = MAX (min, self->preferred_width);
-}
-
-static void
-gs_summary_tile_layout_layout_allocate (GtkLayoutManager *layout_manager,
- GtkWidget *widget,
- gint width,
- gint height,
- gint baseline)
-{
- GtkWidget *child;
-
- for (child = gtk_widget_get_first_child (widget);
- child != NULL;
- child = gtk_widget_get_next_sibling (child)) {
- if (child && gtk_widget_should_layout (child))
- gtk_widget_allocate (child, width, height, baseline, NULL);
- }
-}
-
-static void
-gs_summary_tile_layout_class_init (GsSummaryTileLayoutClass *klass)
-{
- GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
-
- layout_manager_class->measure = gs_summary_tile_layout_layout_measure;
- layout_manager_class->allocate = gs_summary_tile_layout_layout_allocate;
-}
-
-static void
-gs_summary_tile_layout_init (GsSummaryTileLayout *self)
-{
- self->preferred_width = -1;
-}
-
-void
-gs_summary_tile_layout_set_preferred_width (GsSummaryTileLayout *self,
- gint preferred_width)
-{
- g_return_if_fail (GS_IS_SUMMARY_TILE_LAYOUT (self));
-
- if (self->preferred_width == preferred_width)
- return;
-
- self->preferred_width = preferred_width;
- gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (self));
-}
diff --git a/src/gs-summary-tile.c b/src/gs-summary-tile.c
index c447eb617ee7267342790dbc8fe4cf7ab98c23ef..dcd977b4456f43bc7d2c88ec03f22bab159d79a2 100644
--- a/src/gs-summary-tile.c
+++ b/src/gs-summary-tile.c
@@ -12,9 +12,55 @@
#include
#include "gs-summary-tile.h"
-#include "gs-summary-tile-layout.h"
+#include "gs-layout-manager.h"
#include "gs-common.h"
+#define GS_TYPE_SUMMARY_TILE_LAYOUT (gs_summary_tile_layout_get_type ())
+G_DECLARE_FINAL_TYPE (GsSummaryTileLayout, gs_summary_tile_layout, GS, SUMMARY_TILE_LAYOUT, GsLayoutManager)
+
+struct _GsSummaryTileLayout
+{
+ GsLayoutManager parent_instance;
+
+ gint preferred_width;
+};
+
+G_DEFINE_TYPE (GsSummaryTileLayout, gs_summary_tile_layout, GS_TYPE_LAYOUT_MANAGER)
+
+static void
+gs_summary_tile_layout_measure (GtkLayoutManager *layout_manager,
+ GtkWidget *widget,
+ GtkOrientation orientation,
+ gint for_size,
+ gint *minimum,
+ gint *natural,
+ gint *minimum_baseline,
+ gint *natural_baseline)
+{
+ GsSummaryTileLayout *self = GS_SUMMARY_TILE_LAYOUT (layout_manager);
+
+ GTK_LAYOUT_MANAGER_CLASS (gs_summary_tile_layout_parent_class)->measure (layout_manager,
+ widget, orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
+
+ /* Limit the natural width */
+ if (self->preferred_width > 0 && orientation == GTK_ORIENTATION_HORIZONTAL)
+ *natural = MAX (*minimum, self->preferred_width);
+}
+
+static void
+gs_summary_tile_layout_class_init (GsSummaryTileLayoutClass *klass)
+{
+ GtkLayoutManagerClass *layout_manager_class = GTK_LAYOUT_MANAGER_CLASS (klass);
+ layout_manager_class->measure = gs_summary_tile_layout_measure;
+}
+
+static void
+gs_summary_tile_layout_init (GsSummaryTileLayout *self)
+{
+}
+
+/* ********************************************************************* */
+
struct _GsSummaryTile
{
GsAppTile parent_instance;
@@ -138,8 +184,8 @@ gs_summary_tile_set_property (GObject *object,
case PROP_PREFERRED_WIDTH:
app_tile->preferred_width = g_value_get_int (value);
layout_manager = gtk_widget_get_layout_manager (GTK_WIDGET (app_tile));
- gs_summary_tile_layout_set_preferred_width (GS_SUMMARY_TILE_LAYOUT (layout_manager),
- g_value_get_int (value));
+ GS_SUMMARY_TILE_LAYOUT (layout_manager)->preferred_width = app_tile->preferred_width;
+ gtk_layout_manager_layout_changed (layout_manager);
g_object_notify_by_pspec (object, obj_props[PROP_PREFERRED_WIDTH]);
break;
default:
diff --git a/src/meson.build b/src/meson.build
index e1ef51afb812b8aa3ec19a88de394a50bc072ed5..1b58586916f1eaa7a1b1a53b81f015f3a5920533 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -50,8 +50,11 @@ gnome_software_sources = [
'gs-info-window.c',
'gs-installed-page.c',
'gs-language.c',
+ 'gs-layout-manager.c',
'gs-license-tile.c',
'gs-loading-page.c',
+ 'gs-lozenge.c',
+ 'gs-lozenge-layout.c',
'gs-main.c',
'gs-metered-data-dialog.c',
'gs-moderate-page.c',
@@ -79,7 +82,6 @@ gnome_software_sources = [
'gs-star-widget.c',
'gs-storage-context-dialog.c',
'gs-summary-tile.c',
- 'gs-summary-tile-layout.c',
'gs-update-dialog.c',
'gs-update-list.c',
'gs-update-monitor.c',