mql5-execution-microstructu.../Include/RequestLatencyLab/LatencyPanel.mqh

132 lines
No EOL
6.2 KiB
MQL5

//+------------------------------------------------------------------+
//| LatencyPanel.mqh |
//| Copyright 2026, MetaQuotes Ltd. |
//| www.mql5.com |
//+------------------------------------------------------------------+
#ifndef REQUEST_LATENCY_LAB_LATENCY_PANEL_MQH
#define REQUEST_LATENCY_LAB_LATENCY_PANEL_MQH
#include "..\..\Include\RequestLatencyLab\Models.mqh"
#define LAB_PANEL_PREFIX "RLL_Panel_"
class CLatencyPanel
{
private:
long m_chart_id;
bool m_created;
bool m_started; // R13-S1: НАМЕРЕННОЕ состояние кнопки (проекция из контроллера)
string m_status;
public:
CLatencyPanel(void);
void Create(const long chart_id);
void Destroy(void);
bool IsCreated() const { return(m_created); }
bool IsStartPressed() const;
void SetStatus(const string status)
{
m_status = status;
}
//--- R10-B1: состояние кнопки управляется ТОЛЬКО latch команды Start.
//--- Кнопка остаётся нажатой/заблокированной, пока явно не вызван
//--- SetStarted(false) (после финализации прогона).
void SetStarted(const bool started);
//--- R13-S1: OBJ_BUTTON при клике САМ переключает OBJPROP_STATE
//--- (официальная семантика MQL5). После ОТКЛОНЁННОГО клика (повторный
//--- клик занятой кнопки) графический вид восстановливается из
//--- намеренного состояния, а не из того, что осталось в объекте.
void RestoreStartedState(void);
void Update(const bool running);
};
//+------------------------------------------------------------------+
//| Внешние определения методов. |
//+------------------------------------------------------------------+
CLatencyPanel::CLatencyPanel(void)
{
m_chart_id = 0;
m_created = false;
m_started = false;
m_status = "IDLE";
}
void CLatencyPanel::Create(const long chart_id)
{
m_chart_id = chart_id;
if(m_created)
return;
//--- только объекты, принадлежащие программе
ObjectCreate(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJ_RECTANGLE_LABEL, 0, 0, 0);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJPROP_XDISTANCE, 10);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJPROP_YDISTANCE, 20);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJPROP_XSIZE, 320);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJPROP_YSIZE, 110);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJPROP_BGCOLOR, clrDarkSlateGray);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJPROP_BORDER_TYPE, BORDER_FLAT);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Bg", OBJPROP_BACK, false);
ObjectCreate(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJ_BUTTON, 0, 0, 0);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_XDISTANCE, 20);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_YDISTANCE, 30);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_XSIZE, 120);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_YSIZE, 30);
ObjectSetString(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_TEXT, "Start");
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_BGCOLOR, clrForestGreen);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_HIDDEN, false);
ObjectCreate(m_chart_id, LAB_PANEL_PREFIX + "StatusLabel", OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "StatusLabel", OBJPROP_XDISTANCE, 20);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "StatusLabel", OBJPROP_YDISTANCE, 75);
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "StatusLabel", OBJPROP_COLOR, clrWhite);
ObjectSetString(m_chart_id, LAB_PANEL_PREFIX + "StatusLabel", OBJPROP_TEXT, "Status: IDLE");
m_created = true;
ChartRedraw(m_chart_id);
}
void CLatencyPanel::Destroy(void)
{
if(!m_created)
return;
//--- удаляем только объекты с нашим префиксом
for(int i = ObjectsTotal(m_chart_id, 0, -1) - 1; i >= 0; i--)
{
const string name = ObjectName(m_chart_id, i, 0, -1);
if(StringFind(name, LAB_PANEL_PREFIX) == 0)
ObjectDelete(m_chart_id, name);
}
m_created = false;
}
bool CLatencyPanel::IsStartPressed() const
{
if(!m_created)
return(false);
return(ObjectGetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_STATE) != 0);
}
void CLatencyPanel::SetStarted(const bool started)
{
m_started = started; // R13-S1: храним намеренное состояние
if(!m_created)
return;
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_STATE,
(started ? 1 : 0));
ObjectSetString(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_TEXT,
(started ? "Run…" : "Start"));
}
void CLatencyPanel::RestoreStartedState(void)
{
if(!m_created)
return;
ObjectSetInteger(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_STATE,
(m_started ? 1 : 0));
ObjectSetString(m_chart_id, LAB_PANEL_PREFIX + "Start", OBJPROP_TEXT,
(m_started ? "Run…" : "Start"));
}
void CLatencyPanel::Update(const bool running)
{
if(!m_created)
return;
ObjectSetString(m_chart_id, LAB_PANEL_PREFIX + "StatusLabel", OBJPROP_TEXT,
"Status: " + m_status);
//--- во время измерений панель не перерисовывается
if(!running)
ChartRedraw(m_chart_id);
}
#endif // REQUEST_LATENCY_LAB_LATENCY_PANEL_MQH
//+------------------------------------------------------------------+