//+------------------------------------------------------------------+ //| 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; }; //--- //--- 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ñ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ñ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ñ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; /* 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_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 //+------------------------------------------------------------------+