// -*- c++ -*-
//  Generated by gtkmmproc from ./../menushell.gen_h -- DO NOT MODIFY!
#include <gtk--/menushell.h>
#include <gtk--/private/menushell_p.h>

#include <strings.h>

namespace Gtk
{

MenuShell::MenuShell(void)
 : Container((GtkContainer*)(gtk_object_new(get_type(),0))),
   nav_group_(0)
{
  initialize_class();
}

MenuShell::MenuShell(GtkMenuShell* castitem)
: Container(GTK_CONTAINER(castitem)),
  nav_group_(0)
{
  initialize_class();
}

MenuShell::~MenuShell()
{
  if (nav_group_) nav_group_->unref();
}


void
MenuShell::realize_impl()
{
  Widget::realize_impl();
  if (get_toplevel()->is_toplevel())
    accelerate(*get_toplevel());
}

gint
MenuShell::event_impl(GdkEvent* event)
{
  if (nav_group_ && event->type==GDK_KEY_PRESS)
    {
      GdkEventKey* key_event=(GdkEventKey*)event;
      if (nav_group_->activate(key_event->keyval,GdkModifierType(key_event->state)))
        return TRUE;
    }
  return Widget::event_impl(event);
}

void
MenuShell::accelerate(Gtk::Window& window)
{
  Window* parent=get_toplevel();
  AccelGroup* window_group=window.get_accel_group();

  if (!nav_group_)
    {
      nav_group_=AccelGroup::create();
      nav_group_->ref();
    }

  MenuList::iterator i;
  Menu* menu=0;
  set_data("gtkmm-accel-window",&window);

  for (i=items().begin();i!=items().end();++i)
    (*i)->accelerate();

}

/*********************************************************************
***** List properties
*********************************************************************/
typedef G_List_Cpp_Iterator<GtkMenuItem,MenuItem> menu_iterator;

menu_iterator Menu_Helpers::MenuList::insert(menu_iterator position, const Element& e)
  {
    int pos;
    Gtk::MenuItem* item=e.get_child();
    if (!item) return position;

    // locate the items desired position
    if (!parent_) return iterator();
    if (!position.node)
      pos = -1;
    else
      pos = g_list_position(glist(),position.node);

    gtk_menu_shell_insert(GTK_MENU_SHELL(parent_->gtkobj()),
                          GTK_WIDGET(item->gtkobj()), pos);

    // bad hack
    if (parent_->nav_group_)
      item->accelerate();

    // return the right iterator
    if (pos==0)
      return begin();
    if (!position.node)
      return --end();
    return --position;
  }

/*********************************************************************
***** Elements
*********************************************************************/
namespace Menu_Helpers {

Element::~Element()
{}


void
Element::set_callback(SigC::Slot0<void> callback,const string &accel_signal)
  {
    g_return_if_fail (child_!=0);
    if (callback)
      {
        if(accel_signal == "activate")
          child_->activate.connect(callback);
        else if (accel_signal == "toggled")
          {
            g_return_if_fail (CheckMenuItem::isA(child_));
            static_cast<CheckMenuItem*>(child_)->toggled.connect(callback);
          }
        else
          g_warning("Menu_Helpers::MenuElem: Connecting to signal \"%s\" "
                    "not yet implemented\n", accel_signal.c_str());
      }
  }

void
Element::set_navigation(const string& str,const AccelKey& accel_key)
{
  g_return_if_fail (child_!=0);
  Label *label=manage(new Label(str, 0.0, 0.5));
  label->show();
  child_->add(*label);
  child_->accel_key=accel_key.key_;
  child_->nav_key=label->parse_uline(str);
}

void
Element::create_child_menu_item()
{
  child_=manage(new MenuItem());
}

void
Element::init(const string &label,
               SigC::Slot0<void> callback,
               const string &accel_signal,
               const AccelKey &key)
{
  create_child_menu_item();
  set_navigation(label, key);
  set_callback(callback,accel_signal);
  child_->show();
}

void
Element::init(const string &label, Gtk::Menu& submenu, const AccelKey &key)
{
  create_child_menu_item();
  set_navigation(label, key);
  child_->set_submenu(submenu);
  child_->show();
}

MenuElem::MenuElem(const string &label, SigC::Slot0<void> callback,
    const string &accel_signal)
  : Element(0)
{
  init(label, callback, accel_signal);
}

MenuElem::MenuElem(const string &label, const AccelKey& accel_key,
        SigC::Slot0<void> callback,
        const string &accel_signal)
   : Element(0)
{
  init(label, callback, accel_signal, accel_key);
}

MenuElem::MenuElem(const string &label, Menu& submenu)
  : Element(0)
{
  init(label, submenu);
}

MenuElem::MenuElem(const string &label, const AccelKey& accel_key,
                   Menu& submenu)
   : Element(0)
{
  init(label, submenu, accel_key);
}

SeparatorElem::SeparatorElem(void)
  : Element(0)
{
  create_child_menu_item();
  child_->show();
}

CheckMenuElem::CheckMenuElem(const string &label, SigC::Slot0<void> callback,
                             const string &accel_signal)
  : Element(0)
{
  init(label, callback, accel_signal);
}

CheckMenuElem::CheckMenuElem(const string &label, const AccelKey& accel_key,
                             SigC::Slot0<void> callback,
                             const string &accel_signal)
  : Element(0)
{
  init(label, callback, accel_signal, accel_key);
}

void
CheckMenuElem::create_child_menu_item()
{
  child_=manage(new CheckMenuItem());
}



RadioMenuElem::RadioMenuElem(RadioMenuItem::Group& gr,
                             const string &label,
                             SigC::Slot0<void> callback,
                             const string &accel_signal)
  : Element(0),
    gr_(&gr)
{
  init(label, callback, accel_signal);
}

RadioMenuElem::RadioMenuElem(RadioMenuItem::Group& gr,
                             const string &label,
                             const AccelKey &accel_key,
                             SigC::Slot0<void> callback,
                             const string &accel_signal)
  : Element(0),
    gr_(&gr)
{
  init(label, callback, accel_signal, accel_key);
}

void
RadioMenuElem::create_child_menu_item()
{
  child_=manage(new RadioMenuItem(*gr_));
}

TearoffMenuElem::TearoffMenuElem(SigC::Slot0<void> callback,
                                 const string &accel_signal)
  : Element(0)
{
  init(callback,accel_signal);
}

TearoffMenuElem::TearoffMenuElem(const AccelKey &accel_key,
                                 SigC::Slot0<void> callback,
                                 const string &accel_signal)
  : Element(0)
{
  init(callback,accel_signal,accel_key);
}

void
TearoffMenuElem::create_child_menu_item()
{
  child_ = manage(new TearoffMenuItem());
}

void
TearoffMenuElem::init(SigC::Slot0<void> callback,
                      const string &accel_signal,
                      const AccelKey &accel_key)
{
  create_child_menu_item();
  child_->accel_key = accel_key.key_;
  child_->nav_key   = accel_key.key_&KEY_MASK;
  set_callback(callback,accel_signal);
  child_->show();
}

/**************************************************************************/

struct AccelKeyMod
{
  const char * name;
  guint mod;
};

static AccelKeyMod modifiers[]=
{
  { "<release>", Menu_Helpers::RELEASE },
  { "<>", Menu_Helpers::SHIFT },
  { "<control>", Menu_Helpers::CTL },
  { "<ctl>",  Menu_Helpers::CTL },
  { "<alt>",  Menu_Helpers::ALT },
  { "<mod1>", Menu_Helpers::MOD1 },
  { "<mod2>", Menu_Helpers::MOD2 },
  { "<mod3>", Menu_Helpers::MOD3 },
  { "<mod4>", Menu_Helpers::MOD4 },
  { "<mod5>", Menu_Helpers::MOD5 },
  { 0 , 0}
};

AccelKey::AccelKey(const string &str)
{
  parse(str);
}

AccelKey::AccelKey(const char *str)
{
  key_=0;
  if (str) parse(str);
}

string AccelKey::abrev()
{
  if (key()==GDK_VoidSymbol) return "";
  string out;
  // Note: Shift is a special case, as mask is 1<<15, but there
  //       are also (unshifted) keysyms where bit 15 is set.
  char *sym=gdk_keyval_name(key());

  if (key_&SHIFT) {
    guint gdkKey=key();

    if(!sym)
      sym=gdk_keyval_name(gdkKey&~SHIFT);
    if(sym)
      gdkKey=gdk_keyval_from_name(sym);

    if((gdkKey|SHIFT)!=gdkKey) {
      out+="Shft+";
    }
  }

  if (key_&CTL)   out+="Ctl+";
  if (key_&ALT)   out+="Alt+";
  if (key_&MOD2) out+="M2-";
  if (key_&MOD3) out+="M3-";
  if (key_&MOD4) out+="M4-";
  if (key_&MOD5) out+="M5-";

  if (sym) out+=string(sym);
  return out;
}

void AccelKey::parse(string str)
{
  key_=0;
  string::size_type start, stop;
  string::size_type npos = string::npos;
  bool found;

  while ((start=str.find('<')) != npos &&
         (stop=str.find('>',start)) != npos)
    {
      string part(str.substr (start,stop-start+1));
      // do not remove the space between 'substr' and '(' - it prevents
      // m4 macro invocation
      str.erase(start,stop-start+1);
      found=false;
      for (AccelKeyMod *i=modifiers;i->name!=0;i++)
#ifdef GTKMM_MSC
        if (!stricmp(part.c_str(),i->name))
#else
          if (!strcasecmp(part.c_str(),i->name))
#endif
            {
              key_|=i->mod;
              found=true;
              break;
            }
      if (!found)
        g_warning("unable to parse accelerator string (%s)\n",part.c_str());
    }

  //    if (str.length()!=1)
  //      g_warning("unable to parse accelerator string (%s)\n",str.c_str());

  key_|=gdk_keyval_from_name(str.c_str());
}

} // namespace Menu_Helpers

} // namespace Gtk

namespace Gtk {
Gtk::MenuShell *wrap (GtkMenuShell *o)
  {
    return static_cast<Gtk::MenuShell *> (Gtk::wrap_auto ((GtkObject *) (o)));
  }
}

namespace Gtk {
MenuShell_Class MenuShell::menu_shell_class = {0};

Object* MenuShell_Class::wrap_new(GtkObject* o)
  {
    Object* cpp=manage(new MenuShell((GtkMenuShell*)(o)));
    return cpp;
  }

bool MenuShell::isA( Object *checkcast)
  {
    return GTK_IS_MENU_SHELL(checkcast->gtkobj());
  }

GtkType MenuShell::get_type()
  {
    return menu_shell_class.get_type();
  }

GtkType MenuShell_Class::get_type()
  {
    if (!type)
      {
        CppClassParent::CppObjectType::get_type();
        GtkTypeInfo info =
          {
            "Gtk__MenuShell",
            sizeof(BaseObjectType),
            sizeof(BaseClassType),
            (GtkClassInitFunc) class_init_function,
            (GtkObjectInitFunc) object_init_function,
            /* reserved_1 */ NULL,
            /* reserved_2 */ NULL,
            /*base_class_init_func */ (GtkClassInitFunc) NULL
          };
        type=gtk_type_unique(gtk_menu_shell_get_type(), &info);
      }
    return type;
  }

const char* const MenuShell::signal_names[]={
   "deactivate",
   "selection_done",
   "move_current",
   "activate_current",
   "cancel",
   0};

void MenuShell::initialize_class()
  {

     menu_shell_self=this;

  }

void MenuShell_Class::class_init_function(GtkMenuShellClass *klass)
  {
    CppClassParent::class_init_function((BaseClassParent*)klass);
    klass->deactivate=deactivate_callback;
    klass->selection_done=selection_done_callback;
    klass->move_current=move_current_callback;
    klass->activate_current=activate_current_callback;
    klass->cancel=cancel_callback;
  }

void MenuShell_Class::object_init_function(GtkMenuShell *)
  {}

}

void Gtk::Menu_Helpers::MenuList::remove(const_reference child)
{
  g_return_if_fail(child!=0);
  gtk_container_remove(parent_->Container::gtkobj(),
                       (GtkWidget*)(child->gtkobj()));
}

void Gtk::Menu_Helpers::MenuList::remove(Widget &w)
{
  gtk_container_remove(parent_->Container::gtkobj(),(GtkWidget*)(w.gtkobj()));
}

Gtk::Menu_Helpers::MenuList::iterator Gtk::Menu_Helpers::MenuList::erase(iterator position)
{
  if (!position.node||position==end()) return end();
  iterator next=position;
  next++;

  gtk_container_remove(parent_->Container::gtkobj(),
      (GtkWidget*)((*position)->gtkobj()));
  return next;
}

Gtk::Menu_Helpers::MenuList::value_type Gtk::Menu_Helpers::MenuList::operator[](size_type l) const
          { size_type j; iterator i; for (i=begin(),j=0;i!=end(),j<l;++i,++j);
            return (*i);
          }

GList*& Gtk::Menu_Helpers::MenuList::glist() const
{ return parent_->gtkobj()->children; }

Gtk::Menu_Helpers::MenuList::iterator Gtk::Menu_Helpers::MenuList::begin_() const
{return iterator(glist(),glist());}

Gtk::Menu_Helpers::MenuList::iterator Gtk::Menu_Helpers::MenuList::end_() const
{return iterator(glist(),(GList*)0);}

Gtk::Menu_Helpers::MenuList::size_type Gtk::Menu_Helpers::MenuList::size() const
  { return g_list_length(glist()); }

void Gtk::Menu_Helpers::MenuList::clear()
{ erase(begin(),end()); }

void Gtk::Menu_Helpers::MenuList::erase(iterator start, iterator stop)
{ while(start != stop) start=erase(start); }


void Gtk::MenuShell::append(Gtk::MenuItem& menu_item)
  {
    gtk_menu_shell_append(gtkobj(),menu_item.Widget::gtkobj());
  }

void Gtk::MenuShell::prepend(Gtk::MenuItem& menu_item)
  {
    gtk_menu_shell_prepend(gtkobj(),menu_item.Widget::gtkobj());
  }

void Gtk::MenuShell::insert(Gtk::MenuItem& menu_item,gint position)
  {
    gtk_menu_shell_insert(gtkobj(),menu_item.Widget::gtkobj(),position);
  }

void Gtk::MenuShell::select_item(Gtk::MenuItem& menu_item)
  {
    gtk_menu_shell_select_item(gtkobj(),menu_item.Widget::gtkobj());
  }

void Gtk::MenuShell::deselect()
  {
    gtk_menu_shell_deselect(gtkobj());
  }

void Gtk::MenuShell::activate_item(Gtk::MenuItem& menu_item,bool force_deactivate)
  {
    gtk_menu_shell_activate_item(gtkobj(),menu_item.Widget::gtkobj(),force_deactivate);
  }

void Gtk::MenuShell_Class::deactivate_callback(GtkMenuShell* o_)
  {
    CppObjectType *obj=
      static_cast<CppObjectType *>(static_cast<Gtk::Object *>(
        gtk_object_get_data_by_id((GtkObject*)o_,Gtk::quark_)));

    if (obj)
      obj->deactivate_impl();
    else
      {
        BaseClassType* base=
          static_cast<BaseClassType*>(
            gtk_type_parent_class(((GtkObject*)o_)->klass->type));
        if (base->deactivate)
          (base->deactivate)(o_);
      }

  }

void Gtk::MenuShell::deactivate_impl()
  {
    BaseClassType* base=
      static_cast<BaseClassType*>(
        gtk_type_parent_class(gtkobject->klass->type));
    if (base->deactivate)
      (base->deactivate)(gtkobj());

  }

void Gtk::MenuShell_Class::selection_done_callback(GtkMenuShell* o_)
  {
    CppObjectType *obj=
      static_cast<CppObjectType *>(static_cast<Gtk::Object *>(
        gtk_object_get_data_by_id((GtkObject*)o_,Gtk::quark_)));

    if (obj)
      obj->selection_done_impl();
    else
      {
        BaseClassType* base=
          static_cast<BaseClassType*>(
            gtk_type_parent_class(((GtkObject*)o_)->klass->type));
        if (base->selection_done)
          (base->selection_done)(o_);
      }

  }

void Gtk::MenuShell::selection_done_impl()
  {
    BaseClassType* base=
      static_cast<BaseClassType*>(
        gtk_type_parent_class(gtkobject->klass->type));
    if (base->selection_done)
      (base->selection_done)(gtkobj());

  }

void Gtk::MenuShell_Class::move_current_callback(GtkMenuShell* o_,GtkMenuDirectionType p0)
  {
    CppObjectType *obj=
      static_cast<CppObjectType *>(static_cast<Gtk::Object *>(
        gtk_object_get_data_by_id((GtkObject*)o_,Gtk::quark_)));

    if (obj)
      obj->move_current_impl(p0);
    else
      {
        BaseClassType* base=
          static_cast<BaseClassType*>(
            gtk_type_parent_class(((GtkObject*)o_)->klass->type));
        if (base->move_current)
          (base->move_current)(o_,p0);
      }

  }

void Gtk::MenuShell::move_current_impl(GtkMenuDirectionType p0)
  {
    BaseClassType* base=
      static_cast<BaseClassType*>(
        gtk_type_parent_class(gtkobject->klass->type));
    if (base->move_current)
      (base->move_current)(gtkobj(),p0);

  }

void Gtk::MenuShell_Class::activate_current_callback(GtkMenuShell* o_,gboolean p0)
  {
    CppObjectType *obj=
      static_cast<CppObjectType *>(static_cast<Gtk::Object *>(
        gtk_object_get_data_by_id((GtkObject*)o_,Gtk::quark_)));

    if (obj)
      obj->activate_current_impl(p0);
    else
      {
        BaseClassType* base=
          static_cast<BaseClassType*>(
            gtk_type_parent_class(((GtkObject*)o_)->klass->type));
        if (base->activate_current)
          (base->activate_current)(o_,p0);
      }

  }

void Gtk::MenuShell::activate_current_impl(gboolean p0)
  {
    BaseClassType* base=
      static_cast<BaseClassType*>(
        gtk_type_parent_class(gtkobject->klass->type));
    if (base->activate_current)
      (base->activate_current)(gtkobj(),p0);

  }

void Gtk::MenuShell_Class::cancel_callback(GtkMenuShell* o_)
  {
    CppObjectType *obj=
      static_cast<CppObjectType *>(static_cast<Gtk::Object *>(
        gtk_object_get_data_by_id((GtkObject*)o_,Gtk::quark_)));

    if (obj)
      obj->cancel_impl();
    else
      {
        BaseClassType* base=
          static_cast<BaseClassType*>(
            gtk_type_parent_class(((GtkObject*)o_)->klass->type));
        if (base->cancel)
          (base->cancel)(o_);
      }

  }

void Gtk::MenuShell::cancel_impl()
  {
    BaseClassType* base=
      static_cast<BaseClassType*>(
        gtk_type_parent_class(gtkobject->klass->type));
    if (base->cancel)
      (base->cancel)(gtkobj());

  }
