374 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			374 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
//+------------------------------------------------------------------+
 | 
						|
//|                                                          Hor.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_HOR_MQH_BY_LEO
 | 
						|
#define GRAPHICS_HISTOGRAM_EJE_EJES_HOR_MQH_BY_LEO
 | 
						|
 | 
						|
 | 
						|
#include "Ejes.mqh"
 | 
						|
 | 
						|
#define HIST_LINE_MODE_IZQUIERDA 1
 | 
						|
#define HIST_LINE_MODE_DERECHA 0
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
class CHistogramEjeLineHorizontal : public CHistogramEjeLine
 | 
						|
 {
 | 
						|
protected:
 | 
						|
  void               TituloActulize() override;
 | 
						|
  void               RecalculeAndDrawSections() override;
 | 
						|
  void               RedrawSections() override;
 | 
						|
  void               OnNewFunctionFormat() override;
 | 
						|
  void               OnInitialize() override;
 | 
						|
 | 
						|
public:
 | 
						|
  void               CleanPixelsSections() override;
 | 
						|
  void               CreateTitulo(const string &txt, uint clr, int gap_titulo, int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX) override;
 | 
						|
 | 
						|
  //--- Cordenadas y tamaño
 | 
						|
  //- X
 | 
						|
  void               X(int new_value, bool redraw = false) override;
 | 
						|
 | 
						|
  //- Y
 | 
						|
  void               Y(int new_value, bool redraw = false) override;
 | 
						|
 | 
						|
  //- LineSize
 | 
						|
  void               LineSize(int new_value, bool redraw = false) override;
 | 
						|
 | 
						|
  //
 | 
						|
  void               SetCordinates(int x, int y, int line_size, bool redraw = false) override;
 | 
						|
 };
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::OnInitialize(void)
 | 
						|
 {
 | 
						|
  m_c2 = m_y + m_size_line_sections;
 | 
						|
 | 
						|
  if(m_mode_line == HIST_LINE_MODE_IZQUIERDA)
 | 
						|
    m_sections_alingment = TA_RIGHT | TA_VCENTER;
 | 
						|
  else // 0
 | 
						|
    m_sections_alingment = TA_LEFT | TA_VCENTER;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::LineSize(int new_value, bool redraw = false)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  const bool reduce = new_value < m_size_line_sections;
 | 
						|
 | 
						|
//--- Limpiamos la linea
 | 
						|
  if(reduce) // SOlo limpiar si se reducio
 | 
						|
    CleanPixelsSections();
 | 
						|
 | 
						|
//---
 | 
						|
  m_size_line_sections = new_value;
 | 
						|
  m_c2 = m_y + new_value;
 | 
						|
 | 
						|
//--- Dibujamos las secciones
 | 
						|
  RecalculeAndDrawSections(); // Secciones-Line
 | 
						|
  TituloActulize(); // Titulo
 | 
						|
 | 
						|
//---
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::X(int new_value, bool redraw = false)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  CleanPixelsSections();
 | 
						|
 | 
						|
//---
 | 
						|
  m_x = new_value;
 | 
						|
 | 
						|
//--- Dibujamos las secciones
 | 
						|
  RecalculeAndDrawSections(); // Secciones-Line
 | 
						|
  TituloActulize(); // Titulo
 | 
						|
 | 
						|
//---
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::Y(int new_value, bool redraw = false)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  CleanPixelsSections();
 | 
						|
 | 
						|
//---
 | 
						|
  m_y = new_value;
 | 
						|
  m_c2 = m_y + m_size_line_sections;
 | 
						|
 | 
						|
//--- Dibujamos las secciones
 | 
						|
  RecalculeAndDrawSections(); // Secciones-Line
 | 
						|
  TituloActulize(); // Titulo
 | 
						|
 | 
						|
//---
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::SetCordinates(int x, int y, int line_size, bool redraw = false)
 | 
						|
 {
 | 
						|
//--- Limpiamos la linea
 | 
						|
  CleanPixelsSections();
 | 
						|
 | 
						|
//---
 | 
						|
  m_x = x;
 | 
						|
  m_y = y;
 | 
						|
  m_size_line_sections = line_size;
 | 
						|
  m_c2 = y + line_size;
 | 
						|
 | 
						|
//--- Dibujamos las secciones
 | 
						|
  RecalculeAndDrawSections(); // Secciones-Line
 | 
						|
  TituloActulize(); // Titulo
 | 
						|
 | 
						|
//---
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::CreateTitulo(const string &txt, uint clr, int gap_titulo, int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX)
 | 
						|
 {
 | 
						|
  if(HIST_EJE_IS_INIT_TITULO)
 | 
						|
    return;
 | 
						|
 | 
						|
//  (1 = izquierda : 0 = derecha)
 | 
						|
  m_init_flags |= HIST_EJE_FLAG_INIT_TITULO;
 | 
						|
  m_titulo = new CTextCanvas();
 | 
						|
  m_titulo_gap_px = gap_titulo;
 | 
						|
 | 
						|
  if(m_mode_line == HIST_LINE_MODE_IZQUIERDA)
 | 
						|
   {
 | 
						|
    int x = m_x - m_section_size_px - m_section_size_gap_value - m_sections_font_size - m_titulo_gap_px;
 | 
						|
    int y = m_y + (m_size_line_sections >> 1);
 | 
						|
    m_titulo.Create(m_canvas, x, y, txt, clr, TA_CENTER | TA_BOTTOM, fontsize, font, flagtext, 900);
 | 
						|
   }
 | 
						|
  else
 | 
						|
   {
 | 
						|
    int x = m_x + m_section_size_px + m_section_size_gap_value + m_sections_font_size + m_titulo_gap_px;
 | 
						|
    int y = m_y + (m_size_line_sections >> 1);
 | 
						|
    m_titulo.Create(m_canvas, x, y, txt, clr, TA_CENTER | TA_BOTTOM, fontsize, font, flagtext, 2700);
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::TituloActulize()
 | 
						|
 {
 | 
						|
  if(!HIST_EJE_IS_INIT_TITULO)
 | 
						|
    return; // SI el titulo no esta seteado enotnces retornamos
 | 
						|
 | 
						|
  if(m_mode_line == HIST_LINE_MODE_IZQUIERDA)
 | 
						|
   {
 | 
						|
    int x = m_x - m_section_size_px - m_section_size_gap_value - m_sections_font_size - m_titulo_gap_px;
 | 
						|
    int y = m_y + (m_size_line_sections >> 1);
 | 
						|
    m_titulo.ChangeYAndX(x, y);
 | 
						|
   }
 | 
						|
  else
 | 
						|
   {
 | 
						|
    int x = m_x + m_section_size_px + m_section_size_gap_value + m_sections_font_size + m_titulo_gap_px;
 | 
						|
    int y = m_y + (m_size_line_sections >> 1);
 | 
						|
    m_titulo.ChangeYAndX(x, y);
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::RecalculeAndDrawSections(void)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  const double y_percentages_step = 1.00 / double(m_secciones_size - 1); // obtenemos el %decimal que le toca a cada seccion
 | 
						|
  double y_next_per = 0.00; // SIeuiguente porcenrge
 | 
						|
 | 
						|
  double v_step = (m_max_value - m_min_value) / double(m_secciones_size - 1);
 | 
						|
  double v = m_min_value; // Siguiente valor
 | 
						|
 | 
						|
//---
 | 
						|
// m_x = x
 | 
						|
// m_y = y1;
 | 
						|
// m_c2 = y2
 | 
						|
  m_canvas.LineVertical(m_x, m_y, m_c2, m_clr);
 | 
						|
 | 
						|
//--- Line horizontal  (1 = izquierda : 0 = derecha)
 | 
						|
  ::TextSetFont(m_sections_font, m_sections_font_size);
 | 
						|
 | 
						|
// De abajo (menor valor) hacia arriba (mayor valor)
 | 
						|
  if(m_use_change_value)
 | 
						|
   {
 | 
						|
    const double range_min =  m_change_value - m_min_value;
 | 
						|
    const double corte_y_perce = range_min / (m_max_value - m_min_value);
 | 
						|
    const int y_corte = m_c2 - int(corte_y_perce * fabs(m_c2 - m_y)); // Cordenada de anclaje
 | 
						|
    // init = y
 | 
						|
    // c1 = x1
 | 
						|
    // c2 = x2
 | 
						|
 | 
						|
    bool c = false;
 | 
						|
    for(int i = 0; i < m_secciones_size; i++)
 | 
						|
     {
 | 
						|
      const int y =  m_c2 - int(round(m_size_line_sections * y_next_per));
 | 
						|
     // PrintFormat("i = %d |  ypercen = %.2f | value = %.2f", i, y_next_per, v);
 | 
						|
 | 
						|
      //--- Valores de la seccion
 | 
						|
      if(!c && v >= m_change_value) // Si c es falso y se uspero el change value forzamos
 | 
						|
       {
 | 
						|
        m_secciones[i].value = m_change_value;
 | 
						|
        m_secciones[i].init = y_corte;
 | 
						|
        c = true;
 | 
						|
       }
 | 
						|
      else
 | 
						|
       {
 | 
						|
        m_secciones[i].value = v;
 | 
						|
        m_secciones[i].init = y;
 | 
						|
       }
 | 
						|
 | 
						|
      //---
 | 
						|
      m_secciones[i].str_val = m_function_val_to_str(m_secciones[i].value, m_sections_decimals);
 | 
						|
 | 
						|
      //--- Modo
 | 
						|
      // c_text =  x_text
 | 
						|
      /*
 | 
						|
      x1 ----------  x2
 | 
						|
      */
 | 
						|
      if(m_mode_line == HIST_LINE_MODE_IZQUIERDA)
 | 
						|
       {
 | 
						|
        m_secciones[i].c2 = m_x;
 | 
						|
        m_secciones[i].c1 = m_x - m_section_size_px;
 | 
						|
        m_secciones[i].c_text = m_secciones[i].c1 - m_section_size_gap_value;
 | 
						|
       }
 | 
						|
      else
 | 
						|
       {
 | 
						|
        m_secciones[i].c1 = m_x;
 | 
						|
        m_secciones[i].c2 = m_x + m_section_size_px;
 | 
						|
        m_secciones[i].c_text = m_secciones[i].c2 + m_section_size_gap_value;
 | 
						|
       }
 | 
						|
 | 
						|
      //--- Dibujamos
 | 
						|
      m_canvas.TextOuTF(m_secciones[i].c_text, m_secciones[i].init, m_secciones[i].str_val, m_clr, m_sections_alingment);
 | 
						|
      m_canvas.LineHorizontal(m_secciones[i].c1, m_secciones[i].c2, m_secciones[i].init, m_clr);
 | 
						|
 | 
						|
      //--- Next
 | 
						|
      y_next_per += y_percentages_step;
 | 
						|
      v += v_step;
 | 
						|
     }
 | 
						|
   }
 | 
						|
  else
 | 
						|
   {
 | 
						|
    // Duplicaremos el coidog pero la idera es maximoar optimizacion ahcer un terminarioc a cada iteracion talvez no sea lo mejor
 | 
						|
    for(int i = 0; i < m_secciones_size; i++)
 | 
						|
     {
 | 
						|
      const int y =  m_c2 -  int(round(m_size_line_sections * y_next_per));
 | 
						|
 | 
						|
      //--- Valores de la seccion
 | 
						|
      m_secciones[i].value =  v;
 | 
						|
      m_secciones[i].init = y;
 | 
						|
      m_secciones[i].str_val = m_function_val_to_str(m_secciones[i].value, m_sections_decimals);
 | 
						|
 | 
						|
      //--- Modo
 | 
						|
      if(m_mode_line == HIST_LINE_MODE_IZQUIERDA)
 | 
						|
       {
 | 
						|
        m_secciones[i].c2 = m_x;
 | 
						|
        m_secciones[i].c1 = m_x - m_section_size_px;
 | 
						|
        m_secciones[i].c_text = m_secciones[i].c1 - m_section_size_gap_value;
 | 
						|
       }
 | 
						|
      else
 | 
						|
       {
 | 
						|
        m_secciones[i].c1 = m_x;
 | 
						|
        m_secciones[i].c2 = m_x + m_section_size_px;
 | 
						|
        m_secciones[i].c_text = m_secciones[i].c2 + m_section_size_gap_value;
 | 
						|
       }
 | 
						|
 | 
						|
      //--- Dibujamos
 | 
						|
      m_canvas.TextOuTF(m_secciones[i].c_text, m_secciones[i].init, m_secciones[i].str_val, m_clr, m_sections_alingment);
 | 
						|
      m_canvas.LineHorizontal(m_secciones[i].c1, m_secciones[i].c2, m_secciones[i].init, m_clr);
 | 
						|
 | 
						|
      //--- Next
 | 
						|
      y_next_per += y_percentages_step;
 | 
						|
      v += v_step;
 | 
						|
     }
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::RedrawSections(void)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  m_canvas.LineVertical(m_x, m_y, m_c2, m_clr);
 | 
						|
 | 
						|
//--- Line horizontal  (1 = izquierda : 0 = derecha)
 | 
						|
  ::TextSetFont(m_sections_font, m_sections_font_size);
 | 
						|
 | 
						|
//---
 | 
						|
  for(int i = 0; i < m_secciones_size; i++)
 | 
						|
   {
 | 
						|
    m_canvas.TextOuTF(m_secciones[i].c_text, m_secciones[i].init, m_secciones[i].str_val, m_clr, m_sections_alingment);
 | 
						|
    m_canvas.LineHorizontal(m_secciones[i].c1, m_secciones[i].c2, m_secciones[i].init, m_clr);
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::CleanPixelsSections(void)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  m_canvas.LineVertical(m_x, m_y, m_c2, m_clr_clean);
 | 
						|
 | 
						|
//--- Line horizontal  (1 = izquierda : 0 = derecha)
 | 
						|
  ::TextSetFont(m_sections_font, m_sections_font_size);
 | 
						|
 | 
						|
//--- De abajo (menor valor) hacia arriba (mayor valor)
 | 
						|
  for(int i = 0; i < m_secciones_size; i++)
 | 
						|
   {
 | 
						|
    m_canvas.TextOuTF(m_secciones[i].c_text, m_secciones[i].init, m_secciones[i].str_val, m_clr_clean, m_sections_alingment);
 | 
						|
    m_canvas.LineHorizontal(m_secciones[i].c1, m_secciones[i].c2, m_secciones[i].init, m_clr_clean);
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogramEjeLineHorizontal::OnNewFunctionFormat()
 | 
						|
 {
 | 
						|
//--- Line horizontal  (1 = izquierda : 0 = derecha)
 | 
						|
  ::TextSetFont(m_sections_font, m_sections_font_size);
 | 
						|
 | 
						|
//--- De abajo (menor valor) hacia arriba (mayor valor)
 | 
						|
  for(int i = 0; i < m_secciones_size; i++)
 | 
						|
   {
 | 
						|
    m_secciones[i].str_val = m_function_val_to_str(m_secciones[i].value, m_sections_decimals);
 | 
						|
    m_canvas.TextOuTF(m_secciones[i].c_text, m_secciones[i].init, m_secciones[i].str_val, m_clr, m_sections_alingment);
 | 
						|
    m_canvas.LineHorizontal(m_secciones[i].c1, m_secciones[i].c2, m_secciones[i].init, m_clr);
 | 
						|
   }
 | 
						|
 }
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
#endif
 | 
						|
//+------------------------------------------------------------------+
 |