Compare commits
2 Commits
text-rende
...
wip/ebassi
Author | SHA1 | Date | |
---|---|---|---|
|
109593ab18 | ||
|
7b17f6fede |
238
gtk/gtkfixed.c
238
gtk/gtkfixed.c
@@ -75,10 +75,12 @@
|
||||
|
||||
#include "gtkfixed.h"
|
||||
|
||||
#include "gtkadjustment.h"
|
||||
#include "gtkcontainerprivate.h"
|
||||
#include "gtkfixedlayout.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkscrollable.h"
|
||||
#include "gtkwidgetprivate.h"
|
||||
|
||||
static void gtk_fixed_add (GtkContainer *container,
|
||||
@@ -92,19 +94,252 @@ static GType gtk_fixed_child_type (GtkContainer *container);
|
||||
|
||||
typedef struct {
|
||||
GtkLayoutManager *layout;
|
||||
|
||||
GtkAdjustment *hadjustment;
|
||||
GtkAdjustment *vadjustment;
|
||||
|
||||
/* GtkScrollablePolicy needs to be checked when
|
||||
* driving the scrollable adjustment values */
|
||||
GtkScrollablePolicy hscroll_policy;
|
||||
GtkScrollablePolicy vscroll_policy;
|
||||
} GtkFixedPrivate;
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GtkFixed, gtk_fixed, GTK_TYPE_CONTAINER)
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
/* GtkFixed properties */
|
||||
|
||||
N_PROPERTIES,
|
||||
|
||||
/* GtkScrollable properties */
|
||||
PROP_HADJUSTMENT = N_PROPERTIES,
|
||||
PROP_VADJUSTMENT,
|
||||
PROP_HSCROLL_POLICY,
|
||||
PROP_VSCROLL_POLICY
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GtkFixed, gtk_fixed, GTK_TYPE_CONTAINER,
|
||||
G_ADD_PRIVATE (GtkFixed)
|
||||
G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
|
||||
|
||||
static void
|
||||
gtk_fixed_adjustment_changed (GtkFixed *self)
|
||||
{
|
||||
GtkFixedPrivate *priv = gtk_fixed_get_instance_private (self);
|
||||
double scroll_x = 0;
|
||||
double scroll_y = 0;
|
||||
GskTransform *transform;
|
||||
|
||||
if (priv->hadjustment)
|
||||
scroll_x = gtk_adjustment_get_value (priv->hadjustment) * -1.0;
|
||||
|
||||
if (priv->vadjustment)
|
||||
scroll_y = gtk_adjustment_get_value (priv->vadjustment) * -1.0;
|
||||
|
||||
transform = NULL;
|
||||
transform = gsk_transform_translate (transform, &GRAPHENE_POINT_INIT (scroll_x, scroll_y));
|
||||
gtk_fixed_layout_set_child_transform (GTK_FIXED_LAYOUT (priv->layout), transform);
|
||||
gsk_transform_unref (transform);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fixed_set_adjustment_values (GtkFixed *self,
|
||||
GtkOrientation orientation,
|
||||
GtkAdjustment *adjustment)
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
double old_value;
|
||||
double new_value;
|
||||
double size;
|
||||
|
||||
gtk_widget_get_allocation (GTK_WIDGET (self), &allocation);
|
||||
|
||||
old_value = gtk_adjustment_get_value (adjustment);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
size = MAX (allocation.width, gtk_adjustment_get_upper (adjustment));
|
||||
else
|
||||
size = MAX (allocation.height, gtk_adjustment_get_upper (adjustment));
|
||||
|
||||
g_object_set (adjustment,
|
||||
"lower", 0.0,
|
||||
"upper", size,
|
||||
"page-size", size,
|
||||
"step-increment", size * 0.1,
|
||||
"page-increment", size * 0.9,
|
||||
NULL);
|
||||
|
||||
new_value = MAX (old_value, 0);
|
||||
if (!G_APPROX_VALUE (new_value, old_value, 0.001))
|
||||
gtk_adjustment_set_value (adjustment, new_value);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fixed_finalize (GObject *gobject)
|
||||
{
|
||||
GtkFixed *self = GTK_FIXED (gobject);
|
||||
GtkFixedPrivate *priv = gtk_fixed_get_instance_private (self);
|
||||
|
||||
g_clear_object (&priv->hadjustment);
|
||||
g_clear_object (&priv->vadjustment);
|
||||
|
||||
G_OBJECT_CLASS (gtk_fixed_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fixed_set_hadjustment (GtkFixed *self,
|
||||
GtkAdjustment *adjustment)
|
||||
{
|
||||
GtkFixedPrivate *priv = gtk_fixed_get_instance_private (self);
|
||||
|
||||
if (adjustment && priv->hadjustment == adjustment)
|
||||
return;
|
||||
|
||||
if (priv->hadjustment != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->hadjustment,
|
||||
gtk_fixed_adjustment_changed,
|
||||
self);
|
||||
g_object_unref (priv->hadjustment);
|
||||
}
|
||||
|
||||
if (adjustment == NULL)
|
||||
adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
g_signal_connect_swapped (adjustment, "value-changed",
|
||||
G_CALLBACK (gtk_fixed_adjustment_changed),
|
||||
self);
|
||||
priv->hadjustment = g_object_ref_sink (adjustment);
|
||||
gtk_fixed_set_adjustment_values (self, GTK_ORIENTATION_HORIZONTAL, priv->hadjustment);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "hadjustment");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fixed_set_vadjustment (GtkFixed *self,
|
||||
GtkAdjustment *adjustment)
|
||||
{
|
||||
GtkFixedPrivate *priv = gtk_fixed_get_instance_private (self);
|
||||
|
||||
if (adjustment && priv->vadjustment == adjustment)
|
||||
return;
|
||||
|
||||
if (priv->vadjustment != NULL)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->vadjustment,
|
||||
gtk_fixed_adjustment_changed,
|
||||
self);
|
||||
g_object_unref (priv->vadjustment);
|
||||
}
|
||||
|
||||
if (adjustment == NULL)
|
||||
adjustment = gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
g_signal_connect_swapped (adjustment, "value-changed",
|
||||
G_CALLBACK (gtk_fixed_adjustment_changed),
|
||||
self);
|
||||
priv->vadjustment = g_object_ref_sink (adjustment);
|
||||
gtk_fixed_set_adjustment_values (self, GTK_ORIENTATION_VERTICAL, priv->vadjustment);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "vadjustment");
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fixed_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFixed *self = GTK_FIXED (gobject);
|
||||
GtkFixedPrivate *priv = gtk_fixed_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HADJUSTMENT:
|
||||
g_value_set_object (value, priv->hadjustment);
|
||||
break;
|
||||
|
||||
case PROP_VADJUSTMENT:
|
||||
g_value_set_object (value, priv->vadjustment);
|
||||
break;
|
||||
|
||||
case PROP_HSCROLL_POLICY:
|
||||
g_value_set_enum (value, priv->hscroll_policy);
|
||||
break;
|
||||
|
||||
case PROP_VSCROLL_POLICY:
|
||||
g_value_set_enum (value, priv->vscroll_policy);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fixed_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GtkFixed *self = GTK_FIXED (gobject);
|
||||
GtkFixedPrivate *priv = gtk_fixed_get_instance_private (self);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_HADJUSTMENT:
|
||||
gtk_fixed_set_hadjustment (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_VADJUSTMENT:
|
||||
gtk_fixed_set_vadjustment (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_HSCROLL_POLICY:
|
||||
if (priv->hscroll_policy != g_value_get_enum (value))
|
||||
{
|
||||
priv->hscroll_policy = g_value_get_enum (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
g_object_notify_by_pspec (gobject, pspec);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_VSCROLL_POLICY:
|
||||
if (priv->vscroll_policy != g_value_get_enum (value))
|
||||
{
|
||||
priv->vscroll_policy = g_value_get_enum (value);
|
||||
gtk_widget_queue_resize (GTK_WIDGET (self));
|
||||
g_object_notify_by_pspec (gobject, pspec);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_fixed_class_init (GtkFixedClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = gtk_fixed_set_property;
|
||||
gobject_class->get_property = gtk_fixed_get_property;
|
||||
gobject_class->finalize = gtk_fixed_finalize;
|
||||
|
||||
container_class->add = gtk_fixed_add;
|
||||
container_class->remove = gtk_fixed_remove;
|
||||
container_class->forall = gtk_fixed_forall;
|
||||
container_class->child_type = gtk_fixed_child_type;
|
||||
|
||||
/* Scrollable interface */
|
||||
g_object_class_override_property (gobject_class, PROP_HADJUSTMENT, "hadjustment");
|
||||
g_object_class_override_property (gobject_class, PROP_VADJUSTMENT, "vadjustment");
|
||||
g_object_class_override_property (gobject_class, PROP_HSCROLL_POLICY, "hscroll-policy");
|
||||
g_object_class_override_property (gobject_class, PROP_VSCROLL_POLICY, "vscroll-policy");
|
||||
}
|
||||
|
||||
static GType
|
||||
@@ -121,6 +356,7 @@ gtk_fixed_init (GtkFixed *self)
|
||||
gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
|
||||
|
||||
priv->layout = gtk_fixed_layout_new ();
|
||||
gtk_fixed_layout_set_minimum_size (GTK_FIXED_LAYOUT (priv->layout), -1, -1);
|
||||
gtk_widget_set_layout_manager (GTK_WIDGET (self), priv->layout);
|
||||
}
|
||||
|
||||
|
@@ -71,6 +71,11 @@
|
||||
struct _GtkFixedLayout
|
||||
{
|
||||
GtkLayoutManager parent_instance;
|
||||
|
||||
int min_width;
|
||||
int min_height;
|
||||
|
||||
GskTransform *child_transform;
|
||||
};
|
||||
|
||||
struct _GtkFixedLayoutChild
|
||||
@@ -229,7 +234,8 @@ gtk_fixed_layout_measure (GtkLayoutManager *layout_manager,
|
||||
{
|
||||
int child_min = 0, child_nat = 0;
|
||||
int child_min_opp = 0, child_nat_opp = 0;
|
||||
graphene_rect_t min_rect, nat_rect;
|
||||
graphene_rect_t nat_rect;
|
||||
GskTransform *transform = NULL;
|
||||
|
||||
if (!gtk_widget_get_visible (child))
|
||||
continue;
|
||||
@@ -243,23 +249,16 @@ gtk_fixed_layout_measure (GtkLayoutManager *layout_manager,
|
||||
&child_min_opp, &child_nat_opp,
|
||||
NULL, NULL);
|
||||
|
||||
gsk_transform_transform_bounds (child_info->position,
|
||||
&GRAPHENE_RECT_INIT (0.f, 0.f, child_min, child_min_opp),
|
||||
&min_rect);
|
||||
gsk_transform_transform_bounds (child_info->position,
|
||||
transform = gsk_transform_transform (transform, child_info->position);
|
||||
gsk_transform_transform_bounds (transform,
|
||||
&GRAPHENE_RECT_INIT (0.f, 0.f, child_nat, child_nat_opp),
|
||||
&nat_rect);
|
||||
gsk_transform_unref (transform);
|
||||
|
||||
if (orientation == GTK_ORIENTATION_HORIZONTAL)
|
||||
{
|
||||
minimum_size = MAX (minimum_size, min_rect.origin.x + min_rect.size.width);
|
||||
natural_size = MAX (natural_size, nat_rect.origin.x + nat_rect.size.width);
|
||||
}
|
||||
natural_size = MAX (natural_size, nat_rect.origin.x + nat_rect.size.width);
|
||||
else
|
||||
{
|
||||
minimum_size = MAX (minimum_size, min_rect.origin.y + min_rect.size.height);
|
||||
natural_size = MAX (natural_size, nat_rect.origin.y + nat_rect.size.height);
|
||||
}
|
||||
natural_size = MAX (natural_size, nat_rect.origin.y + nat_rect.size.height);
|
||||
}
|
||||
|
||||
if (minimum != NULL)
|
||||
@@ -275,7 +274,9 @@ gtk_fixed_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
int height,
|
||||
int baseline)
|
||||
{
|
||||
GtkFixedLayout *self = GTK_FIXED_LAYOUT (layout_manager);
|
||||
GtkFixedLayoutChild *child_info;
|
||||
GskTransform *transform;
|
||||
GtkWidget *child;
|
||||
|
||||
for (child = _gtk_widget_get_first_child (widget);
|
||||
@@ -290,11 +291,17 @@ gtk_fixed_layout_allocate (GtkLayoutManager *layout_manager,
|
||||
child_info = GTK_FIXED_LAYOUT_CHILD (gtk_layout_manager_get_layout_child (layout_manager, child));
|
||||
gtk_widget_get_preferred_size (child, &child_req, NULL);
|
||||
|
||||
transform = NULL;
|
||||
transform = gsk_transform_transform (transform, self->child_transform);
|
||||
transform = gsk_transform_transform (transform, child_info->position);
|
||||
|
||||
gtk_widget_allocate (child,
|
||||
child_req.width,
|
||||
child_req.height,
|
||||
-1,
|
||||
child_info->position);
|
||||
transform);
|
||||
|
||||
gsk_transform_unref (transform);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,3 +336,56 @@ gtk_fixed_layout_new (void)
|
||||
{
|
||||
return g_object_new (GTK_TYPE_FIXED_LAYOUT, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_fixed_layout_set_minimum_size (GtkFixedLayout *layout,
|
||||
int min_width,
|
||||
int min_height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FIXED_LAYOUT (layout));
|
||||
|
||||
if (layout->min_width != min_width)
|
||||
layout->min_width = min_width;
|
||||
|
||||
if (layout->min_height != min_height)
|
||||
layout->min_height = min_height;
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
|
||||
}
|
||||
|
||||
void
|
||||
gtk_fixed_layout_get_minimum_size (GtkFixedLayout *layout,
|
||||
int *min_width,
|
||||
int *min_height)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FIXED_LAYOUT (layout));
|
||||
|
||||
if (min_width != NULL)
|
||||
*min_width = layout->min_width;
|
||||
|
||||
if (min_height != NULL)
|
||||
*min_height = layout->min_height;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_fixed_layout_set_child_transform (GtkFixedLayout *layout,
|
||||
GskTransform *transform)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_FIXED_LAYOUT (layout));
|
||||
|
||||
if (layout->child_transform == transform)
|
||||
return;
|
||||
|
||||
gsk_transform_unref (layout->child_transform);
|
||||
layout->child_transform = gsk_transform_ref (transform);
|
||||
|
||||
gtk_layout_manager_layout_changed (GTK_LAYOUT_MANAGER (layout));
|
||||
}
|
||||
|
||||
GskTransform *
|
||||
gtk_fixed_layout_get_child_transform (GtkFixedLayout *layout)
|
||||
{
|
||||
g_return_val_if_fail (GTK_IS_FIXED_LAYOUT (layout), NULL);
|
||||
|
||||
return layout->child_transform;
|
||||
}
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gsk/gsk.h>
|
||||
#include <gtk/gtklayoutmanager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
@@ -35,6 +36,20 @@ G_DECLARE_FINAL_TYPE (GtkFixedLayout, gtk_fixed_layout, GTK, FIXED_LAYOUT, GtkLa
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GtkLayoutManager * gtk_fixed_layout_new (void);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_fixed_layout_set_minimum_size (GtkFixedLayout *layout,
|
||||
int min_width,
|
||||
int min_height);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_fixed_layout_get_minimum_size (GtkFixedLayout *layout,
|
||||
int *min_width,
|
||||
int *min_height);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gtk_fixed_layout_set_child_transform (GtkFixedLayout *layout,
|
||||
GskTransform *transform);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GskTransform * gtk_fixed_layout_get_child_transform (GtkFixedLayout *layout);
|
||||
|
||||
/* GtkFixedLayoutChild */
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
|
Reference in New Issue
Block a user