2026-08-31 20:45:03 -05:00
//+------------------------------------------------------------------+
//| 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 "..\\TextoCanvas.mqh"
# include "..\\..\\General\\LineSim\\HorLine.mqh"
# include "..\\..\\General\\LineSim\\VerticalLine.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
{
string str_val ;
double value ;
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 ;
} ;
//---
//--- 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
*/
//---
# define HISTOGRAM_EJE_LINE_FLAG_TEXT 1
# define HISTOGRAM_EJE_LINE_FLAG_LINE 2
# define HISTOGRAM_EJE_LINE_FLAG_SECTIONS 4
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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_line_clr ;
uint m_style ;
//--- Secciones
int m_secciones_size ;
HistogramEjeLineSection m_secciones [ ] ;
int m_section_size_px ; // Tamañ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 ;
int m_co2 ;
uint m_sections_alingment ;
int8_t m_sections_decimals ;
HistFunctionFormatDouble m_function_val_to_str ;
uint m_sections_clr ;
uint m_sections_text_clr ;
//--- Valores
double m_max_value ;
double m_min_value ;
double m_change_value ;
int m_idx_change_value ;
int m_idx_change_value_prev ;
// 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 OnNewFunctionFormat ( ) = 0 ;
virtual void OnInitialize ( ) = 0 ;
//--- Funciones necesarias
virtual void RecalcValuesSections ( ) = 0 ;
//---
void SetIndexChangeValueAndValues ( ) ;
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 , int mode , int co2 , uint style ) ;
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 , uint clr_sections , uint clr_text_setions , HistFunctionFormatDouble func_txt = NULL
, 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 CleanPx ( const uint8_t flags ) = 0 ;
//---
virtual void RedrawPx ( const uint8_t flags ) = 0 ;
//--- Secciones
//- Funcion de formateo
void SectionsFormatStrFunction ( HistFunctionFormatDouble new_function , bool redraw = false ) ;
__forceinline HistFunctionFormatDouble SectionsFormatStrFunction ( ) const { return m_function_val_to_str ; }
//- Tamaño de cada "line" de valor
void SectionsUniqueSizeInPixels ( int new_value , bool redraw = false ) ;
__forceinline int SectionsUniqueSizeInPixels ( ) const { return m_section_size_px ; }
//- 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_sections_clr ; }
//- Estilo de linea
void SectionsStyle ( uint new_style , bool redraw = false ) ;
__forceinline uint SectionsStyle ( ) const { return m_style ; }
//- 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 ) ;
//- Texto
// Fontsize de los textos de la linea del eje
void SectionsTextFontSize ( int new_value , bool redraw = false ) ;
__forceinline int SectionsTextFontSize ( ) const { return m_sections_font_size ; }
// Font de los textos de la linea de eje
void SectionsTextFont ( const string & new_value , bool redraw = false ) ;
__forceinline string SectionsTextFont ( ) const { return m_sections_font ; }
// Color
void SectionsTextColor ( uint new_value , bool redraw = false ) ;
__forceinline uint SectionsTextColor ( ) const { return m_sections_clr ; }
//--- Linea
//- 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 ;
//- Modo
__forceinline int ModeLine ( ) const { return m_mode_line ; }
//- Color
void LineColor ( uint new_clr , bool redraw = false ) ;
__forceinline uint LineColor ( ) const { return m_line_clr ; }
//---
void CleanColor ( uint new_value ) { m_clr_clean = new_value ; }
__forceinline uint CleanColor ( ) const { return m_clr_clean ; }
//---
__forceinline bool HasCo2 ( ) const { return m_co2 > 0 ; }
//---
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 ) , m_co2 ( 0 ) , m_style ( STYLE_SOLID ) , m_idx_change_value ( -1 ) , m_idx_change_value_prev ( -1 ) ,
m_function_val_to_str ( NULL )
{
ArrayResize ( m_secciones , 0 ) ;
}
//+------------------------------------------------------------------+
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 , int mode , int co2 , uint style )
{
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_style = style ;
m_line_clr = clr_line ;
m_mode_line = mode ;
//---
if ( co2 > 1 )
m_co2 = co2 - 1 ;
//--- 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 , uint clr_sections , uint clr_text_setions , HistFunctionFormatDouble func_txt = NULL
, int fontsize = 0 , string font = NULL )
{
if ( HIST_EJE_IS_INIT_SECTIONS )
return ;
/*
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
*/
//---
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_sections_clr = clr_sections ;
m_sections_text_clr = clr_text_setions ;
//---
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 ;
// CAST expkicito (bug en la 6090) antes: m_function_val_to_str = func_txt == NULL ? DoubleToStrPrefix : func_txt
m_function_val_to_str = func_txt = = NULL ? ( HistFunctionFormatDouble ) DoubleToStrPrefix : func_txt ;
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 ;
//---
m_change_value = new_value ;
//--- Dibujamos las secciones
RecalcValuesSections ( ) ;
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
void CHistogramEjeLine : : Min ( double min , bool redraw = false )
{
//---
m_min_value = min ;
//--- Dibujamos las secciones
RecalcValuesSections ( ) ;
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
void CHistogramEjeLine : : Max ( double max , bool redraw = false )
{
//---
m_max_value = max ;
//--- Dibujamos las secciones
RecalcValuesSections ( ) ;
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
void CHistogramEjeLine : : SetNewValues ( double max , double min , double change_value , bool redraw = false )
{
//---
m_min_value = min ;
m_max_value = max ;
m_change_value = change_value ;
//--- Dibujamos las secciones
RecalcValuesSections ( ) ;
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine : : SectionsColor ( uint new_clr , bool redraw = false )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_SECTIONS ) ;
//---
m_sections_clr = new_clr ;
//---
RedrawPx ( HISTOGRAM_EJE_LINE_FLAG_SECTIONS ) ;
//---
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
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_SECTIONS | HISTOGRAM_EJE_LINE_FLAG_TEXT ) ;
//---
m_secciones_size = nv ;
ArrayResize ( m_secciones , m_secciones_size ) ;
//--- Dibujamos las secciones
RecalculeAndDrawSections ( ) ; // Secciones-Line
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
void CHistogramEjeLine : : SectionsUniqueSizeInPixels ( int new_value , bool redraw = false )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_SECTIONS | HISTOGRAM_EJE_LINE_FLAG_TEXT ) ;
//---
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 )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_TEXT ) ;
//---
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 ( ) ;
}
//+------------------------------------------------------------------+
void CHistogramEjeLine : : SectionsStyle ( uint new_style , bool redraw = false )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_SECTIONS ) ;
//---
m_style = new_style ;
//---
RedrawPx ( HISTOGRAM_EJE_LINE_FLAG_SECTIONS ) ;
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine : : SectionsTextFont ( const string & new_value , bool redraw = false )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_TEXT ) ; // Limpieza previa
//---
m_sections_font = new_value ;
//--- Dibujamos las secciones
RedrawPx ( HISTOGRAM_EJE_LINE_FLAG_TEXT ) ; // Secciones-Line
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
void CHistogramEjeLine : : SectionsTextFontSize ( int new_value , bool redraw = false )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_TEXT ) ; // Limpieza previaa
//---
m_sections_font_size = new_value ;
//--- Dibujamos las secciones
RedrawPx ( HISTOGRAM_EJE_LINE_FLAG_TEXT ) ; // 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 : : SectionsTextColor ( uint new_value , bool redraw = false )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_TEXT ) ; // Limpieza previa
//---
m_sections_clr = new_value ;
//--- Dibujamos las secciones
RedrawPx ( HISTOGRAM_EJE_LINE_FLAG_TEXT ) ; // Secciones-Line
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine : : LineColor ( uint new_clr , bool redraw = false )
{
//---
CleanPx ( HISTOGRAM_EJE_LINE_FLAG_LINE ) ;
//---
m_line_clr = new_clr ;
//---
RedrawPx ( HISTOGRAM_EJE_LINE_FLAG_LINE ) ;
//---
if ( redraw )
m_canvas . Update ( ) ;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CHistogramEjeLine : : SetIndexChangeValueAndValues ( void )
{
//---
m_idx_change_value_prev = m_idx_change_value ;
m_idx_change_value = -1 ;
//---
const double v_step = ( m_max_value - m_min_value ) / double ( m_secciones_size - 1 ) ;
double v = m_min_value ; // Siguiente valor
//---
for ( int i = 0 ; i < m_secciones_size ; i + + )
{
//--- Valores de la seccion
if ( m_idx_change_value = = -1 & & v > = m_change_value ) // Si c es falso y se uspero el change value forzamos
{
m_idx_change_value = i ;
m_secciones [ i ] . value = m_change_value ;
}
else
m_secciones [ i ] . value = v ;
//--- Siguiente valor
v + = v_step ;
}
}
# endif
//+------------------------------------------------------------------+