386 lines
13 KiB
Plaintext
386 lines
13 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| Box.mqh |
|
|
//| Enrico Lambino |
|
|
//| www.mql5.com/en/users/iceron|
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Enrico Lambino"
|
|
#property link "www.mql5.com/en/users/iceron"
|
|
#include <Controls\WndClient.mqh>
|
|
#define CLASS_LAYOUT 999
|
|
|
|
#ifdef LAYOUT_BOX_DEBUG
|
|
#define COLOR_BOX_BORDER clrRed
|
|
#else
|
|
#define COLOR_BOX_BORDER clrNONE
|
|
#endif
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
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,const int padding);
|
|
//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);
|
|
}
|
|
CSize GetMinSize() const
|
|
{
|
|
CSize sz;
|
|
sz.cx = m_min_size.cx + m_padding_left + m_padding_right;
|
|
sz.cy = m_min_size.cy + m_padding_top + m_padding_bottom;
|
|
return sz;
|
|
}
|
|
|
|
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(COLOR_BOX_BORDER))
|
|
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 == &m_background) continue;
|
|
CheckControlSize(control);
|
|
if(control.Type() == CLASS_LAYOUT)
|
|
{
|
|
((CBox *)control).GetTotalControlsSize();
|
|
}
|
|
|
|
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;
|
|
if(m_layout_style == LAYOUT_STYLE_HORIZONTAL) m_total_x += control_size.cx;
|
|
else m_total_x = MathMax(m_min_size.cx, m_total_x);
|
|
if(m_layout_style == LAYOUT_STYLE_VERTICAL) m_total_y += control_size.cy;
|
|
else m_total_y = MathMax(m_min_size.cy, m_total_y);
|
|
m_controls_total++;
|
|
}
|
|
|
|
CSize size = Size();
|
|
|
|
if(m_total_x > size.cx && m_layout_style == LAYOUT_STYLE_HORIZONTAL)
|
|
{
|
|
size.cx = m_total_x;
|
|
}
|
|
if(m_total_y > size.cy && m_layout_style == LAYOUT_STYLE_VERTICAL) // shrink
|
|
{
|
|
size.cy = m_total_y;
|
|
}
|
|
|
|
Size(size);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
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);
|
|
|
|
if(x_space < 0) x_space = 0;
|
|
if(y_space < 0) y_space = 0;
|
|
|
|
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
CBox::Padding(const int top, const int right, const int bottom, const int left,const int padding)
|
|
{
|
|
m_padding_top = top;
|
|
m_padding_right = right;
|
|
m_padding_bottom = bottom;
|
|
m_padding_left = left;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
// CBox::Padding(const int padding)
|
|
// {
|
|
// m_padding_top = padding;
|
|
// m_padding_right = padding;
|
|
// m_padding_bottom = padding;
|
|
// m_padding_left = padding;
|
|
// }
|
|
//+------------------------------------------------------------------+
|