EA-Setka-2/Libs/comment.mqh
super.admin a4b861dd93 convert
2025-05-30 14:50:44 +02:00

430 lines
14 KiB
MQL5

//+------------------------------------------------------------------+
//| Comment.mqh |
//| avoitenko |
//| https://login.mql5.com/en/users/avoitenko |
//+------------------------------------------------------------------+
#property copyright "avoitenko"
#property link "https://login.mql5.com/en/users/avoitenko"
#property version "1.00"
#property strict
#include <Canvas/Canvas.mqh>
#include <Arrays/List.mqh>
//---
#define EVENT_NO_EVENTS 0
#define EVENT_MOVE 1
#define EVENT_CHANGE 2
//+------------------------------------------------------------------+
//| TComment |
//+------------------------------------------------------------------+
class TComment : public CObject
{
public:
string text;
color colour;
};
//+------------------------------------------------------------------+
//| CComment |
//+------------------------------------------------------------------+
class CComment
{
private:
bool m_is_collapse;
CPoint m_temp;
CCanvas m_comment;
CPoint m_pos;
CList m_list;
CSize m_size;
//---
string m_name;
string m_font_name;
int m_font_size;
bool m_font_bold;
double m_font_interval;
color m_border_color;
color m_back_color;
uchar m_back_alpha;
bool m_graph_mode;
bool m_auto_colors;
color m_auto_back_color;
color m_auto_text_color;
color m_auto_border_color;
color m_chart_back_color;
//+------------------------------------------------------------------+
color Color2Gray(const color value)
{
int gray=(int)round(0.3*GETRGBR(value)+0.59*GETRGBG(value)+0.11*GETRGBB(value));
if(gray>255)
gray=255;
return((color)ARGB(0,gray,gray,gray));
}
//+------------------------------------------------------------------+
uchar GrayChannel(const color value)
{
int gray=(int)round(0.3*GETRGBR(value)+0.59*GETRGBG(value)+0.11*GETRGBB(value));
if(gray>255)
gray=255;
return((uchar)gray);
}
//+------------------------------------------------------------------+
color Bright(const color value,const int percent)
{
int r,g,b;
//---
r=GETRGBR(value);
g=GETRGBG(value);
b=GETRGBB(value);
//---
if(percent>=0)
{
r+=(255-r)*percent/100;
if(r>255)
r=255;
//---
g+=(255-g)*percent/100;
if(g>255)
g=255;
//---
b+=(255-b)*percent/100;
if(b>255)
b=255;
}
else
{
r+=r*percent/100;
if(r<0)
r=0;
//---
g+=g*percent/100;
if(g<0)
g=0;
//---
b+=b*percent/100;
if(b<0)
b=0;
}
//---
return(ARGB(0,r,g,b));
}
//+------------------------------------------------------------------+
void CalcColors()
{
m_auto_back_color=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND);
color m_back_gray=Color2Gray(m_auto_back_color);
uchar channel=GrayChannel(m_back_gray);
//---
if(channel>120)
{
if(m_back_color==clrNONE)
m_auto_border_color=clrNONE;
else
m_auto_border_color=Bright(m_back_gray,-30);
//---
m_auto_text_color=Bright(m_back_gray,-80);
}
else
{
if(m_back_color==clrNONE)
m_auto_border_color=clrNONE;
else
m_auto_border_color=Bright(m_back_gray,30);
//---
m_auto_text_color=Bright(m_back_gray,80);
}
}
public:
//+------------------------------------------------------------------+
void CComment(void)
{
m_name=NULL;
m_font_name="Lucida Console";
m_font_size=14;
m_font_bold=false;
m_font_interval=1.7;
m_border_color=clrNONE;
m_back_color=clrNONE;
m_back_alpha=10;
m_graph_mode=true;
m_auto_colors=false;
m_chart_back_color=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND);
m_auto_back_color=clrBlack;
m_auto_border_color=clrNONE;
//---
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,true);
};
//+------------------------------------------------------------------+
void Create(const string name,const uint x,const uint y)
{
m_name=name;
m_pos.x=(int)x;
m_pos.y=(int)y;
};
//+------------------------------------------------------------------+
void Move(const uint x,const uint y)
{
m_pos.x=(int)x;
m_pos.y=(int)y;
};
//+------------------------------------------------------------------+
void SetAutoColors(const bool value)
{
m_auto_colors=value;
if(value)
CalcColors();
}
//+------------------------------------------------------------------+
void SetGraphMode(const bool value)
{
m_graph_mode=value;
};
//+------------------------------------------------------------------+
void SetText(const int row,const string text,const color colour)
{
if(row<0)
return;
//---
int total=m_list.Total();
//---
if(row<total)
{
TComment *item=m_list.GetNodeAtIndex(row);
item.text=text;
item.colour=colour;
}
else
{
//--- create new one string
for(int i=total; i<=row; i++)
{
m_list.Add(new TComment);
TComment *item=m_list.GetLastNode();
if(row==i)
{
item.text=text;
item.colour=colour;
}
else
{
item.text="";
item.colour=clrNONE;
}
}
}
}
//+------------------------------------------------------------------+
void SetFont(const string font_name,const int font_size,const bool bold,const double font_interval)
{
m_font_name=font_name;
m_font_size=font_size;
m_font_bold=bold;
m_font_interval=font_interval;
}
//+------------------------------------------------------------------+
void SetColor(const color border,const color back,const uchar alpha)
{
m_border_color=border;
m_back_color=back;
m_back_alpha=alpha;
}
//+------------------------------------------------------------------+
void Destroy()
{
if(!m_graph_mode)
Comment("");
m_comment.Destroy();
m_name=NULL;
};
//+------------------------------------------------------------------+
CList* GetList()
{
return &m_list;
}
//+------------------------------------------------------------------+
void Clear()
{
m_list.Clear();
};
//+------------------------------------------------------------------+
int OnChartEvent(const int id,const long lparam,const double dparam,const string sparam)
{
//--- mouse position
CPoint p;
p.x = (int)lparam;
p.y = (int)dparam;
//---
if(id==CHARTEVENT_MOUSE_MOVE)
{
//--- panel size
CSize psize;
psize.cx=(int)ObjectGetInteger(0,m_name,OBJPROP_XSIZE);
psize.cy=(int)ObjectGetInteger(0,m_name,OBJPROP_YSIZE);
//--- panel position
CPoint pan;
pan.x=(int)ObjectGetInteger(0,m_name,OBJPROP_XDISTANCE);
pan.y=(int)ObjectGetInteger(0,m_name,OBJPROP_YDISTANCE);
//--- chart size
CSize screen;
screen.cx=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);
screen.cy=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);
//---
if(sparam=="1")
{
//---
if(m_temp.x==-1 &&
p.x>=pan.x && p.x<pan.x+psize.cx &&
p.y>=pan.y && p.y<pan.y+psize.cy)
{
m_temp.x=p.x-pan.x;
}
//---
if(m_temp.y==-1 &&
p.x>=pan.x && p.x<pan.x+psize.cx &&
p.y>=pan.y && p.y<pan.y+psize.cy)
{
m_temp.y=p.y-pan.y;
}
//---
if(m_temp.x>=0 && m_temp.y>=0)
{
int new_x=p.x-m_temp.x;
if(new_x>screen.cx-psize.cx)
new_x=screen.cx-psize.cx;
if(new_x<0)
new_x=0;
//---
int new_y=p.y-m_temp.y;
if(new_y>screen.cy-psize.cy)
new_y=screen.cy-psize.cy;
if(new_y<0)
new_y=0;
//---
ObjectSetInteger(0,m_name,OBJPROP_XDISTANCE,new_x);
ObjectSetInteger(0,m_name,OBJPROP_YDISTANCE,new_y);
ChartSetInteger(0,CHART_MOUSE_SCROLL,false);
#ifdef __MQL5__
ChartRedraw();
#endif
return(EVENT_MOVE);
}
}
else
{
m_temp.x=-1;
m_temp.y=-1;
ChartSetInteger(0,CHART_MOUSE_SCROLL,true);
}
}
//---
if(m_auto_colors && id==CHARTEVENT_CHART_CHANGE)
{
//--- changing background color event
if(m_chart_back_color!=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND))
{
CalcColors();
m_chart_back_color=(color)ChartGetInteger(0,CHART_COLOR_BACKGROUND);
return(EVENT_CHANGE);
}
}
//---
if(id==CHARTEVENT_CLICK)
{
//beginning of: detection of a doubleclick
static ulong ClickTimeMemory ; //static is crucial to remember ClickTimeMemory's content next time OnChartEvent() is called
ulong ClickTime = GetTickCount() ; //GetTickCount() uses milliseconds - it's not necessary to use GetMicrosecondCount()
if(ClickTime > ClickTimeMemory && ClickTime < ClickTimeMemory + 300) //the second click should appear within 300 milliseconds after the first click. That's 0.3 seconds - that's about the typical delay of the second click relative to the first click when making a doubleclick
{
//--- panel size
CSize psize;
psize.cx=(int)ObjectGetInteger(0,m_name,OBJPROP_XSIZE);
psize.cy=(int)ObjectGetInteger(0,m_name,OBJPROP_YSIZE);
//--- panel position
CPoint pan;
pan.x=(int)ObjectGetInteger(0,m_name,OBJPROP_XDISTANCE);
pan.y=(int)ObjectGetInteger(0,m_name,OBJPROP_YDISTANCE);
if(p.x>=pan.x && p.x<pan.x+psize.cx &&
p.y>=pan.y && p.y<pan.y+psize.cy)
{
m_is_collapse=!m_is_collapse;
Show();
}
}
ClickTimeMemory = ClickTime ;
}
//---
return(EVENT_NO_EVENTS);
}
//+------------------------------------------------------------------+
void Show()
{
int rows=m_is_collapse? 1 : m_list.Total();
//--- text mode
if(!m_graph_mode)
{
string text;
for(int i=0; i<rows; i++)
{
TComment *item=m_list.GetNodeAtIndex(i);
text+="\n"+item.text;
}
Comment(text);
return;
}
//---
m_comment.FontSet(m_font_name,m_font_size,m_font_bold?FW_BOLD:0);
int text_height=m_comment.TextHeight(" ");
int max_height=(int)((rows)*round(text_height*m_font_interval)+text_height-m_font_interval);
//--- calc max width
int max_width=0;
for(int i=0; i<rows; i++)
{
TComment *item=m_list.GetNodeAtIndex(i);
int width=m_comment.TextWidth(item.text);
if(width>max_width)
max_width=width;
}
max_width+=text_height;
//--- create panel
if(ObjectFind(0,m_name)==-1)
{
//m_comment.CreateBitmapLabel(0,0,m_name,m_pos.x,m_pos.y,max_width,max_height,COLOR_FORMAT_ARGB_NORMALIZE);
m_comment.CreateBitmapLabel(0,0,m_name,m_pos.x,m_pos.y,max_width,max_height,COLOR_FORMAT_ARGB_RAW);
}
else
{
//--- resize panel
if(m_comment.Height()!=max_height ||
m_comment.Width()!=max_width)
{
if(!m_comment.Resize(max_width,max_height))
{
ObjectDelete(0,m_name);
ChartRedraw();
}
}
}
//---
m_comment.Erase(ColorToARGB(m_auto_colors?m_auto_back_color:m_back_color,m_back_alpha));
m_comment.Rectangle(0,0,max_width-1,max_height-1,ColorToARGB(m_auto_colors?m_auto_border_color:m_border_color));
//---
int h=(int)round(text_height/2);
for(int i=0; i<rows; i++)
{
TComment *item=m_list.GetNodeAtIndex(i);
m_comment.TextOut((int)round(text_height/2),h,item.text,ColorToARGB(m_auto_colors?m_auto_text_color:item.colour));
h+=(int)round(text_height*m_font_interval);
}
//---
m_comment.Update();
}
};
//+------------------------------------------------------------------+