2026-03-20 17:16:21 -05:00 | | | //+------------------------------------------------------------------+
|
2026-02-24 10:16:05 -05:00 | | | //| 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"
|
2026-03-20 17:16:21 -05:00 | | | #property strict
|
| | |
|
| | | #ifndef AIDATATASKRUNER_UI_TRAINING_RESULTTAB_MQH
|
| | | #define AIDATATASKRUNER_UI_TRAINING_RESULTTAB_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-03-20 21:40:41 -05:00 | | | //| Include |
|
2026-03-20 17:16:21 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //--- Config tab (base runner)
|
| | | #include "ConfigTab.mqh"
|
| | |
|
2026-03-20 21:40:41 -05:00 | | | //+-------------------------------------------------------------------------------+
|
| | | //| Clase intermediairoa dado que CManagerBasesSimple es generico necesitaremos |
|
| | | //| que el padre ya le de lo que necesite el "abuelo" |
|
| | | //+-------------------------------------------------------------------------------+
|
2026-03-20 17:16:21 -05:00 | | | class CTrainingResultsAlmacenadorInt : public CGuiBaseComponent<IRunPy>
|
| | | {
|
| | | public:
|
| | | CTrainingResultsAlmacenadorInt(void) : CGuiBaseComponent<IRunPy>("CTrainingResultsAlmacenador") {}
|
| | | ~CTrainingResultsAlmacenadorInt(void) {}
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-03-20 21:40:41 -05:00 | | | //| Clase interfaz para alamcenjks los json |
|
2026-03-20 17:16:21 -05:00 | | | //+------------------------------------------------------------------+
|
2026-06-03 22:07:50 -05:00 | | | class CTrainingResultsAlmacenador : public CTrainingResultsAlmacenadorInt
|
2026-03-20 17:16:21 -05:00 | | | {
|
2026-03-20 21:40:41 -05:00 | | | protected:
|
2026-06-03 22:07:50 -05:00 | | | //---
|
2026-07-07 19:11:54 -05:00 | | | struct TrainingResultSnapshot
|
| | | {
|
| | | string lines[];
|
| | | };
|
| | | TrainingResultSnapshot m_data[];
|
2026-06-03 22:07:50 -05:00 | | | int m_data_size;
|
| | |
|
2026-03-20 17:16:21 -05:00 | | | //--- 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() {}
|
| | |
|
| | | //---
|
2026-03-20 21:40:41 -05:00 | | | virtual bool Set(int top_gap, int left_gap, int right_gap, int bottom_gap, CWindow* win, CWndCreate* wnd_create) = 0;
|
2026-03-20 17:16:21 -05:00 | | |
|
| | |
|
| | | //---
|
2026-04-11 07:16:03 -05:00 | | | virtual void Show(const int row) = 0; // con eso se hara el key luego
|
2026-03-20 17:16:21 -05:00 | | | };
|
| | |
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #define AIDATATASKRUNER_TRAINING_COL_PATH (0)
|
| | | #define AIDATATASKRUNER_TRAINING_COL_TYPE (1)
|
| | | #define AIDATATASKRUNER_TRAINING_COL_VIEW (2)
|
| | | #define AIDATATASKRUNER_TRAINING_TOTALCOLS (3)
|
| | |
|
| | | //---
|
2026-03-21 08:06:31 -05:00 | | | #resource "\\Images\\EasyAndFastGUI\\Icons\\bmp16\\settings_light.bmp"
|
2026-03-20 17:16:21 -05:00 | | | string g_arr_training_tab_results_bottom[1] =
|
| | | {
|
2026-03-21 08:06:31 -05:00 | | | "Images\\EasyAndFastGUI\\Icons\\bmp16\\settings_light.bmp"
|
2026-03-20 17:16:21 -05:00 | | | };
|
| | |
|
2026-03-21 08:06:31 -05:00 | | | /*
|
| | | [CTrainingTabResults]
|
| | | m_table_res_header="Ruta|Tipo|Mirar"
|
| | | */
|
| | |
|
2026-03-20 17:16:21 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class CTrainingTabResults : public CGuiBaseComponent<IRunPy>
|
| | | {
|
| | | private:
|
| | | //---
|
| | | // Visualiza y alamcana los resutlados
|
| | | CTrainingResultsAlmacenador* m_res_almacenanor;
|
| | |
|
| | | //---
|
| | | CTable m_table_res;
|
| | |
|
| | | public:
|
2026-03-20 21:40:41 -05:00 | | | CTrainingTabResults(void) : CGuiBaseComponent<IRunPy>("CTrainingTabResults"), m_res_almacenanor(NULL) {}
|
| | | ~CTrainingTabResults(void) { if(::CheckPointer(m_res_almacenanor) == POINTER_DYNAMIC) delete m_res_almacenanor; }
|
2026-03-20 17:16:21 -05:00 | | |
|
| | | //---
|
| | | 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;
|
2026-06-03 22:07:50 -05:00 | | | void OnTrainingNewResult(TSN::CJsonNode& json) override final;
|
2026-03-20 17:16:21 -05:00 | | |
|
| | | //---
|
| | | bool OnClickButtom(const long lparam, const string& sparam);
|
2026-03-20 21:40:41 -05:00 | | | // En este caso lo delegamos dado que la clase como tal no usa on lan change
|
2026-03-21 08:06:31 -05:00 | | | void OnLenguajeChange() override final;
|
| | |
|
| | | //---
|
| | | __forceinline uint8_t EventsFlags() const override final { return TRAINING_RUNNER_PY_FLAG_ON_TRAINIG | TRAINING_RUNNER_PY_FLAG_ON_INIT; }
|
2026-03-20 17:16:21 -05:00 | | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | 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;
|
| | |
|
| | | //---
|
2026-03-21 11:41:29 -05:00 | | | const int initial_right = right_gap;
|
| | | bottom_gap += 5; // Ancho en x para el textbox
|
| | | right_gap += 185; // Mas arriba 5
|
2026-03-20 17:16:21 -05:00 | | |
|
| | | //---
|
| | | 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);
|
2026-04-11 07:16:03 -05:00 | | | text_x_offset[AIDATATASKRUNER_TRAINING_COL_VIEW] += 35;
|
2026-03-20 17:16:21 -05:00 | | |
|
| | | // Width
|
| | | //---
|
| | | int widths[AIDATATASKRUNER_TRAINING_TOTALCOLS];
|
| | |
|
2026-03-21 11:41:29 -05:00 | | | //---
|
| | | int x_size_table = main_window.XSize() - right_gap - left_gap;
|
| | |
|
2026-03-20 17:16:21 -05:00 | | | //--- Hagamos un resize debdio a que los nombres de los params y modelos aveces son GRADENS
|
2026-03-21 11:41:29 -05:00 | | | widths[AIDATATASKRUNER_TRAINING_COL_PATH] = (x_size_table - 150);
|
2026-03-20 17:16:21 -05:00 | | | widths[AIDATATASKRUNER_TRAINING_COL_TYPE] = 80;
|
2026-03-26 12:50:40 -05:00 | | | widths[AIDATATASKRUNER_TRAINING_COL_VIEW] = 100;
|
2026-03-20 17:16:21 -05:00 | | |
|
| | | //---
|
| | | m_table_res.ColumnsWidth(widths);
|
| | |
|
2026-03-21 11:41:29 -05:00 | | |
|
2026-03-20 17:16:21 -05:00 | | | //---
|
| | | 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)
|
| | |
|
| | | //---
|
2026-03-21 11:41:29 -05:00 | | | if(!m_res_almacenanor.Set(y, x, initial_right, bottom_gap, &main_window, p))
|
2026-03-20 21:40:41 -05:00 | | | {
|
| | | AIDATATASKRUNER_ERROR_CREATION(m_res_almacenanor);
|
| | | return false;
|
| | | }
|
2026-03-20 17:16:21 -05:00 | | |
|
| | | //---
|
| | | return true;
|
| | | }
|
2026-02-24 10:16:05 -05:00 | | | //+------------------------------------------------------------------+
|
2026-03-20 17:16:21 -05:00 | | | //| |
|
2026-02-24 10:16:05 -05:00 | | | //+------------------------------------------------------------------+
|
2026-03-21 08:06:31 -05:00 | | | 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);
|
| | | }
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
2026-03-20 17:16:21 -05:00 | | | void CTrainingTabResults::OnTrainingInit(void)
|
| | | {
|
| | | //--- Limpiamos la tabla de resultados
|
2026-04-11 07:16:03 -05:00 | | | m_table_res.ResizeRows(0);
|
2026-03-20 17:16:21 -05:00 | | | }
|
2026-02-24 10:16:05 -05:00 | | | //+------------------------------------------------------------------+
|
2026-03-20 17:16:21 -05:00 | | | //| |
|
2026-02-24 10:16:05 -05:00 | | | //+------------------------------------------------------------------+
|
2026-06-03 22:07:50 -05:00 | | | void CTrainingTabResults::OnTrainingNewResult(TSN::CJsonNode& json)
|
2026-03-20 17:16:21 -05:00 | | | {
|
| | | //---
|
| | | 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);
|
| | | }
|
2026-03-20 21:40:41 -05:00 | | |
|
2026-02-24 10:16:05 -05:00 | | | //+------------------------------------------------------------------+
|
2026-03-20 17:16:21 -05:00 | | | //| |
|
2026-02-24 10:16:05 -05:00 | | | //+------------------------------------------------------------------+
|
2026-03-20 17:16:21 -05:00 | | | 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])
|
2026-04-11 07:16:03 -05:00 | | | m_res_almacenanor.Show(row);
|
2026-03-20 17:16:21 -05:00 | | | return true;
|
| | | }
|
| | | return false;
|
| | | }
|
| | |
|
| | |
|
2026-02-24 10:16:05 -05:00 | | | //+------------------------------------------------------------------+
|
2026-03-20 17:16:21 -05:00 | | | #endif // AIDATATASKRUNER_UI_TRAINING_RESULTTAB_MQH
|