[goffice] Optimize GtkWidget embedding in the canvas. See #465.
- From: Jean Bréfort <jbrefort src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goffice] Optimize GtkWidget embedding in the canvas. See #465.
- Date: Mon, 1 Jun 2020 15:50:30 +0000 (UTC)
commit 40e1716493b484c573f49945a60be071a6c875ba
Author: Jean Brefort <jean brefort normalesup org>
Date: Mon Jun 1 17:49:49 2020 +0200
Optimize GtkWidget embedding in the canvas. See #465.
ChangeLog | 8 +++
NEWS | 1 +
goffice/canvas/goc-canvas.c | 3 ++
goffice/canvas/goc-widget.c | 122 ++++++++++++++++++++++++++------------------
4 files changed, 83 insertions(+), 51 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index e8a1b528..55456034 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2020-06-01 Jean Brefort <jean brefort normalesup org>
+
+ * goffice/canvas/goc-canvas.c (size_changed_cb): optimize GtkWidget
+ embedding in the canvas. See #465.
+ * goffice/canvas/goc-widget.c (goc_widget_connect_signals),
+ (goc_widget_notify_scrolled), (cb_canvas_changed),
+ (goc_widget_set_widget), (goc_widget_draw):
+
2020-05-27 Jean Brefort <jean brefort normalesup org>
* plugins/reg_logfit/gog-logfit.c (gog_log_fit_curve_update): don't emit a
diff --git a/NEWS b/NEWS
index 01a76d89..1812d90f 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Jean:
* Avoid serializing empty graph data. [#46]
* Clip data labels in XY plots. [#47]
* Don't emit a critical for invalid series in Logarithmic fit. [#49]
+ * Optimize GtkWidget embedding in the canvas. See #465.
--------------------------------------------------------------------------
goffice 0.10.47:
diff --git a/goffice/canvas/goc-canvas.c b/goffice/canvas/goc-canvas.c
index eac4c93b..31443b00 100644
--- a/goffice/canvas/goc-canvas.c
+++ b/goffice/canvas/goc-canvas.c
@@ -271,8 +271,11 @@ leave_notify_cb (GocCanvas *canvas, GdkEventCrossing* event, G_GNUC_UNUSED gpoin
static void
size_changed_cb (GocCanvas *canvas, GtkAllocation *alloc, G_GNUC_UNUSED gpointer data)
{
+ GocItemClass *klass = GOC_ITEM_GET_CLASS (canvas->root);
canvas->width = alloc->width;
canvas->height = alloc->height;
+ /* we need to call notify_scroll() to show or hide widgets if necessary */
+ klass->notify_scrolled (GOC_ITEM (canvas->root));
}
static void
diff --git a/goffice/canvas/goc-widget.c b/goffice/canvas/goc-widget.c
index 9edb865a..009b6925 100644
--- a/goffice/canvas/goc-widget.c
+++ b/goffice/canvas/goc-widget.c
@@ -503,6 +503,33 @@ goc_widget_update_bounds (GocItem *item)
item->y1 = widget->y + widget->h;
}
+static void
+goc_widget_connect_signals (GtkWidget *widget, GocWidget *item,
+ gboolean do_connect)
+{
+ if (GTK_IS_CONTAINER (widget)) {
+ GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
+ GList *ptr;
+ for (ptr = children; ptr; ptr = ptr->next) {
+ GtkWidget *child = ptr->data;
+ goc_widget_connect_signals (child, item, do_connect);
+ }
+ g_list_free (children);
+ }
+
+ if (do_connect) {
+ g_signal_connect (widget, "enter-notify-event",
+ G_CALLBACK (enter_notify_cb), item);
+ g_signal_connect (widget, "button-press-event",
+ G_CALLBACK (button_press_cb), item);
+ } else {
+ g_signal_handlers_disconnect_by_func
+ (widget, G_CALLBACK (enter_notify_cb), item);
+ g_signal_handlers_disconnect_by_func
+ (widget, G_CALLBACK (button_press_cb), item);
+ }
+}
+
static void
goc_widget_notify_scrolled (GocItem *item)
{
@@ -546,9 +573,6 @@ goc_widget_notify_scrolled (GocItem *item)
}
y0 = (y0 - item->canvas->scroll_y1) * item->canvas->pixels_per_unit;
y1 = (y1 - item->canvas->scroll_y1) * item->canvas->pixels_per_unit;
- goc_offscreen_box_set_scale (GOC_OFFSCREEN_BOX (widget->ofbox),
- item->canvas->pixels_per_unit * widget->scale);
- gtk_widget_set_size_request (widget->ofbox, go_fake_floor (x1 - x0), go_fake_floor (y1 - y0));
/* ensure we don't wrap throught he infinite */
if (x0 < G_MININT)
x0 = G_MININT;
@@ -558,58 +582,62 @@ goc_widget_notify_scrolled (GocItem *item)
y0 = G_MININT;
else if (y1 > G_MAXINT)
y0 -= y1 - G_MAXINT;
- gtk_layout_move (GTK_LAYOUT (item->canvas), widget->ofbox, x0, y0);
+ if (x1 >= 0 && x0 <= item->canvas->width && y1 >= 0 && y0 <= item->canvas->height) {
+ if (widget->ofbox) {
+ goc_offscreen_box_set_scale (GOC_OFFSCREEN_BOX (widget->ofbox),
+ item->canvas->pixels_per_unit * widget->scale);
+ gtk_widget_set_size_request (widget->ofbox, go_fake_floor (x1 - x0), go_fake_floor
(y1 - y0));
+ gtk_layout_move (GTK_LAYOUT (item->canvas), widget->ofbox, x0, y0);
+ } else {
+ gtk_widget_show (widget->widget);
+ widget->ofbox = GTK_WIDGET (g_object_new (GOC_TYPE_OFFSCREEN_BOX, NULL));
+ gtk_container_add (GTK_CONTAINER (widget->ofbox), widget->widget);
+ gtk_widget_show (widget->ofbox);
+ g_object_ref (widget->ofbox);
+ goc_offscreen_box_set_scale (GOC_OFFSCREEN_BOX (widget->ofbox),
+ item->canvas->pixels_per_unit * widget->scale);
+ gtk_widget_set_size_request (widget->ofbox, go_fake_floor (x1 - x0), go_fake_floor
(y1 - y0));
+ gtk_layout_put (GTK_LAYOUT (item->canvas),
+ widget->ofbox, x0, y0);
+ /* we need to propagate some signals to the parent item */
+ goc_widget_connect_signals (widget->widget, widget, TRUE);
+ }
+ } else if (widget->ofbox) {
+ GtkWidget *parent = gtk_widget_get_parent (widget->ofbox);
+ if (parent) {
+ gtk_container_remove (GTK_CONTAINER (widget->ofbox), widget->widget);
+ goc_widget_connect_signals (widget->widget, widget, FALSE);
+ gtk_widget_hide (widget->widget);
+ gtk_container_remove (GTK_CONTAINER (parent), widget->ofbox);
+ }
+ g_object_unref (widget->ofbox);
+ widget->ofbox = NULL;
+ }
}
static void
cb_canvas_changed (GocWidget *item, G_GNUC_UNUSED GParamSpec *pspec,
G_GNUC_UNUSED gpointer user)
{
- GtkWidget *parent, *w = item->ofbox;
+ GtkWidget *parent, *box = item->ofbox, *w = item->widget;
GocItem *gitem = (GocItem *)item;
- if (!w || !GTK_IS_WIDGET (w))
+ if (!box || !GTK_IS_WIDGET (box))
return;
- parent = gtk_widget_get_parent (w);
+ parent = gtk_widget_get_parent (box);
if (parent == (GtkWidget *)gitem->canvas)
return;
- g_object_ref (w);
- if (parent)
- gtk_container_remove (GTK_CONTAINER (parent), w);
- if (gitem->canvas)
- gtk_layout_put (GTK_LAYOUT (gitem->canvas), w,
- item->x, item->y);
+ if (parent) {
+ gtk_container_remove (GTK_CONTAINER (box), w);
+ goc_widget_connect_signals (w, item, FALSE);
+ gtk_widget_hide (w);
+ gtk_container_remove (GTK_CONTAINER (parent), box);
+ g_object_unref (box);
+ item->ofbox = NULL;
+ }
goc_widget_notify_scrolled (GOC_ITEM (item));
- g_object_unref (w);
-}
-
-static void
-goc_widget_connect_signals (GtkWidget *widget, GocWidget *item,
- gboolean do_connect)
-{
- if (GTK_IS_CONTAINER (widget)) {
- GList *children = gtk_container_get_children (GTK_CONTAINER (widget));
- GList *ptr;
- for (ptr = children; ptr; ptr = ptr->next) {
- GtkWidget *child = ptr->data;
- goc_widget_connect_signals (child, item, do_connect);
- }
- g_list_free (children);
- }
-
- if (do_connect) {
- g_signal_connect (widget, "enter-notify-event",
- G_CALLBACK (enter_notify_cb), item);
- g_signal_connect (widget, "button-press-event",
- G_CALLBACK (button_press_cb), item);
- } else {
- g_signal_handlers_disconnect_by_func
- (widget, G_CALLBACK (enter_notify_cb), item);
- g_signal_handlers_disconnect_by_func
- (widget, G_CALLBACK (button_press_cb), item);
- }
}
static void
@@ -636,17 +664,7 @@ goc_widget_set_widget (GocWidget *item, GtkWidget *widget)
if (widget) {
g_object_ref (widget);
- gtk_widget_show (widget);
- item->ofbox = GTK_WIDGET (g_object_new (GOC_TYPE_OFFSCREEN_BOX, NULL));
- gtk_container_add (GTK_CONTAINER (item->ofbox), widget);
- gtk_widget_show (item->ofbox);
- g_object_ref (item->ofbox);
- if (GOC_ITEM (item)->canvas)
- gtk_layout_put (GTK_LAYOUT (GOC_ITEM (item)->canvas),
- item->ofbox, item->x, item->y);
goc_widget_notify_scrolled (GOC_ITEM (item));
- /* we need to propagate some signals to the parent item */
- goc_widget_connect_signals (widget, item, TRUE);
}
}
@@ -749,6 +767,8 @@ goc_widget_draw (GocItem const *item, cairo_t *cr)
GocWidget *widget = GOC_WIDGET (item);
GocOffscreenBox *ofbox = GOC_OFFSCREEN_BOX (widget->ofbox);
int x, y;
+ if (!widget->ofbox)
+ return; /* the widget has no allocation */
gtk_container_child_get (GTK_CONTAINER (item->canvas), widget->ofbox,
"x", &x, "y", &y, NULL);
cairo_save (cr);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]