Multiplicator/Box.mqh

297 lines
12 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 16:10:33 +02:00
//+------------------------------------------------------------------+
//| Box.mqh |
//| Enrico Lambino |
//| www.mql5.com/en/users/iceron|
//+------------------------------------------------------------------+
#property copyright "Enrico Lambino"
#property link "https://www.mql5.com/en/articles/1867"
#include <Controls\WndClient.mqh>
#define CLASS_LAYOUT 999
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum LAYOUT_STYLE
{
LAYOUT_STYLE_VERTICAL,
LAYOUT_STYLE_HORIZONTAL
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum VERTICAL_ALIGN
{
VERTICAL_ALIGN_CENTER,
VERTICAL_ALIGN_CENTER_NOSIDES,
VERTICAL_ALIGN_TOP,
VERTICAL_ALIGN_BOTTOM
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum HORIZONTAL_ALIGN
{
HORIZONTAL_ALIGN_CENTER,
HORIZONTAL_ALIGN_CENTER_NOSIDES,
HORIZONTAL_ALIGN_LEFT,
HORIZONTAL_ALIGN_RIGHT
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CBox : public CWndClient
{
protected:
LAYOUT_STYLE m_layout_style;
VERTICAL_ALIGN m_vertical_align;
HORIZONTAL_ALIGN m_horizontal_align;
CSize m_min_size;
int m_controls_total;
int m_padding_top;
int m_padding_bottom;
int m_padding_left;
int m_padding_right;
int m_total_x;
int m_total_y;
public:
CBox();
~CBox();
virtual int Type() const {return CLASS_LAYOUT;}
virtual bool Create(const long chart,const string name,const int subwin,
const int x1,const int y1,const int x2,const int y2);
virtual bool Pack();
void LayoutStyle(LAYOUT_STYLE style){m_layout_style=style;}
LAYOUT_STYLE LayoutStyle() const {return(m_layout_style);}
void HorizontalAlign(const HORIZONTAL_ALIGN align){m_horizontal_align=align;}
HORIZONTAL_ALIGN HorizontalAlign() const {return(m_horizontal_align);}
void VerticalAlign(const VERTICAL_ALIGN align){m_vertical_align=align;}
VERTICAL_ALIGN VerticalAlign() const {return(m_vertical_align);}
void Padding(const int top,const int bottom,const int left,const int right);
void Padding(const int padding);
void PaddingTop(const int padding) {m_padding_top=padding;}
int PaddingTop() const {return(m_padding_top);}
void PaddingRight(const int padding) {m_padding_right=padding;}
int PaddingRight() const {return(m_padding_right);}
void PaddingBottom(const int padding) {m_padding_bottom=padding;}
int PaddingBottom() const {return(m_padding_bottom);}
void PaddingLeft(const int padding) {m_padding_left=padding;}
int PaddingLeft() const {return(m_padding_left);}
protected:
virtual void CheckControlSize(CWnd *control);
virtual void GetTotalControlsSize(void);
virtual bool GetSpace(int &x_space,int &y_space);
virtual bool Render(void);
virtual void Shift(CWnd *control,int &x,int &y,const int x_space,const int y_space);
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::CBox() : m_layout_style(LAYOUT_STYLE_HORIZONTAL),
m_vertical_align(VERTICAL_ALIGN_CENTER),
m_horizontal_align(HORIZONTAL_ALIGN_CENTER),
m_controls_total(0),
m_padding_top(2),
m_padding_bottom(2),
m_padding_left(2),
m_padding_right(2),
m_total_x(0),
m_total_y(0)
{
m_min_size.cx = 0;
m_min_size.cy = 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CBox::~CBox()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Create(const long chart,const string name,const int subwin,
const int x1,const int y1,const int x2,const int y2)
{
if(!CWndContainer::Create(chart,name,subwin,x1,y1,x2,y2))
return(false);
if(!CreateBack())
return(false);
if(!ColorBackground(CONTROLS_DIALOG_COLOR_CLIENT_BG))
return(false);
if(!ColorBorder(clrNONE))
return(false);
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Pack(void)
{
GetTotalControlsSize();
return(Render());
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::CheckControlSize(CWnd *control)
{
bool adjust=false;
CSize size=Size();
CSize control_size=control.Size();
if(control_size.cx>size.cx-(m_padding_left+m_padding_right))
{
control_size.cx=size.cx-(m_padding_left+m_padding_right);
adjust=true;
}
if(control_size.cy>size.cy-(m_padding_top+m_padding_bottom))
{
control_size.cy=size.cy-(m_padding_top+m_padding_bottom);
adjust=true;
}
if(adjust)
control.Size(control_size.cx,control_size.cy);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::GetTotalControlsSize(void)
{
m_total_x = 0;
m_total_y = 0;
m_controls_total = 0;
m_min_size.cx = 0;
m_min_size.cy = 0;
int total=ControlsTotal();
for(int i=0;i<total;i++)
{
CWnd *control=Control(i);
if(control==NULL)
continue;
if(control==GetPointer(m_background))
continue;
CheckControlSize(GetPointer(control));
CSize control_size=control.Size();
if(m_min_size.cx<control_size.cx)
m_min_size.cx=control_size.cx;
if(m_min_size.cy<control_size.cy)
m_min_size.cy=control_size.cy;
m_total_x += control_size.cx;
m_total_y += control_size.cy;
m_controls_total++;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::GetSpace(int &x_space,int &y_space)
{
if(m_controls_total==0)
return(true);
if(m_controls_total==1)
{
if(m_horizontal_align==HORIZONTAL_ALIGN_CENTER_NOSIDES)
m_horizontal_align= HORIZONTAL_ALIGN_CENTER;
if(m_vertical_align==VERTICAL_ALIGN_CENTER_NOSIDES)
m_vertical_align= VERTICAL_ALIGN_CENTER;
}
CSize size=Size();
int x_space_total=0;
int y_space_total=0;
if(m_layout_style==LAYOUT_STYLE_HORIZONTAL)
{
x_space_total=size.cx-(m_total_x+m_padding_left+m_padding_right);
y_space_total=size.cy-(m_min_size.cy+m_padding_top+m_padding_bottom);
if(m_horizontal_align==HORIZONTAL_ALIGN_CENTER_NOSIDES)
x_space=x_space_total/(m_controls_total-1);
else if(m_horizontal_align==HORIZONTAL_ALIGN_CENTER)
x_space=x_space_total/(m_controls_total+1);
else
x_space=x_space_total/m_controls_total;
if(m_vertical_align==VERTICAL_ALIGN_CENTER || m_vertical_align==VERTICAL_ALIGN_CENTER_NOSIDES)
y_space=y_space_total/2;
else y_space=y_space_total;
}
else if(m_layout_style==LAYOUT_STYLE_VERTICAL)
{
x_space_total=size.cx-(m_min_size.cx+m_padding_left+m_padding_right);
y_space_total=size.cy -(m_total_y+m_padding_top+m_padding_bottom);
if(m_horizontal_align==HORIZONTAL_ALIGN_CENTER || m_horizontal_align==HORIZONTAL_ALIGN_CENTER_NOSIDES)
x_space=x_space_total/2;
else x_space=x_space_total;
if(m_vertical_align==VERTICAL_ALIGN_CENTER_NOSIDES)
y_space=y_space_total/(m_controls_total-1);
else if(m_vertical_align==VERTICAL_ALIGN_CENTER)
y_space=y_space_total/(m_controls_total+1);
else y_space=y_space_total/m_controls_total;
}
else return(false);
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::Shift(CWnd *control,int &x,int &y,const int x_space,const int y_space)
{
if(m_layout_style==LAYOUT_STYLE_HORIZONTAL)
x+=x_space+control.Width();
else if(m_layout_style==LAYOUT_STYLE_VERTICAL)
y+=y_space+control.Height();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CBox::Render(void)
{
int x_space=0,y_space=0;
if(!GetSpace(x_space,y_space))
return(false);
int x=Left()+m_padding_left+
((m_horizontal_align==HORIZONTAL_ALIGN_LEFT||m_horizontal_align==HORIZONTAL_ALIGN_CENTER_NOSIDES)?0:x_space);
int y=Top()+m_padding_top+
((m_vertical_align==VERTICAL_ALIGN_TOP||m_vertical_align==VERTICAL_ALIGN_CENTER_NOSIDES)?0:y_space);
for(int j=0;j<ControlsTotal();j++)
{
CWnd *control=Control(j);
if(control==NULL)
continue;
if(control==GetPointer(m_background))
continue;
control.Move(x,y);
if(control.Type()==CLASS_LAYOUT)
{
CBox *container=control;
container.Pack();
}
if (j<ControlsTotal()-1)
Shift(GetPointer(control),x,y,x_space,y_space);
}
return(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::Padding(const int top,const int right,const int bottom,const int left)
{
m_padding_top=top;
m_padding_right=right;
m_padding_bottom=bottom;
m_padding_left=left;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CBox::Padding(const int padding)
{
m_padding_top=padding;
m_padding_right=padding;
m_padding_bottom=padding;
m_padding_left=padding;
}
//+------------------------------------------------------------------+