//+------------------------------------------------------------------+ //| Horizontal.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 HISTOGRAM_BARRA_HORIZONTAL_BY_LEO_MQH #define HISTOGRAM_BARRA_HORIZONTAL_BY_LEO_MQH //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "Base.mqh" /* Estructura de la barra: 0 --------- X ------------- | | | x1 x2 | y2 y2 | _____ | | | | | Valores Positivos fpos (si aplica) Y | | ______ | | | | | | Valores negativos fneg (si aplica) | |____| | | x1 x2 | y1 y1 | | IX1 | IY1 | //--- IX1 = x1 inicial = m_barras_x1_init IY1 = y1 inicial = m_barras_y1_init */ //+------------------------------------------------------------------+ //| CLase con valores nroameles | //+------------------------------------------------------------------+ class CHistogramConjuntoHorizontal : public CHistogramConjuntoNor { private: void RecalculeBarCordinates() override; void OnBarrasResize() override; void ResizeBarra(HistogramBar& barra) override; void OnNewValuesPosNegCorte() override; void CalculeTextCordinates() override final; }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramConjuntoHorizontal::CalculeTextCordinates() { m_label_function(m_barras_x1_init, (m_barras_x1_init + m_barras_ancho_total), m_barras_y1_init + m_label_gap_by_eje, (m_barras_y1_init + m_label.font_size + 1) , m_label.x, m_label.y); ::TextSetFont(m_label.font, m_label.font_size); m_canvas.TextOuTF(m_label.x, m_label.y, m_label.value, m_label.clr, m_label.mode); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramConjuntoHorizontal::ResizeBarra(HistogramBar& barra) { const int h_prev = barra.y1 - barra.y2; const int h = HISTOGRAM_CONJ_VALUE_TO_PIXEL(barra.value); if(h < 0 && h_prev >= 0) barra.y1 += 2; // Reduce las cordenas else if(h >= 0 && h_prev < 0) barra.y1 -= 2; barra.y2 = barra.y1 - h; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramConjuntoHorizontal::OnBarrasResize() { int x = m_barras_x1_init; for(int i = 0; i < m_barras_size; i++) { m_barras[i].x1 = x; x += m_barras_ancho_unico; m_barras[i].x2 = x; m_function_draw_rect(m_canvas, m_barras[i].x1, m_barras[i].y1, m_barras[i].x2, m_barras[i].y2, m_barras[i].clr); x += 1; // Siguiente inciio; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramConjuntoHorizontal::RecalculeBarCordinates() { int x = m_barras_x1_init; // Restamos 1 para no cubrir el espacio de la liena // Por defecto positivo luego lo cambiamos de signo const int y = (m_barras_y1_init - m_barras_gap_eje) - 1; // Calculamos el eje del corte si (para positivo por defecto) int newy = 0; for(int i = 0; i < m_barras_size; i++) { const int h = HISTOGRAM_CONJ_VALUE_TO_PIXEL(m_barras[i].value); // Calculaos el height de la barra //--- newy = y; if(h < 0) // Este if solo se ejedcuta cuadno hay corte si no lo hay nunca se ejeuctara newy += 2; // Saltamos la cordenada de inicio pos y la de la linea corte //--- m_barras[i].x1 = x; x += m_barras_ancho_unico; m_barras[i].x2 = x; m_barras[i].y1 = newy; m_barras[i].y2 = newy - h; m_function_draw_rect(m_canvas, m_barras[i].x1, m_barras[i].y1, m_barras[i].x2, m_barras[i].y2, m_barras[i].clr); x += 1; // Siguiente inciio; } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CHistogramConjuntoHorizontal::OnNewValuesPosNegCorte(void) { int x = m_barras_x1_init; // Restamos 1 para no cubrir el espacio de la liena // Por defecto positivo luego lo cambiamos de signo const int y = (m_barras_y1_init - m_barras_gap_eje) - 1; // Calculamos el eje del corte si (para positivo por defecto) int new_y = 0; for(int i = 0; i < m_barras_size; i++) { const int prev_h = m_barras[i].y1 - m_barras[i].y2; // Si este valor es pos entonces la barra es positiva const int h = HISTOGRAM_CONJ_VALUE_TO_PIXEL(m_barras[i].value); // Calculaos el height de la barra //const bool pos = prev_h >= 0 && h >= 0; //--- new_y = y; if(h < 0) // Este if solo se ejedcuta cuadno hay corte si no lo hay nunca se ejeuctara new_y += 2; // Saltamos la cordenada de inicio pos y la de la linea corte //--- // Caso1: Cambio de posicion limpiamos; pos a neg // Caso2: Cambio de posicion limpiamos: neg a pos // Caso3: Valor positivo, pero height menor // Caso4: Valor negativo, pero height menor //PrintFormat("[%d] prev h = %d | h = %d", i, prev_h, h); // if((prev_h >= 0 && h < 0) || (prev_h < 0 && h >= 0) || (pos && prev_h > h) || (!pos && h > prev_h)) // Limpiamos m_function_draw_rect(m_canvas, m_barras[i].x1, m_barras[i].y1, m_barras[i].x2, m_barras[i].y2, m_clean_color); //--- m_barras[i].x1 = x; x += m_barras_ancho_unico; m_barras[i].x2 = x; m_barras[i].y1 = new_y; m_barras[i].y2 = new_y - h; m_function_draw_rect(m_canvas, m_barras[i].x1, m_barras[i].y1, m_barras[i].x2, m_barras[i].y2, m_barras[i].clr); x += 1; // Siguiente inciio; } } #endif //+------------------------------------------------------------------+