* 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 <http://www.gnu.org/licenses/>.
*/
/*
#include "config.h"
#include "gtkcontainer.h"
+#include "gtkcontainerprivate.h"
#include <stdarg.h>
#include <string.h>
#include "gtksizerequest.h"
#include "gtkwidgetprivate.h"
#include "gtkwindow.h"
+#include "gtkassistant.h"
#include "gtkintl.h"
-#include "gtktoolbar.h"
-
+#include "a11y/gtkcontaineraccessible.h"
/**
* SECTION:gtkcontainer
* The second type of container can have more than one child; its purpose is to
* manage <emphasis>layout</emphasis>. This means that these containers assign
* sizes and positions to their children. For example, a #GtkHBox arranges its
- * children in a horizontal row, and a #GtkTable arranges the widgets it contains
+ * children in a horizontal row, and a #GtkGrid arranges the widgets it contains
* in a two-dimensional grid.
*
* <refsect2 id="container-geometry-management">
guint need_resize : 1;
guint reallocate_redraws : 1;
guint resize_mode : 2;
+ guint request_mode : 2;
};
enum {
gint *natural_size,
gint *allocated_pos,
gint *allocated_size);
+static GtkSizeRequestMode gtk_container_get_request_mode (GtkWidget *widget);
static gchar* gtk_container_child_default_composite_name (GtkContainer *container,
GtkWidget *child);
widget_class->adjust_size_request = gtk_container_adjust_size_request;
widget_class->adjust_size_allocation = gtk_container_adjust_size_allocation;
+ widget_class->get_request_mode = gtk_container_get_request_mode;
class->add = gtk_container_add_unimplemented;
class->remove = gtk_container_remove_unimplemented;
GTK_TYPE_WIDGET);
g_type_class_add_private (class, sizeof (GtkContainerPrivate));
+
+ gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_CONTAINER_ACCESSIBLE);
}
static void
const gchar *value)
{
GParamSpec *pspec;
- GValue gvalue = { 0, };
+ GValue gvalue = G_VALUE_INIT;
GError *error = NULL;
pspec = gtk_container_class_find_child_property
}
/* --- GtkContainer child property mechanism --- */
+
+/**
+ * gtk_container_child_notify:
+ * @container: the #GtkContainer
+ * @child: the child widget
+ * @child_property: the name of a child property installed on
+ * the class of @container
+ *
+ * Emits a #GtkWidget::child-notify signal for the
+ * <link linkend="child-properties">child property</link>
+ * @child_property on widget.
+ *
+ * This is an analogue of g_object_notify() for child properties.
+ *
+ * Also see gtk_widget_child_notify().
+ *
+ * Since: 3.2
+ */
+void
+gtk_container_child_notify (GtkContainer *container,
+ GtkWidget *child,
+ const gchar *child_property)
+{
+ GObject *obj;
+ GParamSpec *pspec;
+
+ g_return_if_fail (GTK_IS_CONTAINER (container));
+ g_return_if_fail (GTK_IS_WIDGET (child));
+ g_return_if_fail (child_property != NULL);
+
+ obj = G_OBJECT (child);
+
+ if (obj->ref_count == 0)
+ return;
+
+ g_object_ref (obj);
+
+ pspec = g_param_spec_pool_lookup (_gtk_widget_child_property_pool,
+ child_property,
+ G_OBJECT_TYPE (container),
+ TRUE);
+
+ if (pspec == NULL)
+ {
+ g_warning ("%s: container class `%s' has no child property named `%s'",
+ G_STRLOC,
+ G_OBJECT_TYPE_NAME (container),
+ child_property);
+ }
+ else
+ {
+ GObjectNotifyQueue *nqueue;
+
+ nqueue = g_object_notify_queue_freeze (obj, _gtk_widget_child_property_notify_context);
+
+ g_object_notify_queue_add (obj, nqueue, pspec);
+ g_object_notify_queue_thaw (obj, nqueue);
+ }
+
+ g_object_unref (obj);
+}
+
static inline void
container_get_child_property (GtkContainer *container,
GtkWidget *child,
const GValue *value,
GObjectNotifyQueue *nqueue)
{
- GValue tmp_value = { 0, };
+ GValue tmp_value = G_VALUE_INIT;
GtkContainerClass *class = g_type_class_peek (pspec->owner_type);
/* provide a copy to work from, convert (if necessary) and validate */
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
g_object_ref (container);
g_object_ref (child);
name = first_property_name;
while (name)
{
- GValue value = { 0, };
+ GValue value = G_VALUE_INIT;
GParamSpec *pspec;
gchar *error;
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
g_return_if_fail (property_name != NULL);
g_return_if_fail (G_IS_VALUE (value));
G_OBJECT_TYPE_NAME (container));
else
{
- GValue *prop_value, tmp_value = { 0, };
+ GValue *prop_value, tmp_value = G_VALUE_INIT;
/* auto-conversion of the callers value type
*/
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
g_object_ref (container);
g_object_ref (child);
name = first_property_name;
while (name)
{
- GValue value = { 0, };
+ GValue value = G_VALUE_INIT;
gchar *error = NULL;
GParamSpec *pspec = g_param_spec_pool_lookup (_gtk_widget_child_property_pool,
name,
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
g_return_if_fail (property_name != NULL);
g_return_if_fail (G_IS_VALUE (value));
* @container: a #GtkContainer
* @widget: a widget to be placed inside @container
* @first_prop_name: the name of the first child property to set
- * @Varargs: a %NULL-terminated list of property names and values, starting
- * with @first_prop_name
+ * @...: a %NULL-terminated list of property names and values, starting
+ * with @first_prop_name
*
* Adds @widget to @container, setting child properties at the same time.
* See gtk_container_add() and gtk_container_child_set() for more details.
- **/
+ */
void
gtk_container_add_with_properties (GtkContainer *container,
GtkWidget *widget,
* @container: a #GtkContainer
* @child: a widget which is a child of @container
* @first_prop_name: the name of the first property to set
- * @Varargs: a %NULL-terminated list of property names and values, starting
- * with @first_prop_name
+ * @...: a %NULL-terminated list of property names and values, starting
+ * with @first_prop_name
*
* Sets one or more child properties for @child and @container.
- **/
+ */
void
gtk_container_child_set (GtkContainer *container,
GtkWidget *child,
{
va_list var_args;
- g_return_if_fail (GTK_IS_CONTAINER (container));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
-
va_start (var_args, first_prop_name);
gtk_container_child_set_valist (container, child, first_prop_name, var_args);
va_end (var_args);
* @container: a #GtkContainer
* @child: a widget which is a child of @container
* @first_prop_name: the name of the first property to get
- * @Varargs: return location for the first property, followed
+ * @...: return location for the first property, followed
* optionally by more name/return location pairs, followed by %NULL
*
* Gets the values of one or more child properties for @child and @container.
- **/
+ */
void
gtk_container_child_get (GtkContainer *container,
GtkWidget *child,
{
va_list var_args;
- g_return_if_fail (GTK_IS_CONTAINER (container));
- g_return_if_fail (GTK_IS_WIDGET (child));
- g_return_if_fail (gtk_widget_get_parent (child) == GTK_WIDGET (container));
-
va_start (var_args, first_prop_name);
gtk_container_child_get_valist (container, child, first_prop_name, var_args);
va_end (var_args);
* gtk_container_class_find_child_property:
* @cclass: (type GtkContainerClass): a #GtkContainerClass
* @property_name: the name of the child property to find
- * @returns: (transfer none): the #GParamSpec of the child property or
- * %NULL if @class has no child property with that name.
*
* Finds a child property of a container class by name.
+ *
+ * Returns: (transfer none): the #GParamSpec of the child property
+ * or %NULL if @class has no child property with that name.
*/
GParamSpec*
gtk_container_class_find_child_property (GObjectClass *cclass,
* gtk_container_class_list_child_properties:
* @cclass: (type GtkContainerClass): a #GtkContainerClass
* @n_properties: location to return the number of child properties found
- * @returns: (array length=n_properties) (transfer container): a newly
- * allocated %NULL-terminated array of #GParamSpec*. The
- * array must be freed with g_free().
*
* Returns all child properties of a container class.
+ *
+ * Returns: (array length=n_properties) (transfer container):
+ * a newly allocated %NULL-terminated array of #GParamSpec*.
+ * The array must be freed with g_free().
*/
GParamSpec**
gtk_container_class_list_child_properties (GObjectClass *cclass,
*
* Adds @widget to @container. Typically used for simple containers
* such as #GtkWindow, #GtkFrame, or #GtkButton; for more complicated
- * layout containers such as #GtkBox or #GtkTable, this function will
+ * layout containers such as #GtkBox or #GtkGrid, this function will
* pick default packing parameters that may not be correct. So
* consider functions such as gtk_box_pack_start() and
- * gtk_table_attach() as an alternative to gtk_container_add() in
+ * gtk_grid_attach() as an alternative to gtk_container_add() in
* those cases. A widget may be added to only one container at a time;
* you can't place the same widget inside two different containers.
**/
{
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container));
+ g_return_if_fail (gtk_widget_get_parent (widget) == GTK_WIDGET (container) || GTK_IS_ASSISTANT (container));
g_signal_emit (container, container_signals[REMOVE], 0, widget);
}
allocated_size);
}
+typedef struct {
+ gint hfw;
+ gint wfh;
+} RequestModeCount;
+
+static void
+count_request_modes (GtkWidget *widget,
+ RequestModeCount *count)
+{
+ GtkSizeRequestMode mode = gtk_widget_get_request_mode (widget);
+
+ switch (mode)
+ {
+ case GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH:
+ count->hfw++;
+ break;
+ case GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT:
+ count->wfh++;
+ break;
+ case GTK_SIZE_REQUEST_CONSTANT_SIZE:
+ default:
+ break;
+ }
+}
+
+static GtkSizeRequestMode
+gtk_container_get_request_mode (GtkWidget *widget)
+{
+ GtkContainer *container = GTK_CONTAINER (widget);
+ GtkContainerPrivate *priv = container->priv;
+
+ /* Recalculate the request mode of the children by majority
+ * vote whenever the internal content changes */
+ if (_gtk_widget_get_width_request_needed (widget) ||
+ _gtk_widget_get_height_request_needed (widget))
+ {
+ RequestModeCount count = { 0, 0 };
+
+ gtk_container_forall (container, (GtkCallback)count_request_modes, &count);
+
+ if (!count.hfw && !count.wfh)
+ priv->request_mode = GTK_SIZE_REQUEST_CONSTANT_SIZE;
+ else
+ priv->request_mode = count.wfh > count.hfw ?
+ GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT :
+ GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
+ }
+
+ return priv->request_mode;
+}
+
/**
* gtk_container_class_handle_border_width:
* @klass: the class struct of a #GtkContainer subclass
/* same as gtk_container_get_children, except it includes internals
*/
-static GList *
-gtk_container_get_all_children (GtkContainer *container)
+GList *
+_gtk_container_get_all_children (GtkContainer *container)
{
GList *children = NULL;
g_list_free_1 (cur);
}
+ gtk_widget_path_append_for_widget (path, child);
+
return path;
}
if (priv->has_focus_chain)
children = g_list_copy (get_focus_chain (container));
else
- children = gtk_container_get_all_children (container);
+ children = _gtk_container_get_all_children (container);
if (priv->has_focus_chain &&
(direction == GTK_DIR_TAB_FORWARD ||
* @child: a child of @container
*
* Returns a newly created widget path representing all the widget hierarchy
- * from the toplevel down to @child (this one not being included).
+ * from the toplevel down to and including @child.
*
* Returns: A newly created #GtkWidgetPath
**/
gtk_container_get_path_for_child (GtkContainer *container,
GtkWidget *child)
{
+ GtkWidgetPath *path;
+
g_return_val_if_fail (GTK_IS_CONTAINER (container), NULL);
g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
g_return_val_if_fail (container == (GtkContainer *) gtk_widget_get_parent (child), NULL);
- return GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
+ path = GTK_CONTAINER_GET_CLASS (container)->get_path_for_child (container, child);
+ if (gtk_widget_path_get_object_type (path) != G_OBJECT_TYPE (child))
+ {
+ g_critical ("%s %p returned a widget path for type %s, but child is %s",
+ G_OBJECT_TYPE_NAME (container),
+ container,
+ g_type_name (gtk_widget_path_get_object_type (path)),
+ G_OBJECT_TYPE_NAME (child));
+ }
+
+ return path;
}