//+------------------------------------------------------------------+ //| ResultsTab.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372 | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372" #property strict #ifndef AIDATATASKRUNER_UI_TRAINING_RESULTTAB_MQH #define AIDATATASKRUNER_UI_TRAINING_RESULTTAB_MQH //+------------------------------------------------------------------+ //| Include | //+------------------------------------------------------------------+ //--- Config tab (base runner) #include "ConfigTab.mqh" //+-------------------------------------------------------------------------------+ //| Clase intermediairoa dado que CManagerBasesSimple es generico necesitaremos | //| que el padre ya le de lo que necesite el "abuelo" | //+-------------------------------------------------------------------------------+ class CTrainingResultsAlmacenadorInt : public CGuiBaseComponent { public: CTrainingResultsAlmacenadorInt(void) : CGuiBaseComponent("CTrainingResultsAlmacenador") {} ~CTrainingResultsAlmacenadorInt(void) {} }; //+------------------------------------------------------------------+ //| Clase interfaz para alamcenjks los json | //+------------------------------------------------------------------+ class CTrainingResultsAlmacenador : public CManagerBasesSimple { protected: //--- Espacio donde dibuja int m_top_gap; int m_left_gap; int m_right_gap; int m_bottom_gap; //--- Púnteros a win y al creador de objetos CWindow* m_win; CWndCreate* m_creator; public: CTrainingResultsAlmacenador() {} ~CTrainingResultsAlmacenador() {} //--- virtual bool Set(int top_gap, int left_gap, int right_gap, int bottom_gap, CWindow* win, CWndCreate* wnd_create) = 0; //--- virtual void Show(const int row) = 0; // con eso se hara el key luego }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #define AIDATATASKRUNER_TRAINING_COL_PATH (0) #define AIDATATASKRUNER_TRAINING_COL_TYPE (1) #define AIDATATASKRUNER_TRAINING_COL_VIEW (2) #define AIDATATASKRUNER_TRAINING_TOTALCOLS (3) //--- #resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\settings_light.bmp" string g_arr_training_tab_results_bottom[1] = { "Images\\EasyAndFastGUI\\Icons\\bmp16\\settings_light.bmp" }; /* [CTrainingTabResults] m_table_res_header="Ruta|Tipo|Mirar" */ //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CTrainingTabResults : public CGuiBaseComponent { private: //--- // Visualiza y alamcana los resutlados CTrainingResultsAlmacenador* m_res_almacenanor; //--- CTable m_table_res; public: CTrainingTabResults(void) : CGuiBaseComponent("CTrainingTabResults"), m_res_almacenanor(NULL) {} ~CTrainingTabResults(void) { if(::CheckPointer(m_res_almacenanor) == POINTER_DYNAMIC) delete m_res_almacenanor; } //--- void SetExtra(CTrainingResultsAlmacenador* container) { m_res_almacenanor = container; } bool Create(CWndCreate* p, CWindow& main_window, int top_gap, int left_gap, int right_gap, int bottom_gap); //--- void OnTrainingInit() override final; void OnTrainingNewResult(CJson* json) override final; //--- bool OnClickButtom(const long lparam, const string& sparam); // En este caso lo delegamos dado que la clase como tal no usa on lan change void OnLenguajeChange() override final; //--- __forceinline uint8_t EventsFlags() const override final { return TRAINING_RUNNER_PY_FLAG_ON_TRAINIG | TRAINING_RUNNER_PY_FLAG_ON_INIT; } }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingTabResults::Create(CWndCreate *p, CWindow &main_window, int top_gap, int left_gap, int right_gap, int bottom_gap) { //--- int x = left_gap + 10; int y = top_gap + 15; //--- const int initial_right = right_gap; bottom_gap += 5; // Ancho en x para el textbox right_gap += 185; // Mas arriba 5 //--- string headers[]; const string header_str = m_language[GUIBASE_COMPONENT_NAME(m_table_res) + "_header"]; if(!StrTo::CstArray(headers, header_str, '|', true)) { LogError(StringFormat("Fallo al hacer str to arrary str, str = %s", header_str), FUNCION_ACTUAL); return false; } ArrayResize(headers, AIDATATASKRUNER_TRAINING_TOTALCOLS); // Trim en caso de exendete // Aling ENUM_ALIGN_MODE align[AIDATATASKRUNER_TRAINING_TOTALCOLS]; ArrayFill(align, 0, AIDATATASKRUNER_TRAINING_TOTALCOLS, ALIGN_LEFT); //--- Colores // Headers m_table_res.HeadersColor(C'0x2A,0x4A,0x6A'); // azul oscuro m_table_res.HeadersColorHover(AIDATATASKRUNER_COLOR_ACCENT); // azul accent hover m_table_res.HeadersColorPressed(C'0x1E,0x38,0x52'); // más oscuro al presionar m_table_res.HeadersTextColor(AIDATATASKRUNER_COLOR_TEXT_PRIMARY); // Celdas m_table_res.CellColor(AIDATATASKRUNER_COLOR_FONDO_WIN); // C'37,40,54' m_table_res.CellColorHover(AIDATATASKRUNER_COLOR_EDIT_BACK); // C'0x37,0x3D,0x53' hover sutil m_table_res.CElement::BackColor(AIDATATASKRUNER_COLOR_FONDO_WIN); // Grid m_table_res.GridColor(AIDATATASKRUNER_COLOR_BORDER); // C'58,63,82' sutil // Texto celdas - vía CellInitialize usa m_label_color // necesitas setearlo antes de crear: m_table_res.m_label_color = AIDATATASKRUNER_COLOR_TEXT_SECONDARY; //--- CScrollH *sh = m_table_res.GetScrollHPointer(); // Fondo de la barra (el riel) sh.BackColor(AIDATATASKRUNER_COLOR_FONDO_TAB); // C'26,29,39' - oscuro // Ползunок (thumb) en 3 estados sh.ThumbColor(AIDATATASKRUNER_COLOR_BORDER); // C'58,63,82' - reposo sutil sh.ThumbColorHover(AIDATATASKRUNER_COLOR_BORDER_HOVER); // C'61,142,240' - hover azul sh.ThumbColorPressed(AIDATATASKRUNER_COLOR_ACCENT); // C'0x69,0xA8,0xF3' - presionado // Forzar iconos blancos sh.IncFile((string)RESOURCE_SCROLL_LEFT_WHITE); sh.IncFileLocked((string)RESOURCE_SCROLL_LEFT_WHITE); sh.IncFilePressed((string)RESOURCE_SCROLL_LEFT_WHITE); sh.DecFile((string)RESOURCE_SCROLL_RIGHT_WHITE); sh.DecFileLocked((string)RESOURCE_SCROLL_RIGHT_WHITE); sh.DecFilePressed((string)RESOURCE_SCROLL_RIGHT_WHITE); //--- Base m_table_res.CellYSize(30); m_table_res.FontSize(10); m_table_res.HeaderYSize(25); m_table_res.IsSortMode(true); m_table_res.DefaultTextAlign(ALIGN_LEFT); // m_table_res.TableSize(AIDATATASKRUNER_TRAINING_TOTALCOLS, 1); // m_table_res.DataType(AIDATATASKRUNER_TRAINING_COL_PATH, TYPE_STRING); m_table_res.SetValue(AIDATATASKRUNER_TRAINING_COL_PATH, 0, ""); m_table_res.DataType(AIDATATASKRUNER_TRAINING_COL_TYPE, TYPE_STRING); m_table_res.SetValue(AIDATATASKRUNER_TRAINING_COL_TYPE, 0, ""); m_table_res.DataType(AIDATATASKRUNER_TRAINING_COL_VIEW, TYPE_STRING); m_table_res.SetValue(AIDATATASKRUNER_TRAINING_COL_VIEW, 0, ""); m_table_res.CellType(AIDATATASKRUNER_TRAINING_COL_VIEW, 0, CELL_BUTTON); // m_table_res.SetImages(AIDATATASKRUNER_TASK_TABLLE_ESTADO, 0, g_taskruner_ai_dgen_main_images); // m_table_res.ChangeImage(AIDATATASKRUNER_TASK_TABLLE_ESTADO, 0, 2); // gris // m_table_res.DataType(AIDATATASKRUNER_TASK_TABLLE_MODIFICAR, TYPE_DATETIME); // int arr_offset_imgeage_x[AIDATATASKRUNER_TRAINING_TOTALCOLS]; int arr_offset_imgeage_y[AIDATATASKRUNER_TRAINING_TOTALCOLS]; ArrayFill(arr_offset_imgeage_x, 0, AIDATATASKRUNER_TRAINING_TOTALCOLS, 0); ArrayFill(arr_offset_imgeage_y, 0, AIDATATASKRUNER_TRAINING_TOTALCOLS, 0); arr_offset_imgeage_y[AIDATATASKRUNER_TRAINING_COL_VIEW] = 5; arr_offset_imgeage_x[AIDATATASKRUNER_TRAINING_COL_VIEW] = 5; m_table_res.ImageXOffset(arr_offset_imgeage_x); m_table_res.ImageYOffset(arr_offset_imgeage_y); //--- int text_x_offset[AIDATATASKRUNER_TRAINING_TOTALCOLS]; ::ArrayInitialize(text_x_offset, 10); m_table_res.TextXOffset(text_x_offset); text_x_offset[AIDATATASKRUNER_TRAINING_COL_VIEW] += 35; // Width //--- int widths[AIDATATASKRUNER_TRAINING_TOTALCOLS]; //--- int x_size_table = main_window.XSize() - right_gap - left_gap; //--- Hagamos un resize debdio a que los nombres de los params y modelos aveces son GRADENS widths[AIDATATASKRUNER_TRAINING_COL_PATH] = (x_size_table - 150); widths[AIDATATASKRUNER_TRAINING_COL_TYPE] = 80; widths[AIDATATASKRUNER_TRAINING_COL_VIEW] = 100; //--- m_table_res.ColumnsWidth(widths); //--- if(!p.CreateTable( m_table_res, main_window, 0, m_base_tab, m_base_tab_idx, AIDATATASKRUNER_TRAINING_TOTALCOLS, 1, headers, x, y, 0, 0, false, false, right_gap, bottom_gap )) { AIDATATASKRUNER_ERROR_CREATION(m_table_res); return false; } //--- x += m_table_res.XSize() + 5; // Avanza (+ gap de 5) //--- if(!m_res_almacenanor.Set(y, x, initial_right, bottom_gap, &main_window, p)) { AIDATATASKRUNER_ERROR_CREATION(m_res_almacenanor); return false; } //--- return true; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabResults::OnLenguajeChange(void) { m_res_almacenanor.OnLenguajeChange(); // Headers de la tabla const string header_str = m_language[AIDATATASKRUNNERL_COMPONENT_NAME(m_table_res) + "_header"]; string headers[]; if(StrTo::CstArray(headers, header_str, '|', true)) { const int cols = (int)m_table_res.ColumnsTotal(); for(int i = 0; i < cols; i++) { m_table_res.SetHeaderText(i, headers[i]); } m_table_res.Update(true); } else { LogError("Fallo al hacer split str array en table res", FUNCION_ACTUAL); } } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabResults::OnTrainingInit(void) { //--- Limpiamos la tabla de resultados m_table_res.ResizeRows(0); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CTrainingTabResults::OnTrainingNewResult(CJson *json) { //--- int idx; if(m_table_res.RowsTotal() == 1 && m_table_res.GetValue(0, 0) == "") { idx = 0; } else { idx = (int)m_table_res.RowsTotal(); m_table_res.AddRow(idx); } //--- Path m_table_res.SetValue(AIDATATASKRUNER_TRAINING_COL_PATH, idx, json["path"].ToString("?")); //--- Tipo m_table_res.SetValue(AIDATATASKRUNER_TRAINING_COL_TYPE, idx, json["type"].ToString("?")); //--- Bottom m_table_res.SetImages(AIDATATASKRUNER_TRAINING_COL_VIEW, idx, g_arr_training_tab_results_bottom); m_table_res.SetValue(AIDATATASKRUNER_TRAINING_COL_VIEW, idx, "View"); m_table_res.CellType(AIDATATASKRUNER_TRAINING_COL_VIEW, idx, CELL_BUTTON); //--- m_table_res.Update(true); //--- m_res_almacenanor.AddItemFast(json); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool CTrainingTabResults::OnClickButtom(const long lparam, const string &sparam) { if(lparam == m_table_res.Id() && sparam.Length() > 3 && sparam[0] == 'c' && sparam[1] == 'e' && sparam[2] == 'l' && sparam[3] == 'l') // Click en cell { const int row = int(StringSubstr(sparam, 6)); // Desde la posicion 2 hasta todo (inlcuen [c][e][l][l][N][_][A]) m_res_almacenanor.Show(row); return true; } return false; } //+------------------------------------------------------------------+ #endif // AIDATATASKRUNER_UI_TRAINING_RESULTTAB_MQH