Commit efeaeca8 authored by Colomban Wendling's avatar Colomban Wendling

OVCCGtk: port OVCCGtkWrapLabel to GTK3

parent e526e001
/*
* Copyright 2011 Colomban Wendling <ban@herbesfolles.org>
* Copyright 2011-2013 Colomban Wendling <ban@herbesfolles.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -19,7 +19,8 @@
*
*/
/* Initially written for GeanyGitUI, itself inspired from from GeanyWrapLabel */
/* Initially written for GeanyGitUI, itself inspired from from GeanyWrapLabel.
* GTK3 port is from GeanyWrapLabel */
#include "ovccgtk-wrap-label.h"
......@@ -30,16 +31,32 @@
struct _OVCCGtkWrapLabelPrivate
{
gint wrap_width;
gint wrap_height;
};
static void ovccgtk_wrap_label_size_request (GtkWidget *widget,
GtkRequisition *req);
static void ovccgtk_wrap_label_size_allocate (GtkWidget *widget,
GtkAllocation *alloc);
static void ovccgtk_wrap_label_notify_label_handler (GObject *object,
GParamSpec *pspec,
gpointer data);
static gboolean ovccgtk_wrap_label_draw (GtkWidget *widget,
cairo_t *cr);
static void ovccgtk_wrap_label_get_preferred_width (GtkWidget *widget,
gint *minimal_width,
gint *natural_width);
static void ovccgtk_wrap_label_get_preferred_height (GtkWidget *widget,
gint *minimal_height,
gint *natural_height);
static void ovccgtk_wrap_label_get_preferred_width_for_height (GtkWidget *widget,
gint height,
gint *minimal_width,
gint *natural_width);
static void ovccgtk_wrap_label_get_preferred_height_for_width (GtkWidget *widget,
gint width,
gint *minimal_height,
gint *natural_height);
static GtkSizeRequestMode ovccgtk_wrap_label_get_request_mode (GtkWidget *widget);
static void ovccgtk_wrap_label_size_allocate (GtkWidget *widget,
GtkAllocation *alloc);
static void ovccgtk_wrap_label_notify_label_handler (GObject *object,
GParamSpec *pspec,
gpointer data);
G_DEFINE_TYPE (OVCCGtkWrapLabel,
......@@ -52,8 +69,13 @@ ovccgtk_wrap_label_class_init (OVCCGtkWrapLabelClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
widget_class->size_request = ovccgtk_wrap_label_size_request;
widget_class->size_allocate = ovccgtk_wrap_label_size_allocate;
widget_class->draw = ovccgtk_wrap_label_draw;
widget_class->get_preferred_width = ovccgtk_wrap_label_get_preferred_width;
widget_class->get_preferred_width_for_height = ovccgtk_wrap_label_get_preferred_width_for_height;
widget_class->get_preferred_height = ovccgtk_wrap_label_get_preferred_height;
widget_class->get_preferred_height_for_width = ovccgtk_wrap_label_get_preferred_height_for_width;
widget_class->get_request_mode = ovccgtk_wrap_label_get_request_mode;
widget_class->size_allocate = ovccgtk_wrap_label_size_allocate;
g_type_class_add_private (klass, sizeof (OVCCGtkWrapLabelPrivate));
}
......@@ -65,24 +87,26 @@ ovccgtk_wrap_label_init (OVCCGtkWrapLabel *self)
OVCCGtkWrapLabelPrivate);
self->priv->wrap_width = 0;
self->priv->wrap_height = 0;
gtk_misc_set_alignment (GTK_MISC (self), 0.0, 0.5);
g_signal_connect (self, "notify::label",
G_CALLBACK (ovccgtk_wrap_label_notify_label_handler), NULL);
pango_layout_set_wrap (gtk_label_get_layout (GTK_LABEL (self)),
PANGO_WRAP_WORD_CHAR);
}
/* Sets the point at which the text should wrap. */
static void
ovccgtk_wrap_label_set_wrap_width (OVCCGtkWrapLabel *self,
gint width)
ovccgtk_wrap_label_set_wrap_width (OVCCGtkWrapLabel *self,
gint width)
{
if (width > 0) {
PangoLayout *layout = gtk_label_get_layout (GTK_LABEL (self));
/* We may need to reset the wrap width, so do this regardless of whether
* or not we've changed the width. */
pango_layout_set_width (gtk_label_get_layout (GTK_LABEL (self)),
width * PANGO_SCALE);
pango_layout_set_width (layout, width * PANGO_SCALE);
pango_layout_set_wrap (layout, PANGO_WRAP_WORD_CHAR);
pango_layout_get_pixel_size (layout, NULL, &self->priv->wrap_height);
if (self->priv->wrap_width != width) {
self->priv->wrap_width = width;
......@@ -102,15 +126,71 @@ ovccgtk_wrap_label_notify_label_handler (GObject *object,
ovccgtk_wrap_label_set_wrap_width (self, self->priv->wrap_width);
}
/* Forces the height to be the size necessary for the Pango layout, while allowing the
* width to be flexible. */
/* makes sure the layout is setup for rendering and chains to parent renderer */
static gboolean
ovccgtk_wrap_label_draw (GtkWidget *widget,
cairo_t *cr)
{
OVCCGtkWrapLabel *self = OVCCGTK_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 (ovccgtk_wrap_label_parent_class)->draw) (widget,
cr);
}
static void
ovccgtk_wrap_label_get_preferred_width (GtkWidget *widget,
gint *minimal_width,
gint *natural_width)
{
*minimal_width = *natural_width = 0;
}
static void
ovccgtk_wrap_label_size_request (GtkWidget *widget,
GtkRequisition *req)
ovccgtk_wrap_label_get_preferred_width_for_height (GtkWidget *widget,
gint height,
gint *minimal_width,
gint *natural_width)
{
req->width = 0;
pango_layout_get_pixel_size (gtk_label_get_layout (GTK_LABEL (widget)),
NULL, &req->height);
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
ovccgtk_wrap_label_get_preferred_height (GtkWidget *widget,
gint *minimal_height,
gint *natural_height)
{
*minimal_height = *natural_height = OVCCGTK_WRAP_LABEL (widget)->priv->wrap_height;
}
static void
ovccgtk_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
ovccgtk_wrap_label_get_request_mode (GtkWidget *widget)
{
return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
}
/* Sets the wrap width to the width allocated to us. */
......@@ -118,11 +198,19 @@ static void
ovccgtk_wrap_label_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkWidget *parent = gtk_widget_get_parent (widget);
GTK_WIDGET_CLASS (ovccgtk_wrap_label_parent_class)->size_allocate (widget,
allocation);
ovccgtk_wrap_label_set_wrap_width (OVCCGTK_WRAP_LABEL (widget),
allocation->width);
/* ask the parent to recompute our size, because it seems GTK3 size
* caching is too aggressive */
if (GTK_IS_CONTAINER (parent)) {
gtk_container_check_resize (GTK_CONTAINER (parent));
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment