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.
This commit is contained in:
Matthias Clasen 2014-12-20 19:16:46 -05:00
parent 42a6ae6c6c
commit 10d0ca0a3d
2 changed files with 197 additions and 1 deletions

View File

@ -22,6 +22,7 @@
enum {
PROP_INSPECTED = 1,
PROP_RESIZE,
PROP_MAGNIFICATION
};
@ -33,6 +34,9 @@ struct _GtkMagnifierPrivate
gdouble magnification;
gint x;
gint y;
gboolean resize;
gulong draw_handler;
gulong resize_handler;
};
G_DEFINE_TYPE_WITH_PRIVATE (GtkMagnifier, _gtk_magnifier,
@ -54,6 +58,10 @@ _gtk_magnifier_set_property (GObject *object,
_gtk_magnifier_set_magnification (GTK_MAGNIFIER (object),
g_value_get_double (value));
break;
case PROP_RESIZE:
_gtk_magnifier_set_resize (GTK_MAGNIFIER (object),
g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
@ -79,6 +87,9 @@ _gtk_magnifier_get_property (GObject *object,
case PROP_MAGNIFICATION:
g_value_set_double (value, priv->magnification);
break;
case PROP_RESIZE:
g_value_set_boolean (value, priv->resize);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
}
@ -96,12 +107,17 @@ _gtk_magnifier_draw (GtkWidget *widget,
magnifier = GTK_MAGNIFIER (widget);
priv = _gtk_magnifier_get_instance_private (magnifier);
if (priv->inspected == NULL)
return FALSE;
if (!gtk_widget_is_visible (priv->inspected))
return FALSE;
gtk_widget_get_allocation (widget, &allocation);
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);
y = CLAMP (priv->y, 0, inspected_alloc.height);
@ -109,12 +125,133 @@ _gtk_magnifier_draw (GtkWidget *widget,
cairo_save (cr);
cairo_scale (cr, priv->magnification, priv->magnification);
cairo_translate (cr, -x, -y);
g_signal_handler_block (priv->inspected, priv->draw_handler);
gtk_widget_draw (priv->inspected, cr);
g_signal_handler_unblock (priv->inspected, priv->draw_handler);
cairo_restore (cr);
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
_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->get_property = _gtk_magnifier_get_property;
widget_class->destroy = _gtk_magnifier_destroy;
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,
PROP_INSPECTED,
@ -140,6 +280,13 @@ _gtk_magnifier_class_init (GtkMagnifierClass *klass)
P_("magnification"),
1, G_MAXDOUBLE, 1,
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
@ -156,6 +303,7 @@ _gtk_magnifier_init (GtkMagnifier *magnifier)
gtk_widget_set_has_window (widget, FALSE);
priv->magnification = 1;
priv->resize = FALSE;
}
GtkWidget *
@ -193,7 +341,14 @@ _gtk_magnifier_set_inspected (GtkMagnifier *magnifier,
if (priv->inspected == inspected)
return;
disconnect_draw_handler (magnifier);
disconnect_resize_handler (magnifier);
priv->inspected = inspected;
connect_draw_handler (magnifier);
connect_resize_handler (magnifier);
g_object_notify (G_OBJECT (magnifier), "inspected");
}
@ -252,6 +407,9 @@ _gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
priv->magnification = 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)))
gtk_widget_queue_draw (GTK_WIDGET (magnifier));
}
@ -267,3 +425,37 @@ _gtk_magnifier_get_magnification (GtkMagnifier *magnifier)
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;
}

View File

@ -59,6 +59,10 @@ void _gtk_magnifier_set_magnification (GtkMagnifier *magnifier,
gdouble magnification);
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
#endif /* __GTK_MAGNIFIER_H__ */