[gegl-gtk] GeglGtkView: Implement configurable autoscaling
- From: Jon Nordby <jonnor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl-gtk] GeglGtkView: Implement configurable autoscaling
- Date: Sun, 9 Oct 2011 18:41:51 +0000 (UTC)
commit d7052f3771d9d58f57e7275a58351ed9248b7497
Author: Jon Nordby <jononor gmail com>
Date: Sun Oct 9 20:29:18 2011 +0200
GeglGtkView: Implement configurable autoscaling
examples/c/gegl-gtk-basic.c | 2 +-
examples/c/gegl-gtk-paint.c | 2 +-
examples/c/gegl-gtk-scroll.c | 1 +
gegl-gtk/.gitignore | 1 +
gegl-gtk/Makefile.am | 17 ++++++-
gegl-gtk/gegl-gtk-enums.h | 35 +++++++++++++++
gegl-gtk/gegl-gtk-view.c | 31 +++++++++++--
gegl-gtk/gegl-gtk-view.h | 5 ++
gegl-gtk/internal/view-helper.c | 91 +++++++++++++++++++++++++++-----------
gegl-gtk/internal/view-helper.h | 7 +++-
10 files changed, 155 insertions(+), 37 deletions(-)
---
diff --git a/examples/c/gegl-gtk-basic.c b/examples/c/gegl-gtk-basic.c
index 2498432..010c1c0 100644
--- a/examples/c/gegl-gtk-basic.c
+++ b/examples/c/gegl-gtk-basic.c
@@ -53,7 +53,7 @@ main (gint argc,
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "GEGL-GTK basic example");
- view = gegl_gtk_view_new_for_node(node);
+ view = GTK_WIDGET(gegl_gtk_view_new_for_node(node));
gtk_container_add (GTK_CONTAINER (window), view);
g_signal_connect (window, "destroy",
diff --git a/examples/c/gegl-gtk-paint.c b/examples/c/gegl-gtk-paint.c
index 2dbad93..7e50848 100644
--- a/examples/c/gegl-gtk-paint.c
+++ b/examples/c/gegl-gtk-paint.c
@@ -165,7 +165,7 @@ main (gint argc,
gegl_node_link_many (loadbuf, out, NULL);
- view = gegl_gtk_view_new_for_node(out);
+ view = GTK_WIDGET(gegl_gtk_view_new_for_node(out));
top = loadbuf;
}
diff --git a/examples/c/gegl-gtk-scroll.c b/examples/c/gegl-gtk-scroll.c
index ffcf9e0..6fd85a4 100644
--- a/examples/c/gegl-gtk-scroll.c
+++ b/examples/c/gegl-gtk-scroll.c
@@ -58,6 +58,7 @@ main (gint argc,
scrolled = gtk_scrolled_window_new(NULL, NULL);
view = GTK_WIDGET(gegl_gtk_view_new_for_node(node));
+ gegl_gtk_view_set_autoscale_policy(GEGL_GTK_VIEW(view), GEGL_GTK_VIEW_AUTOSCALE_WIDGET);
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), view);
diff --git a/gegl-gtk/.gitignore b/gegl-gtk/.gitignore
index 2f12be8..ce962ec 100644
--- a/gegl-gtk/.gitignore
+++ b/gegl-gtk/.gitignore
@@ -1,3 +1,4 @@
*.gir
*.typelib
*.vapi
+gegl-gtk-enums.c
diff --git a/gegl-gtk/Makefile.am b/gegl-gtk/Makefile.am
index 15a0eb8..c5feda7 100644
--- a/gegl-gtk/Makefile.am
+++ b/gegl-gtk/Makefile.am
@@ -1,12 +1,25 @@
CLEANFILES =
-headers = gegl-gtk.h gegl-gtk-view.h
-sources = gegl-gtk-view.c
+gen_sources = gegl-gtk-enums.c
+CLEANFILES += $(gen_sources)
+
+headers = gegl-gtk.h gegl-gtk-view.h gegl-gtk-enums.h
+sources = gegl-gtk-view.c $(gen_sources)
INCLUDES = $(GTK_CFLAGS) $(GEGL_CFLAGS)
internal_headers = internal/view-helper.h
internal_sources = internal/view-helper.c
+gegl-gtk-enums.c: $(srcdir)/gegl-gtk-enums.h
+ glib-mkenums \
+ --fhead "/* This is a generated file, do not edit directly */\n\n#include \"config.h\"\n#include <glib-object.h>\n#include \"gegl-gtk-enums.h\"" \
+ --fprod "\n/* enumerations from \"@filename \" */" \
+ --vhead "GType\n enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G Type@Value values[] = {" \
+ --vprod " { @VALUENAME@, \"@valuenick \", \"@valuenick \" }," \
+ --vtail " { 0, NULL, NULL }\n };\n etype = g_ type@_register_static (\"@EnumName \", values);\n }\n return etype;\n}\n\n" \
+ $(srcdir)/gegl-gtk-enums.h > gegl-gtk-enums.c
+
+
gegl_gtk_includedir=$(includedir)/gegl-gtk$(GEGL_GTK_GTK_VERSION)-$(GEGL_GTK_API_VERSION)
gegl_gtk_include_HEADERS = $(headers)
diff --git a/gegl-gtk/gegl-gtk-enums.h b/gegl-gtk/gegl-gtk-enums.h
new file mode 100644
index 0000000..63f9385
--- /dev/null
+++ b/gegl-gtk/gegl-gtk-enums.h
@@ -0,0 +1,35 @@
+/* This file is part of GEGL-GTK
+ *
+ * GEGL-GTK 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 3 of the License, or (at your option) any later version.
+ *
+ * GEGL-GTK 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 GEGL-GTK; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Copyright (C) 2011 Jon Nordby <jononor gmail com>
+ */
+
+#ifndef __GEGL_GTK_ENUMS_H__
+#define __GEGL_GTK_ENUMS_H__
+
+G_BEGIN_DECLS
+
+typedef enum {
+ GEGL_GTK_VIEW_AUTOSCALE_DISABLED = 0,
+ GEGL_GTK_VIEW_AUTOSCALE_WIDGET,
+ GEGL_GTK_VIEW_AUTOSCALE_CONTENT
+} GeglGtkViewAutoscale;
+
+GType gegl_gtk_view_autoscale_get_type (void) G_GNUC_CONST;
+#define GEGL_GTK_TYPE_VIEW_AUTOSCALE (gegl_gtk_view_autoscale_get_type())
+
+G_END_DECLS
+
+#endif /* __GEGL_GTK_ENUMS_H__ */
diff --git a/gegl-gtk/gegl-gtk-view.c b/gegl-gtk/gegl-gtk-view.c
index dde9e22..392802f 100644
--- a/gegl-gtk/gegl-gtk-view.c
+++ b/gegl-gtk/gegl-gtk-view.c
@@ -46,7 +46,8 @@ enum
PROP_X,
PROP_Y,
PROP_SCALE,
- PROP_BLOCK
+ PROP_BLOCK,
+ PROP_AUTOSCALE_POLICY
};
@@ -141,6 +142,12 @@ gegl_gtk_view_class_init (GeglGtkViewClass * klass)
"Make sure all data requested to blit is generated.",
FALSE,
G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_AUTOSCALE_POLICY,
+ g_param_spec_enum ("autoscale-policy", NULL, NULL,
+ GEGL_GTK_TYPE_VIEW_AUTOSCALE,
+ GEGL_GTK_VIEW_AUTOSCALE_CONTENT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
}
@@ -191,6 +198,9 @@ set_property (GObject *gobject,
case PROP_SCALE:
gegl_gtk_view_set_scale(self, g_value_get_double(value));
break;
+ case PROP_AUTOSCALE_POLICY:
+ gegl_gtk_view_set_autoscale_policy(self, g_value_get_enum(value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
@@ -224,6 +234,9 @@ get_property (GObject *gobject,
case PROP_SCALE:
g_value_set_double (value, gegl_gtk_view_get_scale(self));
break;
+ case PROP_AUTOSCALE_POLICY:
+ g_value_set_enum (value, gegl_gtk_view_get_autoscale_policy(self));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
break;
@@ -276,8 +289,6 @@ draw (GtkWidget * widget, cairo_t *cr)
view_helper_draw (priv, cr, &rect);
- view_helper_repaint (priv); /* Only needed due to possible allocation changes? */
-
return FALSE;
}
#endif
@@ -304,8 +315,6 @@ expose_event (GtkWidget *widget,
cairo_destroy (cr);
- view_helper_repaint (priv); /* Only needed due to possible allocation changes? */
-
return FALSE;
}
#endif
@@ -378,3 +387,15 @@ gegl_gtk_view_get_y(GeglGtkView *self)
{
return view_helper_get_y(GET_PRIVATE(self));
}
+
+void
+gegl_gtk_view_set_autoscale_policy(GeglGtkView *self, GeglGtkViewAutoscale autoscale)
+{
+ view_helper_set_autoscale_policy(GET_PRIVATE(self), autoscale);
+}
+
+GeglGtkViewAutoscale
+gegl_gtk_view_get_autoscale_policy(GeglGtkView *self)
+{
+ return view_helper_get_autoscale_policy(GET_PRIVATE(self));
+}
diff --git a/gegl-gtk/gegl-gtk-view.h b/gegl-gtk/gegl-gtk-view.h
index 9ea904b..6cf36e4 100644
--- a/gegl-gtk/gegl-gtk-view.h
+++ b/gegl-gtk/gegl-gtk-view.h
@@ -22,6 +22,8 @@
#include <gtk/gtk.h>
#include <gegl.h>
+#include "gegl-gtk-enums.h"
+
G_BEGIN_DECLS
#define GEGL_GTK_TYPE_VIEW (gegl_gtk_view_get_type ())
@@ -67,6 +69,9 @@ float gegl_gtk_view_get_x(GeglGtkView *self);
void gegl_gtk_view_set_y(GeglGtkView *self, float y);
float gegl_gtk_view_get_y(GeglGtkView *self);
+void gegl_gtk_view_set_autoscale_policy(GeglGtkView *self, GeglGtkViewAutoscale autoscale);
+GeglGtkViewAutoscale gegl_gtk_view_get_autoscale_policy(GeglGtkView *self);
+
G_END_DECLS
#endif /* __GEGL_GTK_VIEW_H__ */
diff --git a/gegl-gtk/internal/view-helper.c b/gegl-gtk/internal/view-helper.c
index add98a3..62e5ee7 100644
--- a/gegl-gtk/internal/view-helper.c
+++ b/gegl-gtk/internal/view-helper.c
@@ -75,11 +75,12 @@ view_helper_init (ViewHelper *self)
self->x = 0;
self->y = 0;
self->scale = 1.0;
+ self->autoscale_policy = GEGL_GTK_VIEW_AUTOSCALE_CONTENT;
+
self->monitor_id = 0;
self->processor = NULL;
self->widget_allocation = invalid_gdkrect;
- self->view_bbox = invalid_rect;
}
static void
@@ -115,6 +116,35 @@ model_rect_to_view_rect(ViewHelper *self, GeglRectangle *rect)
}
static void
+update_autoscale(ViewHelper *self)
+{
+ GdkRectangle viewport = self->widget_allocation;
+ GeglRectangle bbox = gegl_node_get_bounding_box(self->node);
+ model_rect_to_view_rect(self, &bbox);
+
+ if (!self->node || viewport.width < 0 || viewport.height < 0
+ || bbox.width < 0 || bbox.height < 0)
+ return;
+
+ if (self->autoscale_policy == GEGL_GTK_VIEW_AUTOSCALE_WIDGET) {
+ /* Request widget size change */
+ /* XXX: Should we reset scale/x/y here? */
+ g_signal_emit (self, view_helper_signals[SIGNAL_SIZE_CHANGED],
+ 0, &bbox, NULL);
+
+ } else if (self->autoscale_policy == GEGL_GTK_VIEW_AUTOSCALE_CONTENT) {
+ /* Calculate and set scaling factor to make the content fit inside */
+ float width_ratio = bbox.width / (float)viewport.width;
+ float height_ratio = bbox.height / (float)viewport.height;
+ float max_ratio = width_ratio >= height_ratio ? width_ratio : height_ratio;
+
+ float current_scale = view_helper_get_scale(self);
+ view_helper_set_scale(self, current_scale*(1.0/max_ratio));
+ }
+
+}
+
+static void
invalidated_event (GeglNode *node,
GeglRectangle *rect,
ViewHelper *self)
@@ -127,6 +157,7 @@ task_monitor (ViewHelper *self)
{
if (self->processor==NULL)
return FALSE;
+
if (gegl_processor_work (self->processor, NULL))
return TRUE;
@@ -146,22 +177,14 @@ computed_event (GeglNode *node,
GeglRectangle *rect,
ViewHelper *self)
{
- /* Notify about potential size change */
- GeglRectangle bbox = gegl_node_get_bounding_box(node);
- model_rect_to_view_rect(self, &bbox);
-
- if (!gegl_rectangle_equal(&bbox, &(self->view_bbox))) {
- self->view_bbox = bbox;
- g_signal_emit (self, view_helper_signals[SIGNAL_SIZE_CHANGED],
- 0, &bbox, NULL);
- }
+ update_autoscale(self);
- /* Emit redraw-needed */
- GeglRectangle redraw_rect = *rect;
- model_rect_to_view_rect(self, &redraw_rect);
+ /* Emit redraw-needed */
+ GeglRectangle redraw_rect = *rect;
+ model_rect_to_view_rect(self, &redraw_rect);
- g_signal_emit (self, view_helper_signals[SIGNAL_REDRAW_NEEDED],
- 0, &redraw_rect, NULL);
+ g_signal_emit (self, view_helper_signals[SIGNAL_REDRAW_NEEDED],
+ 0, &redraw_rect, NULL);
}
ViewHelper *
@@ -213,7 +236,7 @@ void
view_helper_set_allocation(ViewHelper *self, GdkRectangle *allocation)
{
self->widget_allocation = *allocation;
- view_helper_repaint(self);
+ update_autoscale(self);
}
/* Trigger processing of the GeglNode */
@@ -222,27 +245,25 @@ view_helper_repaint (ViewHelper *self)
{
GeglRectangle roi;
+ if (!self->node)
+ return;
+
roi.x = self->x / self->scale;
roi.y = self->y / self->scale;
roi.width = ceil(self->widget_allocation.width / self->scale+1);
roi.height = ceil(self->widget_allocation.height / self->scale+1);
- if (self->monitor_id == 0)
- {
+ if (self->monitor_id == 0) {
self->monitor_id = g_idle_add_full (G_PRIORITY_LOW,
(GSourceFunc) task_monitor, self,
NULL);
-
- if (self->processor == NULL)
- {
- if (self->node)
- self->processor = gegl_node_new_processor (self->node, &roi);
- }
- }
+ }
if (self->processor)
- gegl_processor_set_rectangle (self->processor, &roi);
+ gegl_processor_set_rectangle (self->processor, &roi);
+ else
+ self->processor = gegl_node_new_processor (self->node, &roi);
}
void
@@ -273,7 +294,7 @@ view_helper_set_node(ViewHelper *self, GeglNode *node)
G_CALLBACK (invalidated_event),
self, 0);
- view_helper_repaint (self);
+ invalidate(self);
} else
self->node = NULL;
@@ -332,3 +353,19 @@ view_helper_get_y(ViewHelper *self)
{
return self->y;
}
+
+void
+view_helper_set_autoscale_policy(ViewHelper *self, GeglGtkViewAutoscale autoscale)
+{
+ if (self->autoscale_policy == autoscale)
+ return;
+
+ self->autoscale_policy = autoscale;
+ update_autoscale(self);
+}
+
+GeglGtkViewAutoscale
+view_helper_get_autoscale_policy(ViewHelper *self)
+{
+ return self->autoscale_policy;
+}
diff --git a/gegl-gtk/internal/view-helper.h b/gegl-gtk/internal/view-helper.h
index 51df6b5..b2f749d 100644
--- a/gegl-gtk/internal/view-helper.h
+++ b/gegl-gtk/internal/view-helper.h
@@ -22,6 +22,8 @@
#include <glib-object.h>
#include <gegl.h>
#include <gtk/gtk.h>
+24ea1a60d4497df6cff9828093a8f6b9eed644cf
+#include <gegl-gtk-enums.h>
G_BEGIN_DECLS
@@ -44,10 +46,11 @@ struct _ViewHelper
gfloat y;
gdouble scale;
gboolean block; /* blocking render */
+ GeglGtkViewAutoscale autoscale_policy;
+
guint monitor_id;
GeglProcessor *processor;
GdkRectangle widget_allocation; /* The allocated size of the widget */
- GeglRectangle view_bbox; /* Bounding box of the node, in view coordinates */
};
struct _ViewHelperClass
@@ -76,6 +79,8 @@ float view_helper_get_x(ViewHelper *self);
void view_helper_set_y(ViewHelper *self, float y);
float view_helper_get_y(ViewHelper *self);
+void view_helper_set_autoscale_policy(ViewHelper *self, GeglGtkViewAutoscale autoscale);
+GeglGtkViewAutoscale view_helper_get_autoscale_policy(ViewHelper *self);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]