Commit 10d0ca0a authored by Matthias Clasen's avatar Matthias Clasen

GtkMagnifier: Add a resizing mode

In addition to the fixed-size mode that is used by the text view,
add a mode in which the magnifier requests enough size to render
the entire inspected widget at the current magnification. In this
mode, the magnifier will update its size when the size of the
inspected widget changes. Also, make the magnifier redraw on its
own whenever the inspected widget draws.
parent 42a6ae6c
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
enum { enum {
PROP_INSPECTED = 1, PROP_INSPECTED = 1,
PROP_RESIZE,
PROP_MAGNIFICATION PROP_MAGNIFICATION
}; };
...@@ -33,6 +34,9 @@ struct _GtkMagnifierPrivate ...@@ -33,6 +34,9 @@ struct _GtkMagnifierPrivate
gdouble magnification; gdouble magnification;
gint x; gint x;
gint y; gint y;
gboolean resize;
gulong draw_handler;
gulong resize_handler;
}; };
G_DEFINE_TYPE_WITH_PRIVATE (GtkMagnifier, _gtk_magnifier, G_DEFINE_TYPE_WITH_PRIVATE (GtkMagnifier, _gtk_magnifier,
...@@ -54,6 +58,10 @@ _gtk_magnifier_set_property (GObject *object, ...@@ -54,6 +58,10 @@ _gtk_magnifier_set_property (GObject *object,
_gtk_magnifier_set_magnification (GTK_MAGNIFIER (object), _gtk_magnifier_set_magnification (GTK_MAGNIFIER (object),
g_value_get_double (value)); g_value_get_double (value));
break; break;
case PROP_RESIZE:
_gtk_magnifier_set_resize (GTK_MAGNIFIER (object),
g_value_get_boolean (value));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
} }
...@@ -79,6 +87,9 @@ _gtk_magnifier_get_property (GObject *object, ...@@ -79,6 +87,9 @@ _gtk_magnifier_get_property (GObject *object,
case PROP_MAGNIFICATION: case PROP_MAGNIFICATION:
g_value_set_double (value, priv->magnification); g_value_set_double (value, priv->magnification);
break; break;
case PROP_RESIZE:
g_value_set_boolean (value, priv->resize);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
} }
...@@ -96,12 +107,17 @@ _gtk_magnifier_draw (GtkWidget *widget, ...@@ -96,12 +107,17 @@ _gtk_magnifier_draw (GtkWidget *widget,
magnifier = GTK_MAGNIFIER (widget); magnifier = GTK_MAGNIFIER (widget);
priv = _gtk_magnifier_get_instance_private (magnifier); priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->inspected == NULL)
return FALSE;
if (!gtk_widget_is_visible (priv->inspected)) if (!gtk_widget_is_visible (priv->inspected))
return FALSE; return FALSE;
gtk_widget_get_allocation (widget, &allocation); gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocation (priv->inspected, &inspected_alloc); gtk_widget_get_allocation (priv->inspected, &inspected_alloc);
cairo_translate (cr, allocation.width / 2, allocation.height / 2);
if (!priv->resize)
cairo_translate (cr, allocation.width / 2, allocation.height / 2);
x = CLAMP (priv->x, 0, inspected_alloc.width); x = CLAMP (priv->x, 0, inspected_alloc.width);
y = CLAMP (priv->y, 0, inspected_alloc.height); y = CLAMP (priv->y, 0, inspected_alloc.height);
...@@ -109,12 +125,133 @@ _gtk_magnifier_draw (GtkWidget *widget, ...@@ -109,12 +125,133 @@ _gtk_magnifier_draw (GtkWidget *widget,
cairo_save (cr); cairo_save (cr);
cairo_scale (cr, priv->magnification, priv->magnification); cairo_scale (cr, priv->magnification, priv->magnification);
cairo_translate (cr, -x, -y); cairo_translate (cr, -x, -y);
g_signal_handler_block (priv->inspected, priv->draw_handler);
gtk_widget_draw (priv->inspected, cr); gtk_widget_draw (priv->inspected, cr);
g_signal_handler_unblock (priv->inspected, priv->draw_handler);
cairo_restore (cr); cairo_restore (cr);
return TRUE; return TRUE;
} }
static void
gtk_magnifier_get_preferred_width (GtkWidget *widget,
gint *minimum_width,
gint *natural_width)
{
GtkMagnifier *magnifier;
GtkMagnifierPrivate *priv;
gint width;
magnifier = GTK_MAGNIFIER (widget);
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->resize && priv->inspected)
width = priv->magnification * gtk_widget_get_allocated_width (priv->inspected);
else
width = 0;
*minimum_width = width;
*natural_width = width;
}
static void
gtk_magnifier_get_preferred_height (GtkWidget *widget,
gint *minimum_height,
gint *natural_height)
{
GtkMagnifier *magnifier;
GtkMagnifierPrivate *priv;
gint height;
magnifier = GTK_MAGNIFIER (widget);
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->resize && priv->inspected)
height = priv->magnification * gtk_widget_get_allocated_height (priv->inspected);
else
height = 0;
*minimum_height = height;
*natural_height = height;
}
static void
resize_handler (GtkWidget *widget,
GtkAllocation *alloc,
GtkWidget *magnifier)
{
gtk_widget_queue_resize (magnifier);
}
static void
connect_resize_handler (GtkMagnifier *magnifier)
{
GtkMagnifierPrivate *priv;
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->inspected && priv->resize)
priv->resize_handler = g_signal_connect (priv->inspected, "size-allocate",
G_CALLBACK (resize_handler), magnifier);
}
static void
disconnect_resize_handler (GtkMagnifier *magnifier)
{
GtkMagnifierPrivate *priv;
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->resize_handler)
{
g_signal_handler_disconnect (priv->inspected, priv->resize_handler);
priv->resize_handler = 0;
}
}
static gboolean
draw_handler (GtkWidget *widget,
cairo_t *cr,
GtkWidget *magnifier)
{
gtk_widget_queue_draw (magnifier);
return FALSE;
}
static void
connect_draw_handler (GtkMagnifier *magnifier)
{
GtkMagnifierPrivate *priv;
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->inspected)
priv->draw_handler = g_signal_connect (priv->inspected, "draw",
G_CALLBACK (draw_handler), magnifier);
}
static void
disconnect_draw_handler (GtkMagnifier *magnifier)
{
GtkMagnifierPrivate *priv;
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->draw_handler)
{
g_signal_handler_disconnect (priv->inspected, priv->draw_handler);
priv->draw_handler = 0;
}
}
static void
_gtk_magnifier_destroy (GtkWidget *widget)
{
_gtk_magnifier_set_inspected (GTK_MAGNIFIER (widget), NULL);
GTK_WIDGET_CLASS (_gtk_magnifier_parent_class)->destroy (widget);
}
static void static void
_gtk_magnifier_class_init (GtkMagnifierClass *klass) _gtk_magnifier_class_init (GtkMagnifierClass *klass)
{ {
...@@ -124,7 +261,10 @@ _gtk_magnifier_class_init (GtkMagnifierClass *klass) ...@@ -124,7 +261,10 @@ _gtk_magnifier_class_init (GtkMagnifierClass *klass)
object_class->set_property = _gtk_magnifier_set_property; object_class->set_property = _gtk_magnifier_set_property;
object_class->get_property = _gtk_magnifier_get_property; object_class->get_property = _gtk_magnifier_get_property;
widget_class->destroy = _gtk_magnifier_destroy;
widget_class->draw = _gtk_magnifier_draw; widget_class->draw = _gtk_magnifier_draw;
widget_class->get_preferred_width = gtk_magnifier_get_preferred_width;
widget_class->get_preferred_height = gtk_magnifier_get_preferred_height;
g_object_class_install_property (object_class, g_object_class_install_property (object_class,
PROP_INSPECTED, PROP_INSPECTED,
...@@ -140,6 +280,13 @@ _gtk_magnifier_class_init (GtkMagnifierClass *klass) ...@@ -140,6 +280,13 @@ _gtk_magnifier_class_init (GtkMagnifierClass *klass)
P_("magnification"), P_("magnification"),
1, G_MAXDOUBLE, 1, 1, G_MAXDOUBLE, 1,
G_PARAM_READWRITE)); G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_RESIZE,
g_param_spec_boolean ("resize",
P_("resize"),
P_("resize"),
FALSE,
G_PARAM_READWRITE));
} }
static void static void
...@@ -156,6 +303,7 @@ _gtk_magnifier_init (GtkMagnifier *magnifier) ...@@ -156,6 +303,7 @@ _gtk_magnifier_init (GtkMagnifier *magnifier)
gtk_widget_set_has_window (widget, FALSE); gtk_widget_set_has_window (widget, FALSE);
priv->magnification = 1; priv->magnification = 1;
priv->resize = FALSE;
} }
GtkWidget * GtkWidget *
...@@ -193,7 +341,14 @@ _gtk_magnifier_set_inspected (GtkMagnifier *magnifier, ...@@ -193,7 +341,14 @@ _gtk_magnifier_set_inspected (GtkMagnifier *magnifier,
if (priv->inspected == inspected) if (priv->inspected == inspected)
return; return;
disconnect_draw_handler (magnifier);
disconnect_resize_handler (magnifier);
priv->inspected = inspected; priv->inspected = inspected;
connect_draw_handler (magnifier);
connect_resize_handler (magnifier);
g_object_notify (G_OBJECT (magnifier), "inspected"); g_object_notify (G_OBJECT (magnifier), "inspected");
} }
...@@ -252,6 +407,9 @@ _gtk_magnifier_set_magnification (GtkMagnifier *magnifier, ...@@ -252,6 +407,9 @@ _gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
priv->magnification = magnification; priv->magnification = magnification;
g_object_notify (G_OBJECT (magnifier), "magnification"); g_object_notify (G_OBJECT (magnifier), "magnification");
if (priv->resize)
gtk_widget_queue_resize (GTK_WIDGET (magnifier));
if (gtk_widget_is_visible (GTK_WIDGET (magnifier))) if (gtk_widget_is_visible (GTK_WIDGET (magnifier)))
gtk_widget_queue_draw (GTK_WIDGET (magnifier)); gtk_widget_queue_draw (GTK_WIDGET (magnifier));
} }
...@@ -267,3 +425,37 @@ _gtk_magnifier_get_magnification (GtkMagnifier *magnifier) ...@@ -267,3 +425,37 @@ _gtk_magnifier_get_magnification (GtkMagnifier *magnifier)
return priv->magnification; return priv->magnification;
} }
void
_gtk_magnifier_set_resize (GtkMagnifier *magnifier,
gboolean resize)
{
GtkMagnifierPrivate *priv;
g_return_if_fail (GTK_IS_MAGNIFIER (magnifier));
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->resize == resize)
return;
priv->resize = resize;
gtk_widget_queue_resize (GTK_WIDGET (magnifier));
if (resize)
connect_resize_handler (magnifier);
else
disconnect_resize_handler (magnifier);
}
gboolean
_gtk_magnifier_get_resize (GtkMagnifier *magnifier)
{
GtkMagnifierPrivate *priv;
g_return_val_if_fail (GTK_IS_MAGNIFIER (magnifier), FALSE);
priv = _gtk_magnifier_get_instance_private (magnifier);
return priv->resize;
}
...@@ -59,6 +59,10 @@ void _gtk_magnifier_set_magnification (GtkMagnifier *magnifier, ...@@ -59,6 +59,10 @@ void _gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
gdouble magnification); gdouble magnification);
gdouble _gtk_magnifier_get_magnification (GtkMagnifier *magnifier); gdouble _gtk_magnifier_get_magnification (GtkMagnifier *magnifier);
void _gtk_magnifier_set_resize (GtkMagnifier *magnifier,
gboolean resize);
gboolean _gtk_magnifier_get_resize (GtkMagnifier *magnifier);
G_END_DECLS G_END_DECLS
#endif /* __GTK_MAGNIFIER_H__ */ #endif /* __GTK_MAGNIFIER_H__ */
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