EasyAndFastMod/Controls/ButtonsGroup.mqh

383 lines
33 KiB
MQL5
Raw Permalink Normal View History

2026-01-15 07:23:17 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| ButtonsGroup.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "Button.mqh"
//+------------------------------------------------------------------+
//| ;0AA 4;O A>740=8O 3@C??K :=>?>: |
//+------------------------------------------------------------------+
class CButtonsGroup : public CElement
{
private:
//--- -:75<?;O@K 4;O A>740=8O M;5<5=B0
CButton m_buttons[];
//--- 568< @048>-:=>?>:
bool m_radio_buttons_mode;
//--- !B8;L >B>1@065=8O @048>-:=>?>:
bool m_radio_buttons_style;
//--- KA>B0 :=>?>:
int m_button_y_size;
//--- (1) "5:AB 8 (2) 8=45:A 2K45;5==>9 :=>?:8
string m_selected_button_text;
int m_selected_button_index;
//---
public:
CButtonsGroup(void);
~CButtonsGroup(void);
//--- 5B>4K 4;O A>740=8O :=>?:8
bool CreateButtonsGroup(const int x_gap,const int y_gap);
//---
private:
void InitializeProperties(const int x_gap,const int y_gap);
bool CreateButtons(void);
//---
public:
//--- >72@0I05B C:070B5;L =0 :=>?:C ?> C:070==><C 8=45:AC
CButton *GetButtonPointer(const uint index);
//--- (1) >;8G5AB2> :=>?>:, (2) 2KA>B0 :=>?>:
int ButtonsTotal(void) const { return(::ArraySize(m_buttons)); }
void ButtonYSize(const int y_size) { m_button_y_size=y_size; }
//--- (1) #AB0=>2:0 @568<0 8 (2) AB8;O >B>1@065=8O @048>-:=>?>:
void RadioButtonsMode(const bool flag) { m_radio_buttons_mode=flag; }
void RadioButtonsStyle(const bool flag) { m_radio_buttons_style=flag; }
//--- >72@0I05B (1) B5:AB 8 (2) 8=45:A 2K45;5==>9 :=>?:8
string SelectedButtonText(void) const { return(m_selected_button_text); }
int SelectedButtonIndex(void) const { return(m_selected_button_index); }
//--- >102;O5B :=>?:C A C:070==K<8 A2>9AB20<8 4> A>740=8O
void AddButton(const int x_gap,const int y_gap,const string text,const int width,
const color button_color=clrNONE,const color button_color_hover=clrNONE,const color button_color_pressed=clrNONE);
//--- 5@5:;NG05B :=>?:C ?> C:070==><C 8=45:AC
void SelectButton(const uint index,const bool is_external_call=true);
//---
public:
//--- 1@01>BG8: A>1KB89 3@0D8:0
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
//--- #?@02;5=85 >1J5:B0<8
virtual void Show(void);
virtual void Delete(void);
//--- 1=>2;O5B M;5<5=B 4;O >B>1@065=8O ?>A;54=8E 87<5=5=89
virtual void Update(const bool redraw=false);
//--- 8AC5B M;5<5=B
virtual void Draw(void);
//---
private:
//--- 1@01>B:0 =060B8O =0 :=>?:C
bool OnClickButton(const string pressed_object,const int id,const int index);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CButtonsGroup::CButtonsGroup(void) : m_button_y_size(20),
m_radio_buttons_mode(false),
m_radio_buttons_style(false),
m_selected_button_text(""),
m_selected_button_index(WRONG_VALUE)
{
//--- !>E@0=8< 8<O :;0AA0 M;5<5=B0 2 107>2>< :;0AA5
CElementBase::ClassName(CLASS_NAME);
//--- 5B:0 ?> C<>;G0=8N
CElementBase::NamePart("button");
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CButtonsGroup::~CButtonsGroup(void)
{
}
//+------------------------------------------------------------------+
//| 1@01>BG8: A>1KB8O 3@0D8:0 |
//+------------------------------------------------------------------+
void CButtonsGroup::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- 1@01>B:0 A>1KB8O =060B8O ;52>9 :=>?:8 <KH8 =0 M;5<5=B5
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
{
if(OnClickButton(sparam,(uint)lparam,(uint)dparam))
return;
//---
return;
}
}
//+------------------------------------------------------------------+
//| !>740QB 3@C??C :=>?>: |
//+------------------------------------------------------------------+
bool CButtonsGroup::CreateButtonsGroup(const int x_gap,const int y_gap)
{
//--- K9B8, 5A;8 =5B C:070B5;O =0 3;02=K9 M;5<5=B
if(!CElement::CheckMainPointer())
return(false);
//--- =8F80;870F8O A2>9AB2
InitializeProperties(x_gap,y_gap);
//--- !>740QB :=>?:8
if(!CreateButtons())
return(false);
//--- K45;8BL @048>-:=>?:C
if(m_radio_buttons_mode)
m_buttons[m_selected_button_index].IsPressed(true);
//---
return(true);
}
//+------------------------------------------------------------------+
//| =8F80;870F8O A2>9AB2 |
//+------------------------------------------------------------------+
void CButtonsGroup::InitializeProperties(const int x_gap,const int y_gap)
{
m_x =CElement::CalculateX(x_gap);
m_y =CElement::CalculateY(y_gap);
//--- =0G5=8O ?> C<>;G0=8N
m_label_x_gap =(m_label_x_gap!=WRONG_VALUE)? m_label_x_gap : 18;
m_label_y_gap =(m_label_y_gap!=WRONG_VALUE)? m_label_y_gap : 0;
//--- 4=0 @048>-:=>?:0 4>;6=0 1KBL 2K45;5=0 >1O70B5;L=>
if(m_radio_buttons_mode)
m_selected_button_index=(m_selected_button_index!=WRONG_VALUE)? m_selected_button_index : 0;
//--- BABC?K >B :@09=59 B>G:8
CElementBase::XGap(x_gap);
CElementBase::YGap(y_gap);
//--- @8>@8B5B, :0: C 3;02=>3> M;5<5=B0, B0: :0: M;5<5=B =5 8<55B A2>59 >1;0AB8 4;O =060B8O
CElement::Z_Order(m_main.Z_Order());
}
//+------------------------------------------------------------------+
//| !>740QB :=>?:8 |
//+------------------------------------------------------------------+
bool CButtonsGroup::CreateButtons(void)
{
//--- >>@48=0BK
int x=0,y=0;
//--- >;CG8< :>;8G5AB2> :=>?>:
int buttons_total=ButtonsTotal();
//--- A;8 =5B =8 >4=>9 :=>?:8 2 3@C??5, A>>1I8BL >1 MB><
if(buttons_total<1)
{
//::Print(__FUNCTION__," > K7>2 MB>3> <5B>40 =C6=> >ACI5AB2;OBL, ...\n"
// "... :>340 2 3@C??5 5ABL E>BO 1K >4=0 :=>?:0! >A?>;L7C9B5AL <5B>4>< CButtonsGroup::AddButton()"
::Print(__FUNCTION__," > You must call this method when there is at least one button in the group! "
"Use the method CButtonsGroup::AddButton()");
return(false);
}
//--- !>74048< C:070==>5 :>;8G5AB2> :=>?>:
for(int i=0; i<buttons_total; i++)
{
//--- !>E@0=8< C:070B5;L =0 @>48B5;LA:89 M;5<5=B
m_buttons[i].MainPointer(this);
//--- >>@48=0BK
x =m_buttons[i].XGap();
y =m_buttons[i].YGap();
//--- !2>9AB20
m_buttons[i].NamePart(CElementBase::NamePart());
m_buttons[i].Alpha(m_alpha);
m_buttons[i].IconXGap(m_icon_x_gap);
m_buttons[i].IconYGap(m_icon_y_gap);
m_buttons[i].LabelXGap(m_label_x_gap);
m_buttons[i].LabelYGap(m_label_y_gap);
m_buttons[i].IsCenterText(CElement::IsCenterText());
m_buttons[i].IsDropdown(CElementBase::IsDropdown());
//--- !>74048< M;5<5=B C?@02;5=8O
if(!m_buttons[i].CreateButton(m_buttons[i].LabelText(),x,y))
return(false);
//--- 06<Q< :=>?:C, 5A;8 >?@545;5=0
if(i==m_selected_button_index)
m_buttons[i].IsPressed(true);
//--- >1028BL M;5<5=B 2 <0AA82
CElement::AddToArray(m_buttons[i]);
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| >72@0I05B C:070B5;L =0 :=>?:C ?> C:070==><C 8=45:AC |
//+------------------------------------------------------------------+
CButton *CButtonsGroup::GetButtonPointer(const uint index)
{
uint array_size=::ArraySize(m_buttons);
//--- @>25@:0 @07<5@0 <0AA820 >1J5:B>2
if(array_size<1)
{
::Print(__FUNCTION__," > There is no button in the group!");
return(NULL);
}
//--- >@@5:B8@>2:0 2 A;CG05 2KE>40 87 480?07>=0
uint i=(index>=array_size)? array_size-1 : index;
//--- 5@=CBL C:070B5;L >1J5:B0
return(::GetPointer(m_buttons[i]));
}
//+------------------------------------------------------------------+
//| >102;O5B :=>?:C |
//+------------------------------------------------------------------+
void CButtonsGroup::AddButton(const int x_gap,const int y_gap,const string text,const int width,
const color button_color=clrNONE,const color button_color_hover=clrNONE,const color button_color_pressed=clrNONE)
{
//--- 575@2=K9 @07<5@
int reserve_size=100;
//--- #25;8G8< @07<5@ <0AA82>2 =0 >48= M;5<5=B
int array_size=::ArraySize(m_buttons);
int new_size=array_size+1;
::ArrayResize(m_buttons,new_size,reserve_size);
//--- #AB0=>28< A2>9AB20
m_buttons[array_size].Index(array_size);
m_buttons[array_size].TwoState(true);
m_buttons[array_size].XSize(width);
m_buttons[array_size].YSize(m_button_y_size);
m_buttons[array_size].XGap(x_gap);
m_buttons[array_size].YGap(y_gap);
m_buttons[array_size].LabelText(text);
m_buttons[array_size].BackColor(button_color);
m_buttons[array_size].BackColorHover(button_color_hover);
m_buttons[array_size].BackColorPressed(button_color_pressed);
//--- K9B8, 5A;8 2K:;NG5= AB8;L @048>-:=>?>:
if(!m_radio_buttons_style)
return;
//---
m_buttons[array_size].BackColor(m_main.BackColor());
m_buttons[array_size].BackColorHover(m_main.BackColor());
m_buttons[array_size].BackColorPressed(m_main.BackColor());
m_buttons[array_size].BackColorLocked(m_main.BackColor());
m_buttons[array_size].BorderColor(m_main.BackColor());
m_buttons[array_size].BorderColorHover(m_main.BackColor());
m_buttons[array_size].BorderColorPressed(m_main.BackColor());
m_buttons[array_size].BorderColorLocked(m_main.BackColor());
m_buttons[array_size].LabelColorHover(C'0,120,215');
m_buttons[array_size].IconXGap(m_icon_x_gap);
m_buttons[array_size].IconYGap(m_icon_y_gap);
m_buttons[array_size].IconFileLocked(RESOURCE_RADIO_BUTTON_OFF_LOCKED);
m_buttons[array_size].IconFile(RESOURCE_RADIO_BUTTON_OFF);
m_buttons[array_size].IconFileLocked(RESOURCE_RADIO_BUTTON_OFF_LOCKED);
m_buttons[array_size].CElement::IconFilePressed(RESOURCE_RADIO_BUTTON_ON);
m_buttons[array_size].CElement::IconFilePressedLocked(RESOURCE_RADIO_BUTTON_ON_LOCKED);
}
//+------------------------------------------------------------------+
//| 5@5:;NG05B :=>?:C ?> C:070==><C 8=45:AC |
//+------------------------------------------------------------------+
void CButtonsGroup::SelectButton(const uint index,const bool is_external_call=true)
{
//--- ;O ?@>25@:8 ACI5AB2>20=8O =060B>9 2 3@C??5 :=>?:8
bool check_pressed_button=false;
//--- >;CG8< :>;8G5AB2> :=>?>:
uint buttons_total=ButtonsTotal();
//--- A;8 =5B =8 >4=>9 :=>?:8 2 3@C??5, A>>1I8BL >1 MB><
if(buttons_total<1)
{
::Print(__FUNCTION__," > You must call this method when there is at least one button in the group! "
"Use the method CButtonsGroup::AddButton()");
return;
}
//--- !:>@@5:B8@>20BL 7=0G5=85 8=45:A0, 5A;8 2KE>48B 87 480?07>=0
uint correct_index=(index>=buttons_total)? buttons_total-1 : index;
//---
if(is_external_call && !m_radio_buttons_mode)
m_buttons[correct_index].IsPressed(!m_buttons[correct_index].IsPressed());
//--- @>94Q<AO 2 F8:;5 ?> 3@C??5 :=>?>:
for(uint i=0; i<buttons_total; i++)
{
if(i==correct_index)
{
if(m_radio_buttons_mode)
m_buttons[i].IsPressed(true);
//--- A;8 5ABL =060B0O :=>?:0
if(m_buttons[i].IsPressed())
check_pressed_button=true;
//---
continue;
}
//--- B>6<Q< >AB0;L=K5 :=>?:8
if(m_buttons[i].IsPressed())
m_buttons[i].IsPressed(false);
}
//--- A;8 5ABL =060B0O :=>?:0, A>E@0=8< 5Q B5:AB 8 8=45:A
m_selected_button_text =(check_pressed_button)? m_buttons[correct_index].LabelText() : "";
m_selected_button_index =(check_pressed_button)? (int)correct_index : WRONG_VALUE;
}
//+------------------------------------------------------------------+
//| >:070BL |
//+------------------------------------------------------------------+
void CButtonsGroup::Show(void)
{
CElement::Show();
int total=ButtonsTotal();
for(int i=0; i<total; i++)
m_buttons[i].Show();
}
//+------------------------------------------------------------------+
//| #40;5=85 |
//+------------------------------------------------------------------+
void CButtonsGroup::Delete(void)
{
CElement::Delete();
//--- A2>1>645=85 <0AA82>2 M;5<5=B0
::ArrayFree(m_buttons);
}
//+------------------------------------------------------------------+
//| 1=>2;5=85 M;5<5=B0 |
//+------------------------------------------------------------------+
void CButtonsGroup::Update(const bool redraw=false)
{
int buttons_total=ButtonsTotal();
//--- ! ?5@5@8A>2:>9 M;5<5=B0
if(redraw)
{
for(int i=0; i<buttons_total; i++)
m_buttons[i].Draw();
for(int i=0; i<buttons_total; i++)
m_buttons[i].Update();
//---
return;
}
//--- @8<5=8BL
for(int i=0; i<buttons_total; i++)
m_buttons[i].Update();
}
//+------------------------------------------------------------------+
//| 060B85 =0 :=>?:C 2 3@C??5 |
//+------------------------------------------------------------------+
bool CButtonsGroup::OnClickButton(const string pressed_object,const int id,const int index)
{
//--- K945<, 5A;8 =060B85 1K;> =5 =0 MB>< M;5<5=B5
if(!CElementBase::CheckElementName(pressed_object))
return(false);
//--- K9B8, 5A;8 (1) 845=B8D8:0B>@K =5 A>2?040NB 8;8 (2) M;5<5=B 701;>:8@>20=
if(id!=CElementBase::Id() || CElementBase::IsLocked())
return(false);
//--- A;8 MB0 :=>?:0 C65 =060B0
if(index==m_selected_button_index)
{
//--- 5@5:;NG8BL :=>?:C
SelectButton(m_selected_button_index,false);
return(true);
}
//---
int check_index=WRONG_VALUE;
//--- @>25@8<, 1K;> ;8 =060B85 =0 >4=>9 87 :=>?>: MB>9 3@C??K
int buttons_total=ButtonsTotal();
//--- A;8 =060B85 1K;>, B> 70?><=8< 8=45:A
for(int i=0; i<buttons_total; i++)
{
if(m_buttons[i].Index()==index)
{
check_index=i;
break;
}
}
//--- K945<, 5A;8 =5 1K;> =060B8O =0 :=>?:C 2 MB>9 3@C??5
if(check_index==WRONG_VALUE)
return(false);
//--- 5@5:;NG8BL :=>?:C
SelectButton(check_index,false);
Update(true);
//--- B?@028< A>>1I5=85 >1 MB><
::EventChartCustom(m_chart_id,ON_CLICK_GROUP_BUTTON,CElementBase::Id(),m_selected_button_index,m_selected_button_text);
return(true);
}
//+------------------------------------------------------------------+
//| 8AC5B M;5<5=B |
//+------------------------------------------------------------------+
void CButtonsGroup::Draw(void)
{
int buttons_total=ButtonsTotal();
for(int i=0; i<buttons_total; i++)
m_buttons[i].Draw();
}
//+------------------------------------------------------------------+