EasyAndFastMod/Controls/ColorPicker.mqh
2026-01-15 07:23:17 -05:00

1186 строки
92 КиБ
MQL5

//+------------------------------------------------------------------+
//| ColorPicker.mqh |
//| Copyright 2015, MetaQuotes Software Corp. |
//| http://www.mql5.com |
//+------------------------------------------------------------------+
#include "..\Element.mqh"
#include "TextEdit.mqh"
#include "Button.mqh"
#include "ButtonsGroup.mqh"
#include "ColorButton.mqh"
//+------------------------------------------------------------------+
//| Класс для создания цветовой палитры для выбора цвета |
//+------------------------------------------------------------------+
class CColorPicker : public CElement
{
private:
//--- Указатель на кнопку вызывающую элемент для выбора цвета
CColorButton *m_color_button;
//--- Экземпляры для создания элемента
CButtonsGroup m_radio_buttons;
CTextEdit m_spin_edits[9];
CButton m_buttons[2];
//--- Координаты
int m_pallete_x1;
int m_pallete_y1;
int m_pallete_x2;
int m_pallete_y2;
//--- Размеры палитры
double m_pallete_x_size;
double m_pallete_y_size;
//--- Цвет рамки палитры
color m_palette_border_color;
//--- Цвета (1) текущего, (2) выбранного и (3) указанного курсором мыши
color m_current_color;
color m_picked_color;
color m_hover_color;
//--- Значения компонентов в разных цветовых моделях:
// HSL
double m_hsl_h;
double m_hsl_s;
double m_hsl_l;
//--- RGB
double m_rgb_r;
double m_rgb_g;
double m_rgb_b;
//--- Lab
double m_lab_l;
double m_lab_a;
double m_lab_b;
//--- XYZ
double m_xyz_x;
double m_xyz_y;
double m_xyz_z;
//--- Счётчик таймера для перемотки списка
int m_timer_counter;
//---
public:
CColorPicker(void);
~CColorPicker(void);
//--- Методы для создания элемента
bool CreateColorPicker(const int x_gap,const int y_gap);
//---
private:
void InitializeProperties(const int x_gap,const int y_gap);
bool CreateCanvas(void);
bool CreateRadioButtons(void);
bool CreateSpinEdits(void);
bool CreateButtons(void);
//---
public:
//--- Возвращает указатели на элементы формы
CButtonsGroup *GetRadioButtonsPointer(void) { return(::GetPointer(m_radio_buttons)); }
CTextEdit *GetSpinEditPointer(const uint index);
CButton *GetButtonPointer(const uint index);
//--- Сохраняет указатель на кнопку вызывающую цветовую палитру
void ColorButtonPointer(CColorButton &object);
//--- Установка цвета выбранного пользователем цвета на палитре
void CurrentColor(const color clr);
//---
public:
//--- Обработчик событий графика
virtual void OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
//--- Таймер
virtual void OnEventTimer(void);
//--- Рисует элемент
virtual void Draw(void);
//---
private:
//--- Получение цвета под курсором мыши
bool OnHoverColor(const int x,const int y);
//--- Обработка нажатия на палитре
bool OnClickPalette(const string clicked_object);
//--- Обработка нажатия на радио-кнопке
bool OnClickRadioButton(const uint id,const uint index,const string pressed_object);
//--- Обработка ввода нового значения в поле ввода
bool OnEndEdit(const uint id,const uint index,const string pressed_object="");
//--- Обработка нажатия на кнопке 'OK'
bool OnClickButtonOK(const uint id,const uint index,const string pressed_object);
//--- Обработка нажатия на кнопке 'Cancel'
bool OnClickButtonCancel(const uint id,const uint index,const string pressed_object);
//--- Рисует палитру
void DrawPalette(const int index);
//--- Рисует палитру по цветовой модели HSL (0: H, 1: S, 2: L)
void DrawHSL(const int index);
//--- Рисует палитру по цветовой модели RGB (3: R, 4: G, 5: B)
void DrawRGB(const int index);
//--- Рисует палитру по цветовой модели LAB (6: L, 7: a, 8: b)
void DrawLab(const int index);
//--- Рисует рамку палитры
void DrawPaletteBorder(void);
//--- Рисует рамку цветовых маркеров
void DrawSamplesBorder(void);
//--- Рисует цветовые маркеры
void DrawCurrentSample(void);
void DrawPickedSample(void);
void DrawHoverSample(void);
//--- Расчёт и установка компонентов цвета
void SetComponents(const int index,const bool fix_selected);
//--- Установка текущих параметров в поля ввода
void SetControls(const int index,const bool fix_selected);
//--- Установка параметров цветовых моделей относительно (1) HSL, (2) RGB, (3) Lab
void SetHSL(void);
void SetRGB(void);
void SetLab(void);
//--- Корректировка компонент RGB
void AdjustmentComponentRGB(void);
//--- Корректировка компонент HSL
void AdjustmentComponentHSL(void);
//--- Ускоренная перемотка значений в поле ввода
void FastSwitching(void);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CColorPicker::CColorPicker(void) : m_palette_border_color(clrSilver),
m_current_color(clrGold),
m_picked_color(clrCornflowerBlue),
m_hover_color(clrRed)
{
//--- Сохраним имя класса элемента в базовом классе
CElementBase::ClassName(CLASS_NAME);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CColorPicker::~CColorPicker(void)
{
}
//+------------------------------------------------------------------+
//| Обработчик события графика |
//+------------------------------------------------------------------+
void CColorPicker::OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{
//--- Обработка события перемещения курсора
if(id==CHARTEVENT_MOUSE_MOVE)
{
//--- Получение цвета под курсором мыши
if(OnHoverColor(m_mouse.X(),m_mouse.Y()))
return;
//---
return;
}
//--- Обработка события нажатия левой кнопки мыши на объекте
if(id==CHARTEVENT_OBJECT_CLICK)
{
//--- Если нажали на палитре
if(OnClickPalette(sparam))
return;
//---
return;
}
//--- Обработка ввода значения в поле ввода
if(id==CHARTEVENT_CUSTOM+ON_END_EDIT)
{
//--- Проверка ввода нового значения
if(OnEndEdit((uint)lparam,(uint)dparam))
return;
//---
return;
}
//--- Обработка нажатия на элементе
if(id==CHARTEVENT_CUSTOM+ON_CLICK_BUTTON)
{
//--- Если нажали на радио-кнопке
if(OnClickRadioButton((uint)lparam,(uint)dparam,sparam))
return;
//--- Проверка ввода нового значения
if(OnEndEdit((uint)lparam,(uint)dparam,sparam))
return;
//--- Если нажали на кнопке "OK"
if(OnClickButtonOK((uint)lparam,(uint)dparam,sparam))
return;
//--- Если нажали на кнопке "CANCEL"
if(OnClickButtonCancel((uint)lparam,(uint)dparam,sparam))
return;
//---
return;
}
}
//+------------------------------------------------------------------+
//| Таймер |
//+------------------------------------------------------------------+
void CColorPicker::OnEventTimer(void)
{
//--- Ускоренная перемотка значений
FastSwitching();
}
//+------------------------------------------------------------------+
//| Создаёт объект Color Picker |
//+------------------------------------------------------------------+
bool CColorPicker::CreateColorPicker(const int x_gap,const int y_gap)
{
//--- Выйти, если нет указателя на главный элемент
if(!CElement::CheckMainPointer())
return(false);
//--- Инициализация свойств
InitializeProperties(x_gap,y_gap);
//--- Создадим объекты элемента
if(!CreateCanvas())
return(false);
if(!CreateRadioButtons())
return(false);
if(!CreateSpinEdits())
return(false);
if(!CreateButtons())
return(false);
//--- Рассчитать компоненты всех цветовых моделей и нарисовать палитру относительно выделенной радио-кнопки
SetComponents(m_radio_buttons.SelectedButtonIndex(),false);
return(true);
}
//+------------------------------------------------------------------+
//| Инициализация свойств |
//+------------------------------------------------------------------+
void CColorPicker::InitializeProperties(const int x_gap,const int y_gap)
{
m_x_size =348;
m_y_size =266;
m_x =CElement::CalculateX(x_gap);
m_y =CElement::CalculateY(y_gap);
//--- Размеры и координаты палитры
m_pallete_x_size =255.0;
m_pallete_y_size =255.0;
m_pallete_x1 =6;
m_pallete_y1 =5;
m_pallete_x2 =m_pallete_x1+(int)m_pallete_x_size;
m_pallete_y2 =m_pallete_y1+(int)m_pallete_y_size;
//--- Цвет фона по умолчанию
m_back_color=(m_back_color!=clrNONE)? m_back_color : m_main.BackColor();
//--- Цвет рамки по умолчанию
m_border_color=(m_border_color!=clrNONE)? m_border_color : m_main.BackColor();
//--- Отступы от крайней точки
CElementBase::XGap(x_gap);
CElementBase::YGap(y_gap);
}
//+------------------------------------------------------------------+
//| Создаёт объект для рисования |
//+------------------------------------------------------------------+
bool CColorPicker::CreateCanvas(void)
{
//--- Формирование имени объекта
string name=CElementBase::ElementName("color_picker");
//--- Создание объекта
if(!CElement::CreateCanvas(name,m_x,m_y,m_x_size,m_y_size))
return(false);
//---
return(true);
}
//+------------------------------------------------------------------+
//| Создаёт группу радио-кнопок |
//+------------------------------------------------------------------+
bool CColorPicker::CreateRadioButtons(void)
{
//--- Идентификатор последнего добавленного элемента
CElementBase::LastId(m_main.LastId());
//--- Сохраним указатель на родительский элемент
m_radio_buttons.MainPointer(this);
//--- Координаты
int x=266,y=35;
//--- Свойства
int buttons_x_offset[] ={0,0,0,0,0,0,0,0,0};
int buttons_y_offset[] ={0,19,38,60,79,98,120,139,158};
string buttons_text[] ={"H:","S:","L:","R:","G:","B:","L:","a:","b:"};
int buttons_width[9];
::ArrayInitialize(buttons_width,35);
//--- Свойства
m_radio_buttons.NamePart("radio_button");
m_radio_buttons.ButtonYSize(18);
m_radio_buttons.RadioButtonsMode(true);
m_radio_buttons.RadioButtonsStyle(true);
m_radio_buttons.IconYGap(4);
m_radio_buttons.LabelYGap(4);
m_radio_buttons.LabelColor(clrBlack);
m_radio_buttons.LabelColorLocked(clrSilver);
//--- Добавим радио-кнопки с указанными свойствами
for(int i=0; i<9; i++)
m_radio_buttons.AddButton(buttons_x_offset[i],buttons_y_offset[i],buttons_text[i],buttons_width[i]);
//--- Создать группу кнопок
if(!m_radio_buttons.CreateButtonsGroup(x,y))
return(false);
//--- Выделим кнопку в группе
m_radio_buttons.SelectButton(8);
//--- Добавить элемент в массив
CElement::AddToArray(m_radio_buttons);
return(true);
}
//+------------------------------------------------------------------+
//| Создаёт поля ввода |
//+------------------------------------------------------------------+
bool CColorPicker::CreateSpinEdits(void)
{
//--- Координаты
int x=297;
int y[9]={36,55,74,96,115,134,156,175,194};
//---
int max[9] ={360,100,100,255,255,255,100,127,127};
int min[9] ={0,0,0,0,0,0,0,-128,-128};
int value[9] ={360,50,100,50,50,50,50,50,50};
//---
for(int i=0; i<9; i++)
{
//--- Сохраним указатель на родительский элемент
m_spin_edits[i].MainPointer(this);
//--- Свойства
m_spin_edits[i].Index(i);
m_spin_edits[i].XSize(45);
m_spin_edits[i].YSize(18);
m_spin_edits[i].MaxValue(max[i]);
m_spin_edits[i].MinValue(min[i]);
m_spin_edits[i].StepValue(1);
m_spin_edits[i].SetDigits(0);
m_spin_edits[i].SpinEditMode(true);
m_spin_edits[i].SetValue((string)value[i]);
m_spin_edits[i].BackColor(m_back_color);
m_spin_edits[i].GetTextBoxPointer().XGap(1);
m_spin_edits[i].GetTextBoxPointer().AutoSelectionMode(true);
m_spin_edits[i].GetTextBoxPointer().XSize(m_spin_edits[i].XSize());
//--- Создание элемента
if(!m_spin_edits[i].CreateTextEdit("",x,y[i]))
return(false);
//--- Отступ для текста в поле ввода
m_spin_edits[i].GetTextBoxPointer().TextYOffset(4);
//--- Добавить элемент в массив
CElement::AddToArray(m_spin_edits[i]);
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Создаёт кнопки |
//+------------------------------------------------------------------+
bool CColorPicker::CreateButtons(void)
{
for(int i=0; i<2; i++)
{
//--- Сохраним указатель на форму
m_buttons[i].MainPointer(this);
//--- Координаты
int x =267;
int y =(i<1)? 218 : 241;
//---
string text=(i<1)? "OK" : "Cancel";
//--- Свойства
m_buttons[i].Index(i+9);
m_buttons[i].NamePart("button");
m_buttons[i].XSize(76);
m_buttons[i].YSize(20);
m_buttons[i].IsCenterText(true);
//--- Создание элемента
if(!m_buttons[i].CreateButton(text,x,y))
return(false);
//--- Добавить элемент в массив
CElement::AddToArray(m_buttons[i]);
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Возвращает указатель на указанное поле ввода |
//+------------------------------------------------------------------+
CTextEdit *CColorPicker::GetSpinEditPointer(const uint index)
{
uint array_size=::ArraySize(m_spin_edits);
//--- Корректировка в случае выхода из диапазона
uint i=(index>=array_size)? array_size-1 : index;
//---
return(::GetPointer(m_spin_edits[i]));
}
//+------------------------------------------------------------------+
//| Возвращает указатель на указанную кнопку |
//+------------------------------------------------------------------+
CButton *CColorPicker::GetButtonPointer(const uint index)
{
uint array_size=::ArraySize(m_buttons);
//--- Корректировка в случае выхода из диапазона
uint i=(index>=array_size)? array_size-1 : index;
//--- Вернуть указатель
return(::GetPointer(m_buttons[index]));
}
//+------------------------------------------------------------------+
//| Сохраняет указатель на кнопку вызывающую цветовую палитру и |
//| открывает окно, к которому палитра присоединена |
//+------------------------------------------------------------------+
void CColorPicker::ColorButtonPointer(CColorButton &object)
{
//--- Сохранить указатель на кнопку
m_color_button=::GetPointer(object);
//--- Установим цвет переданной кнопки всем маркерам палитры
CurrentColor(object.CurrentColor());
//--- Если указатель на окно, к которому присоединена палитра, валиден
if(::CheckPointer(m_wnd)!=POINTER_INVALID)
{
//--- Откроем окно
m_wnd.OpenWindow();
}
//--- Сбросить фокус у кнопки
object.MouseFocus(false);
object.Update(true);
object.GetButtonPointer().MouseFocus(false);
object.GetButtonPointer().Update(true);
}
//+------------------------------------------------------------------+
//| Установка текущего цвета |
//+------------------------------------------------------------------+
void CColorPicker::CurrentColor(const color clr)
{
m_hover_color=clr;
DrawHoverSample();
//---
m_picked_color=clr;
DrawPickedSample();
//---
m_current_color=clr;
DrawCurrentSample();
}
//+------------------------------------------------------------------+
//| Получение цвета под курсором мыши |
//+------------------------------------------------------------------+
bool CColorPicker::OnHoverColor(const int x,const int y)
{
//--- Выйти, если фокус не на элементе
if(!CElementBase::MouseFocus())
return(false);
//--- Проверить фокус на палитре
m_canvas.MouseFocus(x>m_canvas.X()+m_pallete_x1 && x<m_canvas.X()+m_pallete_x2 &&
y>m_canvas.Y()+m_pallete_y1 && y<m_canvas.Y()+m_pallete_y2);
//--- Выйти, если фокус не на палитре
if(!m_canvas.MouseFocus())
{
::ObjectSetString(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TOOLTIP,"\n");
return(false);
}
//--- Определим цвет на палитре под курсором мыши
int lx =x-m_canvas.X();
int ly =y-m_canvas.Y();
m_hover_color=(color)::ColorToARGB(m_canvas.PixelGet(lx,ly),0);
//--- Установим цвет и всплывающую подсказку в соответствующий образец (маркер)
DrawHoverSample();
//--- Установим всплывающую подсказку палитре
::ObjectSetString(m_chart_id,m_canvas.ChartObjectName(),OBJPROP_TOOLTIP,::ColorToString(m_hover_color));
//--- Обновить холст
m_canvas.Update();
return(true);
}
//+------------------------------------------------------------------+
//| Обработка нажатия на цветовой палитре |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickPalette(const string clicked_object)
{
//--- Выйти, если имя объекта не совпадает
if(clicked_object!=m_canvas.ChartObjectName())
return(false);
//--- Установим цвет и всплывающую подсказку в соответствующий образец
m_picked_color=m_hover_color;
DrawPickedSample();
//--- Рассчитаем и установим компоненты цвета относительно выделенной радио-кнопки
SetComponents();
//--- Обновить поля ввода
for(int i=0; i<9; i++)
m_spin_edits[i].GetTextBoxPointer().Update(true);
//--- Обновить холст
m_canvas.Update();
return(true);
}
//+------------------------------------------------------------------+
//| Обработка нажатия на радио-кнопке |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickRadioButton(const uint id,const uint index,const string pressed_object)
{
//--- Выйдем, если нажатие было не на радио-кнопке
if(::StringFind(pressed_object,m_radio_buttons.NamePart())<0)
return(false);
//--- Выйти, если идентификаторы не совпадают
if(id!=CElementBase::Id() || index==m_radio_buttons.SelectedButtonIndex())
return(false);
//--- Обновить палитру с учётом последних изменений
DrawPalette(index);
//--- Обновить холст
m_canvas.Update();
return(true);
}
//+------------------------------------------------------------------+
//| Обработка ввода нового значения в поле ввода |
//+------------------------------------------------------------------+
bool CColorPicker::OnEndEdit(const uint id,const uint index,const string pressed_object="")
{
//--- Выйдем, если нажатие было не на кнопке
if(pressed_object!="")
if(::StringFind(pressed_object,"spin")<0)
return(false);
//--- Выйти, если идентификаторы не совпадают
if(id!=CElementBase::Id())
return(false);
//--- Рассчитаем и установим компоненты цвета для всех цветовых моделей
SetComponents(index>>1,false);
//--- Обновить поля ввода
for(int i=0; i<9; i++)
m_spin_edits[i].GetTextBoxPointer().Update(true);
//--- Обновить холст
m_canvas.Update();
return(true);
}
//+------------------------------------------------------------------+
//| Обработка нажатия на кнопке 'OK' |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonOK(const uint id,const uint index,const string pressed_object)
{
//--- Выйдем, если нажатие было не на кнопке
if(::StringFind(pressed_object,m_buttons[0].NamePart())<0)
return(false);
//--- Выйти, если идентификаторы не совпадают
if(id!=CElementBase::Id() || index!=m_buttons[0].Index())
return(false);
//--- Сохранить выбранный цвет
m_current_color=m_picked_color;
DrawCurrentSample();
m_canvas.Update();
//--- Если есть указатель кнопки вызова окна для выбора цвета
if(::CheckPointer(m_color_button)!=POINTER_INVALID)
{
//--- Установим кнопке выбранный цвет
m_color_button.CurrentColor(m_current_color);
m_color_button.MouseFocus(false);
m_color_button.Update(true);
m_color_button.GetButtonPointer().Update(true);
//--- Закроем окно
m_wnd.CloseDialogBox();
//--- Отправим сообщение об этом
::EventChartCustom(m_chart_id,ON_CHANGE_COLOR,CElementBase::Id(),CElementBase::Index(),m_color_button.LabelText());
//--- Обнулим указатель
m_color_button=NULL;
}
else
{
//--- Если указателя нет и окно диалоговое,
// вывести сообщение, что нет указателя на кнопку для вызова элемента
if(m_wnd.WindowType()==W_DIALOG)
::Print(__FUNCTION__," > Невалидный указатель вызывающего элемента (CColorButton).");
}
//---
return(true);
}
//+------------------------------------------------------------------+
//| Обработка нажатия на кнопке 'Cancel' |
//+------------------------------------------------------------------+
bool CColorPicker::OnClickButtonCancel(const uint id,const uint index,const string pressed_object)
{
//--- Выйдем, если нажатие было не на кнопке
if(::StringFind(pressed_object,m_buttons[1].NamePart())<0)
return(false);
//--- Выйти, если идентификаторы не совпадают
if(id!=CElementBase::Id() || index!=m_buttons[1].Index())
return(false);
//--- Закроем окно, если оно диалоговое
if(m_wnd.WindowType()==W_DIALOG)
m_wnd.CloseDialogBox();
//---
return(true);
}
//+------------------------------------------------------------------+
//| Рисует элемент |
//+------------------------------------------------------------------+
void CColorPicker::Draw(void)
{
//--- Нарисовать фон
CElement::DrawBackground();
//--- Нарисовать рамку
CElement::DrawBorder();
//--- Нарисовать рамку цветовых маркеров
DrawSamplesBorder();
//--- Нарисовать цветовые маркеры
DrawCurrentSample();
DrawPickedSample();
DrawHoverSample();
//--- Рассчитать компоненты всех цветовых моделей и
// нарисовать палитру относительно выделенной радио-кнопки
SetComponents(m_radio_buttons.SelectedButtonIndex(),false);
}
//+------------------------------------------------------------------+
//| Рисует рамку цветовых маркеров |
//+------------------------------------------------------------------+
void CColorPicker::DrawSamplesBorder(void)
{
uint clr=::ColorToARGB(m_palette_border_color);
//--- Рассчитаем координаты
int x1 =m_pallete_x1+(int)m_pallete_x_size+5;
int y1 =m_pallete_y1-1;
int x2 =x1+76;
int y2 =m_pallete_y1+25;
//--- Нарисовать рамку
m_canvas.Line(x1,y1,x2,y1,clr);
m_canvas.Line(x1,y2,x2,y2,clr);
m_canvas.Line(x1,y1,x1,y2,clr);
m_canvas.Line(x2,y1,x2,y2,clr);
}
//+------------------------------------------------------------------+
//| Рисует маркер с текущим цветом |
//+------------------------------------------------------------------+
void CColorPicker::DrawCurrentSample(void)
{
uint clr=::ColorToARGB(m_current_color);
//--- Рассчитаем координаты
int x1 =m_pallete_x1+(int)m_pallete_x_size+6;
int y1 =m_pallete_y1;
int x2 =x1+24;
int y2 =m_pallete_y1+24;
//--- Нарисовать маркер
m_canvas.FillRectangle(x1,y1,x2,y2,clr);
}
//+------------------------------------------------------------------+
//| Рисует маркер с выбранным цветом |
//+------------------------------------------------------------------+
void CColorPicker::DrawPickedSample(void)
{
uint clr=::ColorToARGB(m_picked_color);
//--- Рассчитаем координаты
int x1 =m_pallete_x1+(int)m_pallete_x_size+6+25;
int y1 =m_pallete_y1;
int x2 =x1+24;
int y2 =m_pallete_y1+24;
//--- Нарисовать маркер
m_canvas.FillRectangle(x1,y1,x2,y2,clr);
}
//+------------------------------------------------------------------+
//| Рисует маркер с указанным цветом |
//+------------------------------------------------------------------+
void CColorPicker::DrawHoverSample(void)
{
uint clr=::ColorToARGB(m_hover_color);
//--- Рассчитаем координаты
int x1 =m_pallete_x1+(int)m_pallete_x_size+6+50;
int y1 =m_pallete_y1;
int x2 =x1+24;
int y2 =m_pallete_y1+24;
//--- Нарисовать маркер
m_canvas.FillRectangle(x1,y1,x2,y2,clr);
}
//+------------------------------------------------------------------+
//| Рисует палитру |
//+------------------------------------------------------------------+
void CColorPicker::DrawPalette(const int index)
{
switch(index)
{
//--- HSL (0: H, 1: S, 2: L)
case 0 : case 1 : case 2 :
{
DrawHSL(index);
break;
}
//--- RGB (3: R, 4: G, 5: B)
case 3 : case 4 : case 5 :
{
DrawRGB(index);
break;
}
//--- LAB (6: L, 7: a, 8: b)
case 6 : case 7 : case 8 :
{
DrawLab(index);
break;
}
}
//--- Нарисуем рамку палитры
DrawPaletteBorder();
}
//+------------------------------------------------------------------+
//| Рисует палитру HSL |
//+------------------------------------------------------------------+
void CColorPicker::DrawHSL(const int index)
{
switch(index)
{
//--- Hue (H) - цветовой тон в диапазоне от 0 до 360
case 0 :
{
//--- Рассчитаем H-компоненту
m_hsl_h=(double)m_spin_edits[0].GetValue()/360.0;
//---
for(int ly=m_pallete_y1; ly<m_pallete_y2; ly++)
{
//--- Рассчитаем L-компоненту
m_hsl_l=ly/m_pallete_y_size;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем S-компоненту
m_hsl_s=lx/m_pallete_x_size;
//--- Конвертация HSL-компонент в RGB-компоненты
m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Скорректировать, если компоненты выходят из диапазона
AdjustmentComponentRGB();
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
//--- Saturation (S) - насыщенность в диапазоне от 0 до 100
case 1 :
{
//--- Рассчитаем S-компоненту
m_hsl_s=(double)m_spin_edits[1].GetValue()/100.0;
//---
for(int ly=m_pallete_y1; ly<m_pallete_y2; ly++)
{
//--- Рассчитаем L-компоненту
m_hsl_l=ly/m_pallete_y_size;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем H-компоненту
m_hsl_h=lx/m_pallete_x_size;
//--- Конвертация HSL-компонент в RGB-компоненты
m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Скорректировать, если компоненты выходят из диапазона
AdjustmentComponentRGB();
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
//--- Lightness (L) - яркость в диапазоне от 0 до 100
case 2 :
{
//--- Рассчитаем L-компоненту
m_hsl_l=(double)m_spin_edits[2].GetValue()/100.0;
//---
for(int ly=m_pallete_y1; ly<m_pallete_y2; ly++)
{
//--- Рассчитаем S-компоненту
m_hsl_s=ly/m_pallete_y_size;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем H-компоненту
m_hsl_h=lx/m_pallete_x_size;
//--- Конвертация HSL-компонент в RGB-компоненты
m_clr.HSLtoRGB(m_hsl_h,m_hsl_s,m_hsl_l,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Скорректировать, если компоненты выходят из диапазона
AdjustmentComponentRGB();
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
}
}
//+------------------------------------------------------------------+
//| Рисует палитру RGB |
//+------------------------------------------------------------------+
void CColorPicker::DrawRGB(const int index)
{
//--- Шаги по осям X и Y для расчёта RGB-компонент
double rgb_x_step =255.0/m_pallete_x_size;
double rgb_y_step =255.0/m_pallete_y_size;
//---
switch(index)
{
//--- Red (R) - красный. Цветовой диапазон от 0 до 255
case 3 :
{
//--- Получим текущую R-компоненту и обнулим B-компоненту
m_rgb_r =(double)m_spin_edits[3].GetValue();
m_rgb_b =0;
//---
for(int ly=m_pallete_y1; ly<m_pallete_y2; ly++)
{
//--- Рассчитаем B-компоненту и обнулим R-компоненту
m_rgb_g=0;
m_rgb_b+=rgb_y_step;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем G-компоненту
m_rgb_g+=rgb_x_step;
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
//--- Green (G) - зелёный. Цветовой диапазон от 0 до 255
case 4 :
{
//--- Получим текущую G-компоненту и обнулим B-компоненту
m_rgb_g =(double)m_spin_edits[4].GetValue();
m_rgb_b =0;
//---
for(int ly=m_pallete_y1; ly<m_pallete_y2; ly++)
{
//--- Рассчитаем B-компоненту и обнулим R-компоненту
m_rgb_r=0;
m_rgb_b+=rgb_y_step;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем R-компоненту
m_rgb_r+=rgb_x_step;
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
//--- Blue (B) - синий. Цветовой диапазон от 0 до 255
case 5 :
{
//--- Получим текущую B-компоненту и обнулим G-компоненту
m_rgb_g =0;
m_rgb_b =(double)m_spin_edits[5].GetValue();
//---
for(int ly=m_pallete_y1; ly<m_pallete_y2; ly++)
{
//--- Рассчитаем G-компоненту и обнулим R-компоненту
m_rgb_r=0;
m_rgb_g+=rgb_y_step;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем R-компоненту
m_rgb_r+=rgb_x_step;
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
}
}
//+------------------------------------------------------------------+
//| Рисует палитру Lab |
//+------------------------------------------------------------------+
void CColorPicker::DrawLab(const int index)
{
switch(index)
{
//--- Lightness (L) - яркость в диапазоне от 0 до 100
case 6 :
{
//--- Получим текущую L-компоненту
m_lab_l=(double)m_spin_edits[6].GetValue();
//---
for(int ly=m_pallete_y1; ly<=m_pallete_y2; ly++)
{
//--- Рассчитаем b-компоненту
m_lab_b=(ly/m_pallete_y_size*255.0)-128;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем a-компоненту
m_lab_a=(lx/m_pallete_x_size*255.0)-128;
//--- Конвертация Lab-компонент в RGB-компоненты
m_clr.CIELabToXYZ(m_lab_l,m_lab_a,m_lab_b,m_xyz_x,m_xyz_y,m_xyz_z);
m_clr.XYZtoRGB(m_xyz_x,m_xyz_y,m_xyz_z,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Корректировка компонент RGB
AdjustmentComponentRGB();
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
//--- Хроматическая компонента 'a' - диапазон от -128 (зелёный) до 127 (пурпурный)
case 7 :
{
//--- Получим текущую a-компоненту
m_lab_a=(double)m_spin_edits[7].GetValue();
//---
for(int ly=m_pallete_y1; ly<=m_pallete_y2; ly++)
{
//--- Рассчитаем b-компоненту
m_lab_b=(ly/m_pallete_y_size*255.0)-128;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем L-компоненту
m_lab_l=100.0*lx/m_pallete_x_size;
//--- Конвертация Lab-компонент в RGB-компоненты
m_clr.CIELabToXYZ(m_lab_l,m_lab_a,m_lab_b,m_xyz_x,m_xyz_y,m_xyz_z);
m_clr.XYZtoRGB(m_xyz_x,m_xyz_y,m_xyz_z,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Корректировка компонент RGB
AdjustmentComponentRGB();
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
//--- Хроматическая компонента 'b' - диапазон от -128 (синий) до 127 (жёлтый)
case 8 :
{
//--- Получим текущую b-компоненту
m_lab_b=(double)m_spin_edits[8].GetValue();
//---
for(int ly=m_pallete_y1; ly<=m_pallete_y2; ly++)
{
//--- Рассчитаем a-компоненту
m_lab_a=(ly/m_pallete_y_size*255.0)-128;
//---
for(int lx=m_pallete_x1; lx<m_pallete_x2; lx++)
{
//--- Рассчитаем L-компоненту
m_lab_l=100.0*lx/m_pallete_x_size;
//--- Конвертация Lab-компонент в RGB-компоненты
m_clr.CIELabToXYZ(m_lab_l,m_lab_a,m_lab_b,m_xyz_x,m_xyz_y,m_xyz_z);
m_clr.XYZtoRGB(m_xyz_x,m_xyz_y,m_xyz_z,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Корректировка компонент RGB
AdjustmentComponentRGB();
//--- Соединим каналы
uint rgb_color=XRGB(m_rgb_r,m_rgb_g,m_rgb_b);
m_canvas.PixelSet(lx,ly,rgb_color);
}
}
break;
}
}
}
//+------------------------------------------------------------------+
//| Рисует рамку палитры |
//+------------------------------------------------------------------+
void CColorPicker::DrawPaletteBorder(void)
{
uint clr=::ColorToARGB(m_palette_border_color);
//--- Размер палитры
int x1 =m_pallete_x1-1;
int y1 =m_pallete_y1-1;
int x2 =m_pallete_x1+(int)m_pallete_x_size;
int y2 =m_pallete_y1+(int)m_pallete_y_size;
//--- Нарисовать рамку
m_canvas.Line(x1,y1,x2,y1,clr);
m_canvas.Line(x1,y2,x2,y2,clr);
m_canvas.Line(x2,y1,x2,y2,clr);
m_canvas.Line(x1,y1,x1,y2,clr);
}
//+------------------------------------------------------------------+
//| Расчёт и установка компонентов цвета |
//+------------------------------------------------------------------+
void CColorPicker::SetComponents(const int index=0,const bool fix_selected=true)
{
//--- Если нужно скорректировать цвета относительно выделенного радио-кнопкой компонента
if(fix_selected)
{
//--- Разложим на RGB-компоненты выбранный цвет
m_rgb_r =m_clr.GetR(m_picked_color);
m_rgb_g =m_clr.GetG(m_picked_color);
m_rgb_b =m_clr.GetB(m_picked_color);
//--- Конвертируем RGB-компоненты в HSL-компоненты
m_clr.RGBtoHSL(m_rgb_r,m_rgb_g,m_rgb_b,m_hsl_h,m_hsl_s,m_hsl_l);
//--- Корректировка компонент HSL
AdjustmentComponentHSL();
//--- Конвертируем RGB-компоненты в LAB-компоненты
m_clr.RGBtoXYZ(m_rgb_r,m_rgb_g,m_rgb_b,m_xyz_x,m_xyz_y,m_xyz_z);
m_clr.XYZtoCIELab(m_xyz_x,m_xyz_y,m_xyz_z,m_lab_l,m_lab_a,m_lab_b);
//--- Установим цвета в поля ввода
SetControls(m_radio_buttons.SelectedButtonIndex(),true);
return;
}
//--- Установка параметров цветовых моделей
switch(index)
{
case 0 : case 1 : case 2 :
SetHSL();
break;
case 3 : case 4 : case 5 :
SetRGB();
break;
case 6 : case 7 : case 8 :
SetLab();
break;
}
//--- Нарисовать палитру относительно выделенной радио-кнопки
DrawPalette(m_radio_buttons.SelectedButtonIndex());
}
//+------------------------------------------------------------------+
//| Установка текущих параметров в поля ввода |
//+------------------------------------------------------------------+
void CColorPicker::SetControls(const int index,const bool fix_selected)
{
//--- Если нужно зафиксировать значение в поле ввода выделенной радио-кнопки
if(fix_selected)
{
//--- Компоненты HSL
if(index!=0)
m_spin_edits[0].SetValue(::DoubleToString(m_hsl_h,0),false);
if(index!=1)
m_spin_edits[1].SetValue(::DoubleToString(m_hsl_s,0),false);
if(index!=2)
m_spin_edits[2].SetValue(::DoubleToString(m_hsl_l,0),false);
//--- Компоненты RGB
if(index!=3)
m_spin_edits[3].SetValue(::DoubleToString(m_rgb_r,0),false);
if(index!=4)
m_spin_edits[4].SetValue(::DoubleToString(m_rgb_g,0),false);
if(index!=5)
m_spin_edits[5].SetValue(::DoubleToString(m_rgb_b,0),false);
//--- Компоненты Lab
if(index!=6)
m_spin_edits[6].SetValue(::DoubleToString(m_lab_l,0),false);
if(index!=7)
m_spin_edits[7].SetValue(::DoubleToString(m_lab_a,0),false);
if(index!=8)
m_spin_edits[8].SetValue(::DoubleToString(m_lab_b,0),false);
return;
}
//--- Если нужно скорректировать значения в полях ввода всех цветовых моделей
m_spin_edits[0].SetValue(::DoubleToString(m_hsl_h,0),false);
m_spin_edits[1].SetValue(::DoubleToString(m_hsl_s,0),false);
m_spin_edits[2].SetValue(::DoubleToString(m_hsl_l,0),false);
//---
m_spin_edits[3].SetValue(::DoubleToString(m_rgb_r,0),false);
m_spin_edits[4].SetValue(::DoubleToString(m_rgb_g,0),false);
m_spin_edits[5].SetValue(::DoubleToString(m_rgb_b,0),false);
//---
m_spin_edits[6].SetValue(::DoubleToString(m_lab_l,0),false);
m_spin_edits[7].SetValue(::DoubleToString(m_lab_a,0),false);
m_spin_edits[8].SetValue(::DoubleToString(m_lab_b,0),false);
}
//+------------------------------------------------------------------+
//| Установка параметров цветовых моделей относительно HSL |
//+------------------------------------------------------------------+
void CColorPicker::SetHSL(void)
{
//--- Получим текущие значения компонентов HSL
m_hsl_h =(double)m_spin_edits[0].GetValue();
m_hsl_s =(double)m_spin_edits[1].GetValue();
m_hsl_l =(double)m_spin_edits[2].GetValue();
//--- Конвертация HSL-компонент в RGB-компоненты
m_clr.HSLtoRGB(m_hsl_h/360.0,m_hsl_s/100.0,m_hsl_l/100.0,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Конвертация RGB-компонент в Lab-компоненты
m_clr.RGBtoXYZ(m_rgb_r,m_rgb_g,m_rgb_b,m_xyz_x,m_xyz_y,m_xyz_z);
m_clr.XYZtoCIELab(m_xyz_x,m_xyz_y,m_xyz_z,m_lab_l,m_lab_a,m_lab_b);
//--- Установка текущих параметров в поля ввода
SetControls(0,false);
}
//+------------------------------------------------------------------+
//| Установка параметров цветовых моделей относительно RGB |
//+------------------------------------------------------------------+
void CColorPicker::SetRGB(void)
{
//--- Получим текущие значения компонентов RGB
m_rgb_r =(double)m_spin_edits[3].GetValue();
m_rgb_g =(double)m_spin_edits[4].GetValue();
m_rgb_b =(double)m_spin_edits[5].GetValue();
//--- Конвертация RGB-компонент в HSL-компоненты
m_clr.RGBtoHSL(m_rgb_r,m_rgb_g,m_rgb_b,m_hsl_h,m_hsl_s,m_hsl_l);
//--- Корректировка компонент HSL
AdjustmentComponentHSL();
//--- Конвертация RGB-компонент в Lab-компоненты
m_clr.RGBtoXYZ(m_rgb_r,m_rgb_g,m_rgb_b,m_xyz_x,m_xyz_y,m_xyz_z);
m_clr.XYZtoCIELab(m_xyz_x,m_xyz_y,m_xyz_z,m_lab_l,m_lab_a,m_lab_b);
//--- Установка текущих параметров в поля ввода
SetControls(0,false);
}
//+------------------------------------------------------------------+
//| Установка параметров цветовых моделей относительно Lab |
//+------------------------------------------------------------------+
void CColorPicker::SetLab(void)
{
//--- Получим текущие значения компонентов Lab
m_lab_l =(double)m_spin_edits[6].GetValue();
m_lab_a =(double)m_spin_edits[7].GetValue();
m_lab_b =(double)m_spin_edits[8].GetValue();
//--- Конвертация Lab-компонент в RGB-компоненты
m_clr.CIELabToXYZ(m_lab_l,m_lab_a,m_lab_b,m_xyz_x,m_xyz_y,m_xyz_z);
m_clr.XYZtoRGB(m_xyz_x,m_xyz_y,m_xyz_z,m_rgb_r,m_rgb_g,m_rgb_b);
//--- Корректировка компонент RGB
AdjustmentComponentRGB();
//--- Конвертация RGB-компонент в HSL-компоненты
m_clr.RGBtoHSL(m_rgb_r,m_rgb_g,m_rgb_b,m_hsl_h,m_hsl_s,m_hsl_l);
//--- Корректировка компонент HSL
AdjustmentComponentHSL();
//--- Установка текущих параметров в поля ввода
SetControls(0,false);
}
//+------------------------------------------------------------------+
//| Корректировка компонент RGB |
//+------------------------------------------------------------------+
void CColorPicker::AdjustmentComponentRGB(void)
{
m_rgb_r=::fmin(::fmax(m_rgb_r,0),255);
m_rgb_g=::fmin(::fmax(m_rgb_g,0),255);
m_rgb_b=::fmin(::fmax(m_rgb_b,0),255);
}
//+------------------------------------------------------------------+
//| Корректировка компонент HSL |
//+------------------------------------------------------------------+
void CColorPicker::AdjustmentComponentHSL(void)
{
m_hsl_h*=360;
m_hsl_s*=100;
m_hsl_l*=100;
}
//+------------------------------------------------------------------+
//| Ускоренная промотка значения в поле ввода |
//+------------------------------------------------------------------+
void CColorPicker::FastSwitching(void)
{
//--- Выйдем, если нет фокуса на элементе
if(!CElementBase::MouseFocus())
return;
//--- Вернём счётчик к первоначальному значению, если кнопка мыши отжата
if(!m_mouse.LeftButtonState())
m_timer_counter=SPIN_DELAY_MSC;
//--- Если же кнопка мыши нажата
else
{
//--- Увеличим счётчик на установленный интервал
m_timer_counter+=TIMER_STEP_MSC;
//--- Выйдем, если меньше нуля
if(m_timer_counter<0)
return;
//--- Определение активированного счётчика у активированной радио-кнопки
int index=WRONG_VALUE;
//---
for(int i=0; i<9; i++)
{
if(m_radio_buttons.SelectedButtonIndex()==i &&
(m_spin_edits[i].GetIncButtonPointer().MouseFocus() || m_spin_edits[i].GetDecButtonPointer().MouseFocus()))
{
index=i;
break;
}
}
//--- Если есть, обновим палитру
if(index!=WRONG_VALUE)
{
DrawPalette(index);
//--- Обновить холст
m_canvas.Update();
}
//--- Определение активированного счётчика
index=WRONG_VALUE;
//---
for(int i=0; i<9; i++)
{
if(m_spin_edits[i].GetIncButtonPointer().MouseFocus() || m_spin_edits[i].GetDecButtonPointer().MouseFocus())
{
index=i;
break;
}
}
//--- Если есть, пересчитаем компоненты всех цветовых моделей и обновим палитру
if(index!=WRONG_VALUE)
{
SetComponents(index,false);
//--- Обновить холст
m_canvas.Update();
}
}
}
//+------------------------------------------------------------------+