Logify/Handlers/LogifyHandlerComment.mqh
2025-08-21 11:59:58 -03:00

314 lines
23 KiB
MQL5

//+------------------------------------------------------------------+
//| LogifyHandlerComment.mqh |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "joaopedrodev"
#property link "https://www.mql5.com/en/users/joaopedrodev"
//+------------------------------------------------------------------+
//| Include files |
//+------------------------------------------------------------------+
#include "LogifyHandler.mqh"
//+------------------------------------------------------------------+
//| ENUMS |
//+------------------------------------------------------------------+
enum ENUM_LOG_FRAME_STYLE
{
LOG_FRAME_STYLE_NONE = 0, // No rotation
LOG_FRAME_STYLE_SINGLE, // Rotate based on date
LOG_FRAME_STYLE_DOUBLE, // Rotate based on file size
};
enum ENUM_LOG_DIRECTION
{
LOG_DIRECTION_UP = 0, // Up
LOG_DIRECTION_DOWN, // Down
};
//+------------------------------------------------------------------+
//| Struct: MqlLogifyHandleComment |
//+------------------------------------------------------------------+
struct MqlLogifyHandleCommentConfig
{
int size; // Space in lines that it will occupy
ENUM_LOG_FRAME_STYLE frame_style; // Display grid
ENUM_LOG_DIRECTION direction; // Direction
string title; // log title
//--- Default constructor
MqlLogifyHandleCommentConfig(void)
{
size = 20;
frame_style = LOG_FRAME_STYLE_SINGLE;
direction = LOG_DIRECTION_UP;
title = "LOGIFY";
}
//--- Destructor
~MqlLogifyHandleCommentConfig(void)
{
}
//--- Validate configuration
bool ValidateConfig(string &error_message)
{
//--- Saves the return value
bool is_valid = true;
//--- Check if size is greater than 0
if(size <= 0)
{
size = 20;
error_message = "Size must be greater than 0.";
is_valid = false;
}
//--- Check len
if(StringLen(title) > 40)
{
error_message = "Title is too long for frame. Max 40 chars.";
is_valid = false;
}
//--- No errors found
return(is_valid);
}
};
//+------------------------------------------------------------------+
//| class : CLogifyHandlerComment |
//| |
//| [PROPERTY] |
//| Name : CLogifyHandlerComment |
//| Heritage : CLogifyHandler |
//| Description : Log handler, inserts data into chart comment. |
//| |
//+------------------------------------------------------------------+
class CLogifyHandlerComment : public CLogifyHandler
{
private:
MqlLogifyHandleCommentConfig m_config;
MqlLogifyModel m_cache[];
//--- Aux
string GetBorderTop();
string GetBorderMiddle();
string GetBorderBottom();
string GetSideBorder();
string BuildHeader();
string BuildFooter();
string FormatLogLines();
public:
CLogifyHandlerComment(void);
~CLogifyHandlerComment(void);
//--- Configuration management
void SetConfig(MqlLogifyHandleCommentConfig &config);
MqlLogifyHandleCommentConfig GetConfig(void);
virtual void Emit(MqlLogifyModel &data); // Processes a log message and sends it to the specified destination
virtual void Flush(void); // Clears or completes any pending operations
virtual void Close(void); // Closes the handler and releases any resources
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CLogifyHandlerComment::CLogifyHandlerComment(void)
{
m_name = "comment";
ArrayResize(m_cache, m_config.size);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CLogifyHandlerComment::~CLogifyHandlerComment(void)
{
}
//+------------------------------------------------------------------+
//| Set configuration |
//+------------------------------------------------------------------+
void CLogifyHandlerComment::SetConfig(MqlLogifyHandleCommentConfig &config)
{
m_config = config;
//--- Validade config
string err_msg = "";
if(!m_config.ValidateConfig(err_msg))
{
Print("[ERROR] ["+TimeToString(TimeCurrent())+"] Log system error: "+err_msg);
}
//--- Resize
ArrayResize(m_cache, m_config.size);
}
//+------------------------------------------------------------------+
//| Get configuration |
//+------------------------------------------------------------------+
MqlLogifyHandleCommentConfig CLogifyHandlerComment::GetConfig(void)
{
return(m_config);
}
//+------------------------------------------------------------------+
//| Processes a log message and sends it to the specified destination|
//+------------------------------------------------------------------+
void CLogifyHandlerComment::Emit(MqlLogifyModel &data)
{
//--- Check if log level is allowed
if(data.level < this.GetLevel())
{
return;
}
//--- Shift logs to maintain history
for(int i = m_config.size-1; i > 0; i--)
{
m_cache[i] = m_cache[i-1];
}
m_cache[0] = data;
//--- Build the complete comment
string comment = BuildHeader();
comment += FormatLogLines();
comment += BuildFooter();
//--- Display on chart
Comment(comment);
}
//+------------------------------------------------------------------+
//| Clears or completes any pending operations |
//+------------------------------------------------------------------+
void CLogifyHandlerComment::Flush(void)
{
}
//+------------------------------------------------------------------+
//| Closes the handler and releases any resources |
//+------------------------------------------------------------------+
void CLogifyHandlerComment::Close(void)
{
//--- Clear
Comment("");
}
//+------------------------------------------------------------------+
//| Returns the side border character based on frame style |
//+------------------------------------------------------------------+
string CLogifyHandlerComment::GetSideBorder()
{
if(m_config.frame_style == LOG_FRAME_STYLE_SINGLE) return "";
if(m_config.frame_style == LOG_FRAME_STYLE_DOUBLE) return "";
return "";
}
//+------------------------------------------------------------------+
//| Returns the top border based on frame style |
//+------------------------------------------------------------------+
string CLogifyHandlerComment::GetBorderTop()
{
if(m_config.frame_style == LOG_FRAME_STYLE_SINGLE)
return "┌───────────────────────────────────────────┐\n";
if(m_config.frame_style == LOG_FRAME_STYLE_DOUBLE)
return "╔═══════════════════════════════════════════╗\n";
return "";
}
//+------------------------------------------------------------------+
//| Returns the middle separator based on frame style |
//+------------------------------------------------------------------+
string CLogifyHandlerComment::GetBorderMiddle()
{
if(m_config.frame_style == LOG_FRAME_STYLE_SINGLE)
return "├───────────────────────────────────────────┤\n";
if(m_config.frame_style == LOG_FRAME_STYLE_DOUBLE)
return "╠═══════════════════════════════════════════╣\n";
return "";
}
//+------------------------------------------------------------------+
//| Returns the bottom border based on frame style |
//+------------------------------------------------------------------+
string CLogifyHandlerComment::GetBorderBottom()
{
if(m_config.frame_style == LOG_FRAME_STYLE_SINGLE)
return "└───────────────────────────────────────────┘\n";
if(m_config.frame_style == LOG_FRAME_STYLE_DOUBLE)
return "╚═══════════════════════════════════════════╝\n";
return "";
}
//+------------------------------------------------------------------+
//| Builds the comment header with optional title and frame |
//+------------------------------------------------------------------+
string CLogifyHandlerComment::BuildHeader()
{
string header = "";
if(m_config.title != "" && m_config.title != NULL)
{
if(m_config.frame_style == LOG_FRAME_STYLE_NONE)
{
header += " " + m_config.title + "\n";
header += "─────────────────────────────────────────────\n";
}
else
{
header += GetBorderTop();
header += GetSideBorder() + " " + m_config.title + "\n";
header += GetBorderMiddle();
}
}
else
{
if(m_config.frame_style != LOG_FRAME_STYLE_NONE)
{
header += GetBorderTop();
}
}
return header;
}
//+------------------------------------------------------------------+
//| Builds the comment footer based on frame style |
//+------------------------------------------------------------------+
string CLogifyHandlerComment::BuildFooter()
{
if(m_config.frame_style != LOG_FRAME_STYLE_NONE)
return GetBorderBottom();
return "";
}
//+------------------------------------------------------------------+
//| Formats all log lines according to direction and frame |
//+------------------------------------------------------------------+
string CLogifyHandlerComment::FormatLogLines()
{
string result = "";
string side = GetSideBorder();
if(m_config.direction == LOG_DIRECTION_UP)
{
for(int i = m_config.size-1; i >= 0; i--)
{
string line = m_cache[i].formated;
StringReplace(line,"\n","\n"+side+" ");
if(line != "")
{
result += side + " " + line + "\n";
}
else
{
result += side + "\n";
}
}
}
else // LOG_DIRECTION_DOWN
{
for(int i = 0; i <= m_config.size-1; i++)
{
string line = m_cache[i].formated;
StringReplace(line,"\n","\n"+side+" ");
if(line != "")
{
result += side + " " + line + "\n";
}
else
{
result += side + "\n";
}
}
}
return result;
}
//+------------------------------------------------------------------+