/* 
 * Copyright (c) 2009, 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 _WF_SCROLLPANEL_H_
#define _WF_SCROLLPANEL_H_

/**
 * Specialized mform panel with scrollbars.
 */
using namespace System::Windows::Forms;
using namespace Layout;

namespace MySQL {
  namespace Forms {

    private ref class ScrollFillLayout : public LayoutEngine
    {
    public:
      virtual bool Layout(Object^ container, LayoutEventArgs^ arguments) override;
    };

    //----------------------------------------------------------------------------------------------

    /**
     * A panel with a fill layout that can be scrolled.
     */
    public ref class ScrollFillPanel : public Control
    {
    private:
      IMessageFilter^ wheelMessageFilter;
      ScrollFillLayout^ layoutEngine;
      bool autoHideScrollbars;
      bool hideHorizontalScrollbar;
      bool hideVerticalScrollbar;
      int horizontalOffset;
      int verticalOffset;
      int updateCount;
    protected:
      void HandleHorizontalScrolling(Message% m);
      void HandleVerticalScrolling(Message% m);
      void HandleWheelScrolling(Message% m);
      void SetOffset(int x, int y);
    public:
      ScrollFillPanel();
      ~ScrollFillPanel();

      virtual System::Drawing::Size GetPreferredSize(System::Drawing::Size proposedSize) override;
      virtual void WndProc(Message% m) override;
      void UpdateHorizontalScrollbar(int newWidth);
      void UpdateVerticalScrollbar(int newHeight);
      void ScrollControlIntoView(Control^ control);

      virtual property Windows::Forms::Layout::LayoutEngine^ LayoutEngine
      {
        Windows::Forms::Layout::LayoutEngine^ get() override
        {
          if (layoutEngine == nullptr)
            layoutEngine = gcnew ScrollFillLayout();

          return layoutEngine;
        }
      }

      /**
       * Used to either hide scrollbars completely if they are not needed or show them as disabled.
       */
      property bool AutoHideScrollbars
      {
        bool get() { return autoHideScrollbars; }
        void set(bool value)
        {
          if (autoHideScrollbars != value)
          {
            autoHideScrollbars= value;
            PerformLayout();
          }
        }
      }

      property bool HideHorizontalScrollbar
      {
        bool get() { return hideHorizontalScrollbar; }
        void set(bool value)
        {
          if (hideHorizontalScrollbar != value)
          {
            hideHorizontalScrollbar= value;
            PerformLayout();
          }
        }
      }

      property bool HideVerticalScrollbar
      {
        bool get() { return hideVerticalScrollbar; }
        void set(bool value)
        {
          if (hideVerticalScrollbar != value)
          {
            hideVerticalScrollbar= value;
            PerformLayout();
          }
        }
      }

      property int HorizontalOffset
      {
        int get() { return horizontalOffset; };
      }

      property int VerticalOffset
      {
        int get() { return verticalOffset; };
      }

    };

    //----------------------------------------------------------------------------------------------

    public ref class ScrollPanelImpl : public ViewImpl
    {
    private:
      ScrollFillPanel^ _container; // The actual control that takes the content.

    protected:
      static bool create(::mforms::ScrollPanel *self, ::mforms::ScrollPanelFlags flags);
      static void add(::mforms::ScrollPanel *self, ::mforms::View *view);
      static void remove(::mforms::ScrollPanel *self);
      static void set_autohide_scrollers(::mforms::ScrollPanel *self, bool);
      static void set_visible_scrollers(::mforms::ScrollPanel *self, bool, bool);
      static void scroll_to_view(::mforms::ScrollPanel *self, ::mforms::View *view);
    public:
      ScrollPanelImpl(::mforms::ScrollPanel *self);

      void add(::mforms::View *view);
      void scroll_to_view(::mforms::View *view);
      void remove();

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

        DEF_CALLBACK2(bool, ::mforms::ScrollPanel*, ::mforms::ScrollPanelFlags, mgr, f->_spanel_impl, ScrollPanelImpl, create);
        DEF_CALLBACK2(void, ::mforms::ScrollPanel*, ::mforms::View*, mgr, f->_spanel_impl, ScrollPanelImpl, add);
        DEF_CALLBACK1(void, ::mforms::ScrollPanel*, mgr, f->_spanel_impl, ScrollPanelImpl, remove);
        DEF_CALLBACK3(void, ::mforms::ScrollPanel*, bool, bool, mgr, f->_spanel_impl, ScrollPanelImpl, set_visible_scrollers);
        DEF_CALLBACK2(void, ::mforms::ScrollPanel*, bool, mgr, f->_spanel_impl, ScrollPanelImpl, set_autohide_scrollers);
        DEF_CALLBACK2(void, ::mforms::ScrollPanel*, ::mforms::View*, mgr, f->_spanel_impl, ScrollPanelImpl, scroll_to_view);
      }
    };

  };
};

#endif // _WF_SCROLLPANEL_H_
