/* Copyright (C) 2007 The cluttermm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <clutter/clutter.h>

namespace
{
extern "C"
{
static void SignalProxy_Container_foreach_callback(ClutterActor *actor, gpointer user_data)
{
  Clutter::Container::SlotForEach *const
    the_slot = static_cast<Clutter::Container::SlotForEach*>(user_data);

#ifdef GLIBMM_EXCEPTIONS_ENABLED
  try
#endif
  {
    const Glib::RefPtr<Clutter::Actor> cpp_actor = Glib::wrap(actor, true /* take reference */);
    (*the_slot)(cpp_actor);
  }
#ifdef GLIBMM_EXCEPTIONS_ENABLED
  catch (...)
  {
    Glib::exception_handlers_invoke();
  }
#endif
}
} // extern "C"
} // anonymous namespace

namespace Clutter
{

void Container::raise_child(const Glib::RefPtr<Actor>& actor)
{
  clutter_container_raise_child(gobj(), Glib::unwrap(actor), 0);
}

void Container::lower_child(const Glib::RefPtr<Actor>& actor)
{
  clutter_container_lower_child(gobj(), Glib::unwrap(actor), 0);
}

void Container::foreach(const SlotForEach& slot)
{
  clutter_container_foreach(gobj(),
      &SignalProxy_Container_foreach_callback, const_cast<SlotForEach*>(&slot));
}

void Container::get_child_property_value(const Glib::RefPtr<const Actor>& child,
                     const Glib::ustring& property_name, Glib::ValueBase& value) const
{
  clutter_container_child_get_property(const_cast<ClutterContainer*>(gobj()),
      const_cast<ClutterActor*>(child->gobj()), property_name.c_str(), value.gobj());
}

void Container::actor_added(const Glib::RefPtr<Actor>& actor)
{
  g_signal_emit_by_name(gobj(), "actor_added", actor->gobj());
}

void Container::actor_removed(const Glib::RefPtr<Actor>& actor)
{
  g_signal_emit_by_name(gobj(), "actor_removed", actor->gobj());
}

std::vector<Glib::RefPtr<Actor> > Container::get_children()
{
  GList* actorList = clutter_container_get_children(gobj());
  const guint actorCount = g_list_length(actorList);
  std::vector<Glib::RefPtr<Actor> > actorVec;
  actorVec.reserve(actorCount);

  for(GList* actorNode = actorList; actorNode->next; actorNode = actorList->next)
  {
    actorVec.push_back(Glib::wrap(static_cast<ClutterActor*>(actorNode->data), true));
  }

  return actorVec;
}

std::vector<Glib::RefPtr<const Actor> > Container::get_children() const
{
  GList* actorList = clutter_container_get_children(const_cast<ClutterContainer*>(gobj()));
  const guint actorCount = g_list_length(actorList);
  std::vector<Glib::RefPtr<const Actor> > actorVec;
  actorVec.reserve(actorCount);

  for(GList* actorNode = actorList; actorNode->next; actorNode = actorList->next)
  {
    actorVec.push_back(Glib::wrap(static_cast<ClutterActor*>(actorNode->data), true));
  }

  return actorVec;
}

} // namespace Clutter
