/* 
 * © 2008-2009 Sun Microsystems, Inc.
 *
 * 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 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., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#ifndef _LF_FORM_H_
#define _LF_FORM_H_

#include <mforms/mforms.h>

#include "gtk_helpers.h"
#include "lf_button.h"
#include "lf_view.h"
#include "lf_mforms.h"

namespace mforms {
namespace gtk {

class FormImpl : public ViewImpl
{ 
  Gtk::Window *_window;
  virtual Gtk::Widget *get_outer() const { return _window; }


  static bool create(::mforms::Form *self, ::mforms::Form *owner, mforms::FormFlag flag)
  {
    return new FormImpl(self, owner, flag) != 0;
  }


  static void set_title(::mforms::Form *self, const std::string &title)
  {
    FormImpl* form = self->get_data<FormImpl>();
    if (form)
    {
      form->_window->set_title(title);
    }
  }
  
  void accept_clicked(bool *status)
  {
    *status= true;
    Gtk::Main::quit();
  }

  void cancel_clicked(bool *status)
  {
    *status= false;
    Gtk::Main::quit();
  }
  
    bool on_widget_delete_event(GdkEventAny* event)
  {
    mforms::Form* form = dynamic_cast<mforms::Form*>(owner); // ObjectImpl::owner
    if (form)
      form->was_closed();
      
    return false;
  }
  
  static void show_modal(::mforms::Form *self, ::mforms::Button *accept, ::mforms::Button *cancel)
  {
    FormImpl* form = self->get_data<FormImpl>();
    if (form)
    {
      form->_window->signal_delete_event().connect(sigc::mem_fun(form, &FormImpl::on_widget_delete_event));
      if (get_mainwindow())
        form->_window->set_transient_for(*get_mainwindow());
      form->_window->set_modal(false);
      form->_window->show();
    }
  }

  bool on_key_release(GdkEventKey* event)
  {
    if (event->keyval == GDK_Escape)
    {
      bool status = false;
      cancel_clicked(&status);
    }
    return false;
  }

  static bool run_modal(::mforms::Form *self, ::mforms::Button *accept, ::mforms::Button *cancel)
  {
    FormImpl* form = self->get_data<FormImpl>();
    if (form)
    {
      bool status= false;
      if (get_mainwindow())
        form->_window->set_transient_for(*get_mainwindow());
      form->_window->set_modal(true);
      form->_window->show();
      sigc::connection accept_c;
      sigc::connection cancel_c;

      if (accept)
      {
        ButtonImpl *button= self->get_data<ButtonImpl>();
        
        accept_c= accept->signal_clicked().connect(sigc::bind(sigc::mem_fun(form, &FormImpl::accept_clicked), &status));
      }
      if (cancel)
      {
        cancel_c= cancel->signal_clicked().connect(sigc::bind(sigc::mem_fun(form, &FormImpl::cancel_clicked), &status));
      
        form->_window->signal_key_release_event().connect(sigc::mem_fun(form, &FormImpl::on_key_release));
      }

      Gtk::Main::run();
      
      form->_window->hide();

      accept_c.disconnect();
      cancel_c.disconnect();
      
      return status;
    }
    return false;
  }

  static void close(::mforms::Form *self)
  {
    FormImpl* form = self->get_data<FormImpl>();
    if (form)
    {
      form->_window->hide();
    }
  }

  static void set_content(::mforms::Form *self, ::mforms::View *child)
  {
    FormImpl* form = self->get_data<FormImpl>();
    if (form)
    {
      form->_window->add(*child->get_data<ViewImpl>()->get_outer());
      child->show();
    }
  }

  static void flush_events(::mforms::Form *self)
  {
    while (Gtk::Main::events_pending())
      Gtk::Main::iteration();
  }

  static void center(Form *self)
  {
    FormImpl* form = self->get_data<FormImpl>();
    form->_window->set_position(Gtk::WIN_POS_CENTER);
  }


  FormImpl(::mforms::Form *form, ::mforms::Form *owner, mforms::FormFlag form_flag)
    : ViewImpl(form)
  {
    _window = new Gtk::Window(Gtk::WINDOW_TOPLEVEL);

    if (owner)
      _window->set_transient_for(*static_cast<Gtk::Window*>(owner->get_data<FormImpl>()->get_outer()));

    _window->set_position(Gtk::WIN_POS_CENTER);
    
    switch (form_flag)
    {
      case mforms::FormResizable:
        {
          break;
        }
      case mforms::FormMinimizable:
        {
          break;
        }
    }
        
    _window->signal_realize().connect(sigc::mem_fun(form, &::mforms::View::needs_resize));
  }

  
  virtual void set_size(int width, int height)
  {
    _window->set_default_size(width, height);
    _window->set_size_request(width, height);
  }

public:
  static void init()
  {
    ::mforms::ControlFactory *f = ::mforms::ControlFactory::get_instance();

    f->_form_impl.create     = &FormImpl::create;
    f->_form_impl.close      = &FormImpl::close;
    f->_form_impl.set_title  = &FormImpl::set_title;
//    f->_form_impl.set_flags  = &FormImpl::set_flags;
    f->_form_impl.show_modal = &FormImpl::show_modal;
    f->_form_impl.run_modal = &FormImpl::run_modal;
    f->_form_impl.set_content= &FormImpl::set_content;
    f->_form_impl.flush_events= &FormImpl::flush_events;
    f->_form_impl.center      = &FormImpl::center;
  }
};

};
};

#endif
