GrapichsByLeo/Histogram/Eje/Ejes.mqh

549 lines
35 KiB
MQL5
Raw Permalink Normal View History

2025-10-13 22:07:20 -05:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| Grid.mqh |
//| Copyright 2025, Niquel Mendoza. |
//| https://www.mql5.com/es/users/nique_372/news |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Niquel Mendoza."
#property link "https://www.mql5.com/es/users/nique_372/news"
#property strict
#ifndef GRAPHICS_HISTOGRAM_EJE_EJES_MQH_BY_LEO
#define GRAPHICS_HISTOGRAM_EJE_EJES_MQH_BY_LEO
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#include "..\\..\\PartInf\\ParteInf.mqh"
#include "..\\..\\General\\TextoCanvas.mqh"
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
const string DoubleToStrPrefixArrFormats[5] = {"%.*f", "%.*f K", "%.*f M", "%.*f B", "%.*f T"};
//+------------------------------------------------------------------+
string DoubleToStrPrefix(double value, int8_t decimals)
{
const double abs_val = MathAbs(value);
int idx = 0;
double v = value;
if(abs_val >= 1000000000000.0)
{
v /= 1000000000000.0;
idx = 4;
}
else
if(abs_val >= 1000000000.0)
{
v /= 1000000000.0;
idx = 3;
}
else
if(abs_val >= 1000000.0)
{
v /= 1000000.0;
idx = 2;
}
else
if(abs_val >= 1000.0)
{
v /= 1000.0;
idx = 1;
}
return StringFormat(DoubleToStrPrefixArrFormats[idx], decimals, v);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
struct HistogramEjeLineSection
{
double value;
string str_val;
int init; // X - Y
int c1; // Y1 -X1
int c2; // Y2 - X2
int c_text;
};
//--- EJe de X
struct HistogramEjeLineBasic
{
int init;
int c1;
int c2;
uint clr;
};
//---
2025-10-14 10:58:09 -05:00
2025-10-13 22:07:20 -05:00
//--- Eje Y con multiples secciones
// Obligtorios
#define HIST_EJE_FLAG_INIT_GENERAL 1
#define HIST_EJE_FLAG_INIT_LINE 2
// General
#define HIST_EJE_FLAG_INIT_TITULO 4
/*
X1
_________
Y1 |
|
|
|
|
|
*/
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
typedef string(*HistFunctionFormatDouble)(double value, int8_t decimals);
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CHistogramEjeLine
{
protected:
uint m_init_flags;
CCanvasCustom* m_canvas;
uint m_clr_clean;
//---
CTextCanvas* m_titulo; // Titulo del eje
int m_titulo_gap_px; // Gap respecto al titulok
//--- Linea general
int m_x;
int m_y;
int m_c2; // Cordanada 2
int m_size_line_sections;
uint m_clr;
//--- Secciones
int m_secciones_size;
HistogramEjeLineSection m_secciones[];
int m_section_size_px; // Tama<EFBFBD>o en picxlex
int m_section_size_gap_value; // Gap entre la linea y el texto
int m_sections_font_size;
string m_sections_font;
uint m_sections_alingment;
int8_t m_sections_decimals;
HistFunctionFormatDouble m_function_val_to_str;
//--- Valores
double m_max_value;
double m_min_value;
double m_change_value;
// 0 se ubica a la izquierda lineas a oiuiqer, 1 se ubica a la derecha lineas a la derecha
int m_mode_line;
bool m_use_change_value;
//---
virtual void TituloActulize() = 0;
virtual void RecalculeAndDrawSections() = 0;
virtual void RedrawSections() = 0;
virtual void OnNewFunctionFormat() = 0;
virtual void OnInitialize() = 0;
public:
CHistogramEjeLine();
~CHistogramEjeLine();
//--- Inicializa la clase (clr = linevertial tamibne las lines de las sessionces y texto de cada seccion)
void Init(CCanvasCustom* c, int x, int y, int size_line, uint clr_line_and_text_line, int mode);
void CreateSections(int inital_sections, double max_value, double min_value, bool use_change_val, double change_value,
int section_gap_value, int sections_size_px, int8_t decimals, int fontsize = 0, string font = NULL);
virtual void CreateTitulo(const string &txt, uint clr, int gap_titulo, int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX) = 0;
//--- Limpa los pixles ocupados por la linea dejee, secciones y texto de cada sesion (menos el titulo), solo linmepa pxieles, no cambia el valores
virtual void CleanPixelsSections() = 0;
//--- Secciones
//- Funcion de formateo
void SectionsFormatStrFunction(HistFunctionFormatDouble new_function, bool redraw = false);
__forceinline HistFunctionFormatDouble SectionsFormatStrFunction() const { return m_function_val_to_str; }
//- Tama<EFBFBD>o de cada "line" de valor
void SectionsUniqueSizeInPixels(int new_value, bool redraw = false);
__forceinline int SectionsUniqueSizeInPixels() const { return m_section_size_px; }
//- Fontsize de los textos de la linea del eje
void SectionsFontSize(int new_value, bool redraw = false);
__forceinline int SectionsFontSize() const { return m_sections_font_size;}
//- Font de los textos de la linea de eje
void SectionsFont(const string& new_value, bool redraw = false);
__forceinline string SectionsFont() const { return m_sections_font;}
//- Numero de seccions de la linea del eje
void SectionsSize(int new_value, bool redraw = false);
__forceinline int SectionsSize() const { return m_secciones_size; }
//- COlor de (lineas de sccion + texto de linea de seccion + line general)
void SectionsColor(uint new_clr, bool redraw = false);
__forceinline uint SectionsColor() const { return m_clr; }
//- Maximo de la linea del eje
void Max(double max, bool redraw = false);
__forceinline double Max() const { return m_max_value; }
//- Minimo de la linea del eje
void Min(double min, bool redraw = false);
__forceinline double Min() const { return m_min_value; }
//- Valor de cambio
void ChangeValue(double new_value, bool redraw = false);
__forceinline double ChangeValue() const { return m_change_value; }
__forceinline bool ChangeValueEnable() const { return m_use_change_value; }
//- Setear max, min, y chanbge_value opcional
void SetNewValues(double max, double min, double change_value, bool redraw = false);
//--- Cordenadas y tama<EFBFBD>o
//- X
virtual void X(int new_value, bool redraw = false) = 0;
__forceinline int X() const { return m_x; }
//- Y
virtual void Y(int new_value, bool redraw = false) = 0;
__forceinline int Y() const { return m_y; }
//- LineSize
virtual void LineSize(int new_value, bool redraw = false) = 0;
__forceinline int LineSize() const { return m_size_line_sections; }
//- Set cordenadas
virtual void SetCordinates(int x, int y, int line_size, bool redraw = false) = 0;
//---
__forceinline int ModeLine() const { return m_mode_line; }
//---
void CleanColor(uint new_value) { m_clr_clean = new_value;}
__forceinline uint CleanColor() const { return m_clr_clean; }
//---
CTextCanvas* TituloGetPointer() { return m_titulo;}
};
//+------------------------------------------------------------------+
//| Macros |
//+------------------------------------------------------------------+
#define HIST_EJE_IS_INIT_GENERAL ((m_init_flags&HIST_EJE_FLAG_INIT_GENERAL) != 0)
#define HIST_EJE_IS_INIT_SECTIONS ((m_init_flags&HIST_EJE_FLAG_INIT_LINE) != 0)
#define HIST_EJE_IS_INIT_TITULO ((m_init_flags&HIST_EJE_FLAG_INIT_TITULO) != 0)
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CHistogramEjeLine::CHistogramEjeLine()
: m_init_flags(0), m_titulo(NULL), m_canvas(NULL), m_use_change_value(false)
{
ArrayResize(m_secciones, 0);
m_function_val_to_str = DoubleToStrPrefix; // Funcion por defecto
}
//+------------------------------------------------------------------+
CHistogramEjeLine::~CHistogramEjeLine()
{
if(CheckPointer(m_titulo) == POINTER_DYNAMIC)
{
delete m_titulo;
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::Init(CCanvasCustom* c, int x, int y, int size_line, uint clr_line_and_text_line, int mode)
{
if(HIST_EJE_IS_INIT_GENERAL)
return;
//---
m_canvas = c;
m_init_flags |= HIST_EJE_FLAG_INIT_GENERAL;
m_size_line_sections = size_line;
m_x = x;
m_y = y;
m_clr = clr_line_and_text_line;
m_mode_line = mode;
//--- Seteamos alingement
OnInitialize();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::CreateSections(int inital_sections, double max_value, double min_value, bool use_change_val, double change_value,
int section_gap_value, int sections_size_px, int8_t decimals, int fontsize = 0, string font = NULL)
{
if(HIST_EJE_IS_INIT_SECTIONS)
return;
2025-10-14 10:58:09 -05:00
/*
Como siempre si el fontsize es 0 o font es null, se usa el de canvas, asi que si el usuario ya tiene en fontseteado en canvas (usa el de la clase CHistogram)
, peude dejar los parametros como esta, pero si quiere un font o fontsize cusotm para los ejes le da un valor
*/
2025-10-13 22:07:20 -05:00
//---
int is = inital_sections;
is += 1; // Agregamos el maximo
is += 1; // Agregamos al minimo
is += int(use_change_val); // Si use es true=1, se le sumara 1
//---
m_init_flags |= HIST_EJE_FLAG_INIT_LINE;
m_max_value = max_value;
m_min_value = min_value;
m_change_value = change_value;
m_sections_font = font != NULL ? font : m_canvas.FontNameGet();
m_sections_font_size = fontsize > 0 ? fontsize : m_canvas.FontSizeGet();
m_section_size_gap_value = section_gap_value;
m_sections_decimals = decimals;
m_use_change_value = use_change_val;
m_section_size_px = sections_size_px;
m_secciones_size = is;
ArrayResize(m_secciones, m_secciones_size);
//---
if(!use_change_val)
m_change_value = DBL_MAX; // Lo ponemos a un valor invalido
//---
RecalculeAndDrawSections();
//---
// int xmin = m_section_size_gap_value + m_sections_font_size;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::ChangeValue(double new_value, bool redraw = false)
{
//---
if(!m_use_change_value)
return;
//---
CleanPixelsSections();
//---
m_change_value = new_value;
//--- Dibujamos las secciones
RecalculeAndDrawSections(); // Secciones-Line
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::Min(double min, bool redraw = false)
{
//---
CleanPixelsSections();
//---
m_min_value = min;
//--- Dibujamos las secciones
RecalculeAndDrawSections(); // Secciones-Line
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::Max(double max, bool redraw = false)
{
//---
CleanPixelsSections();
//---
m_max_value = max;
//--- Dibujamos las secciones
RecalculeAndDrawSections(); // Secciones-Line
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::SetNewValues(double max, double min, double change_value, bool redraw = false)
{
//---
CleanPixelsSections();
//---
m_min_value = min;
m_max_value = max;
m_change_value = change_value;
//--- Dibujamos las secciones
RecalculeAndDrawSections(); // Secciones-Line
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::SectionsColor(uint new_clr, bool redraw = false)
{
//---
m_clr = new_clr;
//---
RedrawSections();
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::SectionsSize(int new_value, bool redraw = false)
{
//---
if(new_value < 0)
return;
//---
int nv = new_value + 2 + int(m_use_change_value); // se le suma 2 del minimo y el maximo, ademas de 1 si es que se usa change_value
//---
CleanPixelsSections();
//---
m_secciones_size = nv;
ArrayResize(m_secciones, m_secciones_size);
//--- Dibujamos las secciones
RecalculeAndDrawSections(); // Secciones-Line
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::SectionsFont(const string &new_value, bool redraw = false)
{
//---
CleanPixelsSections(); // Limpieza previa
//---
m_sections_font = new_value;
//--- Dibujamos las secciones
RecalculeAndDrawSections(); // Secciones-Line
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::SectionsFontSize(int new_value, bool redraw = false)
{
//---
CleanPixelsSections(); // Limpieza previa
//---
m_sections_font_size = new_value;
//--- Dibujamos las secciones
RecalculeAndDrawSections(); // Secciones-Line
// Cuidado un fontsize mas grande haria que el titulo se dezplaze myucho, hacinedo que posibledmne desapareza
TituloActulize();
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::SectionsUniqueSizeInPixels(int new_value, bool redraw = false)
{
//---
CleanPixelsSections(); // Limpieza previa
//---
m_section_size_px = new_value;
//--- Dibujamos las secciones
// Cuidado un ancho mas grande haria que el titulo se dezplaze myucho, hacinedo que posibledmne desapareza
RecalculeAndDrawSections(); // Secciones-Line
TituloActulize();
//---
if(redraw)
m_canvas.Update();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine::SectionsFormatStrFunction(HistFunctionFormatDouble new_function, bool redraw = false)
{
//---
CleanPixelsSections();
//---
m_function_val_to_str = new_function;
//---
// Cuidado con el titulo un texto mas gradne podira hacer colisiones, esto se podria ajustar auto auqnue es mas responsabidliad del usuario
OnNewFunctionFormat();
//---
if(redraw)
m_canvas.Update();
}
#endif
//+------------------------------------------------------------------+