AiDataTaskRuner/UI/Training/ResultsTab.mqh
Nique_372 fe0fe88421
2026-03-21 11:41:29 -05:00

359 lines
13 KiB
MQL5

//+------------------------------------------------------------------+
//| 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<IRunPy>
{
public:
CTrainingResultsAlmacenadorInt(void) : CGuiBaseComponent<IRunPy>("CTrainingResultsAlmacenador") {}
~CTrainingResultsAlmacenadorInt(void) {}
};
//+------------------------------------------------------------------+
//| Clase interfaz para alamcenjks los json |
//+------------------------------------------------------------------+
class CTrainingResultsAlmacenador : public CManagerBasesSimple<CJson, CTrainingResultsAlmacenadorInt>
{
protected:
CHashMap<string, int> m_hash_key_to_hist_index;
//--- 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 string path, const string type) = 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<IRunPy>
{
private:
//---
// Visualiza y alamcana los resutlados
CTrainingResultsAlmacenador* m_res_almacenanor;
//---
CTable m_table_res;
public:
CTrainingTabResults(void) : CGuiBaseComponent<IRunPy>("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);
// 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] = 70;
//---
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.DeleteAllRows(true);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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(m_table_res.GetValue(AIDATATASKRUNER_TRAINING_COL_PATH, row), m_table_res.GetValue(AIDATATASKRUNER_TRAINING_COL_TYPE, row));
return true;
}
return false;
}
//+------------------------------------------------------------------+
#endif // AIDATATASKRUNER_UI_TRAINING_RESULTTAB_MQH