//+------------------------------------------------------------------+ //| ButtonsGroup.mqh | //| Copyright 2015, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #include "..\Element.mqh" #include "Button.mqh" //+------------------------------------------------------------------+ //| Класс для создания группы кнопок | //+------------------------------------------------------------------+ class CButtonsGroup : public CElement { private: //--- Экземпляры для создания элемента CButton m_buttons[]; //--- Режим радио-кнопок bool m_radio_buttons_mode; //--- Стиль отображения радио-кнопок bool m_radio_buttons_style; //--- Высота кнопок int m_button_y_size; //--- (1) Текст и (2) индекс выделенной кнопки string m_selected_button_text; int m_selected_button_index; //--- public: CButtonsGroup(void); ~CButtonsGroup(void); //--- Методы для создания кнопки 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: //--- Возвращает указатель на кнопку по указанному индексу CButton *GetButtonPointer(const uint index); //--- (1) Количество кнопок, (2) высота кнопок int ButtonsTotal(void) const { return(::ArraySize(m_buttons)); } void ButtonYSize(const int y_size) { m_button_y_size=y_size; } //--- (1) Установка режима и (2) стиля отображения радио-кнопок void RadioButtonsMode(const bool flag) { m_radio_buttons_mode=flag; } void RadioButtonsStyle(const bool flag) { m_radio_buttons_style=flag; } //--- Возвращает (1) текст и (2) индекс выделенной кнопки string SelectedButtonText(void) const { return(m_selected_button_text); } int SelectedButtonIndex(void) const { return(m_selected_button_index); } //--- Добавляет кнопку с указанными свойствами до создания 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); //--- Переключает кнопку по указанному индексу void SelectButton(const uint index,const bool is_external_call=true); //--- public: //--- Обработчик событий графика virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam); //--- Управление объектами virtual void Show(void); virtual void Delete(void); //--- Обновляет элемент для отображения последних изменений virtual void Update(const bool redraw=false); //--- Рисует элемент virtual void Draw(void); //--- private: //--- Обработка нажатия на кнопку 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) { //--- Сохраним имя класса элемента в базовом классе CElementBase::ClassName(CLASS_NAME); //--- Метка по умолчанию CElementBase::NamePart("button"); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CButtonsGroup::~CButtonsGroup(void) { } //+------------------------------------------------------------------+ //| Обработчик события графика | //+------------------------------------------------------------------+ void CButtonsGroup::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam) { //--- Обработка события нажатия левой кнопки мыши на элементе if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON) { if(OnClickButton(sparam,(uint)lparam,(uint)dparam)) return; //--- return; } } //+------------------------------------------------------------------+ //| Создаёт группу кнопок | //+------------------------------------------------------------------+ bool CButtonsGroup::CreateButtonsGroup(const int x_gap,const int y_gap) { //--- Выйти, если нет указателя на главный элемент if(!CElement::CheckMainPointer()) return(false); //--- Инициализация свойств InitializeProperties(x_gap,y_gap); //--- Создаёт кнопки if(!CreateButtons()) return(false); //--- Выделить радио-кнопку if(m_radio_buttons_mode) m_buttons[m_selected_button_index].IsPressed(true); //--- return(true); } //+------------------------------------------------------------------+ //| Инициализация свойств | //+------------------------------------------------------------------+ void CButtonsGroup::InitializeProperties(const int x_gap,const int y_gap) { m_x =CElement::CalculateX(x_gap); m_y =CElement::CalculateY(y_gap); //--- Значения по умолчанию 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; //--- Одна радио-кнопка должна быть выделена обязательно if(m_radio_buttons_mode) m_selected_button_index=(m_selected_button_index!=WRONG_VALUE)? m_selected_button_index : 0; //--- Отступы от крайней точки CElementBase::XGap(x_gap); CElementBase::YGap(y_gap); //--- Приоритет, как у главного элемента, так как элемент не имеет своей области для нажатия CElement::Z_Order(m_main.Z_Order()); } //+------------------------------------------------------------------+ //| Создаёт кнопки | //+------------------------------------------------------------------+ bool CButtonsGroup::CreateButtons(void) { //--- Координаты int x=0,y=0; //--- Получим количество кнопок int buttons_total=ButtonsTotal(); //--- Если нет ни одной кнопки в группе, сообщить об этом if(buttons_total<1) { //::Print(__FUNCTION__," > Вызов этого метода нужно осуществлять, ...\n" // "... когда в группе есть хотя бы одна кнопка! Воспользуйтесь методом 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); } //--- Создадим указанное количество кнопок for(int i=0; i There is no button in the group!"); return(NULL); } //--- Корректировка в случае выхода из диапазона uint i=(index>=array_size)? array_size-1 : index; //--- Вернуть указатель объекта return(::GetPointer(m_buttons[i])); } //+------------------------------------------------------------------+ //| Добавляет кнопку | //+------------------------------------------------------------------+ 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) { //--- Резервный размер int reserve_size=100; //--- Увеличим размер массивов на один элемент int array_size=::ArraySize(m_buttons); int new_size=array_size+1; ::ArrayResize(m_buttons,new_size,reserve_size); //--- Установим свойства 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); //--- Выйти, если выключен стиль радио-кнопок 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); } //+------------------------------------------------------------------+ //| Переключает кнопку по указанному индексу | //+------------------------------------------------------------------+ void CButtonsGroup::SelectButton(const uint index,const bool is_external_call=true) { //--- Для проверки существования нажатой в группе кнопки bool check_pressed_button=false; //--- Получим количество кнопок uint buttons_total=ButtonsTotal(); //--- Если нет ни одной кнопки в группе, сообщить об этом 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; } //--- Скорректировать значение индекса, если выходит из диапазона 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()); //--- Пройдёмся в цикле по группе кнопок for(uint i=0; i