1662 lines
		
	
	
	
		
			134 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
			
		
		
	
	
			1662 lines
		
	
	
	
		
			134 KiB
		
	
	
	
		
			MQL5
		
	
	
	
	
	
//+------------------------------------------------------------------+
 | 
						|
//|                                                         Base.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_FINAL_FILE_BASES_BY_LEO_MQH
 | 
						|
#define HISTOGRAM_FINAL_FILE_BASES_BY_LEO_MQH
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
#include "..\\..\\PartInf\\ParteInf.mqh"
 | 
						|
#include "LineCorte.mqh"
 | 
						|
#include "..\\Barra\\Barras.mqh"
 | 
						|
#include "Titulo.mqh"
 | 
						|
 | 
						|
//- Ejes de lineas (Estatico + Secciones)
 | 
						|
#include "..\\EjeHist\\Ver.mqh"
 | 
						|
#include "..\\EjeHist\\Hor.mqh"
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
// Esta funcion setea los valores del lienzo de dibujo se debera de llamar despues de llenar data y el titulo
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//---
 | 
						|
#define HIST_FLAG_INIT_TITULO 1
 | 
						|
#define HIST_FLAG_INIT_DATA 2
 | 
						|
#define HIST_FLAG_ALL_INIT (HIST_FLAG_INIT_TITULO | HIST_FLAG_INIT_DATA)
 | 
						|
 | 
						|
#define HIST_FLAG_INIT_CREATE_BITMAP 8
 | 
						|
#define HIST_FLAG_INIT_GENERAL 16
 | 
						|
 | 
						|
 | 
						|
#define HIST_FLAG_INIT_PART_INFO 4
 | 
						|
 | 
						|
 | 
						|
//---
 | 
						|
#define HISTOGRAM_DEBUG
 | 
						|
 | 
						|
//---
 | 
						|
/*
 | 
						|
Nota para los textos y Font...
 | 
						|
- El FontSet de canvas sera utiloizado mayormente por el usuario.. por jemeplo si el usuario quiere setear la fuenta debera
 | 
						|
de usar el fontset de histogram, (hay parametro donde la fuenta es invalida, lo que sifnica que se usara la fuente de canvas, de lo contario una cusotm)
 | 
						|
*/
 | 
						|
 | 
						|
enum ENUM_HIST_MODE_CORTE
 | 
						|
 {
 | 
						|
  HIST_CORTE_NOT_USE = 0,
 | 
						|
  HIST_CORTE_PERCENT = 1,
 | 
						|
  HIST_CORTE_VALUE = 2
 | 
						|
 };
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
class CHistogram : public CLoggerBase
 | 
						|
 {
 | 
						|
protected:
 | 
						|
  CCanvasCustom*     m_canvas; // Canvas
 | 
						|
  CColorGeneratorArgb    m_color_generator; // Generador de colores aleatorios
 | 
						|
  ENUM_HIST_MODE_CORTE m_corte_mode;
 | 
						|
 | 
						|
  //---
 | 
						|
  int                m_bars_size; // Numero de cojuntos de barras
 | 
						|
  CHistogramConjuntoNor* m_bars[]; // Conjunto de barras
 | 
						|
  CHistogramConjuntoNor* m_bar_max; // Barra con el valor maixmo de value
 | 
						|
  CHistogramConjuntoNor* m_bar_min; // Barra con el valor minimo de value
 | 
						|
 | 
						|
  //---
 | 
						|
  uint8_t             m_init_flags; // Bandera de incilizacion
 | 
						|
  ENUM_HISTOGAM_TYPE m_type; // Tipo de histograma
 | 
						|
 | 
						|
 | 
						|
  //--- Generales
 | 
						|
  long               m_chart_id; // Id del grafico
 | 
						|
  int                m_subwin; // Subventana
 | 
						|
  int                m_width; // Ancho total
 | 
						|
  int                m_height; // Alto total
 | 
						|
  string             m_obj_name; // Nombre del objeto (bitmap o bitmaplabel)
 | 
						|
  uint               m_back_color; // Color de fonndo
 | 
						|
 | 
						|
  //--- De la imagen
 | 
						|
  //- Conversiones y Corte
 | 
						|
  double             m_fr_max_value; // Valor maximo
 | 
						|
  double             m_fr_min_value; // Valor minimo
 | 
						|
  double             m_fr_change_value; // Valor de cambio
 | 
						|
  double             m_factor_conversion_value_to_pixel_pos; // Factor de conversion para valores positivos
 | 
						|
  double             m_factor_conversion_value_to_pixel_neg; // Factor de conversion para valores negativos
 | 
						|
  double             m_percent_corte_neg;  // Porcentaje de corte negativo
 | 
						|
  double             m_percent_corte_pos;  // Porcentaje de corte positivo
 | 
						|
  HistogramFuncionCalculatePixel  m_function_value_to_pixel; // Funcion para convertir valor a pixel
 | 
						|
  CHistogramLineCorteBase*  m_line_corte; // Linea de corte
 | 
						|
 | 
						|
  //- General
 | 
						|
  // Gaps del linezo de las barras
 | 
						|
  int                m_gap_superior;
 | 
						|
  int                m_gap_inferior;
 | 
						|
  int                m_gap_derecha;
 | 
						|
  int                m_gap_izquierda;
 | 
						|
 | 
						|
  //- Espacio dibujable de barras
 | 
						|
  int                m_barras_gap_init; // Gap inicial (lienzo)
 | 
						|
  int                m_barras_gap_end; // Gap final (lienzo)
 | 
						|
  int                m_barras_x1; // x1 inicial para barras (del lienzo sin contar gaps)
 | 
						|
  int                m_barras_y1; // y1 inicial para barras
 | 
						|
  int                m_barras_cordinate_init; // Contando el gap (cordenada de iinciio real)
 | 
						|
  int                m_barras_cordenanda_eje_corte; // Cordenanda eje de cambio
 | 
						|
  int                m_barras_espacio_dibujable_width; // Ancho disponible para las barras (ejex)
 | 
						|
  int                m_barras_espacio_dibujable_height; // Alto disonible para las barras (ejey)
 | 
						|
  int                m_barras_max_width;  // Maximo ancho total de las barras (sumando todas, sin gaps)
 | 
						|
  int                m_barras_max_height; // Maximo alto total de las barras  (sumando todas, sin gaps)
 | 
						|
  int                m_barras_espacio_entre; // Espacio entre barras
 | 
						|
  int                m_barras_min_width; // Minimo ancho
 | 
						|
 | 
						|
  //- Titulo
 | 
						|
  CHistogramTitulo*   m_titulo; // Titulo
 | 
						|
 | 
						|
  //- Parte informativa
 | 
						|
  ENUM_HISTOGRAM_PARTE_INFORMATIVA_POSICION m_part_info_position;
 | 
						|
  CHistogramParteInfo* m_part_info_ptr;
 | 
						|
 | 
						|
  //- Copyright
 | 
						|
  CTextCanvas*       m_copyright;
 | 
						|
 | 
						|
  //- Linea de eje
 | 
						|
  CHistogramEje*     m_eje;
 | 
						|
 | 
						|
  //--- Añadir valores
 | 
						|
  int                m_curr_index_bar_p; // Puntero actual en m_bars
 | 
						|
 | 
						|
 | 
						|
  //--- Funciones que debera de ser sobreescirtas
 | 
						|
  virtual void       RecalculeCordinatesBarsAndText() = 0; // Recalcula las cordenans de todos los conhjntos (barras y texto)
 | 
						|
  virtual void       OnNeweCordinatesBarsAndSize() = 0; // Recalcula las cordenans en un nuevo ancho  y x1 e y1 ()
 | 
						|
 | 
						|
  virtual void       OnSetLienzo() = 0; // Funcion que se ejeucta una vez seteada los parametros geneles
 | 
						|
  virtual void       OnBarraAdd(int index) = 0; // Funcion que se ejeucta cada vez qeu se agrega una nueva barra (ya iniciado)
 | 
						|
  virtual void       OnBarrDelete(double extra_value) = 0; // Funcion que se ejeucta cada vez que se elimina una barra (ya iniciado)
 | 
						|
  virtual void       OnMaxOrMinValueSuperate() = 0; // Funcion que se ejcuta para reclauclar los "anch9os" una vez superado el miaxmo o minimo
 | 
						|
 | 
						|
  virtual void       InitCordinates() = 0; // Inicializa todas las clases
 | 
						|
 | 
						|
  //--- De la clase
 | 
						|
  void               SetMaxMin();
 | 
						|
 | 
						|
  //--- Superacion de maximo o minimo
 | 
						|
  void               RecalculeFactorsMaxMinCortePer();
 | 
						|
  void               RecalculeFactorsMaxMinDef();
 | 
						|
  void               RecalculeFactorsMaxMinCorteVal();
 | 
						|
  void               RecalculeFactorsMaxMin();
 | 
						|
  void               OnAfterSetNewMaxMin();
 | 
						|
 | 
						|
private:
 | 
						|
  void               CleanVariables();
 | 
						|
 | 
						|
public:
 | 
						|
                     CHistogram(void);
 | 
						|
                    ~CHistogram(void);
 | 
						|
 | 
						|
 | 
						|
  //--- Creacion
 | 
						|
  // Inicializa la clase
 | 
						|
  void               Initialize(int width, int height, string objname, long chart_id, int subwin, uint back_color);
 | 
						|
 | 
						|
  // Crea un bitmap
 | 
						|
  inline void        CreateBitmap(datetime time, double price, ENUM_COLOR_FORMAT format);
 | 
						|
 | 
						|
  // Crea un bitmap lavel
 | 
						|
  inline void        CreateBitmapLabel(int x, int y, ENUM_COLOR_FORMAT format);
 | 
						|
 | 
						|
  //--- Limpeiza
 | 
						|
  void               Clean(); // LIMPIA TODO
 | 
						|
 | 
						|
  //---
 | 
						|
  CColorGeneratorArgb*   GetColorGeneratorPointer() { return &m_color_generator; }
 | 
						|
 | 
						|
  //--- Trabajo con las Conjuntos de barras
 | 
						|
  //-  Numero de barras
 | 
						|
  virtual void       NumConjuntoBars(int num_bars, int reserve_bars = 0) = 0;
 | 
						|
  inline int         NumConjuntoBars() const { return m_bars_size; }
 | 
						|
 | 
						|
  //- Ninimo ancho
 | 
						|
  __forceinline int  MinConjuntoAncho()        const { return m_barras_min_width;       }
 | 
						|
 | 
						|
  // Configura un minimo ancho para cada conjunto de barras y hace un resize automativo
 | 
						|
  // Se debera de ejecutar luego de llamar a SetLineizo, si es que sesea un minimo ancho
 | 
						|
  virtual void       MinConjuntoAncho(int new_value) = 0;
 | 
						|
 | 
						|
  //- Añadir barras
 | 
						|
  // Añade un nuevo conjunto de barras (iniico)
 | 
						|
  // Nota: el "indice de lectura: m_curr_index_bar_p" interno se mueve al ultimo elemento agregado automaticamente, dicho valor se retorna
 | 
						|
  virtual int        AddConjuntoBar(const string& label, uint label_clr, int label_fontsize, const string& label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode, int barras_de_reserva_,
 | 
						|
                                    int eje_gap, ENUM_HIST_DRAW_RECT_STYLE initial_style, double width = 0.00) = 0 ; // 0.00 = auto (0.00 - 1.00)
 | 
						|
 | 
						|
  __forceinline int  AddConjuntoBar(const string& label, int label_fontsize, const string& label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode, int barras_de_reserva_, int eje_gap
 | 
						|
                                    , ENUM_HIST_DRAW_RECT_STYLE initial_style, double width = 0.00);
 | 
						|
  __forceinline int  AddConjuntoBarDefault(const string& label, int label_fontsize, int barras_de_reserva_ = 0);
 | 
						|
 | 
						|
  void               AddConjuntoBarWithBins(const string& label, uint label_clr, int label_fontsize, const string& label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode,
 | 
						|
      int eje_gap, ENUM_HIST_DRAW_RECT_STYLE initial_style, double& data[], int bins, uint clr_barras);
 | 
						|
 | 
						|
  __forceinline void  AddConjuntoBarWithBinsDeft(const string& label, double& data[], int bins, uint clr_barras = 0);
 | 
						|
 | 
						|
  //-  Añade una barra a un conjunto
 | 
						|
  __forceinline void AddBarToConjuntoBarFast(double value, uint clr); // Añade una barra al conjunto de barras actual (puntero de lectura)
 | 
						|
  __forceinline void AddBarToConjuntoBar(double value, uint clr, bool update_data);
 | 
						|
 | 
						|
  //-  Setea un conjunto de barras (util si se predinifo el numero de cokunto con NumConjuntoBars)
 | 
						|
  // Dado que dicha funcion no lo setea, asi que debra de usar esta funcion
 | 
						|
  // Se debea de configurar el indice de lectura m_curr_index_bar_p
 | 
						|
  __forceinline void BarConjuntoSet(const string label, uint label_clr, int label_fontsize, const string &label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode, int eje_gap, ENUM_HIST_DRAW_RECT_STYLE initial_style,
 | 
						|
                                    double width = 0.00);
 | 
						|
  __forceinline void BarConjuntoSet(const string label, int label_fontsize, const string &label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode, int eje_gap, ENUM_HIST_DRAW_RECT_STYLE initial_style,
 | 
						|
                                    double width = 0.00); // Color aleatorio
 | 
						|
 | 
						|
  //- Setea la data de un conjunto por lote ()
 | 
						|
  // Requieuire indice
 | 
						|
  void               BarConjuntoSetBath(int index, const double& values[], const uint& colores[], bool redraw = false);
 | 
						|
 | 
						|
  // utiliza el indice interno
 | 
						|
  __forceinline void BarConjuntoSetBathCurrReadIndex(const double& values[], const uint& colores[], bool redraw = false) { BarConjuntoSetBath(m_curr_index_bar_p, values, colores, redraw);}
 | 
						|
 | 
						|
  //-  Eliminacion
 | 
						|
  // index = indice del conjunto de barras (m_bars) aquyi no se usa el putneor de lecutra (indice de lectura)
 | 
						|
 | 
						|
  void               RemoveConjuntoBar(int index, bool redraw = false);
 | 
						|
  __forceinline void RemoveConjuntoBar(string name, bool redraw = false);
 | 
						|
  __forceinline void RemoveConjuntoBarCurrReadIndex(bool redraw = false) { RemoveConjuntoBar(m_curr_index_bar_p, redraw); } // Utiliza el punteor de lecutra interno por defecto
 | 
						|
 | 
						|
  //-  Cambia el nombre de un conjunto
 | 
						|
  __forceinline void   BarConjuntoTextValue(string new_name, bool redraw = false); // Requiere tenmer establecido el indice de lecutra
 | 
						|
  __forceinline string BarConjuntoTextValue(int index)     const { return m_bars[index].TextValue(); } // Requiere indice no el punteor de lectura
 | 
						|
  __forceinline string BarConjuntoTextValueCurrReadIndex() const { return m_bars[m_curr_index_bar_p].TextValue(); } // No requiere nada, se accede atravez del indnice de lectura
 | 
						|
 | 
						|
  //- Ancho del conjunto
 | 
						|
  virtual void          ConjuntoBarWidth(int index, double new_value) = 0;
 | 
						|
  __forceinline double  ConjuntoBarWidth(int index)      const { return m_bars[index].ValueForAncho();               } //Requiere indice de lectura
 | 
						|
  __forceinline double  ConjuntoBarWidthCurrReadIndex()  const { return m_bars[m_curr_index_bar_p].ValueForAncho();  } // No requiere, auto, se utiliza el dincei por defcveto
 | 
						|
 | 
						|
  //- Estilo de dibujado
 | 
						|
  __forceinline void DrawRectStyleConjuntoBar(int index, ENUM_HIST_DRAW_RECT_STYLE style, bool update_pixles)  { m_bars[index].DrawRectStyle(style, update_pixles); }
 | 
						|
  __forceinline void DrawRectStyleConjuntoBarReadIndex(ENUM_HIST_DRAW_RECT_STYLE style, bool update_pixles)    { m_bars[m_curr_index_bar_p].DrawRectStyle(style, update_pixles); }
 | 
						|
  __forceinline void DrawRectStyleConjuntoBar(int index, HistFunctionDrawRect function, ENUM_HIST_DRAW_RECT_STYLE style, bool update_pixles) { m_bars[index].DrawRectStyle(function, style, update_pixles); }
 | 
						|
  __forceinline void DrawRectStyleConjuntoBarReadIndex(HistFunctionDrawRect function, ENUM_HIST_DRAW_RECT_STYLE style, bool update_pixles)  { m_bars[m_curr_index_bar_p].DrawRectStyle(function, style, update_pixles); }
 | 
						|
  __forceinline ENUM_HIST_DRAW_RECT_STYLE DrawRectStyleConjuntoBar(int index) const  { return m_bars[index].DrawRectStyle();              }
 | 
						|
  __forceinline ENUM_HIST_DRAW_RECT_STYLE DrawRectStyleConjuntoBarReadIndex() const  { return m_bars[m_curr_index_bar_p].DrawRectStyle(); }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
  //- Finaliza el add de barras a un conjunot (no es necesario si m_init es false, de lo contrario SI)
 | 
						|
  void               FinalizeAddConjunto(int index_fin, bool update_data, bool redraw = false);
 | 
						|
 | 
						|
  //-  Encontrar y retornar
 | 
						|
  inline int         FindIndexByBarConjuntoName(const string& name);
 | 
						|
 | 
						|
  //--- Puntero de lectura
 | 
						|
  // Funciones para cambiar el puntero de lectura interno (indice de lectura (conjunto bars) de m_bars)
 | 
						|
  // Obtiene el puntero/indice de lectura de m_bars
 | 
						|
  __forceinline int  ReadIndex() const                       { return (m_curr_index_bar_p);                                     }
 | 
						|
  __forceinline int  ReadIndex(const int conjunto_bar_index) { return (m_curr_index_bar_p = conjunto_bar_index);                }
 | 
						|
  __forceinline int  ReadIndex(const string& name)           { return (m_curr_index_bar_p = FindIndexByBarConjuntoName(name));  }
 | 
						|
  __forceinline int  ReadIndexFisrtConjunto()                { return (m_curr_index_bar_p = 0);                                 }
 | 
						|
  __forceinline int  ReadIndexLastConjunto()                 { return (m_curr_index_bar_p = m_bars_size - 1);                   }
 | 
						|
  __forceinline int  ReadIndexAument(int add_value = 1)      { return (m_curr_index_bar_p += add_value);                        }
 | 
						|
  __forceinline int  ReadIndexReduce(int reduce_value = 1)   { return (m_curr_index_bar_p -= reduce_value);                     }
 | 
						|
  __forceinline int  ReadIndexMiddle()                       { return (m_curr_index_bar_p = int(round(m_bars_size / 2)));       }
 | 
						|
 | 
						|
  //--- Trabajo con una barra espcifica de un conjunto de barras
 | 
						|
  // index: indice en el conjunto de barras NO de m_bars (este se setea con el indice interno)
 | 
						|
 | 
						|
  // Setea el color de una barra
 | 
						|
  __forceinline void BarColor(int index, uint new_clr, bool redraw = false);
 | 
						|
  __forceinline uint BarColor(int index) const { return m_bars[m_curr_index_bar_p].BarColor(index); }
 | 
						|
 | 
						|
  // Setea el valor de una barra
 | 
						|
  inline void          BarValue(int index, double new_value, bool redraw = false);
 | 
						|
  __forceinline double BarValue(int index) const { return m_bars[m_curr_index_bar_p].BarValue(index); }
 | 
						|
 | 
						|
  // Elimina una barra de un conjunto de barras
 | 
						|
  __forceinline void  RemoveBarFromConjuntoBar(int index_in_conjunto, bool redraw = false);
 | 
						|
 | 
						|
  // Tamaño
 | 
						|
  __forceinline int   SizeBarsOfConjunto() const { return m_bars[m_curr_index_bar_p].SizeBarras(); }
 | 
						|
 | 
						|
  //--- FontSet
 | 
						|
  __forceinline void FontSet(const string name, const int size, const uint flags, const uint angle) { m_canvas.FontSet(name, size, flags, angle);}
 | 
						|
 | 
						|
 | 
						|
  //--- Titulo
 | 
						|
  void               Titulo(const string &titulo, ENUM_HISTOGRAM_TITULO_POSICION posicion, int y_gap_titulo, uint aligement, int x, int y, uint clr,
 | 
						|
                            int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX, uint textpos = UINT_MAX);
 | 
						|
  void               TituloDefault(const string& titulo, int espacio_utilizado_por_el_titulo_y = 30);
 | 
						|
  CHistogramTitulo*  TituloGetPointer() { return m_titulo; }
 | 
						|
 | 
						|
 | 
						|
  //--- Copyright
 | 
						|
  CTextCanvas*       CopyrightGetPointer() { return m_copyright;}
 | 
						|
  void               CreateCopyright(int x, int y, string txt, uint clr, uint align, int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX, uint textpos = UINT_MAX);
 | 
						|
  void               CreateCopyrightDefault(const string& autor, string font = "Arial", int fontsize = 15);
 | 
						|
 | 
						|
  //--- Linea de eje y Estatica
 | 
						|
  virtual void       CreateEjeLine(int mode_position_line_sections, uint clr_line_Sections, uint clr_line_fixed, int initial_sections,
 | 
						|
                                   int section_gap_value, int sections_size_px, int8_t section_decimals, int section_fontsize = 0, string section_font = NULL) = 0;
 | 
						|
  CHistogramEje*     EjeLineGetPointer() { return m_eje;}
 | 
						|
 | 
						|
 | 
						|
  //--- Lienzo general
 | 
						|
  // Inciiliza el liezo sin valores de corte (defualt)
 | 
						|
  void               InitLienzoBarras(int x1, int y1, int x2, int y2, int gap_init, int gap_end, int gap_espacio_entre_barras);
 | 
						|
 | 
						|
  // Inciliza el lienzo con valores de corte (porcentajes)
 | 
						|
  void               InitLienzoBarras(int x1, int y1, int x2, int y2, int gap_init, int gap_end, int gap_espacio_entre_barras, double value_corte_neg, double value_corte_pos);
 | 
						|
 | 
						|
  // Inciiliza el liezo sin valores de corte  (valor)
 | 
						|
  void               InitLienzoBarras(int x1, int y1, int x2, int y2, int gap_init, int gap_end, int gap_espacio_entre_barras, double value_corte);
 | 
						|
 | 
						|
 | 
						|
  //--- Parte informativa - legenda
 | 
						|
  void               CreatePartInformativa(ENUM_HISTOGRAM_PARTE_INFORMATIVA_POSICION pos, int xgap_inicial, int ygap_inicial);
 | 
						|
  __forceinline CHistogramParteInfo* GetPartInfPointer() { return m_part_info_ptr; }
 | 
						|
 | 
						|
  //--- Linea de corte
 | 
						|
  CHistogramLineCorteBase* GetLineCortePtr() { return m_line_corte; } // Solo existe si es que hay corte si no no
 | 
						|
 | 
						|
 | 
						|
  //--- Redibujado
 | 
						|
  __forceinline void Redraw();
 | 
						|
 | 
						|
  //--- Guardar como imagen
 | 
						|
  bool               SavePicture(const string& filename, bool comon); // Guarda la imagen
 | 
						|
 | 
						|
  //--- Obteener array de pixeles
 | 
						|
  void               GetPixelsArray(uint& out_array_px[]) { m_canvas.GetPixelsArray(out_array_px); }
 | 
						|
 | 
						|
 | 
						|
  //--- Generales
 | 
						|
  __forceinline long        ChartId() const    { return m_chart_id;      }
 | 
						|
  __forceinline int         Subwin()  const    { return m_subwin;        }
 | 
						|
  __forceinline string      ObjName() const    { return m_obj_name;      }
 | 
						|
  __forceinline int         Width()   const    { return m_width;         }
 | 
						|
  __forceinline int         Height()  const    { return m_height;        }
 | 
						|
  __forceinline uint        BackColor() const  { return m_back_color;    }
 | 
						|
 | 
						|
 | 
						|
  //--- Inicilizacion
 | 
						|
  __forceinline bool IsInitTitulo()  const  { return (m_init_flags & HIST_FLAG_INIT_TITULO) != 0;         }
 | 
						|
  __forceinline bool IsInitBarras()  const  { return (m_init_flags & HIST_FLAG_INIT_DATA) != 0;           }
 | 
						|
  __forceinline bool IsInitPartInf() const  { return (m_init_flags & HIST_FLAG_INIT_PART_INFO) != 0;      }
 | 
						|
  __forceinline bool IsInitGeneral() const  { return (m_init_flags & HIST_FLAG_INIT_GENERAL) != 0;        }
 | 
						|
  __forceinline bool IsCreateObj()   const  { return (m_init_flags & HIST_FLAG_INIT_CREATE_BITMAP) != 0;  }
 | 
						|
 };
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Macros                                                           |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//---
 | 
						|
#define HISTOGRAM_VALUE_TO_PIXEL(value) m_function_value_to_pixel(value, m_fr_change_value, m_factor_conversion_value_to_pixel_pos, m_factor_conversion_value_to_pixel_neg)
 | 
						|
 | 
						|
//---
 | 
						|
#define HISTOGRAM_IS_INIT_TITULO      ((m_init_flags & HIST_FLAG_INIT_TITULO) != 0)
 | 
						|
#define HISTOGRAM_IS_INIT_DATA        ((m_init_flags & HIST_FLAG_INIT_DATA) != 0)
 | 
						|
#define HISTOGRAM_IS_INIT_INFORMATIVE ((m_init_flags & HIST_FLAG_INIT_PART_INFO) != 0)
 | 
						|
#define HISTOGRAM_IS_INIT_CREATE      ((m_init_flags & HIST_FLAG_INIT_CREATE_BITMAP) != 0)
 | 
						|
#define HISTOGRAM_IS_INIT_GENERAL     ((m_init_flags & HIST_FLAG_INIT_GENERAL) != 0)
 | 
						|
 | 
						|
 | 
						|
// nes = solo lo necesario, informativo es extra no hace falta
 | 
						|
#define HISTOGRAM_IS_INIT_NES         ((m_init_flags &  HIST_FLAG_ALL_INIT) == HIST_FLAG_ALL_INIT)
 | 
						|
 | 
						|
//---
 | 
						|
#define HISTOGRAM_IS_NOT_INIT_TITULO      ((m_init_flags & HIST_FLAG_INIT_TITULO) == 0)
 | 
						|
#define HISTOGRAM_IS_NOT_INIT_DATA        ((m_init_flags & HIST_FLAG_INIT_DATA) == 0)
 | 
						|
#define HISTOGRAM_IS_NOT_INIT_INFORMATIVE ((m_init_flags & HIST_FLAG_INIT_PART_INFO) == 0)
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CHistogram::CHistogram(void)
 | 
						|
 {
 | 
						|
  CleanVariables();
 | 
						|
  m_canvas = new CCanvasCustom();
 | 
						|
  m_canvas.FontSet("Arial", 12, 0, 0); // Seteamos un font por defecto
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
CHistogram::~CHistogram()
 | 
						|
 {
 | 
						|
  Clean();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Limpieza de variables                                            |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::CleanVariables(void)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  m_canvas = NULL;
 | 
						|
  m_titulo = NULL;
 | 
						|
  m_copyright = NULL;
 | 
						|
  m_eje = NULL;
 | 
						|
  m_corte_mode = WRONG_VALUE;
 | 
						|
 | 
						|
//--- Barras
 | 
						|
  m_bars_size = 0;
 | 
						|
  m_bar_max = NULL;
 | 
						|
  m_bar_min = NULL;
 | 
						|
  m_curr_index_bar_p = 0;
 | 
						|
  ArrayResize(m_bars, 0);
 | 
						|
 | 
						|
//--- Flags y tipo
 | 
						|
  m_init_flags = 0;
 | 
						|
  m_type = WRONG_VALUE;
 | 
						|
 | 
						|
//--- Generales
 | 
						|
  m_chart_id = 0;
 | 
						|
  m_subwin = 0;
 | 
						|
  m_width = 0;
 | 
						|
  m_height = 0;
 | 
						|
  m_obj_name = "";
 | 
						|
  m_back_color = 0x00000000;
 | 
						|
 | 
						|
//--- Conversiones y corte
 | 
						|
  m_fr_max_value = 0.0;
 | 
						|
  m_fr_min_value = 0.0;
 | 
						|
  m_fr_change_value = 0.0;
 | 
						|
  m_factor_conversion_value_to_pixel_pos = 0.0;
 | 
						|
  m_factor_conversion_value_to_pixel_neg = 0.0;
 | 
						|
  m_percent_corte_neg = 0.0;
 | 
						|
  m_percent_corte_pos = 0.0;
 | 
						|
  m_function_value_to_pixel = NULL;
 | 
						|
  m_line_corte = NULL;
 | 
						|
 | 
						|
//--- Gaps
 | 
						|
  m_gap_superior = 0;
 | 
						|
  m_gap_inferior = 0;
 | 
						|
  m_gap_derecha = 0;
 | 
						|
  m_gap_izquierda = 0;
 | 
						|
 | 
						|
//--- Espacio dibujable de barras
 | 
						|
  m_barras_gap_init = 0;
 | 
						|
  m_barras_gap_end = 0;
 | 
						|
  m_barras_x1 = 0;
 | 
						|
  m_barras_y1 = 0;
 | 
						|
  m_barras_cordinate_init = 0;
 | 
						|
  m_barras_cordenanda_eje_corte = 0;
 | 
						|
  m_barras_espacio_dibujable_width = 0;
 | 
						|
  m_barras_espacio_dibujable_height = 0;
 | 
						|
  m_barras_max_width = 0;
 | 
						|
  m_barras_max_height = 0;
 | 
						|
  m_barras_espacio_entre = 0;
 | 
						|
  m_barras_min_width = 0;
 | 
						|
 | 
						|
//--- Parte informativa
 | 
						|
  m_part_info_position = WRONG_VALUE;
 | 
						|
  m_part_info_ptr = NULL;
 | 
						|
 }
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Limpieza total                                                   |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::Clean(void)
 | 
						|
 {
 | 
						|
//--- Eliminamos ptrs
 | 
						|
// Parte informativa
 | 
						|
  if(CheckPointer(m_part_info_ptr) == POINTER_DYNAMIC)
 | 
						|
    delete m_part_info_ptr;
 | 
						|
 | 
						|
// Barras
 | 
						|
  for(int i = 0; i < m_bars_size; i++)
 | 
						|
   {
 | 
						|
    if(CheckPointer(m_bars[i]) == POINTER_DYNAMIC)
 | 
						|
      delete m_bars[i];
 | 
						|
   }
 | 
						|
 | 
						|
// Linea de corte
 | 
						|
  if(CheckPointer(m_line_corte) == POINTER_DYNAMIC)
 | 
						|
    delete m_line_corte;
 | 
						|
 | 
						|
// Canvas
 | 
						|
  if(CheckPointer(m_canvas) == POINTER_DYNAMIC)
 | 
						|
   {
 | 
						|
    m_canvas.Destroy(); // Eliminamicino del obejto y liberacion del recurso dinamico
 | 
						|
    delete m_canvas;
 | 
						|
   }
 | 
						|
 | 
						|
// Titulo
 | 
						|
  if(CheckPointer(m_titulo) == POINTER_DYNAMIC)
 | 
						|
    delete m_titulo;
 | 
						|
 | 
						|
// Copyright
 | 
						|
  if(CheckPointer(m_copyright) == POINTER_DYNAMIC)
 | 
						|
   {
 | 
						|
    delete m_copyright;
 | 
						|
    m_copyright = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
// Linea de eje
 | 
						|
  if(CheckPointer(m_eje) == POINTER_DYNAMIC)
 | 
						|
   {
 | 
						|
    delete m_eje;
 | 
						|
    m_eje = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  CleanVariables(); // limpieza de variables
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Inicializa la clase                                              |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::Initialize(int width, int height, string objname, long chart_id, int subwin, uint back_color)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(HISTOGRAM_IS_INIT_GENERAL)
 | 
						|
    return; // Si ya se seteo entonces retornar
 | 
						|
 | 
						|
//---
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_GENERAL;
 | 
						|
 | 
						|
//---
 | 
						|
  m_width = width;
 | 
						|
  m_height = height;
 | 
						|
  m_obj_name = objname;
 | 
						|
  m_subwin = subwin;
 | 
						|
  m_chart_id = chart_id;
 | 
						|
  m_back_color = back_color;
 | 
						|
 }
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Crea un bitmap                                                   |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
inline void CHistogram::CreateBitmap(datetime time, double price, ENUM_COLOR_FORMAT format)
 | 
						|
 {
 | 
						|
  if(HISTOGRAM_IS_INIT_CREATE)
 | 
						|
    return; // Si el objeto ya esta creado salir
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_CREATE_BITMAP;
 | 
						|
  m_canvas.CreateBitmap(m_chart_id, m_subwin, m_obj_name, time, price, m_width, m_height, format);
 | 
						|
  m_canvas.Erase(m_back_color);
 | 
						|
 }
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Crea un bitmap label                                             |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
inline void CHistogram::CreateBitmapLabel(int x, int y, ENUM_COLOR_FORMAT format)
 | 
						|
 {
 | 
						|
  if(HISTOGRAM_IS_INIT_CREATE)
 | 
						|
    return; // Si el objeto ya esta creado salir
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_CREATE_BITMAP;
 | 
						|
  m_canvas.CreateBitmapLabel(m_chart_id, m_subwin, m_obj_name, x, y, m_width, m_height, format);
 | 
						|
  m_canvas.Erase(m_back_color);
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::AddConjuntoBarWithBins(const string &label, uint label_clr, int label_fontsize, const string &label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode,
 | 
						|
                                        int eje_gap, ENUM_HIST_DRAW_RECT_STYLE initial_style, double &data[], int bins, uint clr_barras)
 | 
						|
 {
 | 
						|
 | 
						|
//---
 | 
						|
  const int idx_conj = AddConjuntoBar(label, label_clr, label_fontsize, label_font, label_mode, bins, eje_gap, initial_style);
 | 
						|
 | 
						|
//---
 | 
						|
  const int data_size = ArraySize(data);
 | 
						|
  double min = data[0];
 | 
						|
  double max = data[0];
 | 
						|
 | 
						|
  for(int i = 1; i < data_size; i++)
 | 
						|
   {
 | 
						|
    const double v = data[i];
 | 
						|
    if(v > max)
 | 
						|
      max = v;
 | 
						|
    if(v < min)
 | 
						|
      min = v;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  double bins_range = (max - min) / double(data_size);
 | 
						|
 | 
						|
//---
 | 
						|
  int frecuencias_data[];
 | 
						|
  ArrayResize(frecuencias_data, bins);
 | 
						|
 | 
						|
//---
 | 
						|
  for(int i = 0; i < data_size; i++)
 | 
						|
   {
 | 
						|
    int idx = int((data[i] - min) / bins_range);
 | 
						|
    if(idx >= bins)
 | 
						|
      idx = bins - 1;
 | 
						|
    frecuencias_data[idx]++;
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  for(int i = 0; i < bins; i++)
 | 
						|
   {
 | 
						|
    const double v = (double)frecuencias_data[i];
 | 
						|
    AddBarToConjuntoBarFast(v, clr_barras);
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  FinalizeAddConjunto(idx_conj, true, false); // NO redibuja
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::AddConjuntoBarWithBinsDeft(const string &label, double &data[], int bins, uint clr_barras = 0)
 | 
						|
 {
 | 
						|
  AddConjuntoBarWithBins(label, ColorToARGB(clrBlack), 12, "Arial", HISTOGRAM_TEXT_MODE_CENTER, 30, HIST_DRAW_RECT_FILL, data, bins, (clr_barras == 0 ? m_color_generator.Next() : clr_barras));
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline int CHistogram::AddConjuntoBar(const string &label, int label_fontsize, const string &label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode,
 | 
						|
    int barras_de_reserva_, int eje_gap, ENUM_HIST_DRAW_RECT_STYLE initial_style, double width = 0.000000)
 | 
						|
 {
 | 
						|
  return AddConjuntoBar(label, m_color_generator.Next(), label_fontsize, label_font, label_mode, barras_de_reserva_, eje_gap, initial_style, width);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline int CHistogram::AddConjuntoBarDefault(const string &label, int label_fontsize, int barras_de_reserva_ = 0)
 | 
						|
 {
 | 
						|
  return AddConjuntoBar(label, m_color_generator.Next(), label_fontsize, "Arial", HISTOGRAM_TEXT_MODE_CENTER, barras_de_reserva_, label_fontsize >> 1, HIST_DRAW_RECT_FILL);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Setea un conjunto de barras                                      |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::BarConjuntoSet(const string label, uint label_clr, int label_fontsize, const string &label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode, int eje_gap,
 | 
						|
    ENUM_HIST_DRAW_RECT_STYLE initial_style, double width = 0.00)
 | 
						|
 {
 | 
						|
  m_bars[m_curr_index_bar_p].Set(m_canvas, label, label_clr, label_mode, label_fontsize, label_font, eje_gap, initial_style);
 | 
						|
  m_bars[m_curr_index_bar_p].ValueForAncho(width);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::BarConjuntoSet(const string label, int label_fontsize, const string &label_font, ENUM_HISTOGRAM_TEXT_MODE label_mode, int eje_gap,
 | 
						|
    ENUM_HIST_DRAW_RECT_STYLE initial_style, double width = 0.00)
 | 
						|
 {
 | 
						|
  m_bars[m_curr_index_bar_p].Set(m_canvas, label, m_color_generator.Next(), label_mode, label_fontsize, label_font, eje_gap, initial_style);
 | 
						|
  m_bars[m_curr_index_bar_p].ValueForAncho(width);
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Añade una barra al conjunto de barras                            |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
// Rapida
 | 
						|
__forceinline void CHistogram::AddBarToConjuntoBarFast(double value, uint clr)
 | 
						|
 {
 | 
						|
  m_bars[m_curr_index_bar_p].AddBarraFast(value, clr);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
// Lenta
 | 
						|
__forceinline void CHistogram::AddBarToConjuntoBar(double value, uint clr, bool update_data)
 | 
						|
 {
 | 
						|
  m_bars[m_curr_index_bar_p].AddBarra(value, clr, update_data);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::BarConjuntoSetBath(int index, const double &values[], const uint &colores[], bool redraw = false)
 | 
						|
 {
 | 
						|
  const int s_v = ArraySize(values);
 | 
						|
  const int s_c = ArraySize(colores);
 | 
						|
 | 
						|
//--- Comparacion
 | 
						|
  if(s_v !=  s_c)
 | 
						|
   {
 | 
						|
    LogCriticalError("Array de valores y colores, difieren en tamaño", FUNCION_ACTUAL);
 | 
						|
    Remover();
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//--- Agregamos
 | 
						|
  for(int i = 0; i < s_v; i++)
 | 
						|
    m_bars[index].AddBarraFast(values[i], colores[i]);
 | 
						|
 | 
						|
//---Finalizamos
 | 
						|
  FinalizeAddConjunto(index, true, redraw); // SOlo se ejeucta cuando se haya completado las banderas necesarias
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Finaliza el agregado de barras de un conjunto                    |
 | 
						|
//| El color de la label se elije aleatoriamente                     |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::FinalizeAddConjunto(int index_fin, bool update_data, bool redraw = false)
 | 
						|
 {
 | 
						|
  if(HISTOGRAM_IS_INIT_NES) // Si ya esta iniciado ya se calculo, entonces necesitamos recalcular
 | 
						|
   {
 | 
						|
    const bool ya_existe = m_bars[index_fin].IsInit();
 | 
						|
 | 
						|
    //--- Set max min
 | 
						|
    m_bars[index_fin].SetMaxAndMinValue();
 | 
						|
 | 
						|
    //--- Check rango
 | 
						|
    if(m_bars[index_fin].BarMaxValue() > m_bar_max.BarMaxValue())
 | 
						|
     {
 | 
						|
      m_bar_max = m_bars[index_fin];
 | 
						|
 | 
						|
      //---
 | 
						|
      RecalculeFactorsMaxMin();
 | 
						|
      OnMaxOrMinValueSuperate(); // Recalculamos "los valores" de las barras
 | 
						|
 | 
						|
      if(m_corte_mode) // No es 0
 | 
						|
        m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, false);
 | 
						|
     }
 | 
						|
    else
 | 
						|
      if(m_bars[index_fin].BarMinValue() < m_bar_min.BarMinValue())
 | 
						|
       {
 | 
						|
        m_bar_min = m_bars[index_fin];
 | 
						|
 | 
						|
        //---
 | 
						|
        RecalculeFactorsMaxMin();
 | 
						|
        OnMaxOrMinValueSuperate(); // Recalculamos "los valores" de las barras
 | 
						|
 | 
						|
        if(m_corte_mode) // No es 0
 | 
						|
          m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, false);
 | 
						|
       }
 | 
						|
 | 
						|
    //---
 | 
						|
    if(ya_existe)
 | 
						|
     {
 | 
						|
      // Calculamos las cordenadas
 | 
						|
      if(update_data)
 | 
						|
        m_bars[index_fin].RecalculeCordinatesOnlyBars();
 | 
						|
     }
 | 
						|
    else
 | 
						|
     {
 | 
						|
      OnBarraAdd(index_fin); // Se actulizan los tamaños de las barras, se reclacula el ancho de cada conjunto
 | 
						|
     }
 | 
						|
 | 
						|
    //---
 | 
						|
    if(redraw) // Redibujamos
 | 
						|
      m_canvas.Update();
 | 
						|
   }
 | 
						|
#ifdef HISTOGRAM_DEBUG
 | 
						|
  else
 | 
						|
   {
 | 
						|
    LogWarning("Solo se puede ejecutar FinalizeAddConjunto, para agregar barras a un histograma ya creado", FUNCION_ACTUAL);
 | 
						|
   }
 | 
						|
#endif
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Elimina una conjunto de barras por indice                        |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::RemoveConjuntoBar(int index, bool redraw)
 | 
						|
 {
 | 
						|
// Nota:
 | 
						|
// - No ejeuctar cuando no hay elemetos
 | 
						|
// - index debera de ser valido
 | 
						|
// - Creo que podriamos acutlizar max y min con bucle pero no es necesario.. talvez a futuro
 | 
						|
//---
 | 
						|
  double v = m_bars[index].ValueForAncho();
 | 
						|
 | 
						|
//---
 | 
						|
  if(m_bars_size > 1)
 | 
						|
   {
 | 
						|
    int idx = (index == 0) ? 1 : (index - 1);
 | 
						|
    m_bars[idx].CleanBarras(false, false);
 | 
						|
   }
 | 
						|
 | 
						|
//--- Elimianmos ptr
 | 
						|
  m_bars[index].Destroy(); // Limpiamos el espacio ocupado (texto y barras)
 | 
						|
  delete m_bars[index];
 | 
						|
 | 
						|
//--- Removemos
 | 
						|
  for(int i = index; i < m_bars_size - 1; i++)
 | 
						|
   {
 | 
						|
    m_bars[i] = m_bars[i + 1];
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  m_bars_size--;
 | 
						|
  ArrayResize(m_bars, m_bars_size);
 | 
						|
 | 
						|
//---
 | 
						|
  if(m_bars_size > 0) // Solo revisar si al menos hay 1 barra, si no hay nada no hay que revisar
 | 
						|
    OnBarrDelete(v);
 | 
						|
 | 
						|
//--- SI se peude redibujar recalculamos las cordendas
 | 
						|
  if(redraw)
 | 
						|
   {
 | 
						|
    m_canvas.Update();
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Elimina una barra por nombre                                     |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::RemoveConjuntoBar(string name, bool redraw)
 | 
						|
 {
 | 
						|
  RemoveConjuntoBar(FindIndexByBarConjuntoName(name), redraw);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Elimina una barra de su conjunto                                 |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::RemoveBarFromConjuntoBar(int index_in_conjunto, bool redraw = false)
 | 
						|
 {
 | 
						|
  m_bars[m_curr_index_bar_p].RemoveBar(index_in_conjunto, true);
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Establece el color de una barra por indice                       |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::BarColor(int index, uint new_clr, bool redraw = false)
 | 
						|
 {
 | 
						|
  m_bars[m_curr_index_bar_p].BarColor(index, new_clr);
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Establece el valor de una barra por indice                       |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::BarValue(int index, double new_value, bool redraw = false)
 | 
						|
 {
 | 
						|
// Notas:
 | 
						|
// - Solo ejecutar luego de haber iniciado la clase
 | 
						|
// - m_curr_index_bar_p y index, no se compruebam, debera de ser validos
 | 
						|
 | 
						|
//---  Chekeamos valores
 | 
						|
  if(new_value > m_bar_max.BarMaxValue())
 | 
						|
   {
 | 
						|
    m_bars[m_curr_index_bar_p].BarValue(index, new_value, true, false); // Actulizamos  (no el rect se hara en OnMar...)
 | 
						|
    m_bar_max = m_bars[m_curr_index_bar_p];
 | 
						|
 | 
						|
    RecalculeFactorsMaxMin();
 | 
						|
    OnMaxOrMinValueSuperate(); // Recalculamos "los valores" de las barras
 | 
						|
 | 
						|
    if(m_corte_mode) // No es 0
 | 
						|
      m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, false);
 | 
						|
   }
 | 
						|
  else
 | 
						|
    if(new_value < m_bar_min.BarMinValue())
 | 
						|
     {
 | 
						|
      m_bars[m_curr_index_bar_p].BarValue(index, new_value, true, false); // Actulizamos (no el rect se hara en OnMar...)
 | 
						|
      m_bar_min = m_bars[m_curr_index_bar_p];
 | 
						|
      RecalculeFactorsMaxMin();
 | 
						|
      OnMaxOrMinValueSuperate(); // Recalculamos "los valores" de las barras
 | 
						|
 | 
						|
      if(m_corte_mode) // No es 0
 | 
						|
        m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, false);
 | 
						|
     }
 | 
						|
    else // No es un pico, actulizamos el rectangulo
 | 
						|
     {
 | 
						|
      m_bars[m_curr_index_bar_p].BarValue(index, new_value, true, true); // Actulizamos
 | 
						|
     }
 | 
						|
 | 
						|
//---
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Establece el color de una barra por indice                       |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::BarConjuntoTextValue(string new_name, bool redraw = false)
 | 
						|
 {
 | 
						|
  m_bars[m_curr_index_bar_p].TextValue(new_name);
 | 
						|
  if(redraw)
 | 
						|
    m_canvas.Update();
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Encuentra el indice de un conjunto de barras por su nombres      |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
inline int CHistogram::FindIndexByBarConjuntoName(const string& name)
 | 
						|
 {
 | 
						|
  for(int i = 0; i < m_bars_size; i++)
 | 
						|
    if(m_bars[i].TextValue() == name)
 | 
						|
      return i;
 | 
						|
  return -1;
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::Titulo(const string &titulo, ENUM_HISTOGRAM_TITULO_POSICION posicion, int y_gap_titulo, uint aligement, int x, int y, uint clr,
 | 
						|
                        int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX, uint textpos = UINT_MAX)
 | 
						|
 {
 | 
						|
//---
 | 
						|
  if(HISTOGRAM_IS_INIT_TITULO)
 | 
						|
    return;
 | 
						|
  m_titulo = new CHistogramTitulo();
 | 
						|
  m_titulo.Create(m_canvas, x, y, titulo, clr, aligement, posicion, y_gap_titulo, fontsize, font, flagtext, textpos);
 | 
						|
  m_titulo.CleanColor(m_back_color);
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_TITULO;
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::TituloDefault(const string &titulo, int espacio_utilizado_por_el_titulo_y = 30)
 | 
						|
 {
 | 
						|
  int fontsize = (espacio_utilizado_por_el_titulo_y >> 1) - 3;
 | 
						|
  int x_mitad = m_width >> 1;
 | 
						|
  int y_mitad = espacio_utilizado_por_el_titulo_y >> 1;
 | 
						|
  Titulo(titulo, HISTOGRAM_TITULO_ARRIBA, espacio_utilizado_por_el_titulo_y, TA_CENTER | TA_VCENTER, x_mitad, y_mitad, ColorToARGB(clrBlack), fontsize, "Arial",
 | 
						|
         0);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::SetMaxMin(void)
 | 
						|
 {
 | 
						|
  m_bars[0].SetMaxAndMinValue();
 | 
						|
  m_bar_max = m_bars[0];
 | 
						|
  m_bar_min = m_bars[0];
 | 
						|
  for(int i = 1; i < m_bars_size; i++)
 | 
						|
   {
 | 
						|
    m_bars[i].SetMaxAndMinValue();
 | 
						|
    if(m_bars[i].BarMaxValue() > m_bar_max.BarMaxValue())
 | 
						|
      m_bar_max = m_bars[i];
 | 
						|
    if(m_bars[i].BarMinValue() < m_bar_min.BarMinValue())
 | 
						|
      m_bar_min = m_bars[i];
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::InitLienzoBarras(int x1, int y1, int x2, int y2, int gap_init, int gap_end, int gap_espacio_entre_barras)
 | 
						|
 {
 | 
						|
//--- Check init
 | 
						|
  /*
 | 
						|
  - Para este caso damos la posiblidad que se ejcute denuevo init
 | 
						|
  - Se debera de tenrer cuidad con x1, y2, etc para que "colisionen" con el texto informativo creado
 | 
						|
 | 
						|
    if(HISTOGRAM_IS_INIT_ALL)
 | 
						|
     {
 | 
						|
      LogError(")
 | 
						|
      return;
 | 
						|
     }
 | 
						|
  */
 | 
						|
 | 
						|
//--- Chek titulo
 | 
						|
  if(HISTOGRAM_IS_NOT_INIT_TITULO)
 | 
						|
   {
 | 
						|
    LogError("Primero se tuvo que haber seteado el titulo", FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//---  Check Y
 | 
						|
// Nota: El titulo siempre se setea antes de el lienzo siempre
 | 
						|
  if(m_titulo.TituloPosition() == HISTOGRAM_TITULO_ARRIBA)
 | 
						|
   {
 | 
						|
    if(y1 < m_titulo.ReserveY()) // El y1 inicia antes que la altura reservada para el titulo, conflicvto
 | 
						|
     {
 | 
						|
      LogError("Y1 Del titulo inicia antes de la altura reservada para el titulo", FUNCION_ACTUAL);
 | 
						|
      return;
 | 
						|
     }
 | 
						|
    if(y2 > m_height) // FUERA DE RANGHO
 | 
						|
     {
 | 
						|
      LogError(StringFormat("Y2[%d] Final mayor a height[%d]", y2, m_height), FUNCION_ACTUAL);
 | 
						|
      return;
 | 
						|
     }
 | 
						|
    // A que tener en cuenta que el y2 tambien debe de considerar el espacio para los texto fontsize que se puso al moet o de agregar barras
 | 
						|
    // Como es variable no podemos comporarlo
 | 
						|
    // En teoria podriamos metere mas comprobaciones para todos los parametros pero creo que no hace falta
 | 
						|
   }
 | 
						|
  else
 | 
						|
    if(m_titulo.TituloPosition() == HISTOGRAM_TITULO_ABAJO)
 | 
						|
     {
 | 
						|
      const int y2_titulo = m_width - m_titulo.ReserveY();
 | 
						|
      if(y2 > y2_titulo) // el y2 (eje y de fin) esta mas adelnta que el y2 del titulo, conflicto
 | 
						|
       {
 | 
						|
        LogError("Y2 Del linezo mayor al espacio inferior reservado para el titulo", FUNCION_ACTUAL);
 | 
						|
        return;
 | 
						|
       }
 | 
						|
      if(y1  < 1)
 | 
						|
       {
 | 
						|
        LogError("Y1 Negativo", FUNCION_ACTUAL);
 | 
						|
        return;
 | 
						|
       }
 | 
						|
      // A que tener en cuenta que el y2 tambien debe de considerar el espacio para los texto fontsize que se puso al moet o de agregar barras
 | 
						|
      // Como es variable no podemos comporarlo
 | 
						|
     }
 | 
						|
 | 
						|
//---
 | 
						|
  m_corte_mode = HIST_CORTE_NOT_USE;
 | 
						|
 | 
						|
//---
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_DATA;
 | 
						|
 | 
						|
//---
 | 
						|
  m_barras_gap_end = gap_end;
 | 
						|
  m_barras_gap_init = gap_init;
 | 
						|
  m_barras_x1 = x1;
 | 
						|
  m_barras_y1 = y1;
 | 
						|
  m_barras_espacio_dibujable_height = fabs(y2 - y1);
 | 
						|
  m_barras_espacio_dibujable_width = fabs(x2 - x1);
 | 
						|
  m_barras_espacio_entre = gap_espacio_entre_barras;
 | 
						|
 | 
						|
//---
 | 
						|
  const bool is_h = (m_type == HISTOGRAM_HORIZONTAL);
 | 
						|
 | 
						|
//--- Cordenajda de inicial real
 | 
						|
  if(is_h)
 | 
						|
    m_barras_cordinate_init = m_barras_x1 + m_barras_gap_init;
 | 
						|
  else
 | 
						|
    m_barras_cordinate_init = m_barras_y1 + m_barras_gap_init;
 | 
						|
//---
 | 
						|
  m_gap_izquierda = x1; // Gap entre el ejey y el "left" de la iamge
 | 
						|
  m_gap_derecha = m_width - (m_gap_izquierda + m_barras_espacio_dibujable_width); // Calculamos el gap de la derecha (faltante)
 | 
						|
  m_gap_inferior = m_height - y2; // Gap entre el ejex (inf) y el "bottom" de la imagen
 | 
						|
  m_gap_superior = y1;
 | 
						|
 | 
						|
//---
 | 
						|
  OnSetLienzo();
 | 
						|
 | 
						|
//--- Steamos maximo y minimo
 | 
						|
  SetMaxMin();
 | 
						|
 | 
						|
// Este gap es para cubrir el espacio de la liena de crote (para no suporniciones colisiones de pixeles)
 | 
						|
// 1 De la linea de corte
 | 
						|
// 1 liena del eje
 | 
						|
#define HISTOGRAM_GAP_LINE_CORTE 2
 | 
						|
//--- Maximo y minimo
 | 
						|
  m_fr_max_value = m_bar_max.BarMaxValue();
 | 
						|
  m_fr_min_value = m_bar_min.BarMinValue();
 | 
						|
 | 
						|
//--- Ptp
 | 
						|
  const double ptp = m_fr_max_value - m_fr_min_value;
 | 
						|
  double fc;
 | 
						|
 | 
						|
//--- Factor de conversion
 | 
						|
  if(is_h)
 | 
						|
   {
 | 
						|
    fc = double(m_barras_max_height - HISTOGRAM_GAP_LINE_CORTE) / ptp;
 | 
						|
    m_barras_cordenanda_eje_corte = (m_barras_y1 + m_barras_espacio_dibujable_height); // Y1Real = Corte (no hay separacion)
 | 
						|
   }
 | 
						|
  else
 | 
						|
   {
 | 
						|
    fc = double(m_barras_max_width - HISTOGRAM_GAP_LINE_CORTE) / ptp;
 | 
						|
    m_barras_cordenanda_eje_corte = m_barras_x1; // X1Real = Corte no hay separacion
 | 
						|
   }
 | 
						|
 | 
						|
//--- Set valores
 | 
						|
  m_fr_change_value = m_fr_min_value;
 | 
						|
  m_factor_conversion_value_to_pixel_neg = fc;
 | 
						|
  m_factor_conversion_value_to_pixel_pos = fc;
 | 
						|
 | 
						|
//--- Set funcion de pixel
 | 
						|
  m_function_value_to_pixel = HistogramFunctions::ValueToPixelComplete;
 | 
						|
 | 
						|
//--- Si existe una linea de corte
 | 
						|
  if(CheckPointer(m_line_corte) == POINTER_DYNAMIC)
 | 
						|
    delete m_line_corte;
 | 
						|
  m_line_corte = NULL;
 | 
						|
 | 
						|
 | 
						|
//--- Creamos las barras solo pixeles no dibujamos aun (solo actulizamos pixeles)
 | 
						|
  InitCordinates();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::InitLienzoBarras(int x1, int y1, int x2, int y2, int gap_init, int gap_end, int gap_espacio_entre_barras, double value_corte_neg, double value_corte_pos)
 | 
						|
 {
 | 
						|
//--- Chek titulo
 | 
						|
  if(HISTOGRAM_IS_NOT_INIT_TITULO)
 | 
						|
   {
 | 
						|
    LogError("Primero se tuvo que haber seteado el titulo", FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//---  Check Y
 | 
						|
// Nota: El titulo siempre se setea antes de el lienzo siempre
 | 
						|
  if(m_titulo.TituloPosition() == HISTOGRAM_TITULO_ARRIBA)
 | 
						|
   {
 | 
						|
    if(y1 < m_titulo.ReserveY()) // El y1 inicia antes que la altura reservada para el titulo, conflicvto
 | 
						|
     {
 | 
						|
      LogError("Y1 Del titulo inicia antes de la altura reservada para el titulo", FUNCION_ACTUAL);
 | 
						|
      return;
 | 
						|
     }
 | 
						|
    if(y2 > m_height) // FUERA DE RANGHO
 | 
						|
     {
 | 
						|
      LogError(StringFormat("Y2[%d] Final mayor a height[%d]", y2, m_height), FUNCION_ACTUAL);
 | 
						|
      return;
 | 
						|
     }
 | 
						|
    // A que tener en cuenta que el y2 tambien debe de considerar el espacio para los texto fontsize que se puso al moet o de agregar barras
 | 
						|
    // Como es variable no podemos comporarlo
 | 
						|
    // En teoria podriamos metere mas comprobaciones para todos los parametros pero creo que no hace falta
 | 
						|
   }
 | 
						|
  else
 | 
						|
    if(m_titulo.TituloPosition() == HISTOGRAM_TITULO_ABAJO)
 | 
						|
     {
 | 
						|
      const int y2_titulo = m_width - m_titulo.ReserveY();
 | 
						|
      if(y2 > y2_titulo) // el y2 (eje y de fin) esta mas adelnta que el y2 del titulo, conflicto
 | 
						|
       {
 | 
						|
        LogError("Y2 Del linezo mayor al espacio inferior reservado para el titulo", FUNCION_ACTUAL);
 | 
						|
        return;
 | 
						|
       }
 | 
						|
      if(y1  < 1)
 | 
						|
       {
 | 
						|
        LogError("Y1 Negativo", FUNCION_ACTUAL);
 | 
						|
        return;
 | 
						|
       }
 | 
						|
      // A que tener en cuenta que el y2 tambien debe de considerar el espacio para los texto fontsize que se puso al moet o de agregar barras
 | 
						|
      // Como es variable no podemos comporarlo
 | 
						|
     }
 | 
						|
 | 
						|
//---
 | 
						|
  m_corte_mode = HIST_CORTE_PERCENT;
 | 
						|
 | 
						|
//---
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_DATA;
 | 
						|
 | 
						|
//---
 | 
						|
  m_barras_gap_end = gap_end;
 | 
						|
  m_barras_gap_init = gap_init;
 | 
						|
  m_barras_x1 = x1;
 | 
						|
  m_barras_y1 = y1;
 | 
						|
  m_barras_espacio_dibujable_height = fabs(y2 - y1);
 | 
						|
  m_barras_espacio_dibujable_width = fabs(x2 - x1);
 | 
						|
  m_barras_espacio_entre = gap_espacio_entre_barras;
 | 
						|
  m_percent_corte_neg = value_corte_neg;
 | 
						|
  m_percent_corte_pos = value_corte_pos;
 | 
						|
 | 
						|
//---
 | 
						|
  const bool is_h = (m_type == HISTOGRAM_HORIZONTAL);
 | 
						|
 | 
						|
//--- Cordenajda de inicial real
 | 
						|
  if(is_h)
 | 
						|
    m_barras_cordinate_init = m_barras_x1 + m_barras_gap_init;
 | 
						|
  else
 | 
						|
    m_barras_cordinate_init = m_barras_y1 + m_barras_gap_init;
 | 
						|
//---
 | 
						|
  m_gap_izquierda = x1; // Gap entre el ejey y el "left" de la iamge
 | 
						|
  m_gap_derecha = m_width - (m_gap_izquierda + m_barras_espacio_dibujable_width); // Calculamos el gap de la derecha (faltante)
 | 
						|
  m_gap_inferior = m_height - y2; // Gap entre el ejex (inf) y el "bottom" de la imagen
 | 
						|
  m_gap_superior = y1;
 | 
						|
 | 
						|
//---
 | 
						|
  OnSetLienzo();
 | 
						|
 | 
						|
//--- Steamos maximo y minimo
 | 
						|
  SetMaxMin();
 | 
						|
 | 
						|
//--- Check corte
 | 
						|
  if(m_percent_corte_neg + m_percent_corte_pos != 1.00)
 | 
						|
   {
 | 
						|
    LogCriticalError("Los percentages decimales deben de sumar 1.00", FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//--- Maixmo y minimo, y ptp
 | 
						|
  m_fr_max_value = m_bar_max.BarMaxValue();
 | 
						|
  m_fr_min_value = m_bar_min.BarMinValue();
 | 
						|
  const double ptp =  m_fr_max_value - m_fr_min_value;
 | 
						|
  m_fr_change_value = m_fr_min_value + (ptp * m_percent_corte_neg); // valor de cambio de "neg" a "pos"
 | 
						|
 | 
						|
//--- Funcion de pixel
 | 
						|
  m_function_value_to_pixel = HistogramFunctions::ValueToPixelCorte;
 | 
						|
 | 
						|
//--- Si no existe la creamos
 | 
						|
  const bool exist_pointer = (CheckPointer(m_line_corte) == POINTER_DYNAMIC);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//--- Rangos
 | 
						|
  const double range_mayor = m_fr_max_value - m_fr_change_value;
 | 
						|
  const double rango_menor = m_fr_change_value - m_fr_min_value;
 | 
						|
 | 
						|
//---
 | 
						|
  if(m_type) // Vertical
 | 
						|
   {
 | 
						|
    int width_disponible_neg = int(m_barras_espacio_dibujable_width * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(width_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int width_disponible_pos = int(m_barras_espacio_dibujable_width * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(width_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    m_barras_cordenanda_eje_corte = m_barras_x1 + width_disponible_neg + HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
 | 
						|
    //---
 | 
						|
    if(exist_pointer) // Si ya existe existe
 | 
						|
     {
 | 
						|
      m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, true);
 | 
						|
     }
 | 
						|
    else
 | 
						|
     {
 | 
						|
      m_line_corte = new CHistogramLineCorteVer();
 | 
						|
      m_line_corte.Init(m_canvas);
 | 
						|
      int y1 = m_barras_y1 + 1;
 | 
						|
      int size_corte =  m_barras_espacio_dibujable_height - 2;
 | 
						|
      m_line_corte.Set(m_barras_cordenanda_eje_corte, y1, size_corte, 0xFF000000, m_back_color); //negro por defecto
 | 
						|
     }
 | 
						|
   }
 | 
						|
  else // Horizontal
 | 
						|
   {
 | 
						|
 | 
						|
    int height_disponible_neg = int(m_barras_espacio_dibujable_height * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(height_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int height_disponible_pos = int(m_barras_espacio_dibujable_height * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(height_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    //------------------------------| Y1 (para horizontal)                            - GAP
 | 
						|
    m_barras_cordenanda_eje_corte = (m_barras_y1 + m_barras_espacio_dibujable_height) - (height_disponible_neg + HISTOGRAM_GAP_LINE_CORTE);
 | 
						|
 | 
						|
 | 
						|
    //---
 | 
						|
    if(exist_pointer) // Si ya existe existe
 | 
						|
     {
 | 
						|
      m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, true);
 | 
						|
     }
 | 
						|
    else
 | 
						|
     {
 | 
						|
      m_line_corte = new CHistogramLineCorteHor();
 | 
						|
      m_line_corte.Init(m_canvas);
 | 
						|
      int x1 = m_barras_x1 + 1;
 | 
						|
      int size_corte = m_barras_espacio_dibujable_width - 2;
 | 
						|
      m_line_corte.Set(x1, m_barras_cordenanda_eje_corte, size_corte, 0xFF000000, m_back_color);
 | 
						|
     }
 | 
						|
   }
 | 
						|
 | 
						|
//--- Creamos las barras solo pixeles no dibujamos aun (solo actulizamos pixeles)
 | 
						|
  InitCordinates();
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::InitLienzoBarras(int x1, int y1, int x2, int y2, int gap_init, int gap_end, int gap_espacio_entre_barras, double value_corte)
 | 
						|
 {
 | 
						|
//--- Chek titulo
 | 
						|
  if(HISTOGRAM_IS_NOT_INIT_TITULO)
 | 
						|
   {
 | 
						|
    LogError("Primero se tuvo que haber seteado el titulo", FUNCION_ACTUAL);
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//---  Check Y
 | 
						|
// Nota: El titulo siempre se setea antes de el lienzo siempre
 | 
						|
  if(m_titulo.TituloPosition() == HISTOGRAM_TITULO_ARRIBA)
 | 
						|
   {
 | 
						|
    if(y1 < m_titulo.ReserveY()) // El y1 inicia antes que la altura reservada para el titulo, conflicvto
 | 
						|
     {
 | 
						|
      LogError("Y1 Del titulo inicia antes de la altura reservada para el titulo", FUNCION_ACTUAL);
 | 
						|
      return;
 | 
						|
     }
 | 
						|
    if(y2 > m_height) // FUERA DE RANGHO
 | 
						|
     {
 | 
						|
      LogError(StringFormat("Y2[%d] Final mayor a height[%d]", y2, m_height), FUNCION_ACTUAL);
 | 
						|
      return;
 | 
						|
     }
 | 
						|
    // A que tener en cuenta que el y2 tambien debe de considerar el espacio para los texto fontsize que se puso al moet o de agregar barras
 | 
						|
    // Como es variable no podemos comporarlo
 | 
						|
    // En teoria podriamos metere mas comprobaciones para todos los parametros pero creo que no hace falta
 | 
						|
   }
 | 
						|
  else
 | 
						|
    if(m_titulo.TituloPosition() == HISTOGRAM_TITULO_ABAJO)
 | 
						|
     {
 | 
						|
      const int y2_titulo = m_width - m_titulo.ReserveY();
 | 
						|
      if(y2 > y2_titulo) // el y2 (eje y de fin) esta mas adelnta que el y2 del titulo, conflicto
 | 
						|
       {
 | 
						|
        LogError("Y2 Del linezo mayor al espacio inferior reservado para el titulo", FUNCION_ACTUAL);
 | 
						|
        return;
 | 
						|
       }
 | 
						|
      if(y1  < 1)
 | 
						|
       {
 | 
						|
        LogError("Y1 Negativo", FUNCION_ACTUAL);
 | 
						|
        return;
 | 
						|
       }
 | 
						|
      // A que tener en cuenta que el y2 tambien debe de considerar el espacio para los texto fontsize que se puso al moet o de agregar barras
 | 
						|
      // Como es variable no podemos comporarlo
 | 
						|
     }
 | 
						|
 | 
						|
//---
 | 
						|
  Print("Hola");
 | 
						|
 | 
						|
//---
 | 
						|
  m_corte_mode = HIST_CORTE_VALUE;
 | 
						|
 | 
						|
//---
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_DATA;
 | 
						|
 | 
						|
//---
 | 
						|
  m_barras_gap_end = gap_end;
 | 
						|
  m_barras_gap_init = gap_init;
 | 
						|
  m_barras_x1 = x1;
 | 
						|
  m_barras_y1 = y1;
 | 
						|
  m_barras_espacio_dibujable_height = fabs(y2 - y1);
 | 
						|
  m_barras_espacio_dibujable_width = fabs(x2 - x1);
 | 
						|
  m_barras_espacio_entre = gap_espacio_entre_barras;
 | 
						|
 | 
						|
//---
 | 
						|
  const bool is_h = (m_type == HISTOGRAM_HORIZONTAL);
 | 
						|
 | 
						|
//--- Cordenajda de inicial real
 | 
						|
  if(is_h)
 | 
						|
    m_barras_cordinate_init = m_barras_x1 + m_barras_gap_init;
 | 
						|
  else
 | 
						|
    m_barras_cordinate_init = m_barras_y1 + m_barras_gap_init;
 | 
						|
//---
 | 
						|
  m_gap_izquierda = x1; // Gap entre el ejey y el "left" de la iamge
 | 
						|
  m_gap_derecha = m_width - (m_gap_izquierda + m_barras_espacio_dibujable_width); // Calculamos el gap de la derecha (faltante)
 | 
						|
  m_gap_inferior = m_height - y2; // Gap entre el ejex (inf) y el "bottom" de la imagen
 | 
						|
  m_gap_superior = y1;
 | 
						|
 | 
						|
//--- Steamos valores del lienzo
 | 
						|
  OnSetLienzo();
 | 
						|
 | 
						|
//--- Steamos maximo y minimo
 | 
						|
  SetMaxMin();
 | 
						|
 | 
						|
//--- Maixmo y minimo, y ptp
 | 
						|
  m_fr_max_value = m_bar_max.BarMaxValue();
 | 
						|
  m_fr_min_value = m_bar_min.BarMinValue();
 | 
						|
 | 
						|
 | 
						|
//--- Check corte
 | 
						|
  if(value_corte < m_fr_min_value || value_corte > m_fr_max_value)
 | 
						|
   {
 | 
						|
    LogCriticalError("Valor de corte ha superado los limites", FUNCION_ACTUAL);
 | 
						|
    Remover();
 | 
						|
    return;
 | 
						|
   }
 | 
						|
 | 
						|
//--- Ptp y asigancion a valor de cambio
 | 
						|
  const double ptp =  m_fr_max_value - m_fr_min_value;
 | 
						|
  m_fr_change_value = value_corte;
 | 
						|
 | 
						|
//--- Funcion de pixel
 | 
						|
  m_function_value_to_pixel = HistogramFunctions::ValueToPixelCorte;
 | 
						|
 | 
						|
//--- Si no existe la creamos
 | 
						|
  const bool exist_pointer = (CheckPointer(m_line_corte) == POINTER_DYNAMIC);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//--- Rangos
 | 
						|
  const double range_mayor = m_fr_max_value - m_fr_change_value;
 | 
						|
  const double rango_menor = m_fr_change_value - m_fr_min_value;
 | 
						|
 | 
						|
  PrintFormat("Rango mayor = %.2f | Rango menos = %.2f", range_mayor, rango_menor);
 | 
						|
 | 
						|
//--- Percentages
 | 
						|
  m_percent_corte_neg = rango_menor / ptp;
 | 
						|
  m_percent_corte_pos = range_mayor / ptp;
 | 
						|
 | 
						|
//--- Calc
 | 
						|
  if(m_type) // Vertical
 | 
						|
   {
 | 
						|
    int width_disponible_neg = int(m_barras_espacio_dibujable_width * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(width_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int width_disponible_pos = int(m_barras_espacio_dibujable_width * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(width_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    m_barras_cordenanda_eje_corte = m_barras_x1 + width_disponible_neg + HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
 | 
						|
    //---
 | 
						|
    if(exist_pointer) // Si ya existe existe
 | 
						|
     {
 | 
						|
      m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, true);
 | 
						|
     }
 | 
						|
    else
 | 
						|
     {
 | 
						|
      m_line_corte = new CHistogramLineCorteVer();
 | 
						|
      m_line_corte.Init(m_canvas);
 | 
						|
      int y1 = m_barras_y1 + 1;
 | 
						|
      int size_corte =  m_barras_espacio_dibujable_height - 2;
 | 
						|
      m_line_corte.Set(m_barras_cordenanda_eje_corte, y1, size_corte, 0xFF000000, m_back_color); //negro por defecto
 | 
						|
     }
 | 
						|
   }
 | 
						|
  else // Horizontal
 | 
						|
   {
 | 
						|
    int height_disponible_neg = int(m_barras_espacio_dibujable_height * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(height_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int height_disponible_pos = int(m_barras_espacio_dibujable_height * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(height_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    //------------------------------| Y1 (para horizontal)                            - GAP
 | 
						|
    m_barras_cordenanda_eje_corte = (m_barras_y1 + m_barras_espacio_dibujable_height) - (height_disponible_neg + HISTOGRAM_GAP_LINE_CORTE);
 | 
						|
 | 
						|
    //---
 | 
						|
    if(exist_pointer) // Si ya existe existe
 | 
						|
     {
 | 
						|
      m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte, true);
 | 
						|
     }
 | 
						|
    else
 | 
						|
     {
 | 
						|
      m_line_corte = new CHistogramLineCorteHor();
 | 
						|
      m_line_corte.Init(m_canvas);
 | 
						|
      int x1 = m_barras_x1 + 1;
 | 
						|
      int size_corte = m_barras_espacio_dibujable_width - 2;
 | 
						|
      m_line_corte.Set(x1, m_barras_cordenanda_eje_corte, size_corte, 0xFF000000, m_back_color);
 | 
						|
     }
 | 
						|
   }
 | 
						|
 | 
						|
//--- Creamos las barras solo pixeles no dibujamos aun (solo actulizamos pixeles)
 | 
						|
  InitCordinates();
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::RecalculeFactorsMaxMinCorteVal(void)
 | 
						|
 {
 | 
						|
  m_fr_max_value = m_bar_max.BarMaxValue();
 | 
						|
  m_fr_min_value = m_bar_min.BarMinValue();
 | 
						|
  const double ptp =  m_fr_max_value - m_fr_min_value;
 | 
						|
 | 
						|
//---
 | 
						|
  const double range_mayor = m_fr_max_value - m_fr_change_value;
 | 
						|
  const double rango_menor = m_fr_change_value - m_fr_min_value;
 | 
						|
 | 
						|
//--- Percentages
 | 
						|
  m_percent_corte_neg = rango_menor / ptp;
 | 
						|
  m_percent_corte_pos = range_mayor / ptp;
 | 
						|
 | 
						|
//---
 | 
						|
  if(m_type) // Vertical
 | 
						|
   {
 | 
						|
    int width_disponible_neg = int(m_barras_espacio_dibujable_width * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(width_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int width_disponible_pos = int(m_barras_espacio_dibujable_width * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(width_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    m_barras_cordenanda_eje_corte = m_barras_x1 + width_disponible_neg + HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_line_corte.CleanLine();
 | 
						|
   }
 | 
						|
  else // Horizontal
 | 
						|
   {
 | 
						|
    int height_disponible_neg = int(m_barras_espacio_dibujable_height * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(height_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int height_disponible_pos = int(m_barras_espacio_dibujable_height * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(height_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    //------------------------------| Y1 (para horizontal)                            - GAP
 | 
						|
    m_barras_cordenanda_eje_corte = (m_barras_y1 + m_barras_espacio_dibujable_height) - (height_disponible_neg + HISTOGRAM_GAP_LINE_CORTE);
 | 
						|
    m_line_corte.CleanLine();
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Recalculo de factores para corte por percentage                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::RecalculeFactorsMaxMinCortePer(void)
 | 
						|
 {
 | 
						|
  m_fr_max_value = m_bar_max.BarMaxValue();
 | 
						|
  m_fr_min_value = m_bar_min.BarMinValue();
 | 
						|
  const double ptp =  m_fr_max_value - m_fr_min_value;
 | 
						|
  m_fr_change_value = m_fr_min_value + (ptp * m_percent_corte_neg); // valor de cambio de "neg" a "pos"
 | 
						|
 | 
						|
//---
 | 
						|
  const double range_mayor = m_fr_max_value - m_fr_change_value;
 | 
						|
  const double rango_menor = m_fr_change_value - m_fr_min_value;
 | 
						|
 | 
						|
//---
 | 
						|
  if(m_type) // Vertical
 | 
						|
   {
 | 
						|
    int width_disponible_neg = int(m_barras_espacio_dibujable_width * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(width_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int width_disponible_pos = int(m_barras_espacio_dibujable_width * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(width_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    m_barras_cordenanda_eje_corte = m_barras_x1 + width_disponible_neg + HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_line_corte.CleanLine();
 | 
						|
 | 
						|
    //---
 | 
						|
    // m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte);
 | 
						|
   }
 | 
						|
  else // Horizontal
 | 
						|
   {
 | 
						|
    int height_disponible_neg = int(m_barras_espacio_dibujable_height * m_percent_corte_neg) - HISTOGRAM_GAP_LINE_CORTE; // Espacio disponible para negativos
 | 
						|
    m_factor_conversion_value_to_pixel_neg = double(height_disponible_neg) / rango_menor; // Maximo tamaño de la barra negativa
 | 
						|
 | 
						|
    int height_disponible_pos = int(m_barras_espacio_dibujable_height * m_percent_corte_pos) - HISTOGRAM_GAP_LINE_CORTE;
 | 
						|
    m_factor_conversion_value_to_pixel_pos = double(height_disponible_pos) / range_mayor; // Maximo tamaño de la barra positiva
 | 
						|
 | 
						|
    //--- Calculaos la cordenada de corte (neg -> pos)
 | 
						|
    //------------------------------| Y1 (para horizontal)                            - GAP
 | 
						|
    m_barras_cordenanda_eje_corte = (m_barras_y1 + m_barras_espacio_dibujable_height) - (height_disponible_neg + HISTOGRAM_GAP_LINE_CORTE);
 | 
						|
    m_line_corte.CleanLine();
 | 
						|
    //---
 | 
						|
    // m_line_corte.SetNewValueEjePrincipal(m_barras_cordenanda_eje_corte);
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Recalculo de factor de corte para default                        |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::RecalculeFactorsMaxMinDef(void)
 | 
						|
 {
 | 
						|
  m_fr_max_value = m_bar_max.BarMaxValue();
 | 
						|
  m_fr_min_value = m_bar_min.BarMinValue();
 | 
						|
 | 
						|
//---
 | 
						|
  const double ptp = m_fr_max_value - m_fr_min_value;
 | 
						|
  double fc;
 | 
						|
 | 
						|
//---
 | 
						|
  if(m_type == HISTOGRAM_HORIZONTAL)
 | 
						|
   {
 | 
						|
    fc = double(m_barras_max_height - HISTOGRAM_GAP_LINE_CORTE) / ptp;
 | 
						|
    m_barras_cordenanda_eje_corte = (m_barras_y1 + m_barras_espacio_dibujable_height); // Y1Real = Corte (no hay separacion)
 | 
						|
   }
 | 
						|
  else
 | 
						|
   {
 | 
						|
    fc = double(m_barras_max_width - HISTOGRAM_GAP_LINE_CORTE) / ptp;
 | 
						|
    m_barras_cordenanda_eje_corte = m_barras_x1; // X1Real = Corte no hay separacion
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  m_fr_change_value = m_fr_min_value;
 | 
						|
  m_factor_conversion_value_to_pixel_neg = fc;
 | 
						|
  m_factor_conversion_value_to_pixel_pos = fc;
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Recalculo de los factores                                        |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::RecalculeFactorsMaxMin()
 | 
						|
 {
 | 
						|
  switch(m_corte_mode)
 | 
						|
   {
 | 
						|
    case HIST_CORTE_NOT_USE:
 | 
						|
      RecalculeFactorsMaxMinDef();
 | 
						|
      break;
 | 
						|
    case HIST_CORTE_PERCENT:
 | 
						|
      RecalculeFactorsMaxMinCortePer();
 | 
						|
      break;
 | 
						|
    case HIST_CORTE_VALUE:
 | 
						|
      RecalculeFactorsMaxMinCorteVal();
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      LogCriticalError("No hay tipo de corte", FUNCION_ACTUAL);
 | 
						|
      Remover();
 | 
						|
      break;
 | 
						|
   }
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Actuliza el bitmap                                               |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
__forceinline void CHistogram::Redraw()
 | 
						|
 {
 | 
						|
  m_canvas.Update(true);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//| Crea la parte informativa                                        |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::CreatePartInformativa(ENUM_HISTOGRAM_PARTE_INFORMATIVA_POSICION pos, int xgap_inicial, int ygap_inicial)
 | 
						|
 {
 | 
						|
  if(HISTOGRAM_IS_INIT_INFORMATIVE)
 | 
						|
    return; // SOlo se crea una vez
 | 
						|
 | 
						|
//---
 | 
						|
  m_init_flags |= HIST_FLAG_INIT_PART_INFO;
 | 
						|
  m_part_info_ptr = new CHistogramParteInfo();
 | 
						|
  m_part_info_position = pos;
 | 
						|
 | 
						|
//---
 | 
						|
  int x1, x2, y1, y2;
 | 
						|
 | 
						|
//---
 | 
						|
  if(m_part_info_position == HISTOGRAM_PARTE_INF_DERECHA)
 | 
						|
   {
 | 
						|
    x1 = m_width - m_gap_derecha;
 | 
						|
    x2 = m_width;
 | 
						|
   }
 | 
						|
  else
 | 
						|
   {
 | 
						|
    x1 = 0;
 | 
						|
    x2 = m_gap_izquierda; // Gap izquirdo
 | 
						|
   }
 | 
						|
 | 
						|
//---
 | 
						|
  y1 = m_gap_superior; // No antes del titulo
 | 
						|
  y2 = m_height; // Hasta el final
 | 
						|
 | 
						|
//---
 | 
						|
  m_part_info_ptr.Init(m_canvas, x1, y1, x2, y2, xgap_inicial, ygap_inicial);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::CreateCopyright(int x, int y, string txt, uint clr, uint align, int fontsize = 0, string font = NULL, uint flagtext = UINT_MAX, uint textpos = UINT_MAX)
 | 
						|
 {
 | 
						|
// Apunta a algo, es seguro comprar con NULL, dado que al eliminar o iniciar el puntero tendra un valor de NULL (no hay objeto invalido, pero direccion seigue apuntado a algo)
 | 
						|
  if(m_copyright != NULL)
 | 
						|
    return;
 | 
						|
  m_copyright = new CTextCanvas();
 | 
						|
  m_copyright.Create(m_canvas, x, y, txt, clr, align, fontsize, font, flagtext, textpos);
 | 
						|
 }
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
void CHistogram::CreateCopyrightDefault(const string &autor, string font = "Arial", int fontsize = 15)
 | 
						|
 {
 | 
						|
  MqlDateTime time;
 | 
						|
  TimeToStruct(TimeLocal(), time);
 | 
						|
  CreateCopyright(5, 5, StringFormat("© Copyright %d, %s", time.year, autor), ColorToARGB(clrBlack), TA_TOP | TA_LEFT, fontsize, font, 0, 0); // usar valores por defecto
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
//|                                                                  |
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
bool CHistogram::SavePicture(const string &filename, bool comon)
 | 
						|
 {
 | 
						|
  const bool res = ResourceSave(m_canvas.ResourceName(), filename);
 | 
						|
 | 
						|
//--- Si es comon movemos de la carpeta files a la direccion comon, si ya esicte reescribimos
 | 
						|
  if(comon)
 | 
						|
   {
 | 
						|
    if(!FileMove(filename, true, filename, FILE_COMMON | FILE_REWRITE))
 | 
						|
     {
 | 
						|
      const string local = TerminalInfoString(TERMINAL_DATA_PATH);
 | 
						|
      const string common = TerminalInfoString(TERMINAL_COMMONDATA_PATH);
 | 
						|
      const string r_l = local + filename;
 | 
						|
      const string r_c = common + filename;
 | 
						|
      LogError(StringFormat("No se pudo mover el arhcivo %s de:\n%s\na\n%s", filename, r_l, r_c), FUNCION_ACTUAL);
 | 
						|
     }
 | 
						|
   }
 | 
						|
  return res;
 | 
						|
 }
 | 
						|
//+------------------------------------------------------------------+
 | 
						|
#endif
 | 
						|
//+------------------------------------------------------------------+
 |