Blame clutter/clutter-bin-layout.c

Packit 31ecd5
/*
Packit 31ecd5
 * Clutter.
Packit 31ecd5
 *
Packit 31ecd5
 * An OpenGL based 'interactive canvas' library.
Packit 31ecd5
 *
Packit 31ecd5
 * Copyright (C) 2009  Intel Corporation.
Packit 31ecd5
 *
Packit 31ecd5
 * This library is free software; you can redistribute it and/or
Packit 31ecd5
 * modify it under the terms of the GNU Lesser General Public
Packit 31ecd5
 * License as published by the Free Software Foundation; either
Packit 31ecd5
 * version 2 of the License, or (at your option) any later version.
Packit 31ecd5
 *
Packit 31ecd5
 * This library is distributed in the hope that it will be useful,
Packit 31ecd5
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 31ecd5
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 31ecd5
 * Lesser General Public License for more details.
Packit 31ecd5
 *
Packit 31ecd5
 * You should have received a copy of the GNU Lesser General Public
Packit 31ecd5
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Packit 31ecd5
 *
Packit 31ecd5
 * Author:
Packit 31ecd5
 *   Emmanuele Bassi <ebassi@linux.intel.com>
Packit 31ecd5
 */
Packit 31ecd5
Packit 31ecd5
/**
Packit 31ecd5
 * SECTION:clutter-bin-layout
Packit 31ecd5
 * @short_description: A simple layout manager
Packit 31ecd5
 *
Packit 31ecd5
 * #ClutterBinLayout is a layout manager which implements the following
Packit 31ecd5
 * policy:
Packit 31ecd5
 *
Packit 31ecd5
 *   - the preferred size is the maximum preferred size
Packit 31ecd5
 *   between all the children of the container using the
Packit 31ecd5
 *   layout;
Packit 31ecd5
 *   - each child is allocated in "layers", on on top
Packit 31ecd5
 *   of the other;
Packit 31ecd5
 *   - for each layer there are horizontal and vertical
Packit 31ecd5
 *   alignment policies.
Packit 31ecd5
 *
Packit 31ecd5
 * The [bin-layout example](https://git.gnome.org/browse/clutter/tree/examples/bin-layout.c?h=clutter-1.18)
Packit 31ecd5
 * shows how to pack actors inside a #ClutterBinLayout.
Packit 31ecd5
 *
Packit 31ecd5
 * #ClutterBinLayout is available since Clutter 1.2
Packit 31ecd5
 */
Packit 31ecd5
Packit 31ecd5
#ifdef HAVE_CONFIG_H
Packit 31ecd5
#include "config.h"
Packit 31ecd5
#endif
Packit 31ecd5
Packit 31ecd5
#include <math.h>
Packit 31ecd5
Packit 31ecd5
#define CLUTTER_DISABLE_DEPRECATION_WARNINGS
Packit 31ecd5
#include "deprecated/clutter-container.h"
Packit 31ecd5
#include "deprecated/clutter-bin-layout.h"
Packit 31ecd5
Packit 31ecd5
#include "clutter-actor-private.h"
Packit 31ecd5
#include "clutter-animatable.h"
Packit 31ecd5
#include "clutter-child-meta.h"
Packit 31ecd5
#include "clutter-debug.h"
Packit 31ecd5
#include "clutter-enum-types.h"
Packit 31ecd5
#include "clutter-layout-meta.h"
Packit 31ecd5
#include "clutter-private.h"
Packit 31ecd5
Packit 31ecd5
#define CLUTTER_TYPE_BIN_LAYER          (clutter_bin_layer_get_type ())
Packit 31ecd5
#define CLUTTER_BIN_LAYER(obj)          (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIN_LAYER, ClutterBinLayer))
Packit 31ecd5
#define CLUTTER_IS_BIN_LAYER(obj)       (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIN_LAYER))
Packit 31ecd5
Packit 31ecd5
typedef struct _ClutterBinLayer         ClutterBinLayer;
Packit 31ecd5
typedef struct _ClutterLayoutMetaClass  ClutterBinLayerClass;
Packit 31ecd5
Packit 31ecd5
struct _ClutterBinLayoutPrivate
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinAlignment x_align;
Packit 31ecd5
  ClutterBinAlignment y_align;
Packit 31ecd5
Packit 31ecd5
  ClutterContainer *container;
Packit 31ecd5
};
Packit 31ecd5
Packit 31ecd5
struct _ClutterBinLayer
Packit 31ecd5
{
Packit 31ecd5
  ClutterLayoutMeta parent_instance;
Packit 31ecd5
Packit 31ecd5
  ClutterBinAlignment x_align;
Packit 31ecd5
  ClutterBinAlignment y_align;
Packit 31ecd5
};
Packit 31ecd5
Packit 31ecd5
enum
Packit 31ecd5
{
Packit 31ecd5
  PROP_LAYER_0,
Packit 31ecd5
Packit 31ecd5
  PROP_LAYER_X_ALIGN,
Packit 31ecd5
  PROP_LAYER_Y_ALIGN,
Packit 31ecd5
Packit 31ecd5
  PROP_LAYER_LAST
Packit 31ecd5
};
Packit 31ecd5
Packit 31ecd5
enum
Packit 31ecd5
{
Packit 31ecd5
  PROP_0,
Packit 31ecd5
Packit 31ecd5
  PROP_X_ALIGN,
Packit 31ecd5
  PROP_Y_ALIGN,
Packit 31ecd5
Packit 31ecd5
  PROP_LAST
Packit 31ecd5
};
Packit 31ecd5
Packit 31ecd5
static GParamSpec *layer_props[PROP_LAYER_LAST] = { NULL, };
Packit 31ecd5
static GParamSpec *bin_props[PROP_LAST] = { NULL, };
Packit 31ecd5
Packit 31ecd5
GType clutter_bin_layer_get_type (void);
Packit 31ecd5
Packit 31ecd5
G_DEFINE_TYPE (ClutterBinLayer,
Packit 31ecd5
               clutter_bin_layer,
Packit 31ecd5
               CLUTTER_TYPE_LAYOUT_META)
Packit 31ecd5
Packit 31ecd5
G_DEFINE_TYPE_WITH_PRIVATE (ClutterBinLayout,
Packit 31ecd5
                            clutter_bin_layout,
Packit 31ecd5
                            CLUTTER_TYPE_LAYOUT_MANAGER)
Packit 31ecd5
Packit 31ecd5
/*
Packit 31ecd5
 * ClutterBinLayer
Packit 31ecd5
 */
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
set_layer_x_align (ClutterBinLayer     *self,
Packit 31ecd5
                   ClutterBinAlignment  alignment)
Packit 31ecd5
{
Packit 31ecd5
  ClutterLayoutManager *manager;
Packit 31ecd5
  ClutterLayoutMeta *meta;
Packit 31ecd5
Packit 31ecd5
  if (self->x_align == alignment)
Packit 31ecd5
    return;
Packit 31ecd5
Packit 31ecd5
  self->x_align = alignment;
Packit 31ecd5
Packit 31ecd5
  meta = CLUTTER_LAYOUT_META (self);
Packit 31ecd5
  manager = clutter_layout_meta_get_manager (meta);
Packit 31ecd5
  clutter_layout_manager_layout_changed (manager);
Packit 31ecd5
Packit 31ecd5
  g_object_notify_by_pspec (G_OBJECT (self), layer_props[PROP_LAYER_X_ALIGN]);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
set_layer_y_align (ClutterBinLayer     *self,
Packit 31ecd5
                   ClutterBinAlignment  alignment)
Packit 31ecd5
{
Packit 31ecd5
  ClutterLayoutManager *manager;
Packit 31ecd5
  ClutterLayoutMeta *meta;
Packit 31ecd5
Packit 31ecd5
  if (self->y_align == alignment)
Packit 31ecd5
    return;
Packit 31ecd5
Packit 31ecd5
  self->y_align = alignment;
Packit 31ecd5
Packit 31ecd5
  meta = CLUTTER_LAYOUT_META (self);
Packit 31ecd5
  manager = clutter_layout_meta_get_manager (meta);
Packit 31ecd5
  clutter_layout_manager_layout_changed (manager);
Packit 31ecd5
Packit 31ecd5
  g_object_notify_by_pspec (G_OBJECT (self), layer_props[PROP_LAYER_Y_ALIGN]);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layer_set_property (GObject      *gobject,
Packit 31ecd5
                                guint         prop_id,
Packit 31ecd5
                                const GValue *value,
Packit 31ecd5
                                GParamSpec   *pspec)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject);
Packit 31ecd5
Packit 31ecd5
  switch (prop_id)
Packit 31ecd5
    {
Packit 31ecd5
    case PROP_LAYER_X_ALIGN:
Packit 31ecd5
      set_layer_x_align (layer, g_value_get_enum (value));
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    case PROP_LAYER_Y_ALIGN:
Packit 31ecd5
      set_layer_y_align (layer, g_value_get_enum (value));
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    default:
Packit 31ecd5
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
Packit 31ecd5
      break;
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layer_get_property (GObject    *gobject,
Packit 31ecd5
                                guint       prop_id,
Packit 31ecd5
                                GValue     *value,
Packit 31ecd5
                                GParamSpec *pspec)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject);
Packit 31ecd5
Packit 31ecd5
  switch (prop_id)
Packit 31ecd5
    {
Packit 31ecd5
    case PROP_LAYER_X_ALIGN:
Packit 31ecd5
      g_value_set_enum (value, layer->x_align);
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    case PROP_LAYER_Y_ALIGN:
Packit 31ecd5
      g_value_set_enum (value, layer->y_align);
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    default:
Packit 31ecd5
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
Packit 31ecd5
      break;
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layer_class_init (ClutterBinLayerClass *klass)
Packit 31ecd5
{
Packit 31ecd5
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit 31ecd5
Packit 31ecd5
  gobject_class->set_property = clutter_bin_layer_set_property;
Packit 31ecd5
  gobject_class->get_property = clutter_bin_layer_get_property;
Packit 31ecd5
Packit 31ecd5
  layer_props[PROP_LAYER_X_ALIGN] =
Packit 31ecd5
    g_param_spec_enum ("x-align",
Packit 31ecd5
                       P_("Horizontal Alignment"),
Packit 31ecd5
                       P_("Horizontal alignment for the actor "
Packit 31ecd5
                          "inside the layout manager"),
Packit 31ecd5
                       CLUTTER_TYPE_BIN_ALIGNMENT,
Packit 31ecd5
                       CLUTTER_BIN_ALIGNMENT_CENTER,
Packit 31ecd5
                       CLUTTER_PARAM_READWRITE);
Packit 31ecd5
Packit 31ecd5
  layer_props[PROP_LAYER_Y_ALIGN] =
Packit 31ecd5
    g_param_spec_enum ("y-align",
Packit 31ecd5
                       P_("Vertical Alignment"),
Packit 31ecd5
                       P_("Vertical alignment for the actor "
Packit 31ecd5
                          "inside the layout manager"),
Packit 31ecd5
                       CLUTTER_TYPE_BIN_ALIGNMENT,
Packit 31ecd5
                       CLUTTER_BIN_ALIGNMENT_CENTER,
Packit 31ecd5
                       CLUTTER_PARAM_READWRITE);
Packit 31ecd5
Packit 31ecd5
  g_object_class_install_properties (gobject_class,
Packit 31ecd5
                                     PROP_LAYER_LAST,
Packit 31ecd5
                                     layer_props);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layer_init (ClutterBinLayer *layer)
Packit 31ecd5
{
Packit 31ecd5
  layer->x_align = CLUTTER_BIN_ALIGNMENT_CENTER;
Packit 31ecd5
  layer->y_align = CLUTTER_BIN_ALIGNMENT_CENTER;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
/*
Packit 31ecd5
 * ClutterBinLayout
Packit 31ecd5
 */
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
set_x_align (ClutterBinLayout    *self,
Packit 31ecd5
             ClutterBinAlignment  alignment)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv = self->priv;
Packit 31ecd5
Packit 31ecd5
  if (priv->x_align != alignment)
Packit 31ecd5
    {
Packit 31ecd5
      ClutterLayoutManager *manager;
Packit 31ecd5
Packit 31ecd5
      priv->x_align = alignment;
Packit 31ecd5
Packit 31ecd5
      manager = CLUTTER_LAYOUT_MANAGER (self);
Packit 31ecd5
      clutter_layout_manager_layout_changed (manager);
Packit 31ecd5
Packit 31ecd5
      g_object_notify_by_pspec (G_OBJECT (self), bin_props[PROP_X_ALIGN]);
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
set_y_align (ClutterBinLayout    *self,
Packit 31ecd5
             ClutterBinAlignment  alignment)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv = self->priv;
Packit 31ecd5
Packit 31ecd5
  if (priv->y_align != alignment)
Packit 31ecd5
    {
Packit 31ecd5
      ClutterLayoutManager *manager;
Packit 31ecd5
Packit 31ecd5
      priv->y_align = alignment;
Packit 31ecd5
Packit 31ecd5
      manager = CLUTTER_LAYOUT_MANAGER (self);
Packit 31ecd5
      clutter_layout_manager_layout_changed (manager);
Packit 31ecd5
Packit 31ecd5
      g_object_notify_by_pspec (G_OBJECT (self), bin_props[PROP_Y_ALIGN]);
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_get_preferred_width (ClutterLayoutManager *manager,
Packit 31ecd5
                                        ClutterContainer     *container,
Packit 31ecd5
                                        gfloat                for_height,
Packit 31ecd5
                                        gfloat               *min_width_p,
Packit 31ecd5
                                        gfloat               *nat_width_p)
Packit 31ecd5
{
Packit 31ecd5
  ClutterActor *actor = CLUTTER_ACTOR (container);
Packit 31ecd5
  ClutterActorIter iter;
Packit 31ecd5
  ClutterActor *child;
Packit 31ecd5
  gfloat min_width, nat_width;
Packit 31ecd5
Packit 31ecd5
  min_width = nat_width = 0.0;
Packit 31ecd5
Packit 31ecd5
  clutter_actor_iter_init (&iter, actor);
Packit 31ecd5
  while (clutter_actor_iter_next (&iter, &child))
Packit 31ecd5
    {
Packit 31ecd5
      gfloat minimum, natural;
Packit 31ecd5
Packit 31ecd5
      if (!clutter_actor_is_visible (child))
Packit 31ecd5
        continue;
Packit 31ecd5
Packit 31ecd5
      clutter_actor_get_preferred_width (child, for_height,
Packit 31ecd5
                                         &minimum,
Packit 31ecd5
                                         &natural);
Packit 31ecd5
Packit 31ecd5
      min_width = MAX (min_width, minimum);
Packit 31ecd5
      nat_width = MAX (nat_width, natural);
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  if (min_width_p)
Packit 31ecd5
    *min_width_p = min_width;
Packit 31ecd5
Packit 31ecd5
  if (nat_width_p)
Packit 31ecd5
    *nat_width_p = nat_width;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager,
Packit 31ecd5
                                         ClutterContainer     *container,
Packit 31ecd5
                                         gfloat                for_width,
Packit 31ecd5
                                         gfloat               *min_height_p,
Packit 31ecd5
                                         gfloat               *nat_height_p)
Packit 31ecd5
{
Packit 31ecd5
  ClutterActor *actor = CLUTTER_ACTOR (container);
Packit 31ecd5
  ClutterActorIter iter;
Packit 31ecd5
  ClutterActor *child;
Packit 31ecd5
  gfloat min_height, nat_height;
Packit 31ecd5
Packit 31ecd5
  min_height = nat_height = 0.0;
Packit 31ecd5
Packit 31ecd5
  clutter_actor_iter_init (&iter, actor);
Packit 31ecd5
  while (clutter_actor_iter_next (&iter, &child))
Packit 31ecd5
    {
Packit 31ecd5
      gfloat minimum, natural;
Packit 31ecd5
Packit 31ecd5
      if (!clutter_actor_is_visible (child))
Packit 31ecd5
        continue;
Packit 31ecd5
Packit 31ecd5
      clutter_actor_get_preferred_height (child, for_width,
Packit 31ecd5
                                          &minimum,
Packit 31ecd5
                                          &natural);
Packit 31ecd5
Packit 31ecd5
      min_height = MAX (min_height, minimum);
Packit 31ecd5
      nat_height = MAX (nat_height, natural);
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  if (min_height_p)
Packit 31ecd5
    *min_height_p = min_height;
Packit 31ecd5
Packit 31ecd5
  if (nat_height_p)
Packit 31ecd5
    *nat_height_p = nat_height;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static gdouble
Packit 31ecd5
get_bin_alignment_factor (ClutterBinAlignment alignment,
Packit 31ecd5
                          ClutterTextDirection text_dir)
Packit 31ecd5
{
Packit 31ecd5
  switch (alignment)
Packit 31ecd5
    {
Packit 31ecd5
    case CLUTTER_BIN_ALIGNMENT_CENTER:
Packit 31ecd5
      return 0.5;
Packit 31ecd5
Packit 31ecd5
    case CLUTTER_BIN_ALIGNMENT_START:
Packit 31ecd5
      return text_dir == CLUTTER_TEXT_DIRECTION_LTR ? 0.0 : 1.0;
Packit 31ecd5
Packit 31ecd5
    case CLUTTER_BIN_ALIGNMENT_END:
Packit 31ecd5
      return text_dir == CLUTTER_TEXT_DIRECTION_LTR ? 1.0 : 0.0;
Packit 31ecd5
Packit 31ecd5
    case CLUTTER_BIN_ALIGNMENT_FIXED:
Packit 31ecd5
    case CLUTTER_BIN_ALIGNMENT_FILL:
Packit 31ecd5
      return 0.0;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  return 0.0;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static gdouble
Packit 31ecd5
get_actor_align_factor (ClutterActorAlign alignment)
Packit 31ecd5
{
Packit 31ecd5
  switch (alignment)
Packit 31ecd5
    {
Packit 31ecd5
    case CLUTTER_ACTOR_ALIGN_CENTER:
Packit 31ecd5
      return 0.5;
Packit 31ecd5
Packit 31ecd5
    case CLUTTER_ACTOR_ALIGN_START:
Packit 31ecd5
      return 0.0;
Packit 31ecd5
Packit 31ecd5
    case CLUTTER_ACTOR_ALIGN_END:
Packit 31ecd5
      return 1.0;
Packit 31ecd5
Packit 31ecd5
    case CLUTTER_ACTOR_ALIGN_FILL:
Packit 31ecd5
      return 0.0;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  return 0.0;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_allocate (ClutterLayoutManager   *manager,
Packit 31ecd5
                             ClutterContainer       *container,
Packit 31ecd5
                             const ClutterActorBox  *allocation,
Packit 31ecd5
                             ClutterAllocationFlags  flags)
Packit 31ecd5
{
Packit 31ecd5
  gfloat allocation_x, allocation_y;
Packit 31ecd5
  gfloat available_w, available_h;
Packit 31ecd5
  ClutterActor *actor, *child;
Packit 31ecd5
  ClutterActorIter iter;
Packit 31ecd5
Packit 31ecd5
  clutter_actor_box_get_origin (allocation, &allocation_x, &allocation_y);
Packit 31ecd5
  clutter_actor_box_get_size (allocation, &available_w, &available_h);
Packit 31ecd5
Packit 31ecd5
  actor = CLUTTER_ACTOR (container);
Packit 31ecd5
Packit 31ecd5
  clutter_actor_iter_init (&iter, actor);
Packit 31ecd5
  while (clutter_actor_iter_next (&iter, &child))
Packit 31ecd5
    {
Packit 31ecd5
      ClutterLayoutMeta *meta;
Packit 31ecd5
      ClutterBinLayer *layer;
Packit 31ecd5
      ClutterActorBox child_alloc = { 0, };
Packit 31ecd5
      gdouble x_align, y_align;
Packit 31ecd5
      gboolean x_fill, y_fill, is_fixed_position_set;
Packit 31ecd5
      float fixed_x, fixed_y;
Packit 31ecd5
Packit 31ecd5
      if (!clutter_actor_is_visible (child))
Packit 31ecd5
        continue;
Packit 31ecd5
Packit 31ecd5
      meta = clutter_layout_manager_get_child_meta (manager,
Packit 31ecd5
                                                    container,
Packit 31ecd5
                                                    child);
Packit 31ecd5
      layer = CLUTTER_BIN_LAYER (meta);
Packit 31ecd5
Packit 31ecd5
      fixed_x = fixed_y = 0.f;
Packit 31ecd5
      g_object_get (child,
Packit 31ecd5
                    "fixed-position-set", &is_fixed_position_set,
Packit 31ecd5
                    "fixed-x", &fixed_x,
Packit 31ecd5
                    "fixed-y", &fixed_y,
Packit 31ecd5
                    NULL);
Packit 31ecd5
Packit 31ecd5
      /* XXX:2.0 - remove the FIXED alignment, and just use the fixed position
Packit 31ecd5
       * of the actor if one is set
Packit 31ecd5
       */
Packit 31ecd5
      if (is_fixed_position_set ||
Packit 31ecd5
          layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED)
Packit 31ecd5
	{
Packit 31ecd5
          if (is_fixed_position_set)
Packit 31ecd5
            child_alloc.x1 = fixed_x;
Packit 31ecd5
          else
Packit 31ecd5
            child_alloc.x1 = clutter_actor_get_x (child);
Packit 31ecd5
	}
Packit 31ecd5
      else
Packit 31ecd5
        child_alloc.x1 = allocation_x;
Packit 31ecd5
Packit 31ecd5
      if (is_fixed_position_set ||
Packit 31ecd5
          layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED)
Packit 31ecd5
	{
Packit 31ecd5
	  if (is_fixed_position_set)
Packit 31ecd5
            child_alloc.y1 = fixed_y;
Packit 31ecd5
          else
Packit 31ecd5
	    child_alloc.y1 = clutter_actor_get_y (child);
Packit 31ecd5
	}
Packit 31ecd5
      else
Packit 31ecd5
        child_alloc.y1 = allocation_y;
Packit 31ecd5
Packit 31ecd5
      child_alloc.x2 = allocation_x + available_w;
Packit 31ecd5
      child_alloc.y2 = allocation_y + available_h;
Packit 31ecd5
Packit 31ecd5
      if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_HORIZONTAL))
Packit 31ecd5
        {
Packit 31ecd5
          ClutterActorAlign align;
Packit 31ecd5
Packit 31ecd5
          align = clutter_actor_get_x_align (child);
Packit 31ecd5
          x_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
Packit 31ecd5
          x_align = get_actor_align_factor (align);
Packit 31ecd5
        }
Packit 31ecd5
      else
Packit 31ecd5
        {
Packit 31ecd5
          ClutterTextDirection text_dir;
Packit 31ecd5
Packit 31ecd5
          x_fill = (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL);
Packit 31ecd5
Packit 31ecd5
          text_dir = clutter_actor_get_text_direction (child);
Packit 31ecd5
Packit 31ecd5
          if (!is_fixed_position_set)
Packit 31ecd5
            x_align = get_bin_alignment_factor (layer->x_align, text_dir);
Packit 31ecd5
          else
Packit 31ecd5
            x_align = 0.0;
Packit 31ecd5
        }
Packit 31ecd5
Packit 31ecd5
      if (clutter_actor_needs_expand (child, CLUTTER_ORIENTATION_VERTICAL))
Packit 31ecd5
        {
Packit 31ecd5
          ClutterActorAlign align;
Packit 31ecd5
Packit 31ecd5
          align = clutter_actor_get_y_align (child);
Packit 31ecd5
          y_fill = align == CLUTTER_ACTOR_ALIGN_FILL;
Packit 31ecd5
          y_align = get_actor_align_factor (align);
Packit 31ecd5
        }
Packit 31ecd5
      else
Packit 31ecd5
        {
Packit 31ecd5
          y_fill = (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL);
Packit 31ecd5
Packit 31ecd5
          if (!is_fixed_position_set)
Packit 31ecd5
            y_align = get_bin_alignment_factor (layer->y_align,
Packit 31ecd5
                                                CLUTTER_TEXT_DIRECTION_LTR);
Packit 31ecd5
          else
Packit 31ecd5
            y_align = 0.0;
Packit 31ecd5
        }
Packit 31ecd5
Packit 31ecd5
      clutter_actor_allocate_align_fill (child, &child_alloc,
Packit 31ecd5
                                         x_align, y_align,
Packit 31ecd5
                                         x_fill, y_fill,
Packit 31ecd5
                                         flags);
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static GType
Packit 31ecd5
clutter_bin_layout_get_child_meta_type (ClutterLayoutManager *manager)
Packit 31ecd5
{
Packit 31ecd5
  return CLUTTER_TYPE_BIN_LAYER;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static ClutterLayoutMeta *
Packit 31ecd5
clutter_bin_layout_create_child_meta (ClutterLayoutManager *manager,
Packit 31ecd5
                                      ClutterContainer     *container,
Packit 31ecd5
                                      ClutterActor         *actor)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv;
Packit 31ecd5
Packit 31ecd5
  priv = CLUTTER_BIN_LAYOUT (manager)->priv;
Packit 31ecd5
Packit 31ecd5
  return g_object_new (CLUTTER_TYPE_BIN_LAYER,
Packit 31ecd5
                       "container", container,
Packit 31ecd5
                       "actor", actor,
Packit 31ecd5
                       "manager", manager,
Packit 31ecd5
                       "x-align", priv->x_align,
Packit 31ecd5
                       "y_align", priv->y_align,
Packit 31ecd5
                       NULL);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_set_container (ClutterLayoutManager *manager,
Packit 31ecd5
                                  ClutterContainer     *container)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv;
Packit 31ecd5
  ClutterLayoutManagerClass *parent_class;
Packit 31ecd5
Packit 31ecd5
  priv = CLUTTER_BIN_LAYOUT (manager)->priv;
Packit 31ecd5
  priv->container = container;
Packit 31ecd5
Packit 31ecd5
  parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_bin_layout_parent_class);
Packit 31ecd5
  parent_class->set_container (manager, container);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_set_property (GObject      *gobject,
Packit 31ecd5
                                 guint         prop_id,
Packit 31ecd5
                                 const GValue *value,
Packit 31ecd5
                                 GParamSpec   *pspec)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayout *layout = CLUTTER_BIN_LAYOUT (gobject);
Packit 31ecd5
Packit 31ecd5
  switch (prop_id)
Packit 31ecd5
    {
Packit 31ecd5
    case PROP_X_ALIGN:
Packit 31ecd5
      set_x_align (layout, g_value_get_enum (value));
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    case PROP_Y_ALIGN:
Packit 31ecd5
      set_y_align (layout, g_value_get_enum (value));
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    default:
Packit 31ecd5
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
Packit 31ecd5
      break;
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_get_property (GObject    *gobject,
Packit 31ecd5
                                 guint       prop_id,
Packit 31ecd5
                                 GValue     *value,
Packit 31ecd5
                                 GParamSpec *pspec)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv;
Packit 31ecd5
Packit 31ecd5
  priv = CLUTTER_BIN_LAYOUT (gobject)->priv;
Packit 31ecd5
Packit 31ecd5
  switch (prop_id)
Packit 31ecd5
    {
Packit 31ecd5
    case PROP_X_ALIGN:
Packit 31ecd5
      g_value_set_enum (value, priv->x_align);
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    case PROP_Y_ALIGN:
Packit 31ecd5
      g_value_set_enum (value, priv->y_align);
Packit 31ecd5
      break;
Packit 31ecd5
Packit 31ecd5
    default:
Packit 31ecd5
      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
Packit 31ecd5
      break;
Packit 31ecd5
    }
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_class_init (ClutterBinLayoutClass *klass)
Packit 31ecd5
{
Packit 31ecd5
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Packit 31ecd5
  ClutterLayoutManagerClass *layout_class =
Packit 31ecd5
    CLUTTER_LAYOUT_MANAGER_CLASS (klass);
Packit 31ecd5
Packit 31ecd5
  /**
Packit 31ecd5
   * ClutterBinLayout:x-align:
Packit 31ecd5
   *
Packit 31ecd5
   * The default horizontal alignment policy for actors managed
Packit 31ecd5
   * by the #ClutterBinLayout
Packit 31ecd5
   *
Packit 31ecd5
   * Since: 1.2
Packit 31ecd5
   *
Packit 31ecd5
   * Deprecated: 1.12: Use the #ClutterActor:x-expand and the
Packit 31ecd5
   *   #ClutterActor:x-align properties on #ClutterActor instead.
Packit 31ecd5
   */
Packit 31ecd5
  bin_props[PROP_X_ALIGN] =
Packit 31ecd5
    g_param_spec_enum ("x-align",
Packit 31ecd5
                       P_("Horizontal Alignment"),
Packit 31ecd5
                       P_("Default horizontal alignment for the actors "
Packit 31ecd5
                          "inside the layout manager"),
Packit 31ecd5
                       CLUTTER_TYPE_BIN_ALIGNMENT,
Packit 31ecd5
                       CLUTTER_BIN_ALIGNMENT_CENTER,
Packit 31ecd5
                       CLUTTER_PARAM_READWRITE);
Packit 31ecd5
Packit 31ecd5
  /**
Packit 31ecd5
   * ClutterBinLayout:y-align:
Packit 31ecd5
   *
Packit 31ecd5
   * The default vertical alignment policy for actors managed
Packit 31ecd5
   * by the #ClutterBinLayout
Packit 31ecd5
   *
Packit 31ecd5
   * Since: 1.2
Packit 31ecd5
   *
Packit 31ecd5
   * Deprecated: 1.12: Use the #ClutterActor:y-expand and the
Packit 31ecd5
   *   #ClutterActor:y-align properties on #ClutterActor instead.
Packit 31ecd5
   */
Packit 31ecd5
  bin_props[PROP_Y_ALIGN] =
Packit 31ecd5
    g_param_spec_enum ("y-align",
Packit 31ecd5
                       P_("Vertical Alignment"),
Packit 31ecd5
                       P_("Default vertical alignment for the actors "
Packit 31ecd5
                          "inside the layout manager"),
Packit 31ecd5
                       CLUTTER_TYPE_BIN_ALIGNMENT,
Packit 31ecd5
                       CLUTTER_BIN_ALIGNMENT_CENTER,
Packit 31ecd5
                       CLUTTER_PARAM_READWRITE);
Packit 31ecd5
Packit 31ecd5
  gobject_class->set_property = clutter_bin_layout_set_property;
Packit 31ecd5
  gobject_class->get_property = clutter_bin_layout_get_property;
Packit 31ecd5
  g_object_class_install_properties (gobject_class, PROP_LAST, bin_props);
Packit 31ecd5
Packit 31ecd5
  layout_class->get_preferred_width = clutter_bin_layout_get_preferred_width;
Packit 31ecd5
  layout_class->get_preferred_height = clutter_bin_layout_get_preferred_height;
Packit 31ecd5
  layout_class->allocate = clutter_bin_layout_allocate;
Packit 31ecd5
  layout_class->create_child_meta = clutter_bin_layout_create_child_meta;
Packit 31ecd5
  layout_class->get_child_meta_type = clutter_bin_layout_get_child_meta_type;
Packit 31ecd5
  layout_class->set_container = clutter_bin_layout_set_container;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
static void
Packit 31ecd5
clutter_bin_layout_init (ClutterBinLayout *self)
Packit 31ecd5
{
Packit 31ecd5
  self->priv = clutter_bin_layout_get_instance_private (self);
Packit 31ecd5
Packit 31ecd5
  self->priv->x_align = CLUTTER_BIN_ALIGNMENT_CENTER;
Packit 31ecd5
  self->priv->y_align = CLUTTER_BIN_ALIGNMENT_CENTER;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
/**
Packit 31ecd5
 * clutter_bin_layout_new:
Packit 31ecd5
 * @x_align: the default alignment policy to be used on the
Packit 31ecd5
 *   horizontal axis
Packit 31ecd5
 * @y_align: the default alignment policy to be used on the
Packit 31ecd5
 *   vertical axis
Packit 31ecd5
 *
Packit 31ecd5
 * Creates a new #ClutterBinLayout layout manager
Packit 31ecd5
 *
Packit 31ecd5
 * Return value: the newly created layout manager
Packit 31ecd5
 *
Packit 31ecd5
 * Since: 1.2
Packit 31ecd5
 */
Packit 31ecd5
ClutterLayoutManager *
Packit 31ecd5
clutter_bin_layout_new (ClutterBinAlignment x_align,
Packit 31ecd5
                        ClutterBinAlignment y_align)
Packit 31ecd5
{
Packit 31ecd5
  return g_object_new (CLUTTER_TYPE_BIN_LAYOUT,
Packit 31ecd5
                       "x-align", x_align,
Packit 31ecd5
                       "y-align", y_align,
Packit 31ecd5
                       NULL);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
/**
Packit 31ecd5
 * clutter_bin_layout_set_alignment:
Packit 31ecd5
 * @self: a #ClutterBinLayout
Packit 31ecd5
 * @child: (allow-none): a child of @container
Packit 31ecd5
 * @x_align: the horizontal alignment policy to be used for the @child
Packit 31ecd5
 *   inside @container
Packit 31ecd5
 * @y_align: the vertical aligment policy to be used on the @child
Packit 31ecd5
 *   inside @container
Packit 31ecd5
 *
Packit 31ecd5
 * Sets the horizontal and vertical alignment policies to be applied
Packit 31ecd5
 * to a @child of @self
Packit 31ecd5
 *
Packit 31ecd5
 * If @child is %NULL then the @x_align and @y_align values will
Packit 31ecd5
 * be set as the default alignment policies
Packit 31ecd5
 *
Packit 31ecd5
 * Since: 1.2
Packit 31ecd5
 *
Packit 31ecd5
 * Deprecated: 1.12: Use the #ClutterActor:x-align and
Packit 31ecd5
 *   #ClutterActor:y-align properties of #ClutterActor instead.
Packit 31ecd5
 */
Packit 31ecd5
void
Packit 31ecd5
clutter_bin_layout_set_alignment (ClutterBinLayout    *self,
Packit 31ecd5
                                  ClutterActor        *child,
Packit 31ecd5
                                  ClutterBinAlignment  x_align,
Packit 31ecd5
                                  ClutterBinAlignment  y_align)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv;
Packit 31ecd5
  ClutterLayoutManager *manager;
Packit 31ecd5
  ClutterLayoutMeta *meta;
Packit 31ecd5
Packit 31ecd5
  g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
Packit 31ecd5
  g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
Packit 31ecd5
Packit 31ecd5
  priv = self->priv;
Packit 31ecd5
Packit 31ecd5
  if (priv->container == NULL)
Packit 31ecd5
    {
Packit 31ecd5
      if (child == NULL)
Packit 31ecd5
        {
Packit 31ecd5
          set_x_align (self, x_align);
Packit 31ecd5
          set_y_align (self, y_align);
Packit 31ecd5
        }
Packit 31ecd5
      else
Packit 31ecd5
        g_warning ("The layout of type '%s' must be associated to "
Packit 31ecd5
                   "a ClutterContainer before setting the alignment "
Packit 31ecd5
                   "on its children",
Packit 31ecd5
                   G_OBJECT_TYPE_NAME (self));
Packit 31ecd5
Packit 31ecd5
      return;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  manager = CLUTTER_LAYOUT_MANAGER (self);
Packit 31ecd5
  meta = clutter_layout_manager_get_child_meta (manager,
Packit 31ecd5
                                                priv->container,
Packit 31ecd5
                                                child);
Packit 31ecd5
  g_assert (CLUTTER_IS_BIN_LAYER (meta));
Packit 31ecd5
Packit 31ecd5
  set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
Packit 31ecd5
  set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
/**
Packit 31ecd5
 * clutter_bin_layout_get_alignment:
Packit 31ecd5
 * @self: a #ClutterBinLayout
Packit 31ecd5
 * @child: (allow-none): a child of @container
Packit 31ecd5
 * @x_align: (out) (allow-none): return location for the horizontal
Packit 31ecd5
 *   alignment policy
Packit 31ecd5
 * @y_align: (out) (allow-none): return location for the vertical
Packit 31ecd5
 *   alignment policy
Packit 31ecd5
 *
Packit 31ecd5
 * Retrieves the horizontal and vertical alignment policies for
Packit 31ecd5
 * a child of @self
Packit 31ecd5
 *
Packit 31ecd5
 * If @child is %NULL the default alignment policies will be returned
Packit 31ecd5
 * instead
Packit 31ecd5
 *
Packit 31ecd5
 * Since: 1.2
Packit 31ecd5
 *
Packit 31ecd5
 * Deprecated: 1.12: Use the #ClutterActor:x-align and the
Packit 31ecd5
 *   #ClutterActor:y-align properties of #ClutterActor instead.
Packit 31ecd5
 */
Packit 31ecd5
void
Packit 31ecd5
clutter_bin_layout_get_alignment (ClutterBinLayout    *self,
Packit 31ecd5
                                  ClutterActor        *child,
Packit 31ecd5
                                  ClutterBinAlignment *x_align,
Packit 31ecd5
                                  ClutterBinAlignment *y_align)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv;
Packit 31ecd5
  ClutterLayoutManager *manager;
Packit 31ecd5
  ClutterLayoutMeta *meta;
Packit 31ecd5
  ClutterBinLayer *layer;
Packit 31ecd5
Packit 31ecd5
  g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
Packit 31ecd5
Packit 31ecd5
  priv = self->priv;
Packit 31ecd5
Packit 31ecd5
  if (priv->container == NULL)
Packit 31ecd5
    {
Packit 31ecd5
      if (child == NULL)
Packit 31ecd5
        {
Packit 31ecd5
          if (x_align)
Packit 31ecd5
            *x_align = priv->x_align;
Packit 31ecd5
Packit 31ecd5
          if (y_align)
Packit 31ecd5
            *y_align = priv->y_align;
Packit 31ecd5
        }
Packit 31ecd5
      else
Packit 31ecd5
        g_warning ("The layout of type '%s' must be associated to "
Packit 31ecd5
                   "a ClutterContainer before getting the alignment "
Packit 31ecd5
                   "of its children",
Packit 31ecd5
                   G_OBJECT_TYPE_NAME (self));
Packit 31ecd5
Packit 31ecd5
      return;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  manager = CLUTTER_LAYOUT_MANAGER (self);
Packit 31ecd5
  meta = clutter_layout_manager_get_child_meta (manager,
Packit 31ecd5
                                                priv->container,
Packit 31ecd5
                                                child);
Packit 31ecd5
  g_assert (CLUTTER_IS_BIN_LAYER (meta));
Packit 31ecd5
Packit 31ecd5
  layer = CLUTTER_BIN_LAYER (meta);
Packit 31ecd5
Packit 31ecd5
  if (x_align)
Packit 31ecd5
    *x_align = layer->x_align;
Packit 31ecd5
Packit 31ecd5
  if (y_align)
Packit 31ecd5
    *y_align = layer->y_align;
Packit 31ecd5
}
Packit 31ecd5
Packit 31ecd5
/**
Packit 31ecd5
 * clutter_bin_layout_add:
Packit 31ecd5
 * @self: a #ClutterBinLayout
Packit 31ecd5
 * @child: a #ClutterActor
Packit 31ecd5
 * @x_align: horizontal alignment policy for @child
Packit 31ecd5
 * @y_align: vertical alignment policy for @child
Packit 31ecd5
 *
Packit 31ecd5
 * Adds a #ClutterActor to the container using @self and
Packit 31ecd5
 * sets the alignment policies for it
Packit 31ecd5
 *
Packit 31ecd5
 * This function is equivalent to clutter_container_add_actor()
Packit 31ecd5
 * and clutter_layout_manager_child_set_property() but it does not
Packit 31ecd5
 * require a pointer to the #ClutterContainer associated to the
Packit 31ecd5
 * #ClutterBinLayout
Packit 31ecd5
 *
Packit 31ecd5
 * Since: 1.2
Packit 31ecd5
 *
Packit 31ecd5
 * Deprecated: 1.12: Use clutter_actor_add_child() instead.
Packit 31ecd5
 */
Packit 31ecd5
void
Packit 31ecd5
clutter_bin_layout_add (ClutterBinLayout    *self,
Packit 31ecd5
                        ClutterActor        *child,
Packit 31ecd5
                        ClutterBinAlignment  x_align,
Packit 31ecd5
                        ClutterBinAlignment  y_align)
Packit 31ecd5
{
Packit 31ecd5
  ClutterBinLayoutPrivate *priv;
Packit 31ecd5
  ClutterLayoutManager *manager;
Packit 31ecd5
  ClutterLayoutMeta *meta;
Packit 31ecd5
Packit 31ecd5
  g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
Packit 31ecd5
  g_return_if_fail (CLUTTER_IS_ACTOR (child));
Packit 31ecd5
Packit 31ecd5
  priv = self->priv;
Packit 31ecd5
Packit 31ecd5
  if (priv->container == NULL)
Packit 31ecd5
    {
Packit 31ecd5
      g_warning ("The layout of type '%s' must be associated to "
Packit 31ecd5
                 "a ClutterContainer before adding children",
Packit 31ecd5
                 G_OBJECT_TYPE_NAME (self));
Packit 31ecd5
      return;
Packit 31ecd5
    }
Packit 31ecd5
Packit 31ecd5
  clutter_container_add_actor (priv->container, child);
Packit 31ecd5
Packit 31ecd5
  manager = CLUTTER_LAYOUT_MANAGER (self);
Packit 31ecd5
  meta = clutter_layout_manager_get_child_meta (manager,
Packit 31ecd5
                                                priv->container,
Packit 31ecd5
                                                child);
Packit 31ecd5
  g_assert (CLUTTER_IS_BIN_LAYER (meta));
Packit 31ecd5
Packit 31ecd5
  set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
Packit 31ecd5
  set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
Packit 31ecd5
}