/* 
 * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#ifndef _MFORMS_FORM_H_
#define _MFORMS_FORM_H_

#include <mforms/base.h>
#include <mforms/view.h>

#ifdef __APPLE__
#define TOP_FORM_PADDING 20
#else
#define TOP_FORM_PADDING 12
#endif

namespace mforms {

  enum FormFlag
  {
    FormNone        = 0,
    FormSingleFrame = 1 << 0,
    FormDialogFrame = 1 << 1,
    FormResizable   = 1 << 2,
    FormMinimizable = 1 << 3,
    FormHideOnClose = 1 << 4,
    FormStayOnTop   = 1 << 5,
    FormToolWindow  = 1 << 6  // Not combinable with any of the frame styles above. Also min and max
                              // are not available.
  };

  class Form;
  class Button;

#ifndef DOXYGEN_SHOULD_SKIP_THIS
#ifndef SWIG
  struct MFORMS_EXPORT FormImplPtrs
  {
    bool (__stdcall *create)(Form *self, Form *owner, FormFlag flag);
    void (__stdcall *set_title)(Form *self, const std::string &title);
    void (__stdcall *show_modal)(Form *self, Button *accept, Button *cancel);
    bool (__stdcall *run_modal)(Form *self, Button *accept, Button *cancel);
    void (__stdcall *end_modal)(Form *self, bool result);
    void (__stdcall *set_content)(Form *self, View *view);
    void (__stdcall *close)(Form *self);
    
    void (__stdcall *center)(Form *self);

    void (__stdcall *flush_events)(Form *self);
  };
#endif
#endif

  /** A standalone, top-level window.
   */
  class MFORMS_EXPORT Form : public View
  {
    FormImplPtrs *_form_impl;
    View *_content;
    bool _fixed_size;
    bool _release_on_close;

    boost::signals2::signal<void ()> _closed_signal;
  protected:
    Form();
  public:
    /** Constructor.
     
     @param owner - the owner of this window. Pass 0/None for no owner.
     @param flag - flags specifying some features of the window:
       FormNone       
       FormSingleFrame
       FormDialogFrame
       FormResizable  
       FormMinimizable
       FormHideOnClose
       FormStayOnTop
     */
    Form(Form *owner, FormFlag flag= (FormFlag)(FormResizable | FormMinimizable));
    virtual ~Form();
  
    /** Used to specify the main form to the Form() constructor. The returned object cannot be used for anything else */
    static Form* main_form();

    /** Sets the content view of the window.
     
     Usually a layouting container, such as a Box or a Table.
     */
    virtual void set_content(View *view);
    
    /** Sets the title of the window.
     */
    virtual void set_title(const std::string &title);
    
    /** Deprecated */
    virtual void show_modal(Button *accept, Button *cancel);
    
    /** Shows the window as a modal window.
     
     @param accept - a button to be used as the default accept button (ie when user presses Return key) or None
     @param cancel - button to be used as cancel button (ie when user presses Escape key) or None
     */
    virtual bool run_modal(Button *accept, Button *cancel);

    /** Ends a modal session started with run_modal()
     
     This function is automatically called if accept and cancel buttons are given to run_modal.
     
     @param result - the result to be returned by run_modal
     */
    virtual void end_modal(bool result);
    
    /** Closes the window. */
    virtual void close();
    
    /** Centers the window in the screen. */
    virtual void center();
    
    virtual void flush_events();

    /** Sets whether the window must be automatically released when closed. */
    void set_release_on_close(bool flag);
    
#ifndef SWIG
    /** Signal sent when the user clicks the close button in the window.
     
     In Python use add_closed_callback()
     */
    boost::signals2::signal<void ()>* signal_closed() { return &_closed_signal; }
#endif

    void was_closed()
    {
      _closed_signal();
      if (_release_on_close)
        release();
    }

  };
};

#endif
