//+------------------------------------------------------------------+
//|                                                    ScrollBar.mqh |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                             https://mql5.com/en/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://mql5.com/en/users/artmedia70"
#property version   "1.00"
#property strict    // Necessary for mql4
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "..\WinFormBase.mqh"
#include "ScrollBarThumb.mqh"
#include "ArrowDownButton.mqh"
#include "ArrowUpButton.mqh"
#include "ArrowLeftButton.mqh"
#include "ArrowRightButton.mqh"
//+------------------------------------------------------------------+
//| CScrollBar object class of WForms controls                       |
//+------------------------------------------------------------------+
class CScrollBar : public CWinFormBase
  {
private:
   int               m_thickness;         // Scrollbar width (Width - vertical, Height - horizontal)
//--- Create the ArrowButton objects
   virtual void      CreateArrowButtons(const int width,const int height) { return; }
//--- Create a new graphical object
   virtual CGCnvElement *CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                          const int element_num,
                                          const string descript,
                                          const int x,
                                          const int y,
                                          const int w,
                                          const int h,
                                          const color colour,
                                          const uchar opacity,
                                          const bool movable,
                                          const bool activity);
//--- Calculate the capture area size
   virtual int       CalculateThumbAreaSize(void);
//--- Initialize the element properties
   void              Initialize(void);

protected:
//--- Set the scroll buttons size
   void              SetArrowButtonsSize(const int size);
   
//--- Create the capture area object
   virtual void      CreateThumbArea(void);
//--- Protected constructor with object type, chart ID and subwindow
                     CScrollBar(const ENUM_GRAPH_ELEMENT_TYPE type,
                                CGCnvElement *main_obj,CGCnvElement *base_obj,
                                const long chart_id,
                                const int subwindow,
                                const string descript,
                                const int x,
                                const int y,
                                const int w,
                                const int h);
public:
//--- Supported object properties (1) integer, (2) real and (3) string ones
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_INTEGER property) { return true; }
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_DOUBLE property)  { return true; }
   virtual bool      SupportProperty(ENUM_CANV_ELEMENT_PROP_STRING property)  { return true; }
   
//--- Return the capture area object
   CScrollBarThumb  *GetThumb(void) { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB,0);  }
   
//--- (1) Set and (2) return the scrollbar width
   virtual void      SetThickness(const int value);
   int               Thickness(void)                        const { return this.m_thickness; }
//--- Set the size of drawn arrows on scroll buttons
   void              SetArrowSize(const uchar size);
   
//--- Constructor
                     CScrollBar(CGCnvElement *main_obj,CGCnvElement *base_obj,
                                const long chart_id,
                                const int subwindow,
                                const string descript,
                                const int x,
                                const int y,
                                const int w,
                                const int h);
//--- Timer
   virtual void      OnTimer(void);
  };
//+------------------------------------------------------------------+
//| Protected constructor with an object type,                       |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CScrollBar::CScrollBar(const ENUM_GRAPH_ELEMENT_TYPE type,
                       CGCnvElement *main_obj,CGCnvElement *base_obj,
                       const long chart_id,
                       const int subwindow,
                       const string descript,
                       const int x,
                       const int y,
                       const int w,
                       const int h) : CWinFormBase(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
//--- Set the specified graphical element type for the object and assign the library object type to the current object
   this.SetTypeElement(type);
   this.m_type=OBJECT_DE_TYPE_GWF_HELPER;
   this.Initialize();
  }
//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CScrollBar::CScrollBar(CGCnvElement *main_obj,CGCnvElement *base_obj,
                       const long chart_id,
                       const int subwindow,
                       const string descript,
                       const int x,
                       const int y,
                       const int w,
                       const int h) : CWinFormBase(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR);
   this.m_type=OBJECT_DE_TYPE_GWF_HELPER;
   this.Initialize();
  }
//+------------------------------------------------------------------+
//| Initialize the element properties                                |
//+------------------------------------------------------------------+
void CScrollBar::Initialize(void)
  {
   this.SetBorderSizeAll(1);
   this.SetBorderStyle(FRAME_STYLE_SIMPLE);
   this.SetBackgroundColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR,true);
   this.SetBackgroundColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR);
   this.SetBackgroundColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BACK_COLOR);
   this.SetBorderColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_BORDER_COLOR,true);
   this.SetForeColor(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_COLOR,true);
   this.SetForeColorMouseDown(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_DOWN);
   this.SetForeColorMouseOver(CLR_DEF_CONTROL_SCROLL_BAR_TRACK_FORE_MOUSE_OVER);
   this.SetThickness(DEF_CONTROL_SCROLL_BAR_WIDTH);
   this.SetArrowButtonsSize(this.m_thickness);
   this.SetArrowSize(uchar(this.m_thickness<4 ? 1 : this.m_thickness<6 ? 2 : this.m_thickness<8 ? 3 : this.m_thickness<10 ? 4 : this.m_thickness<12 ? 5 : 6));
  }
//+------------------------------------------------------------------+
//| Create the capture area object                                   |
//+------------------------------------------------------------------+
void CScrollBar::CreateThumbArea(void)
  {
   this.CreateArrowButtons(DEF_CONTROL_SCROLL_BAR_WIDTH,DEF_CONTROL_SCROLL_BAR_WIDTH);
  }
//+------------------------------------------------------------------+
//| Calculate the capture area size                                  |
//+------------------------------------------------------------------+
int CScrollBar::CalculateThumbAreaSize(void)
  {
   return DEF_CONTROL_SCROLL_BAR_THUMB_SIZE_MIN;
  }
//+------------------------------------------------------------------+
//| Create a new graphical object                                    |
//+------------------------------------------------------------------+
CGCnvElement *CScrollBar::CreateNewGObject(const ENUM_GRAPH_ELEMENT_TYPE type,
                                           const int obj_num,
                                           const string descript,
                                           const int x,
                                           const int y,
                                           const int w,
                                           const int h,
                                           const color colour,
                                           const uchar opacity,
                                           const bool movable,
                                           const bool activity)
  {
   CGCnvElement *element=NULL;
   switch(type)
     {
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_THUMB     :
         element=new CScrollBarThumb(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN    :
         element=new CArrowDownButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP      :
         element=new CArrowUpButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT    :
         element=new CArrowLeftButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      case GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT   :
         element=new CArrowRightButton(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);
        break;
      default:
        break;
     }
   if(element==NULL)
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_FAILED_CREATE_ELM_OBJ),this.TypeElementDescription(type));
   return element;
  }
//+------------------------------------------------------------------+
//| Set the scrollbar width                                          |
//+------------------------------------------------------------------+
void CScrollBar::SetThickness(const int value)
  {
//--- Depending on the type
   switch(this.TypeGraphElement())
     {
      //--- For the vertical scrollbar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  :
        //--- set the width equal to the value passed to the method and write it as the width of the object
        this.m_thickness=value;
        this.SetWidth(this.m_thickness);
        this.Redraw(false);
        break;
      //--- For the horizontal scroll bar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL:
        //--- set the width equal to the value passed to the method and write it as the height of the object
        this.m_thickness=value;
        this.SetHeight(this.m_thickness);
        this.Redraw(false);
        break;
      default:
        break;
     }
  }
//+------------------------------------------------------------------+
//| Set the size of the scroll buttons                               |
//+------------------------------------------------------------------+
void CScrollBar::SetArrowButtonsSize(const int size)
  {
//--- Declare the pointers to arrow buttons
   CArrowUpButton    *bu=NULL;
   CArrowDownButton  *bd=NULL;
   CArrowLeftButton  *bl=NULL;
   CArrowRightButton *br=NULL;
//--- Depending on the type
   switch(this.TypeGraphElement())
     {
      //--- For the vertical scrollbar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  :
        //--- Get the pointer to the up arrow button and set its size equal to 'size'
        bu=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0);
        if(bu!=NULL)
           bu.Resize(size,size,false);
        //--- Get the pointer to the down arrow button and set its size equal to 'size'
        bd=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0);
        if(bd!=NULL)
           bd.Resize(size,size,false);
        break;
      //--- For the horizontal scroll bar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL:
        //--- Get the pointer to the left arrow button and set its size equal to 'size'
        bl=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,0);
        if(bl!=NULL)
           bl.Resize(size,size,false);
        //--- Get the pointer to the right arrow button and set its size equal to 'size'
        br=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0);
        if(br!=NULL)
           br.Resize(size,size,false);
        break;
      default:
        break;
     }
  }
//+------------------------------------------------------------------+
//| Set the size of drawn arrows on scroll buttons                   |
//+------------------------------------------------------------------+
void CScrollBar::SetArrowSize(const uchar size)
  {
//--- Declare the pointers to arrow buttons
   CArrowUpButton    *bu=NULL;
   CArrowDownButton  *bd=NULL;
   CArrowLeftButton  *bl=NULL;
   CArrowRightButton *br=NULL;
//--- Depending on the type
   switch(this.TypeGraphElement())
     {
      //--- For the vertical scrollbar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  :
        //--- Get the pointer to the up arrow button and set its arrow size equal to 'size'
        bu=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_UP,0);
        if(bu!=NULL)
          {
           bu.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           bu.Redraw(false);
          }
        //--- Get the pointer to the down arrow button and set its arrow size equal to 'size'
        bd=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_DOWN,0);
        if(bd!=NULL)
          {
           bd.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           bd.Redraw(false);
          }
        break;
      //--- For the horizontal scroll bar
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL:
        //--- Get the pointer to the left arrow button and set its arrow size equal to 'size'
        bl=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_LEFT,0);
        if(bl!=NULL)
          {
           bl.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           bl.Redraw(false);
          }
        //--- Get the pointer to the right arrow button and set its arrow size equal to 'size'
        br=this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_ARROW_BUTTON_RIGHT,0);
        if(br!=NULL)
          {
           br.SetProperty(CANV_ELEMENT_PROP_BUTTON_ARROW_SIZE,size);
           br.Redraw(false);
          }
        break;
      default:
        break;
     }
  }
//+------------------------------------------------------------------+
//| Timer                                                            |
//+------------------------------------------------------------------+
void CScrollBar::OnTimer(void)
  {

  }
//+------------------------------------------------------------------+
