summaryrefslogtreecommitdiff
path: root/lib/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/widgets')
-rw-r--r--lib/widgets/contrib/gd-two-lines-renderer.c621
-rw-r--r--lib/widgets/contrib/gd-two-lines-renderer.h75
-rw-r--r--lib/widgets/ephy-location-entry.c378
-rw-r--r--lib/widgets/ephy-location-entry.h20
-rw-r--r--lib/widgets/meson.build2
5 files changed, 41 insertions, 1055 deletions
diff --git a/lib/widgets/contrib/gd-two-lines-renderer.c b/lib/widgets/contrib/gd-two-lines-renderer.c
deleted file mode 100644
index 5a029f7f2..000000000
--- a/lib/widgets/contrib/gd-two-lines-renderer.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * Copyright (c) 2011 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Cosimo Cecchi <cosimoc@redhat.com>
- *
- */
-
-#include "gd-two-lines-renderer.h"
-#include <string.h>
-
-#define SUBTITLE_DIM_PERCENTAGE 0.55
-#define SUBTITLE_SIZE_PERCENTAGE 0.82
-
-G_DEFINE_TYPE (GdTwoLinesRenderer, gd_two_lines_renderer, GTK_TYPE_CELL_RENDERER_TEXT)
-
-struct _GdTwoLinesRendererPrivate {
- gchar *line_two;
- gint text_lines;
-};
-
-enum {
- PROP_TEXT_LINES = 1,
- PROP_LINE_TWO,
- NUM_PROPERTIES
-};
-
-static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
-
-static PangoLayout *
-create_layout_with_attrs (GtkWidget *widget,
- const GdkRectangle *cell_area,
- GdTwoLinesRenderer *self,
- PangoEllipsizeMode ellipsize)
-{
- PangoLayout *layout;
- gint wrap_width, xpad;
- PangoWrapMode wrap_mode;
- PangoAlignment alignment;
-
- g_object_get (self,
- "wrap-width", &wrap_width,
- "wrap-mode", &wrap_mode,
- "alignment", &alignment,
- "xpad", &xpad,
- NULL);
-
- layout = pango_layout_new (gtk_widget_get_pango_context (widget));
-
- pango_layout_set_ellipsize (layout, ellipsize);
- pango_layout_set_alignment (layout, alignment);
-
- if (wrap_width != -1)
- {
- pango_layout_set_width (layout, wrap_width * PANGO_SCALE);
- pango_layout_set_wrap (layout, wrap_mode);
- }
- else
- {
- if (cell_area != NULL)
- pango_layout_set_width (layout, (cell_area->width - 2 * xpad) * PANGO_SCALE);
- else
- pango_layout_set_width (layout, -1);
-
- pango_layout_set_wrap (layout, PANGO_WRAP_CHAR);
- }
-
- return layout;
-}
-
-static void
-apply_subtitle_style_to_layout (GtkStyleContext *context,
- PangoLayout *layout,
- GtkStateFlags flags)
-{
- PangoFontDescription *desc;
- PangoAttrList *layout_attr;
- PangoAttribute *attr_alpha;
-
- gtk_style_context_save (context);
- gtk_style_context_set_state (context, flags);
- gtk_style_context_get (context, gtk_style_context_get_state (context),
- "font", &desc,
- NULL);
- gtk_style_context_restore (context);
-
- /* Set the font size */
- pango_font_description_set_size (desc, pango_font_description_get_size (desc) * SUBTITLE_SIZE_PERCENTAGE);
- pango_layout_set_font_description (layout, desc);
- pango_font_description_free (desc);
-
- /* Set the font alpha */
- layout_attr = pango_attr_list_new ();
- attr_alpha = pango_attr_foreground_alpha_new (SUBTITLE_DIM_PERCENTAGE * 65535);
- pango_attr_list_insert (layout_attr, attr_alpha);
-
- pango_layout_set_attributes (layout, layout_attr);
- pango_attr_list_unref (layout_attr);
-}
-
-static void
-gd_two_lines_renderer_prepare_layouts (GdTwoLinesRenderer *self,
- const GdkRectangle *cell_area,
- GtkWidget *widget,
- PangoLayout **layout_one,
- PangoLayout **layout_two)
-{
- PangoLayout *line_one;
- PangoLayout *line_two = NULL;
- gchar *text = NULL;
-
- g_object_get (self,
- "text", &text,
- NULL);
-
- line_one = create_layout_with_attrs (widget, cell_area,
- self, PANGO_ELLIPSIZE_MIDDLE);
-
- if (self->priv->line_two == NULL ||
- g_strcmp0 (self->priv->line_two, "") == 0)
- {
- pango_layout_set_height (line_one, - (self->priv->text_lines));
-
- if (text != NULL)
- pango_layout_set_text (line_one, text, -1);
- }
- else
- {
- GtkStyleContext *context;
-
- line_two = create_layout_with_attrs (widget, cell_area,
- self, PANGO_ELLIPSIZE_END);
-
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_save (context);
- apply_subtitle_style_to_layout (context, line_two, GTK_STATE_FLAG_NORMAL);
- gtk_style_context_restore (context);
-
- pango_layout_set_height (line_one, - (self->priv->text_lines - 1));
- pango_layout_set_height (line_two, -1);
- pango_layout_set_text (line_two, self->priv->line_two, -1);
-
- if (text != NULL)
- pango_layout_set_text (line_one, text, -1);
- }
-
- if (layout_one)
- *layout_one = line_one;
- if (layout_two)
- *layout_two = line_two;
-
- g_free (text);
-}
-
-static void
-gd_two_lines_renderer_get_size (GtkCellRenderer *cell,
- GtkWidget *widget,
- PangoLayout *layout_1,
- PangoLayout *layout_2,
- gint *width,
- gint *height,
- const GdkRectangle *cell_area,
- gint *x_offset_1,
- gint *x_offset_2,
- gint *y_offset)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- gint xpad, ypad;
- PangoLayout *layout_one, *layout_two;
- GdkRectangle layout_one_rect, layout_two_rect, layout_union;
-
- if (layout_1 == NULL)
- {
- gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
- }
- else
- {
- layout_one = g_object_ref (layout_1);
-
- if (layout_2 != NULL)
- layout_two = g_object_ref (layout_2);
- else
- layout_two = NULL;
- }
-
- gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
- pango_layout_get_pixel_extents (layout_one, NULL, (PangoRectangle *) &layout_one_rect);
-
- if (layout_two != NULL)
- {
- pango_layout_get_pixel_extents (layout_two, NULL, (PangoRectangle *) &layout_two_rect);
-
- layout_union.width = MAX (layout_one_rect.width, layout_two_rect.width);
- layout_union.height = layout_one_rect.height + layout_two_rect.height;
- }
- else
- {
- layout_union = layout_one_rect;
- }
-
- if (cell_area)
- {
- gfloat xalign, yalign;
-
- gtk_cell_renderer_get_alignment (cell, &xalign, &yalign);
-
- layout_union.width = MIN (layout_union.width, cell_area->width - 2 * xpad);
- layout_union.height = MIN (layout_union.height, cell_area->height - 2 * ypad);
-
- if (x_offset_1)
- {
- if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
- *x_offset_1 = (1.0 - xalign) * (cell_area->width - (layout_one_rect.width + (2 * xpad)));
- else
- *x_offset_1 = xalign * (cell_area->width - (layout_one_rect.width + (2 * xpad)));
-
- *x_offset_1 = MAX (*x_offset_1, 0);
- }
- if (x_offset_2)
- {
- if (layout_two != NULL)
- {
- if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
- *x_offset_2 = (1.0 - xalign) * (cell_area->width - (layout_two_rect.width + (2 * xpad)));
- else
- *x_offset_2 = xalign * (cell_area->width - (layout_two_rect.width + (2 * xpad)));
-
- *x_offset_2 = MAX (*x_offset_2, 0);
- }
- else
- {
- *x_offset_2 = 0;
- }
- }
-
- if (y_offset)
- {
- *y_offset = yalign * (cell_area->height - (layout_union.height + (2 * ypad)));
- *y_offset = MAX (*y_offset, 0);
- }
- }
- else
- {
- if (x_offset_1) *x_offset_1 = 0;
- if (x_offset_2) *x_offset_2 = 0;
- if (y_offset) *y_offset = 0;
- }
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-
- if (height)
- *height = ypad * 2 + layout_union.height;
-
- if (width)
- *width = xpad * 2 + layout_union.width;
-}
-
-static void
-gd_two_lines_renderer_render (GtkCellRenderer *cell,
- cairo_t *cr,
- GtkWidget *widget,
- const GdkRectangle *background_area,
- const GdkRectangle *cell_area,
- GtkCellRendererState flags)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- GtkStyleContext *context;
- gint line_one_height;
- GtkStateFlags state;
- GdkRectangle area, render_area = *cell_area;
- gint xpad, ypad, x_offset_1, x_offset_2, y_offset;
- PangoLayout *layout_one, *layout_two;
- PangoRectangle layout_rect;
-
- /* fetch common information */
- context = gtk_widget_get_style_context (widget);
- gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
- gd_two_lines_renderer_get_size (cell, widget,
- layout_one, layout_two,
- NULL, NULL,
- cell_area,
- &x_offset_1, &x_offset_2, &y_offset);
- gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
-
- area = *cell_area;
- area.x += xpad;
- area.y += ypad;
-
- /* now render the first layout */
- pango_layout_get_pixel_extents (layout_one, NULL, &layout_rect);
-
- render_area = area;
- render_area.x += x_offset_1 - layout_rect.x;
-
- gtk_render_layout (context, cr,
- render_area.x,
- render_area.y,
- layout_one);
-
- /* render the second layout */
- if (layout_two != NULL)
- {
- pango_layout_get_pixel_size (layout_one,
- NULL, &line_one_height);
-
- gtk_style_context_save (context);
-
- apply_subtitle_style_to_layout (context, layout_two, flags);
-
- state = gtk_cell_renderer_get_state (cell, widget, flags);
- gtk_style_context_set_state (context, state);
-
- pango_layout_get_pixel_extents (layout_two, NULL, &layout_rect);
-
- render_area = area;
- render_area.x += x_offset_2 - layout_rect.x;
- render_area.y += line_one_height;
-
- gtk_render_layout (context, cr,
- render_area.x,
- render_area.y,
- layout_two);
-
- gtk_style_context_restore (context);
- }
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-}
-
-static void
-gd_two_lines_renderer_get_preferred_width (GtkCellRenderer *cell,
- GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size)
-{
- PangoContext *context;
- PangoFontMetrics *metrics;
- PangoFontDescription *font_desc;
- GtkStyleContext *style_context;
- gint nat_width, min_width;
- gint xpad, char_width, wrap_width, text_width;
- gint width_chars, ellipsize_chars;
-
- g_object_get (cell,
- "xpad", &xpad,
- "width-chars", &width_chars,
- "wrap-width", &wrap_width,
- NULL);
- style_context = gtk_widget_get_style_context (widget);
- gtk_cell_renderer_get_padding (cell, &xpad, NULL);
-
- gd_two_lines_renderer_get_size (cell, widget,
- NULL, NULL,
- &text_width, NULL,
- NULL,
- NULL, NULL, NULL);
-
- /* Fetch the average size of a character */
- context = gtk_widget_get_pango_context (widget);
- gtk_style_context_save (style_context);
- gtk_style_context_set_state (style_context, 0);
- gtk_style_context_get (style_context, gtk_style_context_get_state (style_context),
- "font", &font_desc, NULL);
- gtk_style_context_restore (style_context);
- metrics = pango_context_get_metrics (context, font_desc,
- pango_context_get_language (context));
-
- char_width = pango_font_metrics_get_approximate_char_width (metrics);
-
- pango_font_metrics_unref (metrics);
- pango_font_description_free (font_desc);
-
- /* enforce minimum width for ellipsized labels at ~3 chars */
- ellipsize_chars = 3;
-
- /* If no width-chars set, minimum for wrapping text will be the wrap-width */
- if (wrap_width > -1)
- min_width = xpad * 2 + MIN (text_width, wrap_width);
- else
- min_width = xpad * 2 +
- MIN (text_width,
- (PANGO_PIXELS (char_width) * MAX (width_chars, ellipsize_chars)));
-
- if (width_chars > 0)
- nat_width = xpad * 2 +
- MAX ((PANGO_PIXELS (char_width) * width_chars), text_width);
- else
- nat_width = xpad * 2 + text_width;
-
- nat_width = MAX (nat_width, min_width);
-
- if (minimum_size)
- *minimum_size = min_width;
-
- if (natural_size)
- *natural_size = nat_width;
-}
-
-static void
-gd_two_lines_renderer_get_preferred_height_for_width (GtkCellRenderer *cell,
- GtkWidget *widget,
- gint width,
- gint *minimum_size,
- gint *natural_size)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- PangoLayout *layout_one, *layout_two;
- gint text_height, wrap_width;
- gint xpad, ypad;
-
- gtk_cell_renderer_get_padding (cell, &xpad, &ypad);
- g_object_get (cell, "wrap-width", &wrap_width, NULL);
- gd_two_lines_renderer_prepare_layouts (self, NULL, widget, &layout_one, &layout_two);
-
- if (wrap_width != -1)
- wrap_width = MIN (width - 2 * xpad, wrap_width);
- else
- wrap_width = width - 2 * xpad;
-
- pango_layout_set_width (layout_one, wrap_width);
- if (layout_two != NULL)
- pango_layout_set_width (layout_two, wrap_width);
-
- gd_two_lines_renderer_get_size (cell, widget,
- layout_one, layout_two,
- NULL, &text_height,
- NULL,
- NULL, NULL, NULL);
-
- text_height += 2 * ypad;
-
- if (minimum_size != NULL)
- *minimum_size = text_height;
-
- if (natural_size != NULL)
- *natural_size = text_height;
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-}
-
-static void
-gd_two_lines_renderer_get_preferred_height (GtkCellRenderer *cell,
- GtkWidget *widget,
- gint *minimum_size,
- gint *natural_size)
-{
- gint min_width;
-
- gtk_cell_renderer_get_preferred_width (cell, widget, &min_width, NULL);
- gd_two_lines_renderer_get_preferred_height_for_width (cell, widget, min_width,
- minimum_size, natural_size);
-}
-
-static void
-gd_two_lines_renderer_get_aligned_area (GtkCellRenderer *cell,
- GtkWidget *widget,
- GtkCellRendererState flags,
- const GdkRectangle *cell_area,
- GdkRectangle *aligned_area)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (cell);
- gint x_offset, x_offset_1, x_offset_2, y_offset;
- PangoLayout *layout_one, *layout_two;
-
- /* fetch common information */
- gd_two_lines_renderer_prepare_layouts (self, cell_area, widget, &layout_one, &layout_two);
- gd_two_lines_renderer_get_size (cell, widget,
- layout_one, layout_two,
- &aligned_area->width, &aligned_area->height,
- cell_area,
- &x_offset_1, &x_offset_2, &y_offset);
-
- x_offset = MIN (x_offset_1, x_offset_2);
-
- aligned_area->x = cell_area->x + x_offset;
- aligned_area->y = cell_area->y;
-
- g_clear_object (&layout_one);
- g_clear_object (&layout_two);
-}
-
-static void
-gd_two_lines_renderer_set_line_two (GdTwoLinesRenderer *self,
- const gchar *line_two)
-{
- if (g_strcmp0 (self->priv->line_two, line_two) == 0)
- return;
-
- g_free (self->priv->line_two);
- self->priv->line_two = g_strdup (line_two);
-
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LINE_TWO]);
-}
-
-static void
-gd_two_lines_renderer_set_text_lines (GdTwoLinesRenderer *self,
- gint text_lines)
-{
- if (self->priv->text_lines == text_lines)
- return;
-
- self->priv->text_lines = text_lines;
- g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TEXT_LINES]);
-}
-
-static void
-gd_two_lines_renderer_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
-
- switch (property_id)
- {
- case PROP_TEXT_LINES:
- gd_two_lines_renderer_set_text_lines (self, g_value_get_int (value));
- break;
- case PROP_LINE_TWO:
- gd_two_lines_renderer_set_line_two (self, g_value_get_string (value));
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gd_two_lines_renderer_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
-
- switch (property_id)
- {
- case PROP_TEXT_LINES:
- g_value_set_int (value, self->priv->text_lines);
- break;
- case PROP_LINE_TWO:
- g_value_set_string (value, self->priv->line_two);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- break;
- }
-}
-
-static void
-gd_two_lines_renderer_finalize (GObject *object)
-{
- GdTwoLinesRenderer *self = GD_TWO_LINES_RENDERER (object);
-
- g_free (self->priv->line_two);
-
- G_OBJECT_CLASS (gd_two_lines_renderer_parent_class)->finalize (object);
-}
-
-static void
-gd_two_lines_renderer_class_init (GdTwoLinesRendererClass *klass)
-{
- GtkCellRendererClass *cclass = GTK_CELL_RENDERER_CLASS (klass);
- GObjectClass *oclass = G_OBJECT_CLASS (klass);
-
- cclass->render = gd_two_lines_renderer_render;
- cclass->get_preferred_width = gd_two_lines_renderer_get_preferred_width;
- cclass->get_preferred_height = gd_two_lines_renderer_get_preferred_height;
- cclass->get_preferred_height_for_width = gd_two_lines_renderer_get_preferred_height_for_width;
- cclass->get_aligned_area = gd_two_lines_renderer_get_aligned_area;
-
- oclass->set_property = gd_two_lines_renderer_set_property;
- oclass->get_property = gd_two_lines_renderer_get_property;
- oclass->finalize = gd_two_lines_renderer_finalize;
-
- properties[PROP_TEXT_LINES] =
- g_param_spec_int ("text-lines",
- "Lines of text",
- "The total number of lines to be displayed",
- 2, G_MAXINT, 2,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- properties[PROP_LINE_TWO] =
- g_param_spec_string ("line-two",
- "Second line",
- "Second line",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- g_type_class_add_private (klass, sizeof (GdTwoLinesRendererPrivate));
- g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
-}
-
-static void
-gd_two_lines_renderer_init (GdTwoLinesRenderer *self)
-{
- self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GD_TYPE_TWO_LINES_RENDERER,
- GdTwoLinesRendererPrivate);
-}
-
-GtkCellRenderer *
-gd_two_lines_renderer_new (void)
-{
- return g_object_new (GD_TYPE_TWO_LINES_RENDERER, NULL);
-}
diff --git a/lib/widgets/contrib/gd-two-lines-renderer.h b/lib/widgets/contrib/gd-two-lines-renderer.h
deleted file mode 100644
index 23bf70f08..000000000
--- a/lib/widgets/contrib/gd-two-lines-renderer.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (c) 2011 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Author: Cosimo Cecchi <cosimoc@redhat.com>
- *
- */
-
-#ifndef _GD_TWO_LINES_RENDERER_H
-#define _GD_TWO_LINES_RENDERER_H
-
-#include <glib-object.h>
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define GD_TYPE_TWO_LINES_RENDERER gd_two_lines_renderer_get_type()
-
-#define GD_TWO_LINES_RENDERER(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRenderer))
-
-#define GD_TWO_LINES_RENDERER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST ((klass), \
- GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass))
-
-#define GD_IS_TWO_LINES_RENDERER(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- GD_TYPE_TWO_LINES_RENDERER))
-
-#define GD_IS_TWO_LINES_RENDERER_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE ((klass), \
- GD_TYPE_TWO_LINES_RENDERER))
-
-#define GD_TWO_LINES_RENDERER_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), \
- GD_TYPE_TWO_LINES_RENDERER, GdTwoLinesRendererClass))
-
-typedef struct _GdTwoLinesRenderer GdTwoLinesRenderer;
-typedef struct _GdTwoLinesRendererClass GdTwoLinesRendererClass;
-typedef struct _GdTwoLinesRendererPrivate GdTwoLinesRendererPrivate;
-
-struct _GdTwoLinesRenderer
-{
- GtkCellRendererText parent;
-
- GdTwoLinesRendererPrivate *priv;
-};
-
-struct _GdTwoLinesRendererClass
-{
- GtkCellRendererTextClass parent_class;
-};
-
-GType gd_two_lines_renderer_get_type (void) G_GNUC_CONST;
-
-GtkCellRenderer *gd_two_lines_renderer_new (void);
-
-G_END_DECLS
-
-#endif /* _GD_TWO_LINES_RENDERER_H */
diff --git a/lib/widgets/ephy-location-entry.c b/lib/widgets/ephy-location-entry.c
index 74b590f9c..472d0ab66 100644
--- a/lib/widgets/ephy-location-entry.c
+++ b/lib/widgets/ephy-location-entry.c
@@ -31,10 +31,11 @@
#include "ephy-gui.h"
#include "ephy-lib-type-builtins.h"
#include "ephy-signal-accumulator.h"
+#include "ephy-suggestion.h"
#include "ephy-title-widget.h"
#include "ephy-uri-helpers.h"
-#include "gd-two-lines-renderer.h"
+#include <dazzle.h>
#include <gdk/gdkkeysyms.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
@@ -54,7 +55,7 @@
*/
struct _EphyLocationEntry {
- GtkEntry parent_instance;
+ DzlSuggestionEntry parent_instance;
GtkTreeModel *model;
@@ -91,12 +92,6 @@ struct _EphyLocationEntry {
static gboolean ephy_location_entry_reset_internal (EphyLocationEntry *, gboolean);
-static void extracell_data_func (GtkCellLayout *cell_layout,
- GtkCellRenderer *cell,
- GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gpointer data);
-
enum {
PROP_0,
PROP_ADDRESS,
@@ -115,11 +110,17 @@ static gint signals[LAST_SIGNAL] = { 0 };
static void ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface);
-G_DEFINE_TYPE_WITH_CODE (EphyLocationEntry, ephy_location_entry, GTK_TYPE_ENTRY,
+G_DEFINE_TYPE_WITH_CODE (EphyLocationEntry, ephy_location_entry, DZL_TYPE_SUGGESTION_ENTRY,
G_IMPLEMENT_INTERFACE (EPHY_TYPE_TITLE_WIDGET,
ephy_location_entry_title_widget_interface_init))
static void
+ephy_location_entry_activate (EphyLocationEntry *entry)
+{
+ g_signal_emit_by_name (entry, "activate");
+}
+
+static void
update_address_state (EphyLocationEntry *entry)
{
const char *text;
@@ -273,8 +274,12 @@ ephy_location_entry_get_property (GObject *object,
static void
ephy_location_entry_constructed (GObject *object)
{
+ EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (object);
+
G_OBJECT_CLASS (ephy_location_entry_parent_class)->constructed (object);
+ dzl_suggestion_entry_set_position_func (DZL_SUGGESTION_ENTRY (entry), dzl_suggestion_entry_window_position_func, NULL, NULL);
+
#if GTK_CHECK_VERSION(3, 22, 20)
gtk_entry_set_input_hints (GTK_ENTRY (object), GTK_INPUT_HINT_NO_EMOJI);
#endif
@@ -361,6 +366,16 @@ ephy_location_entry_cut_clipboard (GtkEntry *entry)
}
static void
+ephy_location_entry_suggestion_activated (DzlSuggestionEntry *entry,
+ DzlSuggestion *suggestion)
+{
+ gtk_entry_set_text (GTK_ENTRY (entry), ephy_suggestion_get_uri (EPHY_SUGGESTION (suggestion)));
+
+ /* Now trigger the load.... */
+ ephy_location_entry_activate (EPHY_LOCATION_ENTRY (entry));
+}
+
+static void
ephy_location_entry_title_widget_interface_init (EphyTitleWidgetInterface *iface)
{
iface->get_address = ephy_location_entry_title_widget_get_address;
@@ -375,7 +390,9 @@ ephy_location_entry_class_init (EphyLocationEntryClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
GtkEntryClass *entry_class = GTK_ENTRY_CLASS (klass);
+ DzlSuggestionEntryClass *dzl_entry_class = DZL_SUGGESTION_ENTRY_CLASS (klass);
+ object_class->constructed = ephy_location_entry_constructed;
object_class->get_property = ephy_location_entry_get_property;
object_class->set_property = ephy_location_entry_set_property;
object_class->constructed = ephy_location_entry_constructed;
@@ -387,6 +404,8 @@ ephy_location_entry_class_init (EphyLocationEntryClass *klass)
entry_class->copy_clipboard = ephy_location_entry_copy_clipboard;
entry_class->cut_clipboard = ephy_location_entry_cut_clipboard;
+ dzl_entry_class->suggestion_activated = ephy_location_entry_suggestion_activated;
+
g_object_class_override_property (object_class, PROP_ADDRESS, "address");
g_object_class_override_property (object_class, PROP_SECURITY_LEVEL, "security-level");
@@ -488,103 +507,18 @@ entry_key_press_cb (GtkEntry *entry,
/* Make sure the location is activated on CTRL+l even when the
* completion popup is shown and have an active keyboard grab.
*/
- ephy_location_entry_activate (location_entry);
- }
-
- return FALSE;
-}
-
-static gboolean
-entry_key_press_after_cb (GtkEntry *entry,
- GdkEventKey *event,
- EphyLocationEntry *lentry)
-{
- guint state = event->state & gtk_accelerator_get_default_mod_mask ();
-
- if ((event->keyval == GDK_KEY_Return ||
- event->keyval == GDK_KEY_KP_Enter ||
- event->keyval == GDK_KEY_ISO_Enter) &&
- (state == GDK_CONTROL_MASK ||
- state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))) {
- /* gtk_im_context_reset (entry->im_context); */
-
- lentry->needs_reset = TRUE;
- g_signal_emit_by_name (entry, "activate");
-
- return TRUE;
+ ephy_location_entry_focus (location_entry);
}
- if ((event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down)
- && state == 0) {
- /* If we are focusing the entry, with the cursor at the end of it
- * we emit the changed signal, so that the completion popup appears */
- const char *string;
-
- string = gtk_entry_get_text (entry);
- if (gtk_editable_get_position (GTK_EDITABLE (entry)) == (int)strlen (string)) {
- g_signal_emit_by_name (entry, "changed", 0);
- return TRUE;
- }
- }
+ if (event->keyval == GDK_KEY_Return ||
+ event->keyval == GDK_KEY_KP_Enter ||
+ event->keyval == GDK_KEY_ISO_Enter)
+ ephy_location_entry_activate (location_entry);
return FALSE;
}
static void
-entry_activate_after_cb (GtkEntry *entry,
- EphyLocationEntry *lentry)
-{
- lentry->user_changed = FALSE;
-
- if (lentry->needs_reset) {
- ephy_location_entry_reset_internal (lentry, TRUE);
- lentry->needs_reset = FALSE;
- }
-}
-
-static gboolean
-match_selected_cb (GtkEntryCompletion *completion,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- EphyLocationEntry *entry)
-{
- char *item = NULL;
- guint state;
-
- gtk_tree_model_get (model, iter,
- entry->action_col, &item, -1);
- if (item == NULL) return FALSE;
-
- ephy_gui_get_current_event (NULL, &state, NULL);
-
- entry->needs_reset = (state == GDK_CONTROL_MASK ||
- state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK));
-
- ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), item);
- /* gtk_im_context_reset (GTK_ENTRY (entry)->im_context); */
- g_signal_emit_by_name (entry, "activate");
-
- g_free (item);
-
- return TRUE;
-}
-
-static void
-action_activated_after_cb (GtkEntryCompletion *completion,
- gint index,
- EphyLocationEntry *lentry)
-{
- guint state, button;
-
- ephy_gui_get_current_event (NULL, &state, &button);
- if ((state == GDK_CONTROL_MASK ||
- state == (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) ||
- button == 2) {
- ephy_location_entry_reset_internal (lentry, TRUE);
- }
-}
-
-static void
entry_clear_activate_cb (GtkMenuItem *item,
EphyLocationEntry *entry)
{
@@ -601,7 +535,7 @@ paste_received (GtkClipboard *clipboard,
{
if (text) {
gtk_entry_set_text (GTK_ENTRY (entry), text);
- g_signal_emit_by_name (entry, "activate");
+ ephy_location_entry_activate (entry);
}
}
@@ -758,11 +692,6 @@ ephy_location_entry_construct_contents (EphyLocationEntry *lentry)
"signal::key-press-event", G_CALLBACK (entry_key_press_cb), lentry,
"signal::changed", G_CALLBACK (editable_changed_cb), lentry,
NULL);
-
- g_signal_connect_after (entry, "key-press-event",
- G_CALLBACK (entry_key_press_after_cb), lentry);
- g_signal_connect_after (entry, "activate",
- G_CALLBACK (entry_activate_after_cb), lentry);
}
static void
@@ -839,238 +768,6 @@ schedule_dns_prefetch (EphyLocationEntry *entry, guint interval, const gchar *ur
}
#endif
-static gboolean
-cursor_on_match_cb (GtkEntryCompletion *completion,
- GtkTreeModel *model,
- GtkTreeIter *iter,
- EphyLocationEntry *le)
-{
- char *url = NULL;
- GtkWidget *entry;
-
- gtk_tree_model_get (model, iter,
- le->url_col,
- &url, -1);
- entry = gtk_entry_completion_get_entry (completion);
-
- /* Prevent the update so we keep the highlight from our input.
- * See textcell_data_func().
- */
- le->block_update = TRUE;
- gtk_entry_set_text (GTK_ENTRY (entry), url);
- gtk_editable_set_position (GTK_EDITABLE (entry), -1);
- le->block_update = FALSE;
-
-#if 0
-/* FIXME: Refactor the DNS prefetch, this is a layering violation */
- schedule_dns_prefetch (le, 250, (const gchar *)url);
-#endif
-
- g_free (url);
-
- return TRUE;
-}
-
-static void
-extracell_data_func (GtkCellLayout *cell_layout,
- GtkCellRenderer *cell,
- GtkTreeModel *tree_model,
- GtkTreeIter *iter,
- gpointer data)
-{
- EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (data);
- gboolean is_bookmark = FALSE;
- GValue visible = { 0, };
-
- gtk_tree_model_get (tree_model, iter,
- entry->extra_col, &is_bookmark,
- -1);
-
- if (is_bookmark)
- g_object_set (cell,
- "icon-name", "user-bookmarks-symbolic",
- NULL);
-
- g_value_init (&visible, G_TYPE_BOOLEAN);
- g_value_set_boolean (&visible, is_bookmark);
- g_object_set_property (G_OBJECT (cell), "visible", &visible);
- g_value_unset (&visible);
-}
-
-/**
- * ephy_location_entry_set_match_func:
- * @entry: an #EphyLocationEntry widget
- * @match_func: a #GtkEntryCompletionMatchFunc
- * @user_data: user_data to pass to the @match_func
- * @notify: a #GDestroyNotify, like the one given to
- * gtk_entry_completion_set_match_func
- *
- * Sets the match_func for the internal #GtkEntryCompletion to @match_func.
- *
- **/
-void
-ephy_location_entry_set_match_func (EphyLocationEntry *entry,
- GtkEntryCompletionMatchFunc match_func,
- gpointer user_data,
- GDestroyNotify notify)
-{
- GtkEntryCompletion *completion;
-
- completion = gtk_entry_get_completion (GTK_ENTRY (entry));
- gtk_entry_completion_set_match_func (completion, match_func, user_data, notify);
-}
-
-/**
- * ephy_location_entry_set_completion:
- * @entry: an #EphyLocationEntry widget
- * @model: the #GtkModel for the completion
- * @text_col: column id to access #GtkModel relevant data
- * @action_col: column id to access #GtkModel relevant data
- * @keywords_col: column id to access #GtkModel relevant data
- * @relevance_col: column id to access #GtkModel relevant data
- * @url_col: column id to access #GtkModel relevant data
- * @extra_col: column id to access #GtkModel relevant data
- * @favicon_col: column id to access #GtkModel relevant data
- *
- * Initializes @entry to have a #GtkEntryCompletion using @model as the
- * internal #GtkModel. The *_col arguments are for internal data retrieval from
- * @model, like when setting the text property of one of the #GtkCellRenderer
- * of the completion.
- *
- **/
-void
-ephy_location_entry_set_completion (EphyLocationEntry *entry,
- GtkTreeModel *model,
- guint text_col,
- guint action_col,
- guint keywords_col,
- guint relevance_col,
- guint url_col,
- guint extra_col,
- guint favicon_col)
-{
- GtkEntryCompletion *completion;
- GtkCellRenderer *cell;
-
- entry->text_col = text_col;
- entry->action_col = action_col;
- entry->keywords_col = keywords_col;
- entry->relevance_col = relevance_col;
- entry->url_col = url_col;
- entry->extra_col = extra_col;
- entry->favicon_col = favicon_col;
-
- completion = gtk_entry_completion_new ();
- gtk_entry_completion_set_model (completion, model);
- g_signal_connect (completion, "match-selected",
- G_CALLBACK (match_selected_cb), entry);
- g_signal_connect_after (completion, "action-activated",
- G_CALLBACK (action_activated_after_cb), entry);
-
- cell = gtk_cell_renderer_pixbuf_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
- cell, FALSE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
- cell, "pixbuf", favicon_col);
-
- /* Pixel-perfect aligment with the location entry favicon
- * (16x16). Consider that this /might/ depend on the theme.
- *
- * The GtkEntryCompletion can not be themed so we work-around
- * that with padding and fixed sizes.
- * For the first cell, this is:
- *
- * ___+++++iiiiiiiiiiiiiiii++__ttt...bbb++++++__
- *
- * _ = widget spacing, can not be handled (3 px)
- * + = padding (5 px) (ICON_PADDING_LEFT)
- * i = the icon (16 px) (ICON_CONTENT_WIDTH)
- * + = padding (2 px) (ICON_PADDING_RIGHT) (cut by the fixed_size)
- * _ = spacing between cells, can not be handled (2 px)
- * t = the text (expands)
- * b = bookmark icon (16 px)
- * + = padding (6 px) (BKMK_PADDING_RIGHT)
- * _ = widget spacing, can not be handled (2 px)
- *
- * Each character is a pixel.
- *
- * The text cell and the bookmark icon cell are much more
- * flexible in its aligment, because they do not have to align
- * with anything in the entry.
- */
-
-#define ROW_PADDING_VERT 4
-
-#define ICON_PADDING_LEFT 5
-#define ICON_CONTENT_WIDTH 16
-#define ICON_PADDING_RIGHT 9
-
-#define ICON_CONTENT_HEIGHT 16
-
-#define TEXT_PADDING_LEFT 0
-
-#define BKMK_PADDING_RIGHT 6
-
- gtk_cell_renderer_set_padding
- (cell, ICON_PADDING_LEFT, ROW_PADDING_VERT);
- gtk_cell_renderer_set_fixed_size
- (cell,
- (ICON_PADDING_LEFT + ICON_CONTENT_WIDTH + ICON_PADDING_RIGHT),
- ICON_CONTENT_HEIGHT);
- gtk_cell_renderer_set_alignment (cell, 0.0, 0.5);
-
- cell = gd_two_lines_renderer_new ();
- g_object_set (cell,
- "ellipsize", PANGO_ELLIPSIZE_END,
- "text-lines", 2,
- NULL);
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
- cell, TRUE);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
- cell, "text", text_col);
- gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
- cell, "line-two", url_col);
-
- /* Pixel-perfect aligment with the text in the location entry.
- * See above.
- */
- gtk_cell_renderer_set_padding
- (cell, TEXT_PADDING_LEFT, ROW_PADDING_VERT);
- gtk_cell_renderer_set_alignment (cell, 0.0, 0.5);
-
- /*
- * As the width of the entry completion is known in advance
- * (as big as the entry you are completing on), we can set
- * any fixed width (the 1 is just this random number here)
- * Since the height is known too, we avoid computing the actual
- * sizes of the cells, which takes a lot of CPU time and does
- * not get used anyway.
- */
- gtk_cell_renderer_set_fixed_size (cell, 1, -1);
- gtk_cell_renderer_text_set_fixed_height_from_font (GTK_CELL_RENDERER_TEXT (cell), 2);
-
- cell = gtk_cell_renderer_pixbuf_new ();
- g_object_set (cell, "follow-state", TRUE, NULL);
- gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (completion),
- cell, FALSE);
- gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (completion),
- cell, extracell_data_func,
- entry,
- NULL);
-
- /* Pixel-perfect aligment. This just keeps the same margin from
- * the border than the favicon on the other side. See above. */
- gtk_cell_renderer_set_padding
- (cell, BKMK_PADDING_RIGHT, ROW_PADDING_VERT);
-
- g_object_set (completion, "inline-selection", TRUE, NULL);
- g_signal_connect (completion, "cursor-on-match",
- G_CALLBACK (cursor_on_match_cb), entry);
-
- gtk_entry_set_completion (GTK_ENTRY (entry), completion);
- g_object_unref (completion);
-}
-
/**
* ephy_location_entry_get_can_undo:
* @entry: an #EphyLocationEntry widget
@@ -1125,9 +822,8 @@ ephy_location_entry_reset_internal (EphyLocationEntry *entry,
ephy_title_widget_set_address (EPHY_TITLE_WIDGET (entry), text);
g_free (url);
- if (notify) {
+ if (notify)
g_signal_emit (entry, signals[USER_CHANGED], 0);
- }
entry->user_changed = FALSE;
@@ -1167,7 +863,7 @@ ephy_location_entry_reset (EphyLocationEntry *entry)
}
/**
- * ephy_location_entry_activate:
+ * ephy_location_entry_focus:
* @entry: an #EphyLocationEntry widget
*
* Set focus on @entry and select the text whithin. This is called when the
@@ -1175,7 +871,7 @@ ephy_location_entry_reset (EphyLocationEntry *entry)
*
**/
void
-ephy_location_entry_activate (EphyLocationEntry *entry)
+ephy_location_entry_focus (EphyLocationEntry *entry)
{
GtkWidget *toplevel, *widget = GTK_WIDGET (entry);
diff --git a/lib/widgets/ephy-location-entry.h b/lib/widgets/ephy-location-entry.h
index 490524a09..950d06158 100644
--- a/lib/widgets/ephy-location-entry.h
+++ b/lib/widgets/ephy-location-entry.h
@@ -23,6 +23,7 @@
#pragma once
+#include <dazzle.h>
#include <gtk/gtk.h>
#include "ephy-security-levels.h"
@@ -31,7 +32,7 @@ G_BEGIN_DECLS
#define EPHY_TYPE_LOCATION_ENTRY (ephy_location_entry_get_type())
-G_DECLARE_FINAL_TYPE (EphyLocationEntry, ephy_location_entry, EPHY, LOCATION_ENTRY, GtkEntry)
+G_DECLARE_FINAL_TYPE (EphyLocationEntry, ephy_location_entry, EPHY, LOCATION_ENTRY, DzlSuggestionEntry)
typedef enum {
EPHY_LOCATION_ENTRY_BOOKMARK_ICON_HIDDEN,
@@ -41,21 +42,6 @@ typedef enum {
GtkWidget *ephy_location_entry_new (void);
-void ephy_location_entry_set_completion (EphyLocationEntry *entry,
- GtkTreeModel *model,
- guint text_col,
- guint action_col,
- guint keywords_col,
- guint relevance_col,
- guint url_col,
- guint extra_col,
- guint favicon_col);
-
-void ephy_location_entry_set_match_func (EphyLocationEntry *entry,
- GtkEntryCompletionMatchFunc match_func,
- gpointer user_data,
- GDestroyNotify notify);
-
gboolean ephy_location_entry_get_can_undo (EphyLocationEntry *entry);
gboolean ephy_location_entry_get_can_redo (EphyLocationEntry *entry);
@@ -66,7 +52,7 @@ gboolean ephy_location_entry_reset (EphyLocationEntr
void ephy_location_entry_undo_reset (EphyLocationEntry *entry);
-void ephy_location_entry_activate (EphyLocationEntry *entry);
+void ephy_location_entry_focus (EphyLocationEntry *entry);
void ephy_location_entry_set_bookmark_icon_state (EphyLocationEntry *entry,
EphyLocationEntryBookmarkIconState state);
diff --git a/lib/widgets/meson.build b/lib/widgets/meson.build
index 1c5c8492d..c927648d3 100644
--- a/lib/widgets/meson.build
+++ b/lib/widgets/meson.build
@@ -7,7 +7,6 @@ enums = gnome.mkenums_simple('ephy-widgets-type-builtins',
)
libephywidgets_sources = [
- 'contrib/gd-two-lines-renderer.c',
'contrib/nautilus-floating-bar.c',
'ephy-certificate-dialog.c',
'ephy-downloads-popover.c',
@@ -30,6 +29,7 @@ libephywidgets_deps = [
gio_dep,
glib_dep,
gtk_dep,
+ libdazzle_dep,
libsoup_dep,
webkit2gtk_dep
]