Compare commits

...

23 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
0d67a19173 hiding-box: expose publicly, update macros
This commit update the GtkHidingBox widget to
3.22 and exposes it publicly.
2016-04-23 20:58:00 -03:00
Carlos Soriano
5f69c23694 gtkhidingbox: add copyright and authors 2016-04-23 19:29:05 -03:00
Carlos Soriano
8702f3af72 gtkhidingbox: prefer width for height 2016-04-23 19:28:49 -03:00
Carlos Soriano
42d4ffe274 gtkhidingbox: add getter for overflow children
Useful to know which children cannot be shown, so clients
can manage themselves those.
A use case is GtkPathBar for the popup overflow menu.
2016-04-23 19:28:38 -03:00
Carlos Soriano
533eb042eb gtkhidingbox: fix wrong extra space distribution
It was using the whole allocation to distribute the space,
instead of the actual extra space.
2016-04-23 19:28:25 -03:00
Carlos Soriano
f730d92d29 gtkhidingbox: use internal gtk_widget_simple_clip 2016-04-23 19:28:15 -03:00
Carlos Soriano
24a5d205d6 gtkhidingbox: remove extra widgets pixels
I have to ask Rafał Lużyński why he added it... It makes everything
jumpy when reallocating.

Remove it for now.
2016-04-23 19:28:05 -03:00
Carlos Soriano
5120663737 gtkhidingbox: add property to choose side to handle overflow
i.e. The case of Nautilus and FileChooser GtkPathBar is that we always
want to show the end part of the path. However that might not be the
case for other uses, like gnome-software and its titles.
2016-04-23 19:27:52 -03:00
Carlos Soriano
3b6aed65dd gtkhidingbox: simplify visibility management
Extract a function, refactor, and manage the widget visibility
and child visibility at once, and use that for further checks.

This will be useful on a later patch when we add a property to choose
between hiding widget from the start or from the end, so we can allocate
or not children just checking the child visibility.
2016-04-23 19:27:17 -03:00
Carlos Soriano
a53c2e886b gtkhidingbox: take into account child expand property 2016-04-23 19:27:06 -03:00
Carlos Soriano
6a75fa6e7c gtkhidingbox: remove unneeded comment 2016-04-23 19:26:40 -03:00
Carlos Soriano
5c4b475d76 gtkhidingbox: use class_install_properties 2016-04-23 19:26:40 -03:00
Carlos Soriano
7682bafdd0 gtkhidingbox: don't nest unneeded loop 2016-04-23 19:26:40 -03:00
Carlos Soriano
4b2ee32f9e gtkhidingbox: use full variable names 2016-04-23 19:26:40 -03:00
Carlos Soriano
31de513be9 gtkhidingbox: use directly the parameters 2016-04-23 19:26:40 -03:00
Carlos Soriano
2e6b1a1fe2 gtkhidingbox: assume we always have min and nat pointers 2016-04-23 19:26:40 -03:00
Carlos Soriano
e2b9532bbf gtkhidingbox: use full variable names 2016-04-23 19:26:40 -03:00
Carlos Soriano
2d3e84161f gtkhidingbox: use the parameters directly 2016-04-23 19:26:40 -03:00
Carlos Soriano
eeb666f370 gtkhidingbox: we can assume we have min and nat pointers 2016-04-23 19:26:40 -03:00
Carlos Soriano
8dd40885f6 gtkhidingbox: reorder variables 2016-04-23 19:26:40 -03:00
Carlos Soriano
00b674ecd9 gtkhidingbox: reorder variables 2016-04-23 19:21:44 -03:00
Carlos Soriano
ad8a9ddaf9 gtkhidingbox: use full variable names
Instead of acronims
2016-04-23 19:21:31 -03:00
Carlos Soriano
a81b075958 Add GtkHidingBox
We didn't have a way to hide children given the allocation size
available set by the parent.
This is an use case for the GtkPathBar, which will be rewrote in future
patches where we will want to use a composite widget instead of a all
custom allocation widget.

For that, implement a container which hides widgets when the allocated
size is smaller than the requested size by its children.
The code is made by Rafał Lużyński for gnome-software and is adapted to
Gtk+ standards.

Now will follow a few patches improving the code and adding support
for some features needed by the GtkPathBar.
2016-04-23 19:21:14 -03:00
3 changed files with 635 additions and 0 deletions

View File

@@ -215,6 +215,7 @@ gtk_public_h_sources = \
gtkglarea.h \
gtkgrid.h \
gtkheaderbar.h \
gtkhidingbox.h \
gtkicontheme.h \
gtkiconview.h \
gtkimage.h \
@@ -779,6 +780,7 @@ gtk_base_c_sources = \
gtkglarea.c \
gtkgrid.c \
gtkheaderbar.c \
gtkhidingbox.c \
gtkhsla.c \
gtkicon.c \
gtkiconcache.c \

555
gtk/gtkhidingbox.c Normal file
View File

@@ -0,0 +1,555 @@
/*
* Copyright (C) 2015 Rafał Lużyński <digitalfreak@lingonborough.com>
* Copyright (C) 2015 Red Hat
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Authors: Rafał Lużyński <digitalfreak@lingonborough.com>
* Carlos Soriano <csoriano@gnome.org>
*/
#include "config.h"
#include "gtkhidingbox.h"
#include "gtkwidgetprivate.h"
#include "gtkintl.h"
#include "gtksizerequest.h"
#include "gtkbuildable.h"
struct _GtkHidingBoxPrivate
{
GList *children;
gint16 spacing;
gint inverted :1;
};
static void
gtk_hiding_box_buildable_add_child (GtkBuildable *buildable,
GtkBuilder *builder,
GObject *child,
const gchar *type)
{
if (!type)
gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
else
GTK_BUILDER_WARN_INVALID_CHILD_TYPE (GTK_HIDING_BOX (buildable), type);
}
static void
gtk_hiding_box_buildable_init (GtkBuildableIface *iface)
{
iface->add_child = gtk_hiding_box_buildable_add_child;
}
G_DEFINE_TYPE_WITH_CODE (GtkHidingBox, gtk_hiding_box, GTK_TYPE_CONTAINER,
G_ADD_PRIVATE (GtkHidingBox)
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, gtk_hiding_box_buildable_init))
enum {
PROP_0,
PROP_SPACING,
PROP_INVERTED,
LAST_PROP
};
static GParamSpec *hiding_box_properties[LAST_PROP] = { NULL, };
static void
gtk_hiding_box_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
GtkHidingBox *box = GTK_HIDING_BOX (object);
switch (prop_id)
{
case PROP_SPACING:
gtk_hiding_box_set_spacing (box, g_value_get_int (value));
break;
case PROP_INVERTED:
gtk_hiding_box_set_inverted (box, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_hiding_box_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GtkHidingBox *box = GTK_HIDING_BOX (object);
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
switch (prop_id)
{
case PROP_SPACING:
g_value_set_int (value, priv->spacing);
break;
case PROP_INVERTED:
g_value_set_boolean (value, priv->inverted);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gtk_hiding_box_add (GtkContainer *container,
GtkWidget *widget)
{
GtkHidingBox *box = GTK_HIDING_BOX (container);
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
priv->children = g_list_append (priv->children, widget);
gtk_widget_set_parent (widget, GTK_WIDGET (box));
}
static void
gtk_hiding_box_remove (GtkContainer *container,
GtkWidget *widget)
{
GList *child;
GtkHidingBox *box = GTK_HIDING_BOX (container);
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
for (child = priv->children; child != NULL; child = child->next)
{
if (child->data == widget)
{
gboolean was_visible = gtk_widget_get_visible (widget) &&
gtk_widget_get_child_visible (widget);
gtk_widget_unparent (widget);
priv->children = g_list_delete_link (priv->children, child);
if (was_visible)
gtk_widget_queue_resize (GTK_WIDGET (container));
break;
}
}
}
static void
gtk_hiding_box_forall (GtkContainer *container,
gboolean include_internals,
GtkCallback callback,
gpointer callback_data)
{
GtkHidingBox *box = GTK_HIDING_BOX (container);
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
GtkWidget *child;
GList *children;
children = priv->children;
while (children)
{
child = children->data;
children = children->next;
(* callback) (child, callback_data);
}
}
static void
update_children_visibility (GtkHidingBox *box,
GtkAllocation *allocation,
GtkRequestedSize *sizes,
gint *children_size,
gint *n_visible_children,
gint *n_visible_children_expanding)
{
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
GtkWidget *child_widget;
GList *child;
GtkRequestedSize *sizes_temp;
gint i;
GList *children;
gboolean allocate_more_children = TRUE;
*n_visible_children = 0;
*n_visible_children_expanding = 0;
*children_size = -priv->spacing;
children = g_list_copy (priv->children);
sizes_temp = g_newa (GtkRequestedSize, g_list_length (priv->children));
if (priv->inverted)
children = g_list_reverse (children);
/* Retrieve desired size for visible children. */
for (i = 0, child = children; child != NULL; i++, child = child->next)
{
child_widget = GTK_WIDGET (child->data);
if (!gtk_widget_get_visible (child_widget) || !allocate_more_children)
{
gtk_widget_set_child_visible (child_widget, FALSE);
continue;
}
gtk_widget_get_preferred_width_for_height (child_widget,
allocation->height,
&sizes_temp[i].minimum_size,
&sizes_temp[i].natural_size);
/* Assert the api is working properly */
if (sizes_temp[i].minimum_size < 0)
g_error ("GtkHidingBox child %s minimum width: %d < 0 for height %d",
gtk_widget_get_name (child_widget),
sizes_temp[i].minimum_size, allocation->height);
if (sizes_temp[i].natural_size < sizes_temp[i].minimum_size)
g_error ("GtkHidingBox child %s natural width: %d < minimum %d for height %d",
gtk_widget_get_name (child_widget),
sizes_temp[i].natural_size, sizes_temp[i].minimum_size,
allocation->height);
*children_size += sizes_temp[i].minimum_size + priv->spacing;
sizes_temp[i].data = child_widget;
if (*children_size > allocation->width)
{
gtk_widget_set_child_visible (child_widget, FALSE);
allocate_more_children = FALSE;
continue;
}
if (gtk_widget_get_hexpand (child_widget))
(*n_visible_children_expanding)++;
(*n_visible_children)++;
gtk_widget_set_child_visible (child_widget, TRUE);
}
for (i = 0; i < *n_visible_children; i++)
{
if (priv->inverted)
{
sizes[*n_visible_children - i - 1].minimum_size = sizes_temp[i].minimum_size;
sizes[*n_visible_children - i - 1].natural_size = sizes_temp[i].natural_size;
}
else
{
sizes[i].minimum_size = sizes_temp[i].minimum_size;
sizes[i].natural_size = sizes_temp[i].natural_size;
}
}
g_list_free (children);
}
static void
gtk_hiding_box_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkHidingBox *box = GTK_HIDING_BOX (widget);
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
GtkTextDirection direction;
GtkAllocation child_allocation;
GtkRequestedSize *sizes;
gint extra_space = 0;
gint x = 0;
gint i;
GList *child;
GtkWidget *child_widget;
gint spacing = priv->spacing;
gint n_visible_children = 0;
gint n_visible_children_expanding = 0;
gint children_size = 0;
gtk_widget_set_allocation (widget, allocation);
sizes = g_newa (GtkRequestedSize, g_list_length (priv->children));
update_children_visibility (box, allocation, sizes, &children_size,
&n_visible_children, &n_visible_children_expanding);
/* If there is no visible child, simply return. */
if (n_visible_children == 0)
return;
direction = gtk_widget_get_direction (widget);
/* Bring children up to allocation width first */
extra_space = allocation->width - (n_visible_children - 1) * spacing - children_size;
extra_space = gtk_distribute_natural_allocation (MAX (0, extra_space), n_visible_children, sizes);
/* Distribute extra space on the expanding children */
if (n_visible_children > 1)
extra_space = extra_space / MAX (1, n_visible_children_expanding);
x = allocation->x;
for (i = 0, child = priv->children; child != NULL; child = child->next)
{
child_widget = GTK_WIDGET (child->data);
if (!gtk_widget_get_child_visible (child_widget))
continue;
child_allocation.x = x;
child_allocation.y = allocation->y;
if (gtk_widget_get_hexpand (child_widget))
child_allocation.width = sizes[i].minimum_size + extra_space;
else
child_allocation.width = sizes[i].minimum_size;
child_allocation.height = allocation->height;
if (direction == GTK_TEXT_DIR_RTL)
child_allocation.x = allocation->x + allocation->width - (child_allocation.x - allocation->x) - child_allocation.width;
/* Let this child be visible */
gtk_widget_size_allocate (child_widget, &child_allocation);
x += child_allocation.width + spacing;
++i;
}
_gtk_widget_set_simple_clip (widget, NULL);
}
static void
gtk_hiding_box_get_preferred_width (GtkWidget *widget,
gint *minimum_width,
gint *natural_width)
{
GtkHidingBox *box = GTK_HIDING_BOX (widget);
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
gint child_minimum_width;
gint child_natural_width;
GList *child;
gint n_visible_children;
gboolean have_min = FALSE;
GList *children;
*minimum_width = 0;
*natural_width = 0;
children = g_list_copy (priv->children);
if (priv->inverted)
children = g_list_reverse (children);
n_visible_children = 0;
for (child = children; child != NULL; child = child->next)
{
if (!gtk_widget_is_visible (child->data))
continue;
++n_visible_children;
gtk_widget_get_preferred_width (child->data, &child_minimum_width, &child_natural_width);
/* Minimum is a minimum of the first visible child */
if (!have_min)
{
*minimum_width = child_minimum_width;
have_min = TRUE;
}
/* Natural is a sum of all visible children */
*natural_width += child_natural_width;
}
/* Natural must also include the spacing */
if (priv->spacing && n_visible_children > 1)
*natural_width += priv->spacing * (n_visible_children - 1);
g_list_free (children);
}
static void
gtk_hiding_box_get_preferred_height (GtkWidget *widget,
gint *minimum_height,
gint *natural_height)
{
GtkHidingBox *box = GTK_HIDING_BOX (widget);
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
gint child_minimum_height;
gint child_natural_height;
GList *child;
*minimum_height = 0;
*natural_height = 0;
for (child = priv->children; child != NULL; child = child->next)
{
if (!gtk_widget_is_visible (child->data))
continue;
gtk_widget_get_preferred_height (child->data, &child_minimum_height, &child_natural_height);
*minimum_height = MAX (*minimum_height, child_minimum_height);
*natural_height = MAX (*natural_height, child_natural_height);
}
}
static GtkSizeRequestMode
gtk_hiding_box_get_request_mode (GtkWidget *self)
{
return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
}
static void
gtk_hiding_box_init (GtkHidingBox *box)
{
GtkHidingBoxPrivate *priv = gtk_hiding_box_get_instance_private (box);
gtk_widget_set_has_window (GTK_WIDGET (box), FALSE);
priv->spacing = 0;
priv->inverted = FALSE;
}
static void
gtk_hiding_box_class_init (GtkHidingBoxClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);
object_class->set_property = gtk_hiding_box_set_property;
object_class->get_property = gtk_hiding_box_get_property;
widget_class->size_allocate = gtk_hiding_box_size_allocate;
widget_class->get_preferred_width = gtk_hiding_box_get_preferred_width;
widget_class->get_preferred_height = gtk_hiding_box_get_preferred_height;
widget_class->get_request_mode = gtk_hiding_box_get_request_mode;
container_class->add = gtk_hiding_box_add;
container_class->remove = gtk_hiding_box_remove;
container_class->forall = gtk_hiding_box_forall;
hiding_box_properties[PROP_SPACING] =
g_param_spec_int ("spacing",
_("Spacing"),
_("The amount of space between children"),
0, G_MAXINT, 0,
G_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
hiding_box_properties[PROP_INVERTED] =
g_param_spec_int ("inverted",
_("Direction of hiding children inverted"),
P_("If false the container will start hiding widgets from the end when there is not enough space, and the oposite in case inverted is true."),
0, G_MAXINT, 0,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, LAST_PROP, hiding_box_properties);
}
/**
* gtk_hiding_box_new:
*
* Creates a new #GtkHidingBox.
*
* Returns: a new #GtkHidingBox.
**/
GtkWidget *
gtk_hiding_box_new (void)
{
return g_object_new (GTK_TYPE_HIDING_BOX, NULL);
}
/**
* gtk_hiding_box_set_spacing:
* @box: a #GtkHidingBox
* @spacing: the number of pixels to put between children
*
* Sets the #GtkHidingBox:spacing property of @box, which is the
* number of pixels to place between children of @box.
*/
void
gtk_hiding_box_set_spacing (GtkHidingBox *box,
gint spacing)
{
GtkHidingBoxPrivate *priv ;
g_return_if_fail (GTK_IS_HIDING_BOX (box));
priv = gtk_hiding_box_get_instance_private (box);
if (priv->spacing != spacing)
{
priv->spacing = spacing;
g_object_notify (G_OBJECT (box), "spacing");
gtk_widget_queue_resize (GTK_WIDGET (box));
}
}
/**
* gtk_hiding_box_get_spacing:
* @box: a #GtkHidingBox
*
* Gets the value set by gtk_hiding_box_set_spacing().
*
* Returns: spacing between children
**/
gint
gtk_hiding_box_get_spacing (GtkHidingBox *box)
{
GtkHidingBoxPrivate *priv ;
g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
priv = gtk_hiding_box_get_instance_private (box);
return priv->spacing;
}
void
gtk_hiding_box_set_inverted (GtkHidingBox *box,
gboolean inverted)
{
GtkHidingBoxPrivate *priv ;
g_return_if_fail (GTK_IS_HIDING_BOX (box));
priv = gtk_hiding_box_get_instance_private (box);
if (priv->inverted != inverted)
{
priv->inverted = inverted != FALSE;
g_object_notify (G_OBJECT (box), "inverted");
gtk_widget_queue_resize (GTK_WIDGET (box));
}
}
gboolean
gtk_hiding_box_get_inverted (GtkHidingBox *box)
{
GtkHidingBoxPrivate *priv ;
g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
priv = gtk_hiding_box_get_instance_private (box);
return priv->inverted;
}
GList *
gtk_hiding_box_get_overflow_children (GtkHidingBox *box)
{
GtkHidingBoxPrivate *priv ;
GList *result = NULL;
GList *l;
g_return_val_if_fail (GTK_IS_HIDING_BOX (box), 0);
priv = gtk_hiding_box_get_instance_private (box);
for (l = priv->children; l != NULL; l = l->next)
if (gtk_widget_is_visible (l->data) && !gtk_widget_get_child_visible (l->data))
result = g_list_append (result, l->data);
return result;
}

78
gtk/gtkhidingbox.h Normal file
View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2015 Rafał Lużyński <digitalfreak@lingonborough.com>
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __GTK_HIDING_BOX_PRIVATE_H__
#define __GTK_HIDING_BOX_PRIVATE_H__
#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
#error "Only <gtk/gtk.h> can be included directly."
#endif
#include <gtk/gtkcontainer.h>
G_BEGIN_DECLS
#define GTK_TYPE_HIDING_BOX (gtk_hiding_box_get_type())
#define GTK_HIDING_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_HIDING_BOX, GtkHidingBox))
#define GTK_HIDING_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_HIDING_BOX, GtkHidingBoxClass))
#define GTK_IS_HIDING_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_HIDING_BOX))
#define GTK_IS_HIDING_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_HIDING_BOX)
#define GTK_HIDING_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_HIDING_BOX, GtkHidingBoxClass))
typedef struct _GtkHidingBox GtkHidingBox;
typedef struct _GtkHidingBoxClass GtkHidingBoxClass;
typedef struct _GtkHidingBoxPrivate GtkHidingBoxPrivate;
struct _GtkHidingBoxClass
{
GtkContainerClass parent;
/* Padding for future expansion */
gpointer reserved[10];
};
struct _GtkHidingBox
{
GtkContainer parent_instance;
};
GDK_AVAILABLE_IN_3_22
GType gtk_hiding_box_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_22
GtkWidget *gtk_hiding_box_new (void);
GDK_AVAILABLE_IN_3_22
void gtk_hiding_box_set_spacing (GtkHidingBox *box,
gint spacing);
GDK_AVAILABLE_IN_3_22
gint gtk_hiding_box_get_spacing (GtkHidingBox *box);
GDK_AVAILABLE_IN_3_22
void gtk_hiding_box_set_inverted (GtkHidingBox *box,
gboolean inverted);
GDK_AVAILABLE_IN_3_22
gboolean gtk_hiding_box_get_inverted (GtkHidingBox *box);
GDK_AVAILABLE_IN_3_22
GList *gtk_hiding_box_get_overflow_children (GtkHidingBox *box);
G_END_DECLS
#endif /* GTK_HIDING_BOX_PRIVATE_H_ */