X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtklayout.c;h=73cdb62f2ac50fceb0166ec8a7389c904a01cb83;hb=HEAD;hp=79d11e436071a2209b1e7884d6e3f648ee4933ef;hpb=867a82c36e49d54dc9ec6f1eb9443974148f0e2f;p=~andy%2Fgtk diff --git a/gtk/gtklayout.c b/gtk/gtklayout.c index 79d11e436..73cdb62f2 100644 --- a/gtk/gtklayout.c +++ b/gtk/gtklayout.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . * * GtkLayout: Widget for scrolling of arbitrary-sized areas. * @@ -29,16 +27,68 @@ */ #include "config.h" -#include "gdkconfig.h" #include "gtklayout.h" -#include "gtkprivate.h" + +#include "gdk/gdk.h" + +#include "gtkadjustment.h" #include "gtkintl.h" #include "gtkmarshalers.h" -#include "gtkalias.h" +#include "gtkprivate.h" +#include "gtkscrollable.h" + + +/** + * SECTION:gtklayout + * @Short_description: Infinite scrollable area containing child widgets + * and/or custom drawing + * @Title: GtkLayout + * @See_also: #GtkDrawingArea, #GtkScrolledWindow + * + * #GtkLayout is similar to #GtkDrawingArea in that it's a "blank slate" + * and doesn't do anything but paint a blank background by default. It's + * different in that it supports scrolling natively (you can add it to a + * #GtkScrolledWindow), and it can contain child widgets, since it's a + * #GtkContainer. However if you're just going to draw, a #GtkDrawingArea + * is a better choice since it has lower overhead. + * + * When handling expose events on a #GtkLayout, you must draw to + * GTK_LAYOUT (layout)->bin_window, rather than to + * GTK_WIDGET (layout)->window, as you would for a drawing + * area. + */ + typedef struct _GtkLayoutChild GtkLayoutChild; +struct _GtkLayoutPrivate +{ + /* Properties */ + guint width; + guint height; + + GtkAdjustment *hadjustment; + GtkAdjustment *vadjustment; + + /* GtkScrollablePolicy needs to be checked when + * driving the scrollable adjustment values */ + guint hscroll_policy : 1; + guint vscroll_policy : 1; + + /* Properties */ + + GdkVisibilityState visibility; + GdkWindow *bin_window; + + GList *children; + + gint scroll_x; + gint scroll_y; + + guint freeze_count; +}; + struct _GtkLayoutChild { GtkWidget *widget; gint x; @@ -49,6 +99,8 @@ enum { PROP_0, PROP_HADJUSTMENT, PROP_VADJUSTMENT, + PROP_HSCROLL_POLICY, + PROP_VSCROLL_POLICY, PROP_WIDTH, PROP_HEIGHT }; @@ -67,19 +119,20 @@ static void gtk_layout_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); -static GObject *gtk_layout_constructor (GType type, - guint n_properties, - GObjectConstructParam *properties); static void gtk_layout_finalize (GObject *object); static void gtk_layout_realize (GtkWidget *widget); static void gtk_layout_unrealize (GtkWidget *widget); static void gtk_layout_map (GtkWidget *widget); -static void gtk_layout_size_request (GtkWidget *widget, - GtkRequisition *requisition); +static void gtk_layout_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural); +static void gtk_layout_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural); static void gtk_layout_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gint gtk_layout_expose (GtkWidget *widget, - GdkEventExpose *event); +static gint gtk_layout_draw (GtkWidget *widget, + cairo_t *cr); static void gtk_layout_add (GtkContainer *container, GtkWidget *widget); static void gtk_layout_remove (GtkContainer *container, @@ -88,9 +141,6 @@ static void gtk_layout_forall (GtkContainer *container, gboolean include_internals, GtkCallback callback, gpointer callback_data); -static void gtk_layout_set_adjustments (GtkLayout *layout, - GtkAdjustment *hadj, - GtkAdjustment *vadj); static void gtk_layout_set_child_property (GtkContainer *container, GtkWidget *child, guint property_id, @@ -105,21 +155,20 @@ static void gtk_layout_allocate_child (GtkLayout *layout, GtkLayoutChild *child); static void gtk_layout_adjustment_changed (GtkAdjustment *adjustment, GtkLayout *layout); -static void gtk_layout_style_set (GtkWidget *widget, - GtkStyle *old_style); +static void gtk_layout_style_updated (GtkWidget *widget); -static void gtk_layout_set_adjustment_upper (GtkAdjustment *adj, - gdouble upper, - gboolean always_emit_changed); +static void gtk_layout_set_hadjustment_values (GtkLayout *layout); +static void gtk_layout_set_vadjustment_values (GtkLayout *layout); -G_DEFINE_TYPE (GtkLayout, gtk_layout, GTK_TYPE_CONTAINER) +G_DEFINE_TYPE_WITH_CODE (GtkLayout, gtk_layout, GTK_TYPE_CONTAINER, + G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL)) /* Public interface */ /** * gtk_layout_new: - * @hadjustment: horizontal scroll adjustment, or %NULL - * @vadjustment: vertical scroll adjustment, or %NULL + * @hadjustment: (allow-none): horizontal scroll adjustment, or %NULL + * @vadjustment: (allow-none): vertical scroll adjustment, or %NULL * * Creates a new #GtkLayout. Unless you have a specific adjustment * you'd like the layout to use for scrolling, pass %NULL for @@ -145,10 +194,10 @@ gtk_layout_new (GtkAdjustment *hadjustment, /** * gtk_layout_get_bin_window: * @layout: a #GtkLayout - * + * * Retrieve the bin window of the layout used for drawing operations. - * - * Return value: a #GdkWindow + * + * Return value: (transfer none): a #GdkWindow * * Since: 2.14 **/ @@ -157,178 +206,231 @@ gtk_layout_get_bin_window (GtkLayout *layout) { g_return_val_if_fail (GTK_IS_LAYOUT (layout), NULL); - return layout->bin_window; + return layout->priv->bin_window; } /** * gtk_layout_get_hadjustment: * @layout: a #GtkLayout - * + * * This function should only be called after the layout has been * placed in a #GtkScrolledWindow or otherwise configured for * scrolling. It returns the #GtkAdjustment used for communication * between the horizontal scrollbar and @layout. * * See #GtkScrolledWindow, #GtkScrollbar, #GtkAdjustment for details. - * - * Return value: horizontal scroll adjustment + * + * Return value: (transfer none): horizontal scroll adjustment + * + * Deprecated: 3.0: Use gtk_scrollable_get_hadjustment() **/ -GtkAdjustment* -gtk_layout_get_hadjustment (GtkLayout *layout) +GtkAdjustment* +gtk_layout_get_hadjustment (GtkLayout *layout) { g_return_val_if_fail (GTK_IS_LAYOUT (layout), NULL); - return layout->hadjustment; + return layout->priv->hadjustment; } /** * gtk_layout_get_vadjustment: * @layout: a #GtkLayout - * + * * This function should only be called after the layout has been * placed in a #GtkScrolledWindow or otherwise configured for * scrolling. It returns the #GtkAdjustment used for communication * between the vertical scrollbar and @layout. * * See #GtkScrolledWindow, #GtkScrollbar, #GtkAdjustment for details. - * - * Return value: vertical scroll adjustment + * + * Return value: (transfer none): vertical scroll adjustment + * + * Deprecated: 3.0: Use gtk_scrollable_get_vadjustment() **/ -GtkAdjustment* -gtk_layout_get_vadjustment (GtkLayout *layout) +GtkAdjustment* +gtk_layout_get_vadjustment (GtkLayout *layout) { g_return_val_if_fail (GTK_IS_LAYOUT (layout), NULL); - return layout->vadjustment; + return layout->priv->vadjustment; } -static GtkAdjustment * -new_default_adjustment (void) +static void +gtk_layout_set_hadjustment_values (GtkLayout *layout) { - return GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); + GtkLayoutPrivate *priv = layout->priv; + GtkAllocation allocation; + GtkAdjustment *adj = priv->hadjustment; + gdouble old_value; + gdouble new_value; + gdouble new_upper; + + gtk_widget_get_allocation (GTK_WIDGET (layout), &allocation); + + old_value = gtk_adjustment_get_value (adj); + new_upper = MAX (allocation.width, priv->width); + + g_object_set (adj, + "lower", 0.0, + "upper", new_upper, + "page-size", (gdouble)allocation.width, + "step-increment", allocation.width * 0.1, + "page-increment", allocation.width * 0.9, + NULL); + + new_value = CLAMP (old_value, 0, new_upper - allocation.width); + if (new_value != old_value) + gtk_adjustment_set_value (adj, new_value); } -static void -gtk_layout_set_adjustments (GtkLayout *layout, - GtkAdjustment *hadj, - GtkAdjustment *vadj) +static void +gtk_layout_set_vadjustment_values (GtkLayout *layout) { - gboolean need_adjust = FALSE; - - g_return_if_fail (GTK_IS_LAYOUT (layout)); - - if (hadj) - g_return_if_fail (GTK_IS_ADJUSTMENT (hadj)); - else if (layout->hadjustment) - hadj = new_default_adjustment (); - if (vadj) - g_return_if_fail (GTK_IS_ADJUSTMENT (vadj)); - else if (layout->vadjustment) - vadj = new_default_adjustment (); - - if (layout->hadjustment && (layout->hadjustment != hadj)) - { - g_signal_handlers_disconnect_by_func (layout->hadjustment, - gtk_layout_adjustment_changed, - layout); - g_object_unref (layout->hadjustment); - } - - if (layout->vadjustment && (layout->vadjustment != vadj)) - { - g_signal_handlers_disconnect_by_func (layout->vadjustment, - gtk_layout_adjustment_changed, - layout); - g_object_unref (layout->vadjustment); - } - - if (layout->hadjustment != hadj) - { - layout->hadjustment = hadj; - g_object_ref_sink (layout->hadjustment); - gtk_layout_set_adjustment_upper (layout->hadjustment, layout->width, FALSE); - - g_signal_connect (layout->hadjustment, "value-changed", - G_CALLBACK (gtk_layout_adjustment_changed), - layout); - need_adjust = TRUE; - } - - if (layout->vadjustment != vadj) - { - layout->vadjustment = vadj; - g_object_ref_sink (layout->vadjustment); - gtk_layout_set_adjustment_upper (layout->vadjustment, layout->height, FALSE); - - g_signal_connect (layout->vadjustment, "value-changed", - G_CALLBACK (gtk_layout_adjustment_changed), - layout); - need_adjust = TRUE; - } - - /* vadj or hadj can be NULL while constructing; don't emit a signal - then */ - if (need_adjust && vadj && hadj) - gtk_layout_adjustment_changed (NULL, layout); + GtkAllocation allocation; + GtkAdjustment *adj = layout->priv->vadjustment; + gdouble old_value; + gdouble new_value; + gdouble new_upper; + + gtk_widget_get_allocation (GTK_WIDGET (layout), &allocation); + + old_value = gtk_adjustment_get_value (adj); + new_upper = MAX (allocation.height, layout->priv->height); + + g_object_set (adj, + "lower", 0.0, + "upper", new_upper, + "page-size", (gdouble)allocation.height, + "step-increment", allocation.height * 0.1, + "page-increment", allocation.height * 0.9, + NULL); + + new_value = CLAMP (old_value, 0, new_upper - allocation.height); + if (new_value != old_value) + gtk_adjustment_set_value (adj, new_value); } static void gtk_layout_finalize (GObject *object) { GtkLayout *layout = GTK_LAYOUT (object); + GtkLayoutPrivate *priv = layout->priv; - g_object_unref (layout->hadjustment); - g_object_unref (layout->vadjustment); + g_object_unref (priv->hadjustment); + g_object_unref (priv->vadjustment); G_OBJECT_CLASS (gtk_layout_parent_class)->finalize (object); } +static void +gtk_layout_do_set_hadjustment (GtkLayout *layout, + GtkAdjustment *adjustment) +{ + GtkLayoutPrivate *priv; + + priv = layout->priv; + + if (adjustment && priv->hadjustment == adjustment) + return; + + if (priv->hadjustment != NULL) + { + g_signal_handlers_disconnect_by_func (priv->hadjustment, + gtk_layout_adjustment_changed, + layout); + 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 (adjustment, "value-changed", + G_CALLBACK (gtk_layout_adjustment_changed), layout); + priv->hadjustment = g_object_ref_sink (adjustment); + gtk_layout_set_hadjustment_values (layout); + + g_object_notify (G_OBJECT (layout), "hadjustment"); +} + /** * gtk_layout_set_hadjustment: * @layout: a #GtkLayout - * @adjustment: new scroll adjustment + * @adjustment: (allow-none): new scroll adjustment * * Sets the horizontal scroll adjustment for the layout. * * See #GtkScrolledWindow, #GtkScrollbar, #GtkAdjustment for details. - * + * + * Deprecated: 3.0: Use gtk_scrollable_set_hadjustment() **/ -void +void gtk_layout_set_hadjustment (GtkLayout *layout, - GtkAdjustment *adjustment) + GtkAdjustment *adjustment) { g_return_if_fail (GTK_IS_LAYOUT (layout)); + g_return_if_fail (adjustment == NULL || GTK_IS_ADJUSTMENT (adjustment)); - gtk_layout_set_adjustments (layout, adjustment, layout->vadjustment); - g_object_notify (G_OBJECT (layout), "hadjustment"); + gtk_layout_do_set_hadjustment (layout, adjustment); } - + +static void +gtk_layout_do_set_vadjustment (GtkLayout *layout, + GtkAdjustment *adjustment) +{ + GtkLayoutPrivate *priv; + + priv = layout->priv; + + if (adjustment && priv->vadjustment == adjustment) + return; + + if (priv->vadjustment != NULL) + { + g_signal_handlers_disconnect_by_func (priv->vadjustment, + gtk_layout_adjustment_changed, + layout); + 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 (adjustment, "value-changed", + G_CALLBACK (gtk_layout_adjustment_changed), layout); + priv->vadjustment = g_object_ref_sink (adjustment); + gtk_layout_set_vadjustment_values (layout); + + g_object_notify (G_OBJECT (layout), "vadjustment"); +} + /** * gtk_layout_set_vadjustment: * @layout: a #GtkLayout - * @adjustment: new scroll adjustment + * @adjustment: (allow-none): new scroll adjustment * * Sets the vertical scroll adjustment for the layout. * * See #GtkScrolledWindow, #GtkScrollbar, #GtkAdjustment for details. - * + * + * Deprecated: 3.0: Use gtk_scrollable_set_vadjustment() **/ -void +void gtk_layout_set_vadjustment (GtkLayout *layout, - GtkAdjustment *adjustment) + GtkAdjustment *adjustment) { g_return_if_fail (GTK_IS_LAYOUT (layout)); - - gtk_layout_set_adjustments (layout, layout->hadjustment, adjustment); - g_object_notify (G_OBJECT (layout), "vadjustment"); + g_return_if_fail (adjustment == NULL || GTK_IS_ADJUSTMENT (adjustment)); + + gtk_layout_do_set_vadjustment (layout, adjustment); } static GtkLayoutChild* get_child (GtkLayout *layout, GtkWidget *widget) { + GtkLayoutPrivate *priv = layout->priv; GList *children; - - children = layout->children; + + children = priv->children; while (children) { GtkLayoutChild *child; @@ -360,21 +462,24 @@ gtk_layout_put (GtkLayout *layout, gint x, gint y) { + GtkLayoutPrivate *priv; GtkLayoutChild *child; g_return_if_fail (GTK_IS_LAYOUT (layout)); g_return_if_fail (GTK_IS_WIDGET (child_widget)); - + + priv = layout->priv; + child = g_new (GtkLayoutChild, 1); child->widget = child_widget; child->x = x; child->y = y; - layout->children = g_list_append (layout->children, child); - - if (GTK_WIDGET_REALIZED (layout)) - gtk_widget_set_parent_window (child->widget, layout->bin_window); + priv->children = g_list_append (priv->children, child); + + if (gtk_widget_get_realized (GTK_WIDGET (layout))) + gtk_widget_set_parent_window (child->widget, priv->bin_window); gtk_widget_set_parent (child_widget, GTK_WIDGET (layout)); } @@ -409,8 +514,9 @@ gtk_layout_move_internal (GtkLayout *layout, gtk_widget_thaw_child_notify (widget); - if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (layout)) - gtk_widget_queue_resize (GTK_WIDGET (widget)); + if (gtk_widget_get_visible (widget) && + gtk_widget_get_visible (GTK_WIDGET (layout))) + gtk_widget_queue_resize (widget); } /** @@ -431,39 +537,11 @@ gtk_layout_move (GtkLayout *layout, { g_return_if_fail (GTK_IS_LAYOUT (layout)); g_return_if_fail (GTK_IS_WIDGET (child_widget)); - g_return_if_fail (child_widget->parent == GTK_WIDGET (layout)); + g_return_if_fail (gtk_widget_get_parent (child_widget) == GTK_WIDGET (layout)); gtk_layout_move_internal (layout, child_widget, TRUE, x, TRUE, y); } -static void -gtk_layout_set_adjustment_upper (GtkAdjustment *adj, - gdouble upper, - gboolean always_emit_changed) -{ - gboolean changed = FALSE; - gboolean value_changed = FALSE; - - gdouble min = MAX (0., upper - adj->page_size); - - if (upper != adj->upper) - { - adj->upper = upper; - changed = TRUE; - } - - if (adj->value > min) - { - adj->value = min; - value_changed = TRUE; - } - - if (changed || always_emit_changed) - gtk_adjustment_changed (adj); - if (value_changed) - gtk_adjustment_value_changed (adj); -} - /** * gtk_layout_set_size: * @layout: a #GtkLayout @@ -478,43 +556,48 @@ gtk_layout_set_size (GtkLayout *layout, guint width, guint height) { + GtkLayoutPrivate *priv; GtkWidget *widget; - + g_return_if_fail (GTK_IS_LAYOUT (layout)); - + + priv = layout->priv; widget = GTK_WIDGET (layout); - + g_object_freeze_notify (G_OBJECT (layout)); - if (width != layout->width) + if (width != priv->width) { - layout->width = width; + priv->width = width; g_object_notify (G_OBJECT (layout), "width"); } - if (height != layout->height) + if (height != priv->height) { - layout->height = height; + priv->height = height; g_object_notify (G_OBJECT (layout), "height"); } g_object_thaw_notify (G_OBJECT (layout)); - if (layout->hadjustment) - gtk_layout_set_adjustment_upper (layout->hadjustment, layout->width, FALSE); - if (layout->vadjustment) - gtk_layout_set_adjustment_upper (layout->vadjustment, layout->height, FALSE); - - if (GTK_WIDGET_REALIZED (layout)) + if (gtk_widget_get_realized (widget)) { - width = MAX (width, widget->allocation.width); - height = MAX (height, widget->allocation.height); - gdk_window_resize (layout->bin_window, width, height); + GtkAllocation allocation; + + gtk_widget_get_allocation (widget, &allocation); + width = MAX (width, allocation.width); + height = MAX (height, allocation.height); + gdk_window_resize (priv->bin_window, width, height); } + + gtk_layout_set_hadjustment_values (layout); + gtk_layout_set_vadjustment_values (layout); } /** * gtk_layout_get_size: * @layout: a #GtkLayout - * @width: location to store the width set on @layout, or %NULL - * @height: location to store the height set on @layout, or %NULL + * @width: (out) (allow-none): location to store the width set on + * @layout, or %NULL + * @height: (out) (allow-none): location to store the height set on + * @layout, or %NULL * * Gets the size that has been set on the layout, and that determines * the total extents of the layout's scrollbar area. See @@ -525,48 +608,16 @@ gtk_layout_get_size (GtkLayout *layout, guint *width, guint *height) { - g_return_if_fail (GTK_IS_LAYOUT (layout)); - - if (width) - *width = layout->width; - if (height) - *height = layout->height; -} - -/** - * gtk_layout_freeze: - * @layout: a #GtkLayout - * - * This is a deprecated function, it doesn't do anything useful. - **/ -void -gtk_layout_freeze (GtkLayout *layout) -{ - g_return_if_fail (GTK_IS_LAYOUT (layout)); - - layout->freeze_count++; -} + GtkLayoutPrivate *priv; -/** - * gtk_layout_thaw: - * @layout: a #GtkLayout - * - * This is a deprecated function, it doesn't do anything useful. - **/ -void -gtk_layout_thaw (GtkLayout *layout) -{ g_return_if_fail (GTK_IS_LAYOUT (layout)); - if (layout->freeze_count) - { - if (!(--layout->freeze_count)) - { - gtk_widget_queue_draw (GTK_WIDGET (layout)); - gdk_window_process_updates (GTK_WIDGET (layout)->window, TRUE); - } - } + priv = layout->priv; + if (width) + *width = priv->width; + if (height) + *height = priv->height; } /* Basic Object handling procedures @@ -585,7 +636,6 @@ gtk_layout_class_init (GtkLayoutClass *class) gobject_class->set_property = gtk_layout_set_property; gobject_class->get_property = gtk_layout_get_property; gobject_class->finalize = gtk_layout_finalize; - gobject_class->constructor = gtk_layout_constructor; container_class->set_child_property = gtk_layout_set_child_property; container_class->get_child_property = gtk_layout_get_child_property; @@ -610,21 +660,11 @@ gtk_layout_class_init (GtkLayoutClass *class) 0, GTK_PARAM_READWRITE)); - g_object_class_install_property (gobject_class, - PROP_HADJUSTMENT, - g_param_spec_object ("hadjustment", - P_("Horizontal adjustment"), - P_("The GtkAdjustment for the horizontal position"), - GTK_TYPE_ADJUSTMENT, - GTK_PARAM_READWRITE)); - - g_object_class_install_property (gobject_class, - PROP_VADJUSTMENT, - g_param_spec_object ("vadjustment", - P_("Vertical adjustment"), - P_("The GtkAdjustment for the vertical position"), - GTK_TYPE_ADJUSTMENT, - GTK_PARAM_READWRITE)); + /* 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"); g_object_class_install_property (gobject_class, PROP_WIDTH, @@ -647,27 +687,17 @@ gtk_layout_class_init (GtkLayoutClass *class) widget_class->realize = gtk_layout_realize; widget_class->unrealize = gtk_layout_unrealize; widget_class->map = gtk_layout_map; - widget_class->size_request = gtk_layout_size_request; + widget_class->get_preferred_width = gtk_layout_get_preferred_width; + widget_class->get_preferred_height = gtk_layout_get_preferred_height; widget_class->size_allocate = gtk_layout_size_allocate; - widget_class->expose_event = gtk_layout_expose; - widget_class->style_set = gtk_layout_style_set; + widget_class->draw = gtk_layout_draw; + widget_class->style_updated = gtk_layout_style_updated; container_class->add = gtk_layout_add; container_class->remove = gtk_layout_remove; container_class->forall = gtk_layout_forall; - class->set_scroll_adjustments = gtk_layout_set_adjustments; - - widget_class->set_scroll_adjustments_signal = - g_signal_new (I_("set_scroll_adjustments"), - G_OBJECT_CLASS_TYPE (gobject_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GtkLayoutClass, set_scroll_adjustments), - NULL, NULL, - _gtk_marshal_VOID__OBJECT_OBJECT, - G_TYPE_NONE, 2, - GTK_TYPE_ADJUSTMENT, - GTK_TYPE_ADJUSTMENT); + g_type_class_add_private (class, sizeof (GtkLayoutPrivate)); } static void @@ -677,20 +707,27 @@ gtk_layout_get_property (GObject *object, GParamSpec *pspec) { GtkLayout *layout = GTK_LAYOUT (object); - + GtkLayoutPrivate *priv = layout->priv; + switch (prop_id) { case PROP_HADJUSTMENT: - g_value_set_object (value, layout->hadjustment); + g_value_set_object (value, priv->hadjustment); break; case PROP_VADJUSTMENT: - g_value_set_object (value, layout->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; case PROP_WIDTH: - g_value_set_uint (value, layout->width); + g_value_set_uint (value, priv->width); break; case PROP_HEIGHT: - g_value_set_uint (value, layout->height); + g_value_set_uint (value, priv->height); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -705,23 +742,30 @@ gtk_layout_set_property (GObject *object, GParamSpec *pspec) { GtkLayout *layout = GTK_LAYOUT (object); - + GtkLayoutPrivate *priv = layout->priv; + switch (prop_id) { case PROP_HADJUSTMENT: - gtk_layout_set_hadjustment (layout, - (GtkAdjustment*) g_value_get_object (value)); + gtk_layout_do_set_hadjustment (layout, g_value_get_object (value)); break; case PROP_VADJUSTMENT: - gtk_layout_set_vadjustment (layout, - (GtkAdjustment*) g_value_get_object (value)); + gtk_layout_do_set_vadjustment (layout, g_value_get_object (value)); + break; + case PROP_HSCROLL_POLICY: + priv->hscroll_policy = g_value_get_enum (value); + gtk_widget_queue_resize (GTK_WIDGET (layout)); + break; + case PROP_VSCROLL_POLICY: + priv->vscroll_policy = g_value_get_enum (value); + gtk_widget_queue_resize (GTK_WIDGET (layout)); break; case PROP_WIDTH: gtk_layout_set_size (layout, g_value_get_uint (value), - layout->height); + priv->height); break; case PROP_HEIGHT: - gtk_layout_set_size (layout, layout->width, + gtk_layout_set_size (layout, priv->width, g_value_get_uint (value)); break; default: @@ -785,45 +829,28 @@ gtk_layout_get_child_property (GtkContainer *container, static void gtk_layout_init (GtkLayout *layout) { - layout->children = NULL; - - layout->width = 100; - layout->height = 100; - - layout->hadjustment = NULL; - layout->vadjustment = NULL; + GtkLayoutPrivate *priv; - layout->bin_window = NULL; + layout->priv = G_TYPE_INSTANCE_GET_PRIVATE (layout, + GTK_TYPE_LAYOUT, + GtkLayoutPrivate); + priv = layout->priv; - layout->scroll_x = 0; - layout->scroll_y = 0; - layout->visibility = GDK_VISIBILITY_PARTIAL; + priv->children = NULL; - layout->freeze_count = 0; -} - -static GObject * -gtk_layout_constructor (GType type, - guint n_properties, - GObjectConstructParam *properties) -{ - GtkLayout *layout; - GObject *object; - GtkAdjustment *hadj, *vadj; - - object = G_OBJECT_CLASS (gtk_layout_parent_class)->constructor (type, - n_properties, - properties); + priv->width = 100; + priv->height = 100; - layout = GTK_LAYOUT (object); + priv->hadjustment = NULL; + priv->vadjustment = NULL; - hadj = layout->hadjustment ? layout->hadjustment : new_default_adjustment (); - vadj = layout->vadjustment ? layout->vadjustment : new_default_adjustment (); + priv->bin_window = NULL; - if (!layout->hadjustment || !layout->vadjustment) - gtk_layout_set_adjustments (layout, hadj, vadj); + priv->scroll_x = 0; + priv->scroll_y = 0; + priv->visibility = GDK_VISIBILITY_PARTIAL; - return object; + priv->freeze_count = 0; } /* Widget methods @@ -833,62 +860,69 @@ static void gtk_layout_realize (GtkWidget *widget) { GtkLayout *layout = GTK_LAYOUT (widget); - GList *tmp_list; + GtkLayoutPrivate *priv = layout->priv; + GtkAllocation allocation; + GdkWindow *window; GdkWindowAttr attributes; + GList *tmp_list; gint attributes_mask; - GTK_WIDGET_SET_FLAGS (layout, GTK_REALIZED); + gtk_widget_set_realized (widget, TRUE); + + gtk_widget_get_allocation (widget, &allocation); attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = widget->allocation.x; - attributes.y = widget->allocation.y; - attributes.width = widget->allocation.width; - attributes.height = widget->allocation.height; + attributes.x = allocation.x; + attributes.y = allocation.y; + attributes.width = allocation.width; + attributes.height = allocation.height; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK; - attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); - gdk_window_set_back_pixmap (widget->window, NULL, FALSE); - gdk_window_set_user_data (widget->window, widget); + window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gtk_widget_set_window (widget, window); + gtk_widget_register_window (widget, window); - attributes.x = - layout->hadjustment->value, - attributes.y = - layout->vadjustment->value; - attributes.width = MAX (layout->width, widget->allocation.width); - attributes.height = MAX (layout->height, widget->allocation.height); - attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | - gtk_widget_get_events (widget); + gtk_widget_get_allocation (widget, &allocation); - layout->bin_window = gdk_window_new (widget->window, - &attributes, attributes_mask); - gdk_window_set_user_data (layout->bin_window, widget); + attributes.x = - gtk_adjustment_get_value (priv->hadjustment), + attributes.y = - gtk_adjustment_get_value (priv->vadjustment); + attributes.width = MAX (priv->width, allocation.width); + attributes.height = MAX (priv->height, allocation.height); + attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | + GDK_SMOOTH_SCROLL_MASK | + gtk_widget_get_events (widget); - widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, layout->bin_window, GTK_STATE_NORMAL); + priv->bin_window = gdk_window_new (window, + &attributes, attributes_mask); + gtk_widget_register_window (widget, priv->bin_window); + gtk_style_context_set_background (gtk_widget_get_style_context (widget), priv->bin_window); - tmp_list = layout->children; + tmp_list = priv->children; while (tmp_list) { GtkLayoutChild *child = tmp_list->data; tmp_list = tmp_list->next; - gtk_widget_set_parent_window (child->widget, layout->bin_window); + gtk_widget_set_parent_window (child->widget, priv->bin_window); } } static void -gtk_layout_style_set (GtkWidget *widget, GtkStyle *old_style) +gtk_layout_style_updated (GtkWidget *widget) { - if (GTK_WIDGET_CLASS (gtk_layout_parent_class)->style_set) - (* GTK_WIDGET_CLASS (gtk_layout_parent_class)->style_set) (widget, old_style); + GtkLayoutPrivate *priv; + + GTK_WIDGET_CLASS (gtk_layout_parent_class)->style_updated (widget); - if (GTK_WIDGET_REALIZED (widget)) + if (gtk_widget_get_realized (widget)) { - gtk_style_set_background (widget->style, GTK_LAYOUT (widget)->bin_window, GTK_STATE_NORMAL); + priv = GTK_LAYOUT (widget)->priv; + gtk_style_context_set_background (gtk_widget_get_style_context (widget), priv->bin_window); } } @@ -896,73 +930,68 @@ static void gtk_layout_map (GtkWidget *widget) { GtkLayout *layout = GTK_LAYOUT (widget); + GtkLayoutPrivate *priv = layout->priv; GList *tmp_list; - GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); + gtk_widget_set_mapped (widget, TRUE); - tmp_list = layout->children; + tmp_list = priv->children; while (tmp_list) { GtkLayoutChild *child = tmp_list->data; tmp_list = tmp_list->next; - if (GTK_WIDGET_VISIBLE (child->widget)) + if (gtk_widget_get_visible (child->widget)) { - if (!GTK_WIDGET_MAPPED (child->widget)) + if (!gtk_widget_get_mapped (child->widget)) gtk_widget_map (child->widget); } } - gdk_window_show (layout->bin_window); - gdk_window_show (widget->window); + gdk_window_show (priv->bin_window); + gdk_window_show (gtk_widget_get_window (widget)); } static void gtk_layout_unrealize (GtkWidget *widget) { GtkLayout *layout = GTK_LAYOUT (widget); + GtkLayoutPrivate *priv = layout->priv; - gdk_window_set_user_data (layout->bin_window, NULL); - gdk_window_destroy (layout->bin_window); - layout->bin_window = NULL; + gtk_widget_unregister_window (widget, priv->bin_window); + gdk_window_destroy (priv->bin_window); + priv->bin_window = NULL; - if (GTK_WIDGET_CLASS (gtk_layout_parent_class)->unrealize) - (* GTK_WIDGET_CLASS (gtk_layout_parent_class)->unrealize) (widget); + GTK_WIDGET_CLASS (gtk_layout_parent_class)->unrealize (widget); } -static void -gtk_layout_size_request (GtkWidget *widget, - GtkRequisition *requisition) +static void +gtk_layout_get_preferred_width (GtkWidget *widget, + gint *minimum, + gint *natural) { - GtkLayout *layout = GTK_LAYOUT (widget); - GList *tmp_list; - - requisition->width = 0; - requisition->height = 0; - - tmp_list = layout->children; - - while (tmp_list) - { - GtkLayoutChild *child = tmp_list->data; - GtkRequisition child_requisition; - - tmp_list = tmp_list->next; + *minimum = *natural = 0; +} - gtk_widget_size_request (child->widget, &child_requisition); - } +static void +gtk_layout_get_preferred_height (GtkWidget *widget, + gint *minimum, + gint *natural) +{ + *minimum = *natural = 0; } -static void +static void gtk_layout_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkLayout *layout = GTK_LAYOUT (widget); + GtkLayoutPrivate *priv = layout->priv; GList *tmp_list; - widget->allocation = *allocation; + gtk_widget_set_allocation (widget, allocation); - tmp_list = layout->children; + tmp_list = priv->children; while (tmp_list) { @@ -972,40 +1001,30 @@ gtk_layout_size_allocate (GtkWidget *widget, gtk_layout_allocate_child (layout, child); } - if (GTK_WIDGET_REALIZED (widget)) + if (gtk_widget_get_realized (widget)) { - gdk_window_move_resize (widget->window, + gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x, allocation->y, allocation->width, allocation->height); - gdk_window_resize (layout->bin_window, - MAX (layout->width, allocation->width), - MAX (layout->height, allocation->height)); + gdk_window_resize (priv->bin_window, + MAX (priv->width, allocation->width), + MAX (priv->height, allocation->height)); } - layout->hadjustment->page_size = allocation->width; - layout->hadjustment->page_increment = allocation->width * 0.9; - layout->hadjustment->lower = 0; - /* set_adjustment_upper() emits ::changed */ - gtk_layout_set_adjustment_upper (layout->hadjustment, MAX (allocation->width, layout->width), TRUE); - - layout->vadjustment->page_size = allocation->height; - layout->vadjustment->page_increment = allocation->height * 0.9; - layout->vadjustment->lower = 0; - layout->vadjustment->upper = MAX (allocation->height, layout->height); - gtk_layout_set_adjustment_upper (layout->vadjustment, MAX (allocation->height, layout->height), TRUE); + gtk_layout_set_hadjustment_values (layout); + gtk_layout_set_vadjustment_values (layout); } -static gint -gtk_layout_expose (GtkWidget *widget, - GdkEventExpose *event) +static gboolean +gtk_layout_draw (GtkWidget *widget, + cairo_t *cr) { GtkLayout *layout = GTK_LAYOUT (widget); + GtkLayoutPrivate *priv = layout->priv; - if (event->window != layout->bin_window) - return FALSE; - - (* GTK_WIDGET_CLASS (gtk_layout_parent_class)->expose_event) (widget, event); + if (gtk_cairo_should_draw_window (cr, priv->bin_window)) + GTK_WIDGET_CLASS (gtk_layout_parent_class)->draw (widget, cr); return FALSE; } @@ -1024,10 +1043,11 @@ gtk_layout_remove (GtkContainer *container, GtkWidget *widget) { GtkLayout *layout = GTK_LAYOUT (container); + GtkLayoutPrivate *priv = layout->priv; GList *tmp_list; GtkLayoutChild *child = NULL; - tmp_list = layout->children; + tmp_list = priv->children; while (tmp_list) { child = tmp_list->data; @@ -1040,7 +1060,7 @@ gtk_layout_remove (GtkContainer *container, { gtk_widget_unparent (widget); - layout->children = g_list_remove_link (layout->children, tmp_list); + priv->children = g_list_remove_link (priv->children, tmp_list); g_list_free_1 (tmp_list); g_free (child); } @@ -1053,10 +1073,11 @@ gtk_layout_forall (GtkContainer *container, gpointer callback_data) { GtkLayout *layout = GTK_LAYOUT (container); + GtkLayoutPrivate *priv = layout->priv; GtkLayoutChild *child; GList *tmp_list; - tmp_list = layout->children; + tmp_list = priv->children; while (tmp_list) { child = tmp_list->data; @@ -1078,7 +1099,8 @@ gtk_layout_allocate_child (GtkLayout *layout, allocation.x = child->x; allocation.y = child->y; - gtk_widget_get_child_requisition (child->widget, &requisition); + + gtk_widget_get_preferred_size (child->widget, &requisition, NULL); allocation.width = requisition.width; allocation.height = requisition.height; @@ -1091,18 +1113,15 @@ static void gtk_layout_adjustment_changed (GtkAdjustment *adjustment, GtkLayout *layout) { - if (layout->freeze_count) + GtkLayoutPrivate *priv = layout->priv; + + if (priv->freeze_count) return; - if (GTK_WIDGET_REALIZED (layout)) + if (gtk_widget_get_realized (GTK_WIDGET (layout))) { - gdk_window_move (layout->bin_window, - - layout->hadjustment->value, - - layout->vadjustment->value); - - gdk_window_process_updates (layout->bin_window, TRUE); + gdk_window_move (priv->bin_window, + - gtk_adjustment_get_value (priv->hadjustment), + - gtk_adjustment_get_value (priv->vadjustment)); } } - -#define __GTK_LAYOUT_C__ -#include "gtkaliasdef.c"