//+------------------------------------------------------------------+
//|                                               SplitContainer.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 "Container.mqh"
#include "..\Helpers\SplitContainerPanel.mqh"
#include "..\Helpers\Splitter.mqh"
//+------------------------------------------------------------------+
//| SplitContainer WForms control object class                       |
//+------------------------------------------------------------------+
class CSplitContainer : public CContainer
  {
private:
   int               m_panel1_x;             // panel1 X coordinate
   int               m_panel1_y;             // panel1 Y coordinate
   int               m_panel1_w;             // panel1 width
   int               m_panel1_h;             // panel1 height
   int               m_panel2_x;             // panel2 X coordinate
   int               m_panel2_y;             // panel2 Y coordinate
   int               m_panel2_w;             // panel2 width
   int               m_panel2_h;             // panel2 height
   int               m_splitter_x;           // Separator X coordinate
   int               m_splitter_y;           // Separator Y coordinate
   int               m_splitter_w;           // separator width
   int               m_splitter_h;           // separator height
//--- 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);
//--- Set the panel parameters
   bool              SetsPanelParams(void);

//--- (1) Collapse and (2) expand the panel 1
   void              CollapsePanel1(void);
   void              ExpandPanel1(void);
//--- (1) Collapse and (2) expand the panel 2
   void              CollapsePanel2(void);
   void              ExpandPanel2(void);

protected:
   
public:
//--- Create the panels
   void              CreatePanels(void);
//--- Returns pointer to the specified panel
   CWinFormBase     *GetPanel(const int index)                 { return CForm::GetElement(index);  }
   
//--- Return the pointer to the (1) panel1 and (2) panel2
   CWinFormBase     *GetPanel1(void)                           { return this.GetPanel(0);          }
   CWinFormBase     *GetPanel2(void)                           { return this.GetPanel(1);          }
   
//--- Return the element from the specified panel (1) by index, (2) by type and index and (3) by name
   CGCnvElement     *GetPanelElement(const int panel,const int index);
   CGCnvElement     *GetPanelElementByType(const int panel,const ENUM_GRAPH_ELEMENT_TYPE type,const int index);
   CGCnvElement     *GetPanelElementByName(const int panel,const string name);
   
//--- Return the pointer to the separator
   CSplitter        *GetSplitter(void)                         { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_SPLITTER,0);                      }
//--- Return a pointer to the (1) "Left shift", (1) "Right shift", (1) "Up shift" and (1) "Down shift" hint objects
   CHintMoveLeft    *GetHintMoveLeft(void)                     { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT,0);                }
   CHintMoveRight   *GetHintMoveRight(void)                    { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT,0);               }
   CHintMoveUp      *GetHintMoveUp(void)                       { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP,0);                  }
   CHintMoveDown    *GetHintMoveDown(void)                     { return this.GetElementByType(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN,0);                }
//--- Add ToolTip to the separator
   bool              AddTooltipToSplitter(CForm *tooltip);

//--- (1) set and (2) return the minimum possible size of the panel 1 and 2
   void              SetPanel1MinSize(const int value)         { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE,value);           }
   int               Panel1MinSize(void)                 const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_MIN_SIZE);     }
   void              SetPanel2MinSize(const int value)         { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE,value);           }
   int               Panel2MinSize(void)                 const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_MIN_SIZE);     }
   
//--- (1) set and (2) return the flag of collapsed panel 1
   void              SetPanel1Collapsed(const int flag);
   bool              Panel1Collapsed(void)               const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED);   }
//--- (1) set and (2) return the flag of collapsed panel 2
   void              SetPanel2Collapsed(const int flag);
   bool              Panel2Collapsed(void)               const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED);   }
   
//--- (1) set and (2) return the separator distance from the edge
   void              SetSplitterDistance(const int value,const bool only_prop);
   int               SplitterDistance(void)              const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE);   }
   
//--- (1) set and (2) return the separator non-removability flag
   void              SetSplitterFixed(const bool flag)         { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_FIXED,flag);             }
   bool              SplitterFixed(void)                 const { return (bool)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_FIXED);     }
   
//--- (1) set and (2) return the separator width
   void              SetSplitterWidth(const int value,const bool only_prop);
   int               SplitterWidth(void)                 const { return (int)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH);      }
   
//--- (1) set and (2) return the separator location
   void              SetSplitterOrientation(const ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION value,const bool only_prop);
   ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION SplitterOrientation(void) const
                       { return (ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION);     }
   
//--- (1) set and (2) return the panel that does not change its size when the container is resized
   void              SetFixedPanel(const ENUM_CANV_ELEMENT_SPLIT_CONTAINER_FIXED_PANEL value)
                       { this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_FIXED_PANEL,value);                                                       }
   ENUM_CANV_ELEMENT_SPLIT_CONTAINER_FIXED_PANEL FixedPanel(void) const
                       { return (ENUM_CANV_ELEMENT_SPLIT_CONTAINER_FIXED_PANEL)this.GetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_FIXED_PANEL);       }
   
   //--- Draw an (1) empty and (2) dotted rectangle
   virtual void      DrawRectangleEmpty(void);
   virtual void      DrawRectangleDotted(void);
   
//--- Create a new attached element on the specified panel
   bool              CreateNewElement(const int panel_index,
                                      const ENUM_GRAPH_ELEMENT_TYPE element_type,
                                      const int x,
                                      const int y,
                                      const int w,
                                      const int h,
                                      const color colour,
                                      const uchar opacity,
                                      const bool activity,
                                      const bool redraw);
   
//--- Event handler
   virtual void      OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam);

//--- 'The cursor is inside the active area, the mouse buttons are not clicked' event handler
   virtual void      MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam);
//--- 'The cursor is inside the control area, no mouse buttons are clicked' event handler
   virtual void      MouseControlAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam);
//--- 'The cursor is inside the control area, a mouse button is clicked (any)' event handler
   virtual void      MouseControlAreaPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam);
//--- Last mouse event handler
   virtual void      OnMouseEventPostProcessing(void);
//--- Create and attach the ToolTip object (1) to the current and (2) to the specified control
   CWinFormBase     *SetToolTip(const string tooltip_description,const string tooltip_title,const string tooltip_text,ENUM_CANV_ELEMENT_TOOLTIP_ICON tooltip_ico);
   CWinFormBase     *SetToolTipTo(CForm *element,const string tooltip_description,const string tooltip_title,const string tooltip_text,ENUM_CANV_ELEMENT_TOOLTIP_ICON tooltip_ico);
   
protected:
//--- Protected constructor with object type, chart ID and subwindow
                     CSplitContainer(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:
//--- Constructor
                     CSplitContainer(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);
  };
//+------------------------------------------------------------------+
//| Protected constructor with an object type,                       |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CSplitContainer::CSplitContainer(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) : CContainer(type,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(type);
   this.m_type=OBJECT_DE_TYPE_GWF_CONTAINER;
   this.SetBorderSizeAll(0);
   this.SetBorderStyle(FRAME_STYLE_NONE);
   this.SetPaddingAll(0);
   this.SetMarginAll(3);
   this.SetOpacity(0,true);
   this.SetBackgroundColor(CLR_CANV_NULL,true);
   this.SetBackgroundColorMouseDown(CLR_CANV_NULL);
   this.SetBackgroundColorMouseOver(CLR_CANV_NULL);
   this.SetBorderColor(CLR_CANV_NULL,true);
   this.SetBorderColorMouseDown(CLR_CANV_NULL);
   this.SetBorderColorMouseOver(CLR_CANV_NULL);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
   this.SetSplitterFixed(false);
   this.CreatePanels();
  }
//+------------------------------------------------------------------+
//| Constructor indicating the main and base objects,                |
//| chart ID and subwindow                                           |
//+------------------------------------------------------------------+
CSplitContainer::CSplitContainer(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) : CContainer(GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER,main_obj,base_obj,chart_id,subwindow,descript,x,y,w,h)
  {
   this.SetTypeElement(GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER);
   this.m_type=OBJECT_DE_TYPE_GWF_CONTAINER;
   this.SetBorderSizeAll(0);
   this.SetBorderStyle(FRAME_STYLE_NONE);
   this.SetPaddingAll(0);
   this.SetMarginAll(3);
   this.SetOpacity(0,true);
   this.SetBackgroundColor(CLR_CANV_NULL,true);
   this.SetBackgroundColorMouseDown(CLR_CANV_NULL);
   this.SetBackgroundColorMouseOver(CLR_CANV_NULL);
   this.SetBorderColor(CLR_CANV_NULL,true);
   this.SetBorderColorMouseDown(CLR_CANV_NULL);
   this.SetBorderColorMouseOver(CLR_CANV_NULL);
   this.SetForeColor(CLR_DEF_FORE_COLOR,true);
   this.SetSplitterFixed(false);
   this.CreatePanels();
  }
//+------------------------------------------------------------------+
//| Create a new graphical object                                    |
//+------------------------------------------------------------------+
CGCnvElement *CSplitContainer::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_SPLIT_CONTAINER_PANEL: element=new CSplitContainerPanel(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);break;
      case GRAPH_ELEMENT_TYPE_WF_SPLITTER             : element=new CSplitter(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);           break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_BASE            : element=new CHintBase(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);           break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT       : element=new CHintMoveLeft(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);       break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT      : element=new CHintMoveRight(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);      break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP         : element=new CHintMoveUp(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);         break;
      case GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN       : element=new CHintMoveDown(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);       break;
      case GRAPH_ELEMENT_TYPE_WF_TOOLTIP              : element=new CToolTip(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);            break;
      case GRAPH_ELEMENT_TYPE_WF_PROGRESS_BAR         : element=new CProgressBar(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);        break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR           : element=new CScrollBar(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);          break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_VERTICAL  : element=new CScrollBarVertical(this.GetMain(),this.GetObject(),this.ChartID(),this.SubWindow(),descript,x,y,w,h);  break;
      case GRAPH_ELEMENT_TYPE_WF_SCROLL_BAR_HORISONTAL: element=new CScrollBarHorisontal(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;
  }
//+------------------------------------------------------------------+
//| Create a new attached element on the specified panel             |
//+------------------------------------------------------------------+
bool CSplitContainer::CreateNewElement(const int panel_index,
                                       const ENUM_GRAPH_ELEMENT_TYPE element_type,
                                       const int x,
                                       const int y,
                                       const int w,
                                       const int h,
                                       const color colour,
                                       const uchar opacity,
                                       const bool activity,
                                       const bool redraw)
  {
   CSplitContainerPanel *panel=this.GetPanel(panel_index);
   if(panel==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_ERR_FAILED_GET_SPLIT_CONTAINER_PANEL_OBJ)," (Panel",(string)panel_index,")");
      return false;
     }
   return panel.CreateNewElement(element_type,x,y,w,h,colour,opacity,activity,redraw);
  }
//+------------------------------------------------------------------+
//| Create the panels                                                |
//+------------------------------------------------------------------+
void CSplitContainer::CreatePanels(void)
  {
   this.m_list_elements.Clear();
   if(this.SetsPanelParams())
     {
      //--- Create two panels
      if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL,this.m_panel1_x,this.m_panel1_y,this.m_panel1_w,this.m_panel1_h,clrNONE,255,true,false))
         return;
      if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SPLIT_CONTAINER_PANEL,this.m_panel2_x,this.m_panel2_y,this.m_panel2_w,this.m_panel2_h,clrNONE,255,true,false))
         return;
      //--- Create a separator object
      if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_SPLITTER,this.m_splitter_x,this.m_splitter_y,this.m_splitter_w,this.m_splitter_h,clrNONE,255,true,false))
         return;
      CSplitter *splitter=this.GetSplitter();
      if(splitter!=NULL)
        {
         splitter.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,this.SplitterOrientation());
         splitter.SetMovable(true);
         splitter.SetDisplayed(false);
         splitter.Hide();
        }
      //--- Create the HintMoveLeft object
      if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_LEFT,this.m_splitter_x-DEF_HINT_ICON_SIZE,this.m_splitter_y,DEF_HINT_ICON_SIZE,DEF_HINT_ICON_SIZE,clrNONE,255,true,false))
         return;
      CHintMoveLeft *hint_ml=this.GetHintMoveLeft();
      if(hint_ml!=NULL)
        {
         hint_ml.SetMovable(false);
         hint_ml.SetDisplayed(false);
         hint_ml.Hide();
        }
      //--- Create the HintMoveRight object
      if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_RIGHT,this.m_splitter_x+this.m_splitter_w,this.m_splitter_y,DEF_HINT_ICON_SIZE,DEF_HINT_ICON_SIZE,clrNONE,255,true,false))
         return;
      CHintMoveRight *hint_mr=this.GetHintMoveRight();
      if(hint_mr!=NULL)
        {
         hint_mr.SetMovable(false);
         hint_mr.SetDisplayed(false);
         hint_mr.Hide();
        }
      //--- Create the HintMoveUp object
      if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_UP,this.m_splitter_x,this.m_splitter_y-DEF_HINT_ICON_SIZE,DEF_HINT_ICON_SIZE,DEF_HINT_ICON_SIZE,clrNONE,255,true,false))
         return;
      CHintMoveUp *hint_mu=this.GetHintMoveUp();
      if(hint_mu!=NULL)
        {
         hint_mu.SetMovable(false);
         hint_mu.SetDisplayed(false);
         hint_mu.Hide();
        }
      //--- Create the HintMoveDown object
      if(!this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_HINT_MOVE_DOWN,this.m_splitter_x,this.m_splitter_y+this.m_splitter_h,DEF_HINT_ICON_SIZE,DEF_HINT_ICON_SIZE,clrNONE,255,true,false))
         return;
      CHintMoveDown *hint_md=this.GetHintMoveDown();
      if(hint_md!=NULL)
        {
         hint_md.SetMovable(false);
         hint_md.SetDisplayed(false);
         hint_md.Hide();
        }
     }
  }
//+------------------------------------------------------------------+
//| Return the control by index from the specified panel             |
//+------------------------------------------------------------------+
CGCnvElement *CSplitContainer::GetPanelElement(const int panel,const int index)
  {
   CSplitContainerPanel *obj=this.GetPanel(panel);
   if(obj==NULL)
     {
      CMessage::ToLog(DFUN,MSG_ERR_FAILED_GET_SPLIT_CONTAINER_PANEL_OBJ);
      return NULL;
     }
   return obj.GetElement(index);
  }
//+------------------------------------------------------------------+
//| Return the control from the specified panel by type and index    |
//+------------------------------------------------------------------+
CGCnvElement *CSplitContainer::GetPanelElementByType(const int panel,const ENUM_GRAPH_ELEMENT_TYPE type,const int index)
  {
   CSplitContainerPanel *obj=this.GetPanel(panel);
   if(obj==NULL)
     {
      CMessage::ToLog(DFUN,MSG_ERR_FAILED_GET_SPLIT_CONTAINER_PANEL_OBJ);
      return NULL;
     }
   return obj.GetElementByType(type,index);
  }
//+------------------------------------------------------------------+
//| Return the control by name from the specified panel              |
//+------------------------------------------------------------------+
CGCnvElement *CSplitContainer::GetPanelElementByName(const int panel,const string name)
  {
   CSplitContainerPanel *obj=this.GetPanel(panel);
   if(obj==NULL)
     {
      CMessage::ToLog(DFUN,MSG_ERR_FAILED_GET_SPLIT_CONTAINER_PANEL_OBJ);
      return NULL;
     }
   return obj.GetElementByName(name);
  }
//+------------------------------------------------------------------+
//| Set the panel parameters                                         |
//+------------------------------------------------------------------+
bool CSplitContainer::SetsPanelParams(void)
  {
   switch(this.SplitterOrientation())
     {
      //--- The separator is positioned vertically
      case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL    :
        //--- If both panels are not collapsed,
        if(!this.Panel1Collapsed() && !this.Panel2Collapsed())
          {
           //--- set the panel1 coordinates and size
           this.m_panel1_x=0;
           this.m_panel1_y=0;
           this.m_panel1_w=this.SplitterDistance();
           this.m_panel1_h=this.Height();
           //--- set the panel2 coordinates and size
           this.m_panel2_x=this.SplitterDistance()+this.SplitterWidth();
           this.m_panel2_y=0;
           this.m_panel2_w=this.Width()-this.m_panel2_x;
           this.m_panel2_h=this.Height();
           //--- write separator coordinates and size
           this.m_splitter_x=this.SplitterDistance();
           this.m_splitter_y=0;
           this.m_splitter_w=this.SplitterWidth();
           this.m_splitter_h=this.Height();
          }
        //--- If panel1 or panel2 is collapsed,
        else
          {
           //--- write the coordinates and sizes of panel1 and panel2
           this.m_panel2_x=this.m_panel1_x=0;
           this.m_panel2_y=this.m_panel1_y=0;
           this.m_panel2_w=this.m_panel1_w=this.Width();
           this.m_panel2_h=this.m_panel1_h=this.Height();
           //--- write separator coordinates and size
           this.m_splitter_x=0;
           this.m_splitter_y=0;
           this.m_splitter_w=this.SplitterWidth();
           this.m_splitter_h=this.Height();
          }
        break;
      //--- The separator is located horizontally
      case CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL  :
        //--- If both panels are not collapsed,
        if(!this.Panel1Collapsed() && !this.Panel2Collapsed())
          {
           //--- set the panel1 coordinates and size
           this.m_panel1_x=0;
           this.m_panel1_y=0;
           this.m_panel1_w=this.Width();
           this.m_panel1_h=this.SplitterDistance();
           //--- set the panel2 coordinates and size
           this.m_panel2_x=0;
           this.m_panel2_y=this.SplitterDistance()+this.SplitterWidth();
           this.m_panel2_w=this.Width();
           this.m_panel2_h=this.Height()-this.m_panel2_y;
           //--- write separator coordinates and size
           this.m_splitter_x=0;
           this.m_splitter_y=this.SplitterDistance();
           this.m_splitter_w=this.Width();
           this.m_splitter_h=this.SplitterWidth();
          }
        //--- If panel1 or panel2 is collapsed,
        else
          {
           //--- write the coordinates and sizes of panel1 and panel2
           this.m_panel2_x=this.m_panel1_x=0;
           this.m_panel2_y=this.m_panel1_y=0;
           this.m_panel2_w=this.m_panel1_w=this.Width();
           this.m_panel2_h=this.m_panel1_h=this.Height();
           //--- write separator coordinates and size
           this.m_splitter_x=0;
           this.m_splitter_y=0;
           this.m_splitter_w=this.Width();
           this.m_splitter_h=this.SplitterWidth();
          }
        break;
      default:
        return false;
        break;
     }
//--- Set the coordinates and sizes of the control area equal to the properties set by the separator
   this.SetControlAreaX(this.m_splitter_x);
   this.SetControlAreaY(this.m_splitter_y);
   this.SetControlAreaWidth(this.m_splitter_w);
   this.SetControlAreaHeight(this.m_splitter_h);
   return true;
  }
//+------------------------------------------------------------------+
//| Set the flag of collapsed panel 1                                |
//+------------------------------------------------------------------+
void CSplitContainer::SetPanel1Collapsed(const int flag)
  {
//--- Set the flag, passed to the method, to the object property
   this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,flag);
   CSplitContainerPanel *p1=this.GetPanel1();
   CSplitContainerPanel *p2=this.GetPanel2();
   if(p1==NULL || p2==NULL)
      return;
//--- Set the parameters of the panels and the separator
   this.SetsPanelParams();
//--- If panel1 should be collapsed
   if(this.Panel1Collapsed())
     {
      //--- If panel1 is shifted to new coordinates and its size is changed, hide panel1
      if(p1.Move(this.CoordX()+this.m_panel1_x,this.CoordY()+this.m_panel1_y) && p1.Resize(this.m_panel1_w,this.m_panel1_h,false))
        {
         p1.SetCoordXRelative(p1.CoordX()-this.CoordX());
         p1.SetCoordYRelative(p1.CoordY()-this.CoordY());
         this.CollapsePanel1();
        }
      //--- set the expanded flag for panel2
      this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,false);
      //--- If panel2 is shifted to new coordinates and its size is changed, display panel2
      if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y) && p2.Resize(this.m_panel2_w,this.m_panel2_h,true))
        {
         p2.SetCoordXRelative(p2.CoordX()-this.CoordX());
         p2.SetCoordYRelative(p2.CoordY()-this.CoordY());
         this.ExpandPanel2();
        }
     }
//--- If panel1 should be expanded,
   else
     {
      //--- set the collapsed flag for panel2
      this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,true);
      //--- If panel2 is shifted to new coordinates and its size is changed, hide panel2
      if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y) && p2.Resize(this.m_panel2_w,this.m_panel2_h,false))
        {
         p2.SetCoordXRelative(p2.CoordX()-this.CoordX());
         p2.SetCoordYRelative(p2.CoordY()-this.CoordY());
         this.CollapsePanel2();
        }
      //--- If panel1 is shifted to new coordinates and its size is changed, display panel1
      if(p1.Move(this.CoordX()+this.m_panel1_x,this.CoordY()+this.m_panel1_y) && p1.Resize(this.m_panel1_w,this.m_panel1_h,true))
        {
         p1.SetCoordXRelative(p1.CoordX()-this.CoordX());
         p1.SetCoordYRelative(p1.CoordY()-this.CoordY());
         this.ExpandPanel1();
        }
     }
  }
//+------------------------------------------------------------------+
//| Set the flag of collapsed panel 2                                |
//+------------------------------------------------------------------+
void CSplitContainer::SetPanel2Collapsed(const int flag)
  {
//--- Set the flag, passed to the method, to the object property
   this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL2_COLLAPSED,flag);
   CSplitContainerPanel *p1=this.GetPanel1();
   CSplitContainerPanel *p2=this.GetPanel2();
   if(p1==NULL || p2==NULL)
      return;
//--- Set the parameters of the panels and the separator
   this.SetsPanelParams();
//--- If panel2 should be collapsed,
   if(this.Panel2Collapsed())
     {
      //--- If panel2 is shifted to new coordinates and its size is changed, hide panel2
      if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y) && p2.Resize(this.m_panel2_w,this.m_panel2_h,false))
        {
         p2.SetCoordXRelative(p2.CoordX()-this.CoordX());
         p2.SetCoordYRelative(p2.CoordY()-this.CoordY());
         this.CollapsePanel2();
        }
      //--- set the expanded flag for panel1
      this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,false);
      //--- If panel1 is shifted to new coordinates and its size is changed, display panel1
      if(p1.Move(this.CoordX()+this.m_panel1_x,this.CoordY()+this.m_panel1_y) && p1.Resize(this.m_panel1_w,this.m_panel1_h,true))
        {
         p1.SetCoordXRelative(p1.CoordX()-this.CoordX());
         p1.SetCoordYRelative(p1.CoordY()-this.CoordY());
         this.ExpandPanel1();
        }
     }
//--- If panel2 should be expanded,
   else
     {
      //--- set the collapsed flag for panel1
      this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_PANEL1_COLLAPSED,true);
      //--- If panel1 is shifted to new coordinates and its size is changed, hide panel1
      if(p1.Move(this.CoordX()+this.m_panel1_x,this.CoordY()+this.m_panel1_y) && p1.Resize(this.m_panel1_w,this.m_panel1_h,false))
        {
         p1.SetCoordXRelative(p1.CoordX()-this.CoordX());
         p1.SetCoordYRelative(p1.CoordY()-this.CoordY());
         this.CollapsePanel1();
        }
      //--- If panel2 is shifted to new coordinates and its size is changed, display panel2
      if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y) && p2.Resize(this.m_panel2_w,this.m_panel2_h,true))
        {
         p2.SetCoordXRelative(p2.CoordX()-this.CoordX());
         p2.SetCoordYRelative(p2.CoordY()-this.CoordY());
         this.ExpandPanel2();
        }
     }
  }
//+------------------------------------------------------------------+
//| Set the separator distance from the edge                         |
//+------------------------------------------------------------------+
void CSplitContainer::SetSplitterDistance(const int value,const bool only_prop)
  {
//--- Set the value, passed to the method, to the object property
   this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_DISTANCE,value);
//--- Depending on the direction of the separator (vertical or horizontal),
//--- set the values to the coordinates of the object control area
   switch(this.SplitterOrientation())
     {
      case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL :
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,this.SplitterDistance());
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,0);
        break;
      //---CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL
      default:
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_X,0);
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_Y,this.SplitterDistance());
        break;
     }
//--- If only setting the property, leave
   if(only_prop)
      return;
//--- If there are no panels or separator, leave
   CSplitContainerPanel *p1=this.GetPanel1();
   CSplitContainerPanel *p2=this.GetPanel2();
   CSplitter *sp=this.GetSplitter();
   if(p1==NULL || p2==NULL || sp==NULL)
      return;
//--- Set the parameters of the panels and the separator
   this.SetsPanelParams();
//--- If the size of the separator object has been successfully changed
   if(sp.Resize(this.m_splitter_w,this.m_splitter_h,false))
     {
      //--- Shift the separator
      if(sp.Move(this.CoordX()+this.m_splitter_x,this.CoordY()+this.m_splitter_y,false))
        {
         //--- Set new relative separator coordinates
         sp.SetCoordXRelative(sp.CoordX()-this.CoordX());
         sp.SetCoordYRelative(sp.CoordY()-this.CoordY());
         //--- If panel 1 is resized successfully
         if(p1.Resize(this.m_panel1_w,this.m_panel1_h,true))
           {
            //--- If panel 2 coordinates are changed to new ones
            if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y,false))
              {
               //--- if panel 2 has been successfully resized,
               if(p2.Resize(this.m_panel2_w,this.m_panel2_h,true))
                 {
                  //--- set new relative coordinates of panel 2
                  p2.SetCoordXRelative(p2.CoordX()-this.CoordX());
                  p2.SetCoordYRelative(p2.CoordY()-this.CoordY());
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| Set the separator width                                          |
//+------------------------------------------------------------------+
void CSplitContainer::SetSplitterWidth(const int value,const bool only_prop)
  {
//--- Set the value, passed to the method, to the object property
   this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_WIDTH,value);
//--- Depending on the direction of the separator (vertical or horizontal),
//--- set the values to the object control area width and height
   switch(this.SplitterOrientation())
     {
      case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL :
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,this.SplitterWidth());
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,this.Height());
        break;
      //---CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL
      default:
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_WIDTH,this.Width());
        this.SetProperty(CANV_ELEMENT_PROP_CONTROL_AREA_HEIGHT,this.SplitterWidth());
        break;
     }
//--- If only setting the property, leave
   if(only_prop)
      return;
//--- If there are no panels or separator, leave
   CSplitContainerPanel *p1=this.GetPanel1();
   CSplitContainerPanel *p2=this.GetPanel2();
   CSplitter *sp=this.GetSplitter();
   if(p1==NULL || p2==NULL || sp==NULL)
      return;
//--- Set the parameters of the panels and the separator
   this.SetsPanelParams();
//--- If the size of the separator object has been successfully changed
   if(sp.Resize(this.m_splitter_w,this.m_splitter_h,false))
     {
      //--- If the separator is shifted to new coordinates
      if(sp.Move(this.CoordX()+this.m_splitter_x,this.CoordY()+this.m_splitter_y))
        {
         //--- Set new relative separator coordinates
         sp.SetCoordXRelative(sp.CoordX()-this.CoordX());
         sp.SetCoordYRelative(sp.CoordY()-this.CoordY());
         //--- If panel 1 is resized successfully
         if(p1.Resize(this.m_panel1_w,this.m_panel1_h,true))
           {
            //--- If panel 2 coordinates are changed to new ones
            if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y,true))
              {
               //--- if panel 2 has been successfully resized,
               if(p2.Resize(this.m_panel2_w,this.m_panel2_h,true))
                 {
                  //--- set new relative coordinates of panel 2
                  p2.SetCoordXRelative(p2.CoordX()-this.CoordX());
                  p2.SetCoordYRelative(p2.CoordY()-this.CoordY());
                 }
              }
           }
        }
     }
  }
//+------------------------------------------------------------------+
//| set the separator location                                       |
//+------------------------------------------------------------------+
void CSplitContainer::SetSplitterOrientation(const ENUM_CANV_ELEMENT_SPLITTER_ORIENTATION value,const bool only_prop)
  {
   this.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,value);
//--- If there are no panels or separator, leave
   CSplitContainerPanel *p1=this.GetPanel1();
   CSplitContainerPanel *p2=this.GetPanel2();
   CSplitter *sp=this.GetSplitter();
   if(p1==NULL || p2==NULL || sp==NULL)
      return;
//--- Set the orientation property for the separator object
   sp.SetProperty(CANV_ELEMENT_PROP_SPLIT_CONTAINER_SPLITTER_ORIENTATION,value);
//--- If only setting the property, leave
   if(only_prop)
      return;
//--- Set the parameters of the panels and the separator
   this.SetsPanelParams();
//--- If panel 1 is resized successfully
   if(p1.Resize(this.m_panel1_w,this.m_panel1_h,true))
     {
      //--- If panel 2 coordinates are changed to new ones
      if(p2.Move(this.CoordX()+this.m_panel2_x,this.CoordY()+this.m_panel2_y,true))
        {
         //--- if panel 2 has been successfully resized,
         if(p2.Resize(this.m_panel2_w,this.m_panel2_h,true))
           {
            //--- set new relative coordinates of panel 2
            p2.SetCoordXRelative(p2.CoordX()-this.CoordX());
            p2.SetCoordYRelative(p2.CoordY()-this.CoordY());
           }
        }
      //--- If the size of the separator object has been successfully changed, 
      //--- set new values of separator coordinates
      if(sp.Resize(this.m_splitter_w,this.m_splitter_h,false))
         this.SetSplitterDistance(this.SplitterDistance(),true);
     }
  }
//+------------------------------------------------------------------+
//| Event handler                                                    |
//+------------------------------------------------------------------+
void CSplitContainer::OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- Adjust subwindow Y shift
   CGCnvElement::OnChartEvent(id,lparam,dparam,sparam);
//--- If the event ID is moving the separator
   if(id==WF_CONTROL_EVENT_MOVING)
     {
      //--- Get the pointer to the separator object
      CSplitter *splitter=this.GetSplitter();
      if(splitter==NULL || this.SplitterFixed())
         return;
      //--- Get the pointers to hint objects
      CHintMoveLeft *hint_ml=this.GetHintMoveLeft();
      CHintMoveRight *hint_mr=this.GetHintMoveRight();
      CHintMoveUp *hint_mu=this.GetHintMoveUp();
      CHintMoveDown *hint_md=this.GetHintMoveDown();
      if(hint_ml==NULL || hint_mr==NULL || hint_mu==NULL || hint_md==NULL)
         return;
      
      //--- Disable the display of hints and hide them
      hint_ml.SetDisplayed(false);
      hint_ml.Hide();
      hint_mr.SetDisplayed(false);
      hint_mr.Hide();
      hint_mu.SetDisplayed(false);
      hint_mu.Hide();
      hint_md.SetDisplayed(false);
      hint_md.Hide();
         
      //--- Declare the variables for separator coordinates
      int x=(int)lparam;
      int y=(int)dparam;
      //--- Depending on the separator direction,
      switch(this.SplitterOrientation())
        {
         //--- vertical position
         case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL :
           //--- Set the Y coordinate equal to the Y coordinate of the control element
           y=this.CoordY();
           //--- Adjust the X coordinate so that the separator does not go beyond the control element
           //--- taking into account the resulting minimum width of the panels
           if(x<this.CoordX()+this.Panel1MinSize())
              x=this.CoordX()+this.Panel1MinSize();
           if(x>this.CoordX()+this.Width()-this.Panel2MinSize()-this.SplitterWidth())
              x=this.CoordX()+this.Width()-this.Panel2MinSize()-this.SplitterWidth();
           break;
         //---CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL
         //--- horizontal position of the separator
         default:
           //--- Set the X coordinate equal to the X coordinate of the control element
           x=this.CoordX();
           //--- Adjust the Y coordinate so that the separator does not go beyond the control element
           //--- taking into account the resulting minimum height of the panels
           if(y<this.CoordY()+this.Panel1MinSize())
              y=this.CoordY()+this.Panel1MinSize();
           if(y>this.CoordY()+this.Height()-this.Panel2MinSize()-this.SplitterWidth())
              y=this.CoordY()+this.Height()-this.Panel2MinSize()-this.SplitterWidth();
           break;
        }
      //--- Draw an empty rectangle
      this.DrawRectangleEmpty();
      //--- If the separator is shifted by the calculated coordinates,
      if(splitter.Move(x,y,true))
        {
         //--- set the separator relative coordinates
         splitter.SetCoordXRelative(splitter.CoordX()-this.CoordX());
         splitter.SetCoordYRelative(splitter.CoordY()-this.CoordY());
         //--- Depending on the direction of the separator, set its new coordinates
         this.SetSplitterDistance(!this.SplitterOrientation() ? splitter.CoordX()-this.CoordX() : splitter.CoordY()-this.CoordY(),false);
        }
     }
  }
//+------------------------------------------------------------------+
//| 'The cursor is inside the active area,                           |
//| no mouse buttons are clicked' event                              |
//+------------------------------------------------------------------+
void CSplitContainer::MouseActiveAreaNotPressedHandler(const int id,const long& lparam,const double& dparam,const string& sparam)
  {
//--- If the separator is non-movable, leave
   if(this.SplitterFixed())
      return;
//--- Draw an empty rectangle in the control area
   this.DrawRectangleEmpty();
//--- Get the pointer to the separator
   CSplitter *splitter=this.GetSplitter();
   if(splitter==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ),": ",this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_SPLITTER));
      return;
     }
//--- If the separator is not displayed
   if(!splitter.Displayed())
     {
      //--- Enable the display of the separator, show and redraw it
      splitter.SetDisplayed(true);
      splitter.Show();
      splitter.Redraw(true);
     }
//--- Get the pointer to hint objects
   CHintMoveLeft *hint_ml=this.GetHintMoveLeft();
   CHintMoveRight *hint_mr=this.GetHintMoveRight();
   CHintMoveUp *hint_mu=this.GetHintMoveUp();
   CHintMoveDown *hint_md=this.GetHintMoveDown();
   if(hint_ml==NULL || hint_mr==NULL || hint_mu==NULL || hint_md==NULL)
      return;
   hint_ml.SetDisplayed(false);
   hint_ml.Hide();
   hint_mr.SetDisplayed(false);
   hint_mr.Hide();
   hint_mu.SetDisplayed(false);
   hint_mu.Hide();
   hint_md.SetDisplayed(false);
   hint_md.Hide();
  }
//+------------------------------------------------------------------+
//| The cursor is inside the control area,                           |
//| no mouse buttons are clicked' event                              |
//+------------------------------------------------------------------+
void CSplitContainer::MouseControlAreaNotPressedHandler(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- If the separator is non-movable, leave
   if(this.SplitterFixed())
      return;
//--- Draw an empty rectangle in the control area
   this.DrawRectangleEmpty();
//--- Draw a dotted rectangle in the control area
   this.DrawRectangleDotted();
//--- Get the pointer to the separator
   CSplitter *splitter=this.GetSplitter();
   if(splitter==NULL)
     {
      ::Print(DFUN,CMessage::Text(MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ),": ",this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_SPLITTER));
      return;
     }
//--- If the separator is not displayed
   if(!splitter.Displayed())
     {
      //--- Enable the display of the separator and show it
      splitter.SetDisplayed(true);
      splitter.Erase(true);
      splitter.Show();
     }
//--- Get the pointer to hint objects
   CHintMoveLeft *hint_ml=this.GetHintMoveLeft();
   CHintMoveRight *hint_mr=this.GetHintMoveRight();
   CHintMoveUp *hint_mu=this.GetHintMoveUp();
   CHintMoveDown *hint_md=this.GetHintMoveDown();
   if(hint_ml==NULL || hint_mr==NULL || hint_mu==NULL || hint_md==NULL)
      return;
//--- Get cursor coordinates
   int x=this.m_mouse.CoordX()-this.CoordX();
   int y=this.m_mouse.CoordY()-this.CoordY();
//--- Depending on the separator direction,
   switch(this.SplitterOrientation())
     {
      //--- vertical position
      case CANV_ELEMENT_SPLITTER_ORIENTATION_VERTICAL :
        //--- Set and adjust the coordinates of the "left shift" hint object
        x=this.CoordX()+this.m_splitter_x-hint_ml.Width();//-1;
        y+=this.CoordY()-hint_ml.Height()-1;
        if(y<this.CoordY()+this.m_splitter_y)
           y=this.CoordY()+this.m_splitter_y;
        //--- Shift the hint object to the calculated coordinates, set its visibility flag and display the object
        if(hint_ml.Move(x,y))
          {
           hint_ml.SetCoordXRelative(x-this.CoordX());
           hint_ml.SetCoordYRelative(y-this.CoordY());
           hint_ml.SetDisplayed(true);
           hint_ml.Show();
          }
        //--- Set and adjust the coordinates of the "right shift" hint object
        x=this.CoordX()+this.m_splitter_x+this.m_splitter_w;//+1;
        //--- Shift the hint object to the calculated coordinates, set its visibility flag and display the object
        if(hint_mr.Move(x,y))
          {
           hint_mr.SetCoordXRelative(x-this.CoordX());
           hint_mr.SetCoordYRelative(y-this.CoordY());
           hint_mr.SetDisplayed(true);
           hint_mr.Show();
          }
        break;
      //---CANV_ELEMENT_SPLITTER_ORIENTATION_HORISONTAL
      //--- horizontal position of the separator
      default:
        //--- Set and adjust the coordinates of the "up shift" hint object
        y=this.CoordY()+this.m_splitter_y-hint_mu.Height();//-1;
        x+=this.CoordX()-hint_mu.Width()-1;
        if(x<this.CoordX()+this.m_splitter_x)
           x=this.CoordX()+this.m_splitter_x;
        //--- Shift the hint object to the calculated coordinates, set its visibility flag and display the object
        if(hint_mu.Move(x,y))
          {
           hint_mu.SetCoordXRelative(x-this.CoordX());
           hint_mu.SetCoordYRelative(y-this.CoordY());
           hint_mu.SetDisplayed(true);
           hint_mu.Show();
          }
        //--- Set and adjust the coordinates of the "down shift" hint object
        y=this.CoordY()+this.m_splitter_y+this.m_splitter_h;//+1;
        //--- Shift the hint object to the calculated coordinates, set its visibility flag and display the object
        if(hint_md.Move(x,y))
          {
           hint_md.SetCoordXRelative(x-this.CoordX());
           hint_md.SetCoordYRelative(y-this.CoordY());
           hint_md.SetDisplayed(true);
           hint_md.Show();
          }
        break;
     }
  }
//+------------------------------------------------------------------+
//| The cursor is inside the control area,                           |
//| a mouse button is clicked (any)                                  |
//+------------------------------------------------------------------+
void CSplitContainer::MouseControlAreaPressedHandler(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
//--- If the separator is non-movable, leave
   if(this.SplitterFixed())
      return;
//--- Draw an empty rectangle in the control area
   this.DrawRectangleEmpty();
  }
//+------------------------------------------------------------------+
//| Last mouse event handler                                         |
//+------------------------------------------------------------------+
void CSplitContainer::OnMouseEventPostProcessing(void)
  {
   if(!this.IsVisible() || !this.Enabled() || !this.Displayed())
      return;
   ENUM_MOUSE_FORM_STATE state=this.GetMouseState();
   switch(state)
     {
      //--- The cursor is outside the form, the mouse buttons are not clicked
      //--- The cursor is outside the form, any mouse button is clicked
      //--- The cursor is outside the form, the mouse wheel is being scrolled
      case MOUSE_FORM_STATE_OUTSIDE_FORM_NOT_PRESSED        :
      case MOUSE_FORM_STATE_OUTSIDE_FORM_PRESSED            :
      case MOUSE_FORM_STATE_OUTSIDE_FORM_WHEEL              :
      case MOUSE_FORM_STATE_NONE                            :
        if(this.MouseEventLast()==MOUSE_EVENT_INSIDE_ACTIVE_AREA_NOT_PRESSED  || 
           this.MouseEventLast()==MOUSE_EVENT_INSIDE_FORM_NOT_PRESSED         || 
           this.MouseEventLast()==MOUSE_EVENT_OUTSIDE_FORM_NOT_PRESSED        ||
           this.MouseEventLast()==MOUSE_EVENT_INSIDE_CONTROL_AREA_NOT_PRESSED ||
           this.MouseEventLast()==MOUSE_EVENT_INSIDE_CONTROL_AREA_PRESSED     ||
           this.MouseEventLast()==MOUSE_EVENT_INSIDE_CONTROL_AREA_WHEEL       ||
           this.MouseEventLast()==MOUSE_EVENT_NO_EVENT)
          {
            //--- Draw an empty rectangle in the control area
            this.DrawRectangleEmpty();
            //--- Get the pointer to the separator
            CSplitter *splitter=this.GetSplitter();
            if(splitter==NULL)
              {
               ::Print(DFUN,CMessage::Text(MSG_ELM_LIST_ERR_FAILED_GET_GRAPH_ELEMENT_OBJ),": ",this.TypeElementDescription(GRAPH_ELEMENT_TYPE_WF_SPLITTER));
               return;
              }
            splitter.SetDisplayed(false);
            splitter.Hide();
            //--- Get the pointers to hint objects
            CHintMoveLeft *hint_ml=this.GetHintMoveLeft();
            CHintMoveRight *hint_mr=this.GetHintMoveRight();
            CHintMoveUp *hint_mu=this.GetHintMoveUp();
            CHintMoveDown *hint_md=this.GetHintMoveDown();
            if(hint_ml==NULL || hint_mr==NULL || hint_mu==NULL || hint_md==NULL)
               return;
            //--- If the hide object is displayed, disable its display and hide it
            if(hint_ml.Displayed())
              {
               hint_ml.SetDisplayed(false);
               hint_ml.Hide();
              }
            if(hint_mr.Displayed())
              {
               hint_mr.SetDisplayed(false);
               hint_mr.Hide();
              }
            if(hint_mu.Displayed())
              {
               hint_mu.SetDisplayed(false);
               hint_mu.Hide();
              }
            if(hint_md.Displayed())
              {
               hint_md.SetDisplayed(false);
               hint_md.Hide();
              }
            //--- Set the current mouse state as the last one
            this.m_mouse_event_last=ENUM_MOUSE_EVENT(state+MOUSE_EVENT_NO_EVENT);
          }
        break;
      //--- The cursor is inside the form, the mouse buttons are not clicked
      //--- The cursor is inside the form, any mouse button is clicked
      //--- The cursor is inside the form, the mouse wheel is being scrolled
      //--- The cursor is inside the active area, the mouse buttons are not clicked
      //--- The cursor is inside the active area, any mouse button is clicked
      //--- The cursor is inside the active area, the mouse wheel is being scrolled
      //--- The cursor is inside the active area, left mouse button is released
      //--- The cursor is within the window scrolling area, the mouse buttons are not clicked
      //--- The cursor is within the window scrolling area, any mouse button is clicked
      //--- The cursor is within the window scrolling area, the mouse wheel is being scrolled
      //--- The cursor is within the window resizing area, the mouse buttons are not clicked
      //--- The cursor is within the window resizing area, the mouse button (any) is clicked
      //--- The cursor is within the window resizing area, the mouse wheel is being scrolled
      //--- The cursor is within the window resizing area, the mouse buttons are not clicked
      //--- The cursor is within the window resizing area, the mouse button (any) is clicked
      //--- The cursor is within the window separator area, the mouse wheel is being scrolled
      case MOUSE_FORM_STATE_INSIDE_FORM_NOT_PRESSED                     :
      case MOUSE_FORM_STATE_INSIDE_FORM_PRESSED                         :
      case MOUSE_FORM_STATE_INSIDE_FORM_WHEEL                           :
//--- Within the active area
      case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_NOT_PRESSED              :
      case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_PRESSED                  :
      case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_WHEEL                    :
      case MOUSE_FORM_STATE_INSIDE_ACTIVE_AREA_RELEASED                 :
//--- Within the scrolling area at the bottom
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_NOT_PRESSED       :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_PRESSED           :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_BOTTOM_WHEEL             :
//--- Within the scrolling area to the right
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_NOT_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_PRESSED            :
      case MOUSE_FORM_STATE_INSIDE_SCROLL_AREA_RIGHT_WHEEL              :
//--- Within the window resizing area at the top
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_NOT_PRESSED          :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_PRESSED              :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_AREA_WHEEL                :
//--- Within the window resizing area at the bottom
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_NOT_PRESSED       :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_PRESSED           :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_AREA_WHEEL             :
//--- Within the window resizing area to the left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_NOT_PRESSED         :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_PRESSED             :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_LEFT_AREA_WHEEL               :
//--- Within the window resizing area to the right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_NOT_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_PRESSED            :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_RIGHT_AREA_WHEEL              :
//--- Within the window resizing area to the top-left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_NOT_PRESSED     :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_PRESSED         :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_LEFT_AREA_WHEEL           :
//--- Within the window resizing area to the top-right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_NOT_PRESSED    :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_PRESSED        :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_TOP_RIGHT_AREA_WHEEL          :
//--- Within the window resizing area at the bottom left
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_NOT_PRESSED  :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_PRESSED      :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_LEFT_AREA_WHEEL        :
//--- Within the window resizing area at the bottom-right
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_NOT_PRESSED :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_PRESSED     :
      case MOUSE_FORM_STATE_INSIDE_RESIZE_BOTTOM_RIGHT_AREA_WHEEL       :
//--- Within the control area
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_NOT_PRESSED             :
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_PRESSED                 :
      case MOUSE_FORM_STATE_INSIDE_CONTROL_AREA_WHEEL                   :
        break;
      //--- MOUSE_EVENT_NO_EVENT
      default:
        break;
     }
  }
//+------------------------------------------------------------------+
//| Collapse the panel 1                                             |
//+------------------------------------------------------------------+
void CSplitContainer::CollapsePanel1(void)
  {
   CSplitContainerPanel *panel=this.GetPanel1();
   if(panel==NULL)
      return;
   panel.SetDisplayed(false);
   panel.Hide();
  }
//+------------------------------------------------------------------+
//| Collapse the panel 2                                             |
//+------------------------------------------------------------------+
void CSplitContainer::CollapsePanel2(void)
  {
   CSplitContainerPanel *panel=this.GetPanel2();
   if(panel==NULL)
      return;
   panel.SetDisplayed(false);
   panel.Hide();
  }
//+------------------------------------------------------------------+
//| Expand the panel 1                                               |
//+------------------------------------------------------------------+
void CSplitContainer::ExpandPanel1(void)
  {
   CSplitContainerPanel *panel=this.GetPanel1();
   if(panel==NULL)
      return;
   panel.SetDisplayed(true);
   panel.Show();
   panel.BringToTop();
  }
//+------------------------------------------------------------------+
//| Expand the panel 2                                               |
//+------------------------------------------------------------------+
void CSplitContainer::ExpandPanel2(void)
  {
   CSplitContainerPanel *panel=this.GetPanel2();
   if(panel==NULL)
      return;
   panel.SetDisplayed(true);
   panel.Show();
   panel.BringToTop();
  }
//+------------------------------------------------------------------+
//| Draw an empty rectangle                                          |
//+------------------------------------------------------------------+
void CSplitContainer::DrawRectangleEmpty(void)
  {
   int cx1=this.ControlAreaLeftRelative();
   int cx2=this.ControlAreaRightRelative();
   int cy1=this.ControlAreaTopRelative();
   int cy2=this.ControlAreaBottomRelative();
   this.DrawRectangleFill(cx1,cy1,cx2,cy2,CLR_CANV_NULL,0);
   this.Update();
  }
//+------------------------------------------------------------------+
//| Draw a dotted rectangle                                          |
//+------------------------------------------------------------------+
void CSplitContainer::DrawRectangleDotted(void)
  {
   int shift=0;
   int cx1=this.ControlAreaLeftRelative();
   int cx2=fmin(this.ControlAreaRightRelative(),this.VisibleAreaWidth()+2);
   int cy1=this.ControlAreaTopRelative();
   int cy2=this.ControlAreaBottomRelative();
//--- Draw points in the next-but-one fashion along the upper border of the rectangle from left to right
   for(int x=cx1+1;x<cx2-2;x+=2)
      this.SetPixel(x,cy1,this.ForeColor(),255);
//--- Get the offset of the next point depending on where the last point was placed
   shift=((cx2-cx1-2) %2==0 ? 0 : 1);
//--- Draw points in the next-but-one fashion along the right border of the rectangle from top to bottom
   for(int y=cy1+1+shift;y<cy2-2;y+=2)
      this.SetPixel(cx2-2,y,this.ForeColor(),255);
//--- Get the offset of the next point depending on where the last point was placed
   shift=(this.ControlAreaHeight()-2 %2==0 ? 1 : 0);
//--- Draw points in the next-but-one fashion along the lower border of the rectangle from right to left
   for(int x=cx2-2-shift;x>cx1;x-=2)
      this.SetPixel(x,cy2-2,this.ForeColor(),255);
//--- Get the offset of the next point depending on where the last point was placed
   shift=((cx2-cx1-2) %2==0 ? 0 : 1);
//--- Draw points in the next-but-one fashion along the left border of the rectangle from bottom to top
   for(int y=cy2-2-shift;y>cy1;y-=2)
      this.SetPixel(cx1+1,y,this.ForeColor(),255);
//--- Update the canvas
   this.Update();
  }
//+------------------------------------------------------------------+
//| Add ToolTip to the separator                                     |
//+------------------------------------------------------------------+
bool CSplitContainer::AddTooltipToSplitter(CForm *tooltip)
  {
   CSplitter *obj=this.GetSplitter();
   return(obj!=NULL ? obj.AddTooltip(tooltip) : false);
  }
//+------------------------------------------------------------------+
//| Create and attach the ToolTip object to the current element      |
//+------------------------------------------------------------------+
CWinFormBase *CSplitContainer::SetToolTip(const string tooltip_description,const string tooltip_title,const string tooltip_text,ENUM_CANV_ELEMENT_TOOLTIP_ICON tooltip_ico)
  {
   this.CreateNewElement(GRAPH_ELEMENT_TYPE_WF_TOOLTIP,0,0,10,10,clrNONE,0,false,false);
   CArrayObj *list=this.GetListElementsByType(GRAPH_ELEMENT_TYPE_WF_TOOLTIP);
   if(list==NULL || list.Total()==0)
      return NULL;
   CToolTip *tooltip=list.At(list.Total()-1);
   if(tooltip!=NULL)
     {
      tooltip.SetDescription(tooltip_description);
      tooltip.SetIcon(tooltip_ico);
      tooltip.SetTitle(tooltip_title);
      tooltip.SetTooltipText(tooltip_text);
     }
   return tooltip;
  }
//+------------------------------------------------------------------+
//| Create and attach the ToolTip object to the specified element    |
//+------------------------------------------------------------------+
CWinFormBase *CSplitContainer::SetToolTipTo(CForm *element,const string tooltip_description,const string tooltip_title,const string tooltip_text,ENUM_CANV_ELEMENT_TOOLTIP_ICON tooltip_ico)
  {
   CToolTip *tooltip=this.SetToolTip(tooltip_description,tooltip_title,tooltip_text,tooltip_ico);
   if(tooltip==NULL)
      return NULL;
   element.AddTooltip(tooltip);
   return tooltip;
  }
//+------------------------------------------------------------------+
