//+------------------------------------------------------------------+ //| Ver.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_VER_MQH_BY_LEO #define GRAPHICS_HISTOGRAM_EJE_EJES_VER_MQH_BY_LEO #include "Ejes.mqh" #define HIST_LINE_MODE_ARRIBA 1 #define HIST_LINE_MODE_ABAJO 0 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CHistogramEjeLineVertical : public CHistogramEjeLine { protected: void TituloActulize() override; void RecalculeAndDrawSections() override; void OnNewFunctionFormat() override; void OnInitialize() override; void RecalcValuesSections() override; public: void CreateTitulo(const string &txt, uint clr, int gap_titulo, int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX) override; //--- void CleanPx(const uint8_t flags) override; void RedrawPx(const uint8_t flags) 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 CHistogramEjeLineVertical::OnInitialize(void) { //--- m_c2 = m_x + m_size_line_sections; //--- if(m_mode_line == HIST_LINE_MODE_ARRIBA) { m_sections_alingment = TA_CENTER | TA_BOTTOM; if(m_co2 > 0) m_co2 = m_co2 - m_y; } else // 0 { m_sections_alingment = TA_CENTER | TA_TOP; if(m_co2 > 0) m_co2 = m_y - m_co2; } //--- m_canvas.LineHorizontal(m_x, m_c2, m_y, m_line_clr); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::LineSize(int new_value, bool redraw = false) { //--- Limpiamos la linea CleanPx(HISTOGRAM_EJE_LINE_FLAG_LINE | HISTOGRAM_EJE_LINE_FLAG_SECTIONS | HISTOGRAM_EJE_LINE_FLAG_TEXT); //--- m_size_line_sections = new_value; m_c2 = m_x + new_value; //--- Dibujamos las secciones RecalculeAndDrawSections(); // Secciones-Line TituloActulize(); // Titulo //--- if(redraw) m_canvas.Update(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::X(int new_value, bool redraw = false) { //--- CleanPx(HISTOGRAM_EJE_LINE_FLAG_LINE | HISTOGRAM_EJE_LINE_FLAG_SECTIONS | HISTOGRAM_EJE_LINE_FLAG_TEXT); //--- m_x = new_value; m_c2 = m_x + m_size_line_sections; //--- Dibujamos las secciones RedrawPx(HISTOGRAM_EJE_LINE_FLAG_LINE); // Linea RecalculeAndDrawSections(); // Secciones-Line TituloActulize(); // Titulo //--- if(redraw) m_canvas.Update(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::Y(int new_value, bool redraw = false) { //--- CleanPx(HISTOGRAM_EJE_LINE_FLAG_LINE | HISTOGRAM_EJE_LINE_FLAG_SECTIONS | HISTOGRAM_EJE_LINE_FLAG_TEXT); //--- m_y = new_value; //--- Dibujamos las secciones RedrawPx(HISTOGRAM_EJE_LINE_FLAG_LINE); // Linea RecalculeAndDrawSections(); // Secciones-Line TituloActulize(); // Titulo //--- if(redraw) m_canvas.Update(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::SetCordinates(int x, int y, int line_size, bool redraw = false) { //--- Limpiamos la linea CleanPx(HISTOGRAM_EJE_LINE_FLAG_LINE | HISTOGRAM_EJE_LINE_FLAG_SECTIONS | HISTOGRAM_EJE_LINE_FLAG_TEXT); //--- m_x = x; m_y = y; m_size_line_sections = line_size; m_c2 = m_x + line_size; //--- Dibujamos las secciones RedrawPx(HISTOGRAM_EJE_LINE_FLAG_LINE); // Linea RecalculeAndDrawSections(); // Secciones-Line TituloActulize(); // Titulo //--- if(redraw) m_canvas.Update(); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::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(); if(m_mode_line == HIST_LINE_MODE_ARRIBA) { int y = m_y - m_section_size_px - m_section_size_gap_value - m_sections_font_size - m_titulo_gap_px; int x = m_x + (m_size_line_sections >> 1); m_titulo.Create(m_canvas, x, y, txt, clr, m_sections_alingment, fontsize, font, flagtext, 0); } else { int y = m_y + m_section_size_px + m_section_size_gap_value + m_sections_font_size + m_titulo_gap_px; int x = m_x + (m_size_line_sections >> 1); m_titulo.Create(m_canvas, x, y, txt, clr, m_sections_alingment, fontsize, font, flagtext, 0); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::TituloActulize() { if(!HIST_EJE_IS_INIT_TITULO) return; // SI el titulo no esta seteado enotnces retornamos if(m_mode_line == HIST_LINE_MODE_ARRIBA) { int y = m_y - m_section_size_px - m_section_size_gap_value - m_sections_font_size - m_titulo_gap_px; int x = m_x + (m_size_line_sections >> 1); m_titulo.ChangeYAndX(x, y); } else { int y = m_y + m_section_size_px + m_section_size_gap_value + m_sections_font_size + m_titulo_gap_px; int x = m_x + (m_size_line_sections >> 1); m_titulo.ChangeYAndX(x, y); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::RecalcValuesSections(void) { //--- const int lasti = m_secciones_size - 1; double ran = (m_max_value - m_min_value); double v_step = ran / double(lasti); double v = m_min_value; // Siguiente valor //--- Line horizontal (1 = izquierda : 0 = derecha) ::TextSetFont(m_sections_font, m_sections_font_size); m_canvas.LineStyleSet(m_style); // De izquierda (menor valor) hacia derecha (mayor valor) const bool esarriba = m_mode_line == HIST_LINE_MODE_ARRIBA; //--- if(m_use_change_value) { //--- #define EsValorDeCambioONoDibj(fi) (fi==0 || fi==lasti || fi==m_idx_change_value) //--- const double x_percentages_step = 1.00 / double(lasti); // obtenemos el %decimal que le toca a cada seccion double x_next_per = 0.00; // SIeuiguente porcenrge //--- const double range_min = m_change_value - m_min_value; const double corte_x_perce = range_min / ran; const int x_corte = m_x + int(corte_x_perce * fabs(m_c2 - m_x)); // Cordenada de anclaje // init = x // c1 = y1 // c2 = y2 m_idx_change_value = -1; for(int i = 0; i < m_secciones_size; i++) { //--- m_canvas.LineAA(m_secciones[i].init, m_secciones[i].c1, m_secciones[i].init, m_secciones[i].c2, m_clr_clean); m_canvas.TextOuTF(m_secciones[i].init, m_secciones[i].c_text, m_secciones[i].str_val, m_clr_clean, m_sections_alingment); //--- const int x = m_x + int(round(m_size_line_sections * x_next_per)); //--- 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_secciones[i].value = m_change_value; m_secciones[i].init = x_corte; m_idx_change_value = i; } else { m_secciones[i].value = v; m_secciones[i].init = x; } m_secciones[i].str_val = m_function_val_to_str(m_secciones[i].value, m_sections_decimals); //--- Modo // c_text = y_text /* y1 c1 | | | | y2 c2 */ if(esarriba) { m_secciones[i].c2 = m_y + (EsValorDeCambioONoDibj(i) ? 0 : m_co2); m_secciones[i].c1 = m_y - m_section_size_px; m_secciones[i].c_text = m_secciones[i].c1 - m_section_size_gap_value; } else { m_secciones[i].c1 = m_y - (EsValorDeCambioONoDibj(i) ? 0 : m_co2); m_secciones[i].c2 = m_y + 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].init, m_secciones[i].c_text, m_secciones[i].str_val, m_sections_text_clr, m_sections_alingment); //--- Next x_next_per += x_percentages_step; v += v_step; } #undef EsValorDeCambioONoDibj } 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++) { //--- //m_canvas.LineAA(m_secciones[i].init, m_secciones[i].c1, m_secciones[i].init, m_secciones[i].c2, m_clr_clean); m_canvas.TextOuTF(m_secciones[i].init, m_secciones[i].c_text, m_secciones[i].str_val, m_clr_clean, m_sections_alingment); //--- m_secciones[i].value = v; m_secciones[i].str_val = m_function_val_to_str(m_secciones[i].value, m_sections_decimals); //--- Dibujamos m_canvas.TextOuTF(m_secciones[i].init, m_secciones[i].c_text, m_secciones[i].str_val, m_sections_text_clr, m_sections_alingment); //--- Next v += v_step; } } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::RecalculeAndDrawSections(void) { //--- const int lasti = m_secciones_size - 1; const double x_percentages_step = 1.00 / double(lasti); // obtenemos el %decimal que le toca a cada seccion double x_next_per = 0.00; // SIeuiguente porcenrge double ran = (m_max_value - m_min_value); double v_step = ran / double(lasti); double v = m_min_value; // Siguiente valor //--- Line horizontal (1 = izquierda : 0 = derecha) ::TextSetFont(m_sections_font, m_sections_font_size); m_canvas.LineStyleSet(m_style); // De izquierda (menor valor) hacia derecha (mayor valor) const bool esarriba = m_mode_line == HIST_LINE_MODE_ARRIBA; //--- if(m_use_change_value) { //--- #define EsValorDeCambioONoDibj(fi) (fi==0 || fi==lasti || fi==m_idx_change_value) //--- const double range_min = m_change_value - m_min_value; const double corte_x_perce = range_min / ran; const int x_corte = m_x + int(corte_x_perce * fabs(m_c2 - m_x)); // Cordenada de anclaje // init = x // c1 = y1 // c2 = y2 m_idx_change_value = -1; for(int i = 0; i < m_secciones_size; i++) { const int x = m_x + int(round(m_size_line_sections * x_next_per)); //--- 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_secciones[i].value = m_change_value; m_secciones[i].init = x_corte; m_idx_change_value = i; } else { m_secciones[i].value = v; m_secciones[i].init = x; } m_secciones[i].str_val = m_function_val_to_str(m_secciones[i].value, m_sections_decimals); //--- Modo // c_text = y_text /* y1 c1 | | | | y2 c2 */ if(esarriba) { m_secciones[i].c2 = m_y + (EsValorDeCambioONoDibj(i) ? 0 : m_co2); m_secciones[i].c1 = m_y - m_section_size_px; m_secciones[i].c_text = m_secciones[i].c1 - m_section_size_gap_value; } else { m_secciones[i].c1 = m_y - (EsValorDeCambioONoDibj(i) ? 0 : m_co2); m_secciones[i].c2 = m_y + 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].init, m_secciones[i].c_text, m_secciones[i].str_val, m_sections_text_clr, m_sections_alingment); m_canvas.LineAA(m_secciones[i].init, m_secciones[i].c1, m_secciones[i].init, m_secciones[i].c2, m_sections_clr); //--- Next x_next_per += x_percentages_step; v += v_step; } #undef EsValorDeCambioONoDibj } else { #define EsValorDeCambioONoDibj(fi) (fi==lasti||fi==0) // 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 x = m_x + int(round(m_size_line_sections * x_next_per)); //--- Valores de la seccion m_secciones[i].value = v; m_secciones[i].init = x; m_secciones[i].str_val = m_function_val_to_str(m_secciones[i].value, m_sections_decimals); //--- Modo if(esarriba) { m_secciones[i].c2 = m_y + (EsValorDeCambioONoDibj(i) ? 0 : m_co2); m_secciones[i].c1 = m_y - m_section_size_px; m_secciones[i].c_text = m_secciones[i].c1 - m_section_size_gap_value; } else { m_secciones[i].c1 = m_y - (EsValorDeCambioONoDibj(i) ? 0 : m_co2); m_secciones[i].c2 = m_y + 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].init, m_secciones[i].c_text, m_secciones[i].str_val, m_sections_text_clr, m_sections_alingment); m_canvas.LineAA(m_secciones[i].init, m_secciones[i].c1, m_secciones[i].init, m_secciones[i].c2, m_sections_clr); //--- Next x_next_per += x_percentages_step; v += v_step; } } #undef EsValorDeCambioONoDibj } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::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].init, m_secciones[i].c_text, m_secciones[i].str_val, m_sections_text_clr, m_sections_alingment); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::RedrawPx(const uchar flags) { //--- if((flags & HISTOGRAM_EJE_LINE_FLAG_SECTIONS) != 0) { m_canvas.LineStyleSet(m_style); for(int i = 0; i < m_secciones_size; i++) m_canvas.LineAA(m_secciones[i].init, m_secciones[i].c1, m_secciones[i].init, m_secciones[i].c2, m_sections_clr); } //--- if((flags & HISTOGRAM_EJE_LINE_FLAG_TEXT) != 0) { ::TextSetFont(m_sections_font, m_sections_font_size); for(int i = 0; i < m_secciones_size; i++) m_canvas.TextOuTF(m_secciones[i].init, m_secciones[i].c_text, m_secciones[i].str_val, m_sections_text_clr, m_sections_alingment); } //--- if((flags & HISTOGRAM_EJE_LINE_FLAG_LINE) != 0) m_canvas.LineHorizontal(m_x, m_c2, m_y, m_line_clr); } //+------------------------------------------------------------------+ void CHistogramEjeLineVertical::CleanPx(const uchar flags) { //--- if((flags & HISTOGRAM_EJE_LINE_FLAG_SECTIONS) != 0) { m_canvas.LineStyleSet(m_style); for(int i = 0; i < m_secciones_size; i++) m_canvas.LineAA(m_secciones[i].init, m_secciones[i].c1, m_secciones[i].init, m_secciones[i].c2, m_clr_clean); } //--- if((flags & HISTOGRAM_EJE_LINE_FLAG_TEXT) != 0) { ::TextSetFont(m_sections_font, m_sections_font_size); for(int i = 0; i < m_secciones_size; i++) m_canvas.TextOuTF(m_secciones[i].init, m_secciones[i].c_text, m_secciones[i].str_val, m_clr_clean, m_sections_alingment); } //--- if((flags & HISTOGRAM_EJE_LINE_FLAG_LINE) != 0) m_canvas.LineHorizontal(m_x, m_c2, m_y, m_clr_clean); } //+------------------------------------------------------------------+ #endif //+------------------------------------------------------------------+