/**********************************************************************
This file is part of Crack dot Com's free source code release of Golgotha.
for information about compiling & licensing issues visit this URL
 If that doesn't help, contact Jonathan Clark at 
  golgotha_source@usa.net (Subject should have "GOLG" in it) 
***********************************************************************/

#include "menu/pull.hh"
#include "window/win_evt.hh"
#include "device/device.hh"
#include "device/keys.hh"

i4_pull_menu_class::i4_pull_menu_class(i4_graphical_style_class *style, 
                                       i4_parent_window_class *root_window)
  : i4_menu_class(i4_F),
    menu_colors(*style->color_hint),
    root(root_window),
    style(style)
{
  active_top=0;
  active_sub=0;
  sub_focused=i4_F;
  watching_mouse=i4_F;

  menu_colors.selected_text_foreground=i4_read_color_from_resource("selected_menu_foreground");
  menu_colors.selected_text_background=i4_read_color_from_resource("selected_menu_background");
}

void i4_pull_menu_class::watch()
{
  if (!watching_mouse)
  {
    watching_mouse=i4_T;
    i4_kernel.request_events(this,     
                             i4_device_class::FLAG_KEY_PRESS |
                             i4_device_class::FLAG_KEY_RELEASE |
                             i4_device_class::FLAG_MOUSE_BUTTON_DOWN |
                             i4_device_class::FLAG_MOUSE_BUTTON_UP);

  }
}

void i4_pull_menu_class::unwatch()
{
  if (watching_mouse)
  {
    i4_kernel.unrequest_events(this,
                               i4_device_class::FLAG_KEY_PRESS |
                               i4_device_class::FLAG_KEY_RELEASE |
                               i4_device_class::FLAG_MOUSE_BUTTON_DOWN |
                               i4_device_class::FLAG_MOUSE_BUTTON_UP);

    watching_mouse=i4_F;
  }
}

i4_pull_menu_class::~i4_pull_menu_class()
{
  unwatch();
  hide_active();

  sub_menus.destroy_all();
}


void i4_pull_menu_class::show_active(i4_menu_item_class *who)
{
  win_iter name=children.begin(), sub=sub_menus.begin(), last=sub_menus.end();
  while (who!=&*name)
  {
    last=sub;
    ++name;
    ++sub;
  }

  sw32 px,py;

  py=who->y()+who->height();
  px=who->x();

  i4_menu_class *m=((i4_menu_class *)(&*sub));

  if (last==sub_menus.end())
    sub_menus.erase();
  else
    sub_menus.erase_after(last);


  m->show(root, px-root->x(), py-root->y());

  if (sub->height()+sub->y()>root->height())
  {
    m->hide();
    py=who->y()-sub->height();
    m->show(root, px-root->x(), py-root->y());
  }

   
  if (sub->width()+sub->x()>root->width())
  {
    m->hide();
    px=root->width()-sub->width();
    m->show(root, px-root->x(), py-root->y());
  }    

  active_top=who;
  active_sub=m;
  watch();
}

void i4_pull_menu_class::note_reaction_sent(i4_menu_item_class *who,       // this is who sent it
                                            i4_event_reaction_class *ev,   // who it was to 
                                            i4_menu_item_class::reaction_type type)
{
  i4_menu_class::note_reaction_sent(who, ev, type);

  if (type==i4_menu_item_class::PRESSED)
  {
    who->do_depress();
    if (!active_sub)
      show_active(who);
  } else if (type==i4_menu_item_class::ACTIVATED)
  {
    if (active_sub)
    {
      hide_active();
      show_active(who);
    }
      
    active_top=who;
  } else if (type==i4_menu_item_class::DEACTIVATED)
  {
    if (active_sub)
      who->do_activate();
  }
}

void i4_pull_menu_class::hide_active()
{
  if (active_sub)
  {
    active_sub->hide();

    if ((i4_window_class *)active_top==&*children.begin())
      sub_menus.insert(*active_sub);
    else
    {
      win_iter s=sub_menus.begin(), t=children.begin();
      ++t;
      for (;(*&t)!=active_top;)
      {
        ++s;
        ++t;
      }
      sub_menus.insert_after(s, *active_sub);
    }
    unwatch();
  }

  if (active_top)
    active_top->do_deactivate();

  active_top=0;
  active_sub=0;
}

void i4_pull_menu_class::receive_event(i4_event *ev)
{
  if (ev->type()==i4_event::OBJECT_MESSAGE)
  {
    CAST_PTR(lev, i4_menu_focus_event_class, ev);

    if (lev->focus_state==i4_menu_focus_event_class::lost_focus)
      sub_focused=i4_F;
    else
      sub_focused=i4_T;
  } 
  else if (ev->type()==i4_event::WINDOW_MESSAGE)
  {
    CAST_PTR(wev, i4_window_message_class, ev);
    if (wev->sub_type==i4_window_message_class::LOST_MOUSE_FOCUS)
      focused=i4_F;
    else if (wev->sub_type==i4_window_message_class::GOT_MOUSE_FOCUS)
      focused=i4_T;      
    
    i4_menu_class::receive_event(ev);
  }
  else if (ev->type()==i4_event::MOUSE_BUTTON_DOWN ||
           ev->type()==i4_event::MOUSE_BUTTON_UP)
  {
    if (!focused && !sub_focused)
      hide_active();

    if (focused)
      i4_menu_class::receive_event(ev);
  }
  else if (ev->type()==i4_event::KEY_PRESS)
  {
    CAST_PTR(kev, i4_key_press_event_class, ev);
    if (kev->key_code==I4_ESC)
      hide_active();
    else
      i4_menu_class::receive_event(ev);
  }  
  else if (focused)
    i4_menu_class::receive_event(ev);
}


void i4_pull_menu_class::parent_draw(i4_draw_context_class &context)
{
  i4_rect_list_class child_clip(&context.clip,0,0);
  child_clip.intersect_list(&undrawn_area);

  child_clip.swap(&context.clip);

  style->deco_neutral_fill(local_image, 0,0, width()-1, height()-1, context);


  //  local_image->clear(menu_colors.text_background,context);

  child_clip.swap(&context.clip);
  i4_parent_window_class::parent_draw(context);
}

void i4_pull_menu_class::add_sub_menu(i4_menu_item_class *name,
                                      i4_menu_class *sub_menu)
{
  add_item(name);
  name->set_menu_parent(this);
  sub_menu->notify_focus_change(this);

  sub_menus.insert_end(*sub_menu);

  reparent(local_image, parent);
}

void i4_pull_menu_class::reparent(i4_image_class *draw_area, i4_parent_window_class *parent)
{
  i4_parent_window_class::reparent(draw_area, parent);
  if (parent)
  {
    resize(parent->width(), 0);
    arrange_right_down();

    w32 max_h=0;
    for (win_iter c=children.begin(); c!=children.end(); ++c)
      if (c->y()-y()+c->height()>max_h)
        max_h=c->y()-y()+c->height();

    resize(parent->width(), max_h);
  }
}

void i4_pull_menu_class::resize(w16 new_width, w16 new_height)
{
  i4_window_class::resize(new_width, new_height);
  arrange_right_down();
}



void i4_pull_menu_class::hide()
{
  if (parent)     
  {
    parent->remove_child(this);
    hide_active();
  }
  parent=0;
}