/* 
 * Copyright (c) 2008, 2013, 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 _WF_VIEW_H_
#define _WF_VIEW_H_

#include "wf_mforms.h"

using namespace System;
using namespace Drawing;

using namespace Windows::Forms;

namespace MySQL {
  namespace Forms {

    public enum class AutoResizeMode {
      ResizeNone,
      ResizeVertical,
      ResizeHorizontal,
      ResizeBoth
    };

    public ref class ViewImpl : public ObjectImpl
    {
    private:
      ToolTip^ tooltip;
      Image^ backgroundImage;
      mforms::Alignment backgroundImageAlignment;
      bool layoutSuspended;
      AutoResizeMode _resize_mode; // Used to constrain certain layout operations.
    protected:
      ViewImpl(mforms::View *view);
      ~ViewImpl();

      static void destroy(mforms::View *self);
      static void show(mforms::View *self, bool show);
      static int get_width(mforms::View *self);
      static int get_height(mforms::View *self);
      static int get_preferred_width(mforms::View *self);
      static int get_preferred_height(mforms::View *self);
      static int get_x(mforms::View *self);
      static int get_y(mforms::View *self);
      static void set_size(mforms::View *self, int w, int h);
      static void set_padding(mforms::View *self, int left, int top, int right, int bottom);
      static void set_position(mforms::View *self, int x, int y);
      static void client_to_screen(mforms::View *self, int& x, int& y);

      static void set_enabled(mforms::View *self, bool flag);
      static bool is_enabled(mforms::View *self);
      static View *find_subview(mforms::View *self, std::string &name);
      static void set_name(mforms::View *self, const std::string& text);
      static void relayout(mforms::View *self);
      static void set_needs_repaint(mforms::View *self);
      static void set_tooltip(mforms::View *self, const std::string& text);
      static void set_font(mforms::View *self, const std::string& text);
      static bool is_shown(mforms::View *self);
      static void suspend_layout(mforms::View *self, bool flag);
      static void set_front_color(mforms::View *self, const std::string &color);
      static std::string get_front_color(mforms::View *self);
      static void set_back_color(mforms::View *self, const std::string &color);
      static std::string get_back_color(mforms::View *self);
      static void set_back_image(mforms::View *self, const std::string &path, mforms::Alignment alignment);
      static void flush_events(mforms::View *self);
      static void focus(mforms::View *self);

      virtual void initialize() override;

      virtual void set_size(int width, int height);
      virtual void set_padding(int left, int top, int right, int bottom);
      virtual void set_position(int x, int y);
      virtual void set_tooltip(const std::string& text);
      virtual void set_font(const std::string& text);
      virtual ViewImpl^ get_parent();
      virtual void relayout();
      virtual void set_front_color(String ^color);
      String^ get_front_color();
      void set_back_color(String ^color);
      String^ get_back_color();
      virtual void set_back_image(String ^path, mforms::Alignment alignment);
      
      void Resize(System::Object^ sender, System::EventArgs^ e);
      void Enter(System::Object^ sender, System::EventArgs^ e);
    public:

      // Only containers allow drawing a background (restriction imposed by other platforms)
      // so we simulate this here by triggering background drawing only for those classes.
      void draw_background(PaintEventArgs ^args);
      void set_resize_mode(AutoResizeMode mode);

      // Utility functions need for event handlers.
      static bool use_min_width_for_layout(Control^ control);
      static bool use_min_height_for_layout(Control^ control);
      static void remove_auto_resize(Control^ control, AutoResizeMode mode);
      static AutoResizeMode get_auto_resize(Control^ control);
      static bool can_auto_resize_vertically(Control^ control);
      static void set_full_auto_resize(Control^ control);
      static bool can_auto_resize_horizontally(Control^ control);
      static void set_auto_resize(Control^ control, AutoResizeMode mode);
      static bool is_layout_dirty(Control^ control);
      static void set_layout_dirty(Control^ control, bool value);
      static void resize_with_docking(Control^ control, System::Drawing::Size& size);
      static void adjust_auto_resize_from_docking(Control^ control);
      static bool can_layout(Control ^control, String ^reason);

      static void init(Manager ^mgr)
      {
        mforms::ControlFactory *f= mforms::ControlFactory::get_instance();

        DEF_CALLBACK1(void, mforms::View*, mgr, f->_view_impl, ViewImpl, destroy);
        DEF_CALLBACK1(int, mforms::View*, mgr, f->_view_impl, ViewImpl, get_x);
        DEF_CALLBACK1(int, mforms::View*, mgr, f->_view_impl, ViewImpl, get_y);
        DEF_CALLBACK1(int, mforms::View*, mgr, f->_view_impl, ViewImpl, get_width);
        DEF_CALLBACK1(int, mforms::View*, mgr, f->_view_impl, ViewImpl, get_height);
        DEF_CALLBACK1(int, mforms::View*, mgr, f->_view_impl, ViewImpl, get_preferred_width);
        DEF_CALLBACK1(int, mforms::View*, mgr, f->_view_impl, ViewImpl, get_preferred_height);
        DEF_CALLBACK3(void, mforms::View*, int, int, mgr, f->_view_impl, ViewImpl, set_position);
        DEF_CALLBACK3(void, mforms::View*, int, int, mgr, f->_view_impl, ViewImpl, set_size);
        DEF_CALLBACK5(void, mforms::View*, int, int, int, int, mgr, f->_view_impl, ViewImpl, set_padding);
        DEF_CALLBACK3(void, mforms::View*, int&, int&, mgr, f->_view_impl, ViewImpl, client_to_screen);

        DEF_CALLBACK2(void, mforms::View*, bool, mgr, f->_view_impl, ViewImpl, show);
        DEF_CALLBACK2(void, mforms::View*, bool, mgr, f->_view_impl, ViewImpl, set_enabled);
        DEF_CALLBACK1(bool, mforms::View*, mgr, f->_view_impl, ViewImpl, is_enabled);
        DEF_CALLBACK2(void, mforms::View*, const std::string&, mgr, f->_view_impl, ViewImpl, set_name);
        DEF_CALLBACK1(void, mforms::View*, mgr, f->_view_impl, ViewImpl, relayout);
        DEF_CALLBACK1(void, mforms::View*, mgr, f->_view_impl, ViewImpl, set_needs_repaint);
        DEF_CALLBACK2(void, mforms::View*, const std::string&, mgr, f->_view_impl, ViewImpl, set_tooltip);
        DEF_CALLBACK2(void, mforms::View*, const std::string&, mgr, f->_view_impl, ViewImpl, set_font);
        DEF_CALLBACK1(bool, mforms::View*, mgr, f->_view_impl, ViewImpl, is_shown);
        DEF_CALLBACK2(void, mforms::View*, bool, mgr, f->_view_impl, ViewImpl, suspend_layout);
        DEF_CALLBACK2(void, mforms::View*, const std::string&, mgr, f->_view_impl, ViewImpl, set_front_color);
        DEF_CALLBACK1(std::string, mforms::View*, mgr, f->_view_impl, ViewImpl, get_front_color);
        DEF_CALLBACK2(void, mforms::View*, const std::string&, mgr, f->_view_impl, ViewImpl, set_back_color);
        DEF_CALLBACK1(std::string, mforms::View*, mgr, f->_view_impl, ViewImpl, get_back_color);
        DEF_CALLBACK3(void, mforms::View*, const std::string&, mforms::Alignment, mgr, f->_view_impl, ViewImpl, set_back_image);
        DEF_CALLBACK1(void, mforms::View*, mgr, f->_view_impl, ViewImpl, flush_events);
        DEF_CALLBACK1(void, mforms::View*, mgr, f->_view_impl, ViewImpl, focus);
      }
    };

  };
};

#endif
