From d6fba7ac8244ebf077e76468a5072552fa02aa89 Mon Sep 17 00:00:00 2001 From: Colomban Wendling Date: Sun, 16 Sep 2012 15:57:04 +0200 Subject: [PATCH] Make GeanyWrapLabel work with GTK3 Although theoretically GtkLabel from GTK3 should be able to replace GeanyWrapLabel altogether, a bug [1] with it makes it use way too much space in our about dialog (and possibly other places), making it not really usable. So, port the GeanyWrapLabel hack to GTK3, with the appropriate additional hacks for it to work. At least it looks good and don't seem to have resizing issues now. [1] https://bugzilla.gnome.org/show_bug.cgi?id=657621 --- src/geanywraplabel.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/geanywraplabel.h | 25 ------------- 2 files changed, 96 insertions(+), 31 deletions(-) diff --git a/src/geanywraplabel.c b/src/geanywraplabel.c index 59bcf4e99..b4380c2fd 100644 --- a/src/geanywraplabel.c +++ b/src/geanywraplabel.c @@ -29,8 +29,6 @@ #include "utils.h" #include "geanywraplabel.h" -#if ! GTK_CHECK_VERSION(3, 0, 0) - struct _GeanyWrapLabelClass { @@ -50,9 +48,22 @@ struct _GeanyWrapLabel }; +#if GTK_CHECK_VERSION(3, 0, 0) +static gboolean geany_wrap_label_draw(GtkWidget *widget, cairo_t *cr); +static void geany_wrap_label_get_preferred_width (GtkWidget *widget, + gint *minimal_width, gint *natural_width); +static void geany_wrap_label_get_preferred_height (GtkWidget *widget, + gint *minimal_height, gint *natural_height); +static void geany_wrap_label_get_preferred_width_for_height (GtkWidget *widget, + gint height, gint *minimal_width, gint *natural_width); +static void geany_wrap_label_get_preferred_height_for_width (GtkWidget *widget, + gint width, gint *minimal_height, gint *natural_height); +static GtkSizeRequestMode geany_wrap_label_get_request_mode(GtkWidget *widget); +#else +static gboolean geany_wrap_label_expose (GtkWidget *widget, GdkEventExpose *event); static void geany_wrap_label_size_request (GtkWidget *widget, GtkRequisition *req); +#endif static void geany_wrap_label_size_allocate (GtkWidget *widget, GtkAllocation *alloc); -static gboolean geany_wrap_label_expose (GtkWidget *widget, GdkEventExpose *event); static void geany_wrap_label_set_wrap_width (GtkWidget *widget, gint width); static void geany_wrap_label_label_notify (GObject *object, GParamSpec *pspec, gpointer data); @@ -63,9 +74,18 @@ static void geany_wrap_label_class_init(GeanyWrapLabelClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass); - widget_class->size_request = geany_wrap_label_size_request; widget_class->size_allocate = geany_wrap_label_size_allocate; +#if GTK_CHECK_VERSION(3, 0, 0) + widget_class->draw = geany_wrap_label_draw; + widget_class->get_preferred_width = geany_wrap_label_get_preferred_width; + widget_class->get_preferred_width_for_height = geany_wrap_label_get_preferred_width_for_height; + widget_class->get_preferred_height = geany_wrap_label_get_preferred_height; + widget_class->get_preferred_height_for_width = geany_wrap_label_get_preferred_height_for_width; + widget_class->get_request_mode = geany_wrap_label_get_request_mode; +#else + widget_class->size_request = geany_wrap_label_size_request; widget_class->expose_event = geany_wrap_label_expose; +#endif g_type_class_add_private(klass, sizeof (GeanyWrapLabelPrivate)); } @@ -120,6 +140,67 @@ static void geany_wrap_label_label_notify(GObject *object, GParamSpec *pspec, gp } +#if GTK_CHECK_VERSION(3, 0, 0) +/* makes sure the layout is setup for rendering and chains to parent renderer */ +static gboolean geany_wrap_label_draw(GtkWidget *widget, cairo_t *cr) +{ + GeanyWrapLabel *self = GEANY_WRAP_LABEL(widget); + PangoLayout *layout = gtk_label_get_layout(GTK_LABEL(widget)); + + pango_layout_set_width(layout, self->priv->wrap_width * PANGO_SCALE); + pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); + + return (* GTK_WIDGET_CLASS(geany_wrap_label_parent_class)->draw)(widget, cr); +} + + +static void geany_wrap_label_get_preferred_width (GtkWidget *widget, + gint *minimal_width, gint *natural_width) +{ + *minimal_width = *natural_width = 0; +} + + +static void geany_wrap_label_get_preferred_width_for_height (GtkWidget *widget, + gint height, gint *minimal_width, gint *natural_width) +{ + PangoLayout *layout = gtk_label_get_layout(GTK_LABEL(widget));; + + pango_layout_set_height(layout, height * PANGO_SCALE); + pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); + pango_layout_get_pixel_size(layout, natural_width, NULL); + + *minimal_width = 0; +} + + +static void geany_wrap_label_get_preferred_height (GtkWidget *widget, + gint *minimal_height, gint *natural_height) +{ + *minimal_height = *natural_height = GEANY_WRAP_LABEL(widget)->priv->wrap_height; +} + + +static void geany_wrap_label_get_preferred_height_for_width (GtkWidget *widget, + gint width, gint *minimal_height, gint *natural_height) +{ + PangoLayout *layout = gtk_label_get_layout(GTK_LABEL(widget)); + + pango_layout_set_width(layout, width * PANGO_SCALE); + pango_layout_set_wrap(layout, PANGO_WRAP_WORD_CHAR); + pango_layout_get_pixel_size(layout, NULL, natural_height); + + *minimal_height = *natural_height; +} + + +static GtkSizeRequestMode geany_wrap_label_get_request_mode(GtkWidget *widget) +{ + return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT; +} + +#else /* GTK3 */ + /* makes sure the layout is setup for rendering and chains to parent renderer */ static gboolean geany_wrap_label_expose(GtkWidget *widget, GdkEventExpose *event) { @@ -140,6 +221,7 @@ static void geany_wrap_label_size_request(GtkWidget *widget, GtkRequisition *req req->width = 0; req->height = GEANY_WRAP_LABEL(widget)->priv->wrap_height; } +#endif /* GTK3 */ /* Sets the wrap width to the width allocated to us. */ @@ -148,6 +230,16 @@ static void geany_wrap_label_size_allocate(GtkWidget *widget, GtkAllocation *all (* GTK_WIDGET_CLASS(geany_wrap_label_parent_class)->size_allocate)(widget, alloc); geany_wrap_label_set_wrap_width(widget, alloc->width); + +#if GTK_CHECK_VERSION(3, 0, 0) +{ + /* ask the parent to recompute our size, because it seems GTK3 size + * caching is too aggressive */ + GtkWidget *parent = gtk_widget_get_parent(widget); + if (GTK_IS_CONTAINER(parent)) + gtk_container_check_resize(GTK_CONTAINER(parent)); +} +#endif } @@ -155,5 +247,3 @@ GtkWidget *geany_wrap_label_new(const gchar *text) { return g_object_new(GEANY_WRAP_LABEL_TYPE, "label", text, NULL); } - -#endif diff --git a/src/geanywraplabel.h b/src/geanywraplabel.h index 037a7a6a8..eef012c48 100644 --- a/src/geanywraplabel.h +++ b/src/geanywraplabel.h @@ -25,8 +25,6 @@ G_BEGIN_DECLS -#if ! GTK_CHECK_VERSION(3, 0, 0) - #define GEANY_WRAP_LABEL_TYPE (geany_wrap_label_get_type()) #define GEANY_WRAP_LABEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), \ GEANY_WRAP_LABEL_TYPE, GeanyWrapLabel)) @@ -44,29 +42,6 @@ typedef struct _GeanyWrapLabelClass GeanyWrapLabelClass; GType geany_wrap_label_get_type (void); GtkWidget* geany_wrap_label_new (const gchar *text); -#else /* GTK 3.0 */ - -#define GEANY_WRAP_LABEL_TYPE GTK_TYPE_LABEL -#define GEANY_WRAP_LABEL GTK_LABEL -#define GEANY_WRAP_LABEL_CLASS GTK_LABEL_CLASS -#define IS_GEANY_WRAP_LABEL GTK_IS_LABEL -#define IS_GEANY_WRAP_LABEL_CLASS GTK_IS_LABEL_CLASS - -#define GeanyWrapLabel GtkLabel -#define GeanyWrapLabelClass GtkLabelClass - -#define geany_wrap_label_get_type gtk_label_get_type -#define geany_wrap_label_new(text) \ - g_object_new(GTK_TYPE_LABEL, \ - "label", (text), \ - "wrap", TRUE, \ - "wrap-mode", PANGO_WRAP_WORD_CHAR, \ - "xalign", 0.0, \ - "yalign", 0.0, \ - NULL) - -#endif - G_END_DECLS -- 2.11.4.GIT