mql5/Experts/_Architecture/Graphics/Screen.mqh

185 lines
6.1 KiB
MQL5

2026-08-14 16:19:56 +02:00
//+------------------------------------------------------------------+
//| Screen.mqh |
//| Copyright 2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Collection/DynamicArraylist.mqh>
#include "ZoneObject.mqh"
#include "ScreenListener.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class Screen
{
private:
long m_chart_id;
int m_width, m_height;
long m_zoom;
int m_fontSize;
long m_min_zoom_to_keep_texts;
bool m_min_zoom_reached_already;
datetime m_from_time, m_to_time;
double m_min_price, m_max_price;
CArrayList<ZoneObject*>* objects;
void UpdateViewBounds();
void OnZoomChanged();
void OnViewChanged();
void OnMinZoomReached();
int FindExist(ZoneObject* zoneObject)
{
for(int i = objects.Size() - 1; i >= 0; i--)
{
ZoneObject* z = objects.At(i);
if(z.GetName() == zoneObject.GetName() && z.GetName() == zoneObject.GetName())
{
return i;
}
}
return -1;
}
int GetScaledFontSize(int baseSizePoints) const
{
return (int)MathMax(6.0, baseSizePoints - (m_zoom - 2));
}
public:
Screen(): m_fontSize(12), m_chart_id(ChartID()) { objects = new CArrayList<ZoneObject*>(); UpdateViewBounds(); }
~Screen() {delete objects;}
void SetMinZoomForTexts(long zoomLevel) { m_min_zoom_to_keep_texts = zoomLevel; }
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam);
void AddLevel(ZoneObject* zoneObject);
void Render();
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Screen::OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_CHART_CHANGE)
{
UpdateViewBounds();
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Screen::AddLevel(ZoneObject* zoneObject)
{
if(zoneObject.GetSymbol() != _Symbol)
{
Print("Error Adding Levels");
return;
}
objects.Add(zoneObject);
Render();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Screen::Render()
{
UpdateViewBounds();
bool boundsValid = (m_from_time < m_to_time && m_min_price < m_max_price);
for(int i = objects.Size() - 1; i >= 0; i--)
{
objects.At(i).UpdateDraw(ChartGetInteger(m_chart_id, CHART_SCALE), m_from_time, m_to_time, m_min_price, m_max_price, m_min_zoom_to_keep_texts);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Screen::OnZoomChanged()
{
if(!m_min_zoom_reached_already)
{
for(int i = objects.Size() - 1; i >= 0; i--)
{
objects.At(i).SetFontSize(GetScaledFontSize(m_fontSize));
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Screen::OnViewChanged()
{
Render();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void Screen::OnMinZoomReached()
{
for(int i = objects.Size() - 1; i >= 0; i--)
{
objects.At(i).DeleteAllText();
}
}
//+------------------------------------------------------------------+
//| View bounds update |
//+------------------------------------------------------------------+
void Screen::UpdateViewBounds()
{
long old_zoom = m_zoom;
datetime old_from = m_from_time;
datetime old_to = m_to_time;
double old_minp = m_min_price;
double old_maxp = m_max_price;
m_width = (int)ChartGetInteger(m_chart_id, CHART_WIDTH_IN_PIXELS);
m_height = (int)ChartGetInteger(m_chart_id, CHART_HEIGHT_IN_PIXELS);
m_zoom = ChartGetInteger(m_chart_id, CHART_SCALE);
int sub_window = 0;
ChartXYToTimePrice(m_chart_id, 0, 0, sub_window, m_from_time, m_max_price);
ChartXYToTimePrice(m_chart_id, m_width, m_height, sub_window, m_to_time, m_min_price);
if(m_zoom != old_zoom)
{
OnZoomChanged();
bool below_threshold = (m_zoom < m_min_zoom_to_keep_texts);
if(below_threshold && !m_min_zoom_reached_already)
{
OnMinZoomReached();
m_min_zoom_reached_already = true;
}
else
if(!below_threshold)
{
m_min_zoom_reached_already = false;
// Render();
}
}
if(m_from_time != old_from || m_to_time != old_to ||
m_min_price != old_minp || m_max_price != old_maxp)
{
OnViewChanged();
}
}
//+------------------------------------------------------------------+