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

#pragma once

/**
 * 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:
      Windows::Forms::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(this, "Padding");
          }
        }
      }

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

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

      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);
      }
    };

  };
};
