//+------------------------------------------------------------------+
//|                                                    WndClient.mqh |
//|                             Copyright 2000-2026, MetaQuotes Ltd. |
//|                                                     www.mql5.com |
//+------------------------------------------------------------------+
#include "WndContainer.mqh"
#include "Panel.mqh"
#include "Scrolls.mqh"
//+------------------------------------------------------------------+
//| Class CWndClient                                                 |
//| Usage: base class to create areas with                           |
//|             the scrollbars                                       |
//+------------------------------------------------------------------+
class CWndClient : public CWndContainer
  {
protected:
   //--- flags
   bool              m_v_scrolled;          // "vertical scrolling is possible" flag
   bool              m_h_scrolled;          // "horizontal scrolling is possible" flag
   //--- dependent controls
   CPanel            m_background;          // the "scrollbar background" object
   CScrollV          m_scroll_v;            // the vertical scrollbar object
   CScrollH          m_scroll_h;            // the horizontal scrollbar object

public:
                     CWndClient(void);
                    ~CWndClient(void);
   //--- create
   virtual bool      Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
   //--- chart event handler
   virtual bool      OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
   //--- parameters
   virtual bool      ColorBackground(const color value)          { return(m_background.ColorBackground(value)); }
   virtual bool      ColorBorder(const color value)              { return(m_background.ColorBorder(value));     }
   virtual bool      BorderType(const ENUM_BORDER_TYPE flag)     { return(m_background.BorderType(flag));       }
   //--- settings
   virtual bool      VScrolled(void) { return(m_v_scrolled); }
   virtual bool      VScrolled(const bool flag);
   virtual bool      HScrolled(void) { return(m_h_scrolled); }
   virtual bool      HScrolled(const bool flag);
   //--- ID
   virtual long      Id(const long id);
   virtual long      Id(void) const { return(CWnd::Id()); }
   //--- state
   virtual bool      Show(void);

protected:
   //--- create dependent controls
   virtual bool      CreateBack(void);
   virtual bool      CreateScrollV(void);
   virtual bool      CreateScrollH(void);
   //--- internal event handlers
   virtual bool      OnResize(void);
   //--- handlers of the dependent controls events
   virtual bool      OnVScrollShow(void)                         { return(true); }
   virtual bool      OnVScrollHide(void)                         { return(true); }
   virtual bool      OnHScrollShow(void)                         { return(true); }
   virtual bool      OnHScrollHide(void)                         { return(true); }
   virtual bool      OnScrollLineDown(void)                      { return(true); }
   virtual bool      OnScrollLineUp(void)                        { return(true); }
   virtual bool      OnScrollLineLeft(void)                      { return(true); }
   virtual bool      OnScrollLineRight(void)                     { return(true); }
   //--- resize
   virtual bool      Rebound(const CRect &rect);
  };
//+------------------------------------------------------------------+
//| Common handler of chart events                                   |
//+------------------------------------------------------------------+
EVENT_MAP_BEGIN(CWndClient)
   ON_NAMED_EVENT(ON_SHOW,m_scroll_v,OnVScrollShow)
   ON_NAMED_EVENT(ON_HIDE,m_scroll_v,OnVScrollHide)
   ON_EVENT(ON_SCROLL_DEC,m_scroll_v,OnScrollLineUp)
   ON_EVENT(ON_SCROLL_INC,m_scroll_v,OnScrollLineDown)
   ON_NAMED_EVENT(ON_SHOW,m_scroll_h,OnHScrollShow)
   ON_NAMED_EVENT(ON_HIDE,m_scroll_h,OnHScrollHide)
   ON_EVENT(ON_SCROLL_DEC,m_scroll_h,OnScrollLineLeft)
   ON_EVENT(ON_SCROLL_INC,m_scroll_h,OnScrollLineRight)
EVENT_MAP_END(CWndContainer)
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CWndClient::CWndClient(void) : m_v_scrolled(false),
                               m_h_scrolled(false)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CWndClient::~CWndClient(void)
  {
  }
//+------------------------------------------------------------------+
//| Create a control                                                 |
//+------------------------------------------------------------------+
bool CWndClient::Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2)
  {
//--- call of the method of the parent class
   if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
      return(false);
//--- create dependent controls
   if(!CreateBack())
      return(false);
   if(m_v_scrolled && !CreateScrollV())
      return(false);
   if(m_h_scrolled && !CreateScrollH())
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Create scrollbar background                                      |
//+------------------------------------------------------------------+
bool CWndClient::CreateBack(void)
  {
//--- create
   if(!m_background.Create(m_chart_id,m_name+"Back",m_subwin,0,0,Width(),Height()))
      return(false);
   if(!m_background.ColorBorder(CONTROLS_CLIENT_COLOR_BORDER))
      return(false);
   if(!m_background.ColorBackground(CONTROLS_CLIENT_COLOR_BG))
      return(false);
   if(!Add(m_background))
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Create vertical scrollbar                                        |
//+------------------------------------------------------------------+
bool CWndClient::CreateScrollV(void)
  {
//--- calculate coordinates
   int x1=Width()-CONTROLS_SCROLL_SIZE-CONTROLS_BORDER_WIDTH;
   int y1=CONTROLS_BORDER_WIDTH;
   int x2=Width()-CONTROLS_BORDER_WIDTH;
   int y2=Height()-CONTROLS_BORDER_WIDTH;
   if(m_h_scrolled) y2-=CONTROLS_SCROLL_SIZE;
//--- create
   if(!m_scroll_v.Create(m_chart_id,m_name+"VScroll",m_subwin,x1,y1,x2,y2))
      return(false);
   if(!Add(m_scroll_v))
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Create horizontal scrollbar                                      |
//+------------------------------------------------------------------+
bool CWndClient::CreateScrollH(void)
  {
//--- calculate coordinates
   int x1=CONTROLS_BORDER_WIDTH;
   int y1=Height()-CONTROLS_SCROLL_SIZE-CONTROLS_BORDER_WIDTH;
   int x2=Width()-CONTROLS_BORDER_WIDTH;
   int y2=Height()-CONTROLS_BORDER_WIDTH;
   if(m_v_scrolled) x2-=CONTROLS_SCROLL_SIZE;
//--- create
   if(!m_scroll_h.Create(m_chart_id,m_name+"HScroll",m_subwin,x1,y1,x2,y2))
      return(false);
   if(!Add(m_scroll_h))
      return(false);
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Set up vertical scrollbar                                        |
//+------------------------------------------------------------------+
bool CWndClient::VScrolled(const bool flag)
  {
   if(m_v_scrolled==flag)
      return(true);
//--- there are changes
   int d_size=0;
   if(flag)
     {
      //--- create vertical scrollbar
      if(!CreateScrollV())
         return(false);
      //--- need to shorten horizontal scrollbar (if there is one)
      d_size=-CONTROLS_SCROLL_SIZE;
     }
   else
     {
      //--- delete vertical scrollbar
      m_scroll_v.Destroy();
      if(!Delete(m_scroll_v))
         return(false);
      //--- need to lengthen horizontal scrollbar (if there is one)
      d_size=CONTROLS_SCROLL_SIZE;
     }
   m_v_scrolled=flag;
//--- change width of horizontal scrollbar (if there is one)
   if(m_h_scrolled)
     {
      if(!m_scroll_h.Width(m_scroll_h.Width()+d_size))
         return(false);
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Set up horizontal scrollbar                                      |
//+------------------------------------------------------------------+
bool CWndClient::HScrolled(const bool flag)
  {
   if(m_h_scrolled==flag)
      return(true);
//--- there are changes
   int d_size=0;
   if(flag)
     {
      //--- create horizontal scrollbar
      if(!CreateScrollH())
         return(false);
      //--- need to shorten vertical scrollbar (if there is one)
      d_size=-CONTROLS_SCROLL_SIZE;
     }
   else
     {
      //--- delete horizontal scrollbar
      m_scroll_h.Destroy();
      if(!Delete(m_scroll_h))
         return(false);
      //--- need to lengthen vertical scrollbar (if there is one)
      d_size=CONTROLS_SCROLL_SIZE;
     }
   m_h_scrolled=flag;
//--- change width of vertical scrollbar (if there is one)
   if(m_v_scrolled)
     {
      if(!m_scroll_v.Height(m_scroll_v.Height()+d_size))
         return(false);
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Set ID of control                                                |
//+------------------------------------------------------------------+
long CWndClient::Id(const long id)
  {
//--- reserve ID for container
   long id_used=CWndContainer::Id(id);
//---
   if(!m_v_scrolled)
      id_used+=m_scroll_v.Id(id+id_used);
   if(!m_h_scrolled)
      id_used+=m_scroll_h.Id(id+id_used);
//--- return number of used IDs
   return(id_used);
  }
//+------------------------------------------------------------------+
//| Makes the control visible                                        |
//+------------------------------------------------------------------+
bool CWndClient::Show(void)
  {
//--- call of the method of the parent class
   CWndContainer::Show();
//---
   if(!m_v_scrolled)
      m_scroll_v.Hide();
   if(!m_h_scrolled)
      m_scroll_h.Hide();
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Handler of resizing                                              |
//+------------------------------------------------------------------+
bool CWndClient::OnResize(void)
  {
//--- call of the method of the parent class
   if(!CWndContainer::OnResize())
      return(false);
//--- resize background
   int d_size=0;
   m_background.Width(Width());
   m_background.Height(Height());
//---
   if(m_v_scrolled)
     {
      //--- move vertical scrollbar
      m_scroll_v.Move(Right()-CONTROLS_SCROLL_SIZE,Top());
      //--- modify vertical scrollbar
      d_size=(m_h_scrolled) ? CONTROLS_SCROLL_SIZE : 0;
      m_scroll_v.Height(Height()-d_size);
     }
   if(m_h_scrolled)
     {
      //--- move horizontal scrollbar
      m_scroll_h.Move(Left(),Bottom()-CONTROLS_SCROLL_SIZE);
      //--- modify horizontal scrollbar
      d_size=(m_v_scrolled) ? CONTROLS_SCROLL_SIZE : 0;
      m_scroll_h.Width(Width()-d_size);
     }
//--- succeed
   return(true);
  }
//+------------------------------------------------------------------+
//| Resize                                                           |
//+------------------------------------------------------------------+
bool CWndClient::Rebound(const CRect &rect)
  {
   m_rect.SetBound(rect);
//--- call virtual event handler
   return(OnResize());
  }
//+------------------------------------------------------------------+
