//+------------------------------------------------------------------+ //| Dashboard_SelfContained.mqh | //| Fully Self-Contained Dashboard with Internal Colors | //| Complete Implementation with All Functions | //+------------------------------------------------------------------+ #ifndef DASHBOARD_SELF_CONTAINED_MQH #define DASHBOARD_SELF_CONTAINED_MQH #include "DataTypes.mqh" //+------------------------------------------------------------------+ //| Dashboard Theme Enumeration | //+------------------------------------------------------------------+ enum ENUM_DASH_THEME { DASH_THEME_DARK, // Dark Professional DASH_THEME_LIGHT, // Light Modern DASH_THEME_CONTRAST, // High Contrast DASH_THEME_MATRIX, // Matrix Green DASH_THEME_OCEAN, // Ocean Blue DASH_THEME_AUTO // Auto-Adjust to Market }; //+------------------------------------------------------------------+ //| Self-Contained Dashboard Class | //+------------------------------------------------------------------+ class CDashboardSelfContained { private: //--- Dashboard Properties string m_prefix; // Object name prefix int m_x; // X position int m_y; // Y position int m_width; // Dashboard width int m_height; // Dashboard height bool m_visible; // Visibility flag bool m_compact; // Compact mode flag ENUM_DASH_THEME m_theme; // Current theme //--- Color Properties color m_colorBackground; // Background color color m_colorBorder; // Border color color m_colorText; // Text color color m_colorHeader; // Header color color m_colorSuccess; // Success color (green) color m_colorDanger; // Danger color (red) color m_colorWarning; // Warning color (orange) color m_colorInfo; // Info color (blue) //--- Object Management string m_objects[100]; // Array of object names int m_objCount; // Number of objects //--- Cache for Performance double m_lastBalance; // Last balance value double m_lastEquity; // Last equity value double m_lastDrawdown; // Last drawdown value datetime m_lastUpdate; // Last update time //--- Private Methods void CreateBackground(); void CreateHeader(); void CreateLabels(); void ApplyTheme(ENUM_DASH_THEME theme); color GetRiskColor(double riskPercent); color GetPnLColor(double value); string FormatMoney(double value); string FormatPercent(double value); void UpdateLabel(string suffix, string text, color clr = clrNONE); bool ObjectExists(string name); void AddObject(string name); public: //--- Constructor/Destructor CDashboardSelfContained(); ~CDashboardSelfContained(); //--- Main Public Methods bool Create(string name, int x, int y, int width = 320, int height = 200); void Update(const RiskMetrics &risk, const PerformanceMetrics &perf); void Destroy(); //--- Additional Public Methods void RefreshColors(); void Resize(int newWidth = 0, int newHeight = 0); void ShowHide(bool show); void SetTheme(ENUM_DASH_THEME theme); void SetCompact(bool compact); bool IsVisible() { return m_visible; } }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CDashboardSelfContained::CDashboardSelfContained() { m_prefix = "DSC_" + IntegerToString(GetTickCount()) + "_"; m_x = 10; m_y = 30; m_width = 320; m_height = 200; m_visible = true; m_compact = false; m_theme = DASH_THEME_DARK; m_objCount = 0; // Initialize cache m_lastBalance = 0; m_lastEquity = 0; m_lastDrawdown = 0; m_lastUpdate = 0; // Apply default theme ApplyTheme(DASH_THEME_DARK); } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CDashboardSelfContained::~CDashboardSelfContained() { Destroy(); } //+------------------------------------------------------------------+ //| Create Dashboard | //+------------------------------------------------------------------+ bool CDashboardSelfContained::Create(string name, int x, int y, int width, int height) { // Store position and size m_x = x; m_y = y; m_width = width; m_height = height; // Update prefix with name m_prefix = "DSC_" + name + "_"; // Create visual elements CreateBackground(); CreateHeader(); CreateLabels(); return true; } //+------------------------------------------------------------------+ //| Create Background Panel | //+------------------------------------------------------------------+ void CDashboardSelfContained::CreateBackground() { string bgName = m_prefix + "BG"; if(ObjectCreate(0, bgName, OBJ_RECTANGLE_LABEL, 0, 0, 0)) { ObjectSetInteger(0, bgName, OBJPROP_XDISTANCE, m_x); ObjectSetInteger(0, bgName, OBJPROP_YDISTANCE, m_y); ObjectSetInteger(0, bgName, OBJPROP_XSIZE, m_width); ObjectSetInteger(0, bgName, OBJPROP_YSIZE, m_height); ObjectSetInteger(0, bgName, OBJPROP_BGCOLOR, m_colorBackground); ObjectSetInteger(0, bgName, OBJPROP_BORDER_TYPE, BORDER_FLAT); ObjectSetInteger(0, bgName, OBJPROP_COLOR, m_colorBorder); ObjectSetInteger(0, bgName, OBJPROP_WIDTH, 2); ObjectSetInteger(0, bgName, OBJPROP_BACK, true); ObjectSetInteger(0, bgName, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, bgName, OBJPROP_HIDDEN, false); AddObject(bgName); } } //+------------------------------------------------------------------+ //| Create Header | //+------------------------------------------------------------------+ void CDashboardSelfContained::CreateHeader() { string headerName = m_prefix + "HEADER"; if(ObjectCreate(0, headerName, OBJ_LABEL, 0, 0, 0)) { ObjectSetInteger(0, headerName, OBJPROP_XDISTANCE, m_x + m_width/2); ObjectSetInteger(0, headerName, OBJPROP_YDISTANCE, m_y + 10); ObjectSetString(0, headerName, OBJPROP_TEXT, "ERMT Dashboard"); ObjectSetString(0, headerName, OBJPROP_FONT, "Arial Bold"); ObjectSetInteger(0, headerName, OBJPROP_FONTSIZE, 10); ObjectSetInteger(0, headerName, OBJPROP_COLOR, m_colorHeader); ObjectSetInteger(0, headerName, OBJPROP_ANCHOR, ANCHOR_CENTER); ObjectSetInteger(0, headerName, OBJPROP_SELECTABLE, false); AddObject(headerName); } } //+------------------------------------------------------------------+ //| Create Labels | //+------------------------------------------------------------------+ void CDashboardSelfContained::CreateLabels() { int yPos = m_y + 35; int xLabel = m_x + 10; int xValue = m_x + 150; int lineHeight = 20; // Define label pairs string labels[][2] = { {"Balance:", "BALANCE"}, {"Equity:", "EQUITY"}, {"Profit/Loss:", "PNL"}, {"Drawdown:", "DRAWDOWN"}, {"Risk Level:", "RISK"}, {"Open Positions:", "POSITIONS"}, {"Win Rate:", "WINRATE"} }; int numLabels = m_compact ? 4 : ArrayRange(labels, 0); for(int i = 0; i < numLabels; i++) { // Create label text string labelName = m_prefix + labels[i][1] + "_L"; if(ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0)) { ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, xLabel); ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, yPos); ObjectSetString(0, labelName, OBJPROP_TEXT, labels[i][0]); ObjectSetString(0, labelName, OBJPROP_FONT, "Consolas"); ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 9); ObjectSetInteger(0, labelName, OBJPROP_COLOR, m_colorText); ObjectSetInteger(0, labelName, OBJPROP_SELECTABLE, false); AddObject(labelName); } // Create value text string valueName = m_prefix + labels[i][1] + "_V"; if(ObjectCreate(0, valueName, OBJ_LABEL, 0, 0, 0)) { ObjectSetInteger(0, valueName, OBJPROP_XDISTANCE, xValue); ObjectSetInteger(0, valueName, OBJPROP_YDISTANCE, yPos); ObjectSetString(0, valueName, OBJPROP_TEXT, "---"); ObjectSetString(0, valueName, OBJPROP_FONT, "Consolas"); ObjectSetInteger(0, valueName, OBJPROP_FONTSIZE, 9); ObjectSetInteger(0, valueName, OBJPROP_COLOR, m_colorInfo); ObjectSetInteger(0, valueName, OBJPROP_SELECTABLE, false); AddObject(valueName); } yPos += lineHeight; } } //+------------------------------------------------------------------+ //| Update Dashboard | //+------------------------------------------------------------------+ void CDashboardSelfContained::Update(const RiskMetrics &risk, const PerformanceMetrics &perf) { // Get current account info double balance = AccountInfoDouble(ACCOUNT_BALANCE); double equity = AccountInfoDouble(ACCOUNT_EQUITY); double pnl = equity - balance; // Update Balance UpdateLabel("BALANCE_V", FormatMoney(balance), m_colorText); // Update Equity UpdateLabel("EQUITY_V", FormatMoney(equity), equity >= balance ? m_colorSuccess : m_colorDanger); // Update P&L UpdateLabel("PNL_V", FormatMoney(pnl), GetPnLColor(pnl)); // Update Drawdown UpdateLabel("DRAWDOWN_V", FormatPercent(risk.currentDrawdown), GetRiskColor(risk.currentDrawdown)); // Update Risk Level UpdateLabel("RISK_V", FormatPercent(risk.totalRisk), GetRiskColor(risk.totalRisk)); // Update Open Positions UpdateLabel("POSITIONS_V", IntegerToString(risk.openPositions), m_colorInfo); // Update Win Rate if(!m_compact) { UpdateLabel("WINRATE_V", FormatPercent(perf.winRate), perf.winRate >= 50 ? m_colorSuccess : m_colorWarning); } // Store last update time m_lastUpdate = TimeCurrent(); ChartRedraw(); } //+------------------------------------------------------------------+ //| Refresh Colors | //+------------------------------------------------------------------+ void CDashboardSelfContained::RefreshColors() { // Update background string bgName = m_prefix + "BG"; if(ObjectExists(bgName)) { ObjectSetInteger(0, bgName, OBJPROP_BGCOLOR, m_colorBackground); ObjectSetInteger(0, bgName, OBJPROP_COLOR, m_colorBorder); } // Update header string headerName = m_prefix + "HEADER"; if(ObjectExists(headerName)) { ObjectSetInteger(0, headerName, OBJPROP_COLOR, m_colorHeader); } // Update all labels for(int i = 0; i < m_objCount; i++) { if(StringFind(m_objects[i], "_L") > 0) { ObjectSetInteger(0, m_objects[i], OBJPROP_COLOR, m_colorText); } } ChartRedraw(); } //+------------------------------------------------------------------+ //| Resize Dashboard | //+------------------------------------------------------------------+ void CDashboardSelfContained::Resize(int newWidth, int newHeight) { // Update dimensions if provided if(newWidth > 0) m_width = newWidth; if(newHeight > 0) m_height = newHeight; // Update background size string bgName = m_prefix + "BG"; if(ObjectExists(bgName)) { ObjectSetInteger(0, bgName, OBJPROP_XSIZE, m_width); ObjectSetInteger(0, bgName, OBJPROP_YSIZE, m_height); } // Update header position string headerName = m_prefix + "HEADER"; if(ObjectExists(headerName)) { ObjectSetInteger(0, headerName, OBJPROP_XDISTANCE, m_x + m_width/2); } ChartRedraw(); } //+------------------------------------------------------------------+ //| Show or Hide Dashboard | //+------------------------------------------------------------------+ void CDashboardSelfContained::ShowHide(bool show) { m_visible = show; long visibility = show ? OBJ_ALL_PERIODS : OBJ_NO_PERIODS; for(int i = 0; i < m_objCount; i++) { if(ObjectExists(m_objects[i])) { ObjectSetInteger(0, m_objects[i], OBJPROP_TIMEFRAMES, visibility); } } ChartRedraw(); } //+------------------------------------------------------------------+ //| Set Theme | //+------------------------------------------------------------------+ void CDashboardSelfContained::SetTheme(ENUM_DASH_THEME theme) { m_theme = theme; ApplyTheme(theme); RefreshColors(); } //+------------------------------------------------------------------+ //| Set Compact Mode | //+------------------------------------------------------------------+ void CDashboardSelfContained::SetCompact(bool compact) { if(m_compact != compact) { m_compact = compact; // Destroy and recreate with new layout Destroy(); Create(m_prefix, m_x, m_y, m_width, m_compact ? 120 : 200); } } //+------------------------------------------------------------------+ //| Apply Theme Colors | //+------------------------------------------------------------------+ void CDashboardSelfContained::ApplyTheme(ENUM_DASH_THEME theme) { switch(theme) { case DASH_THEME_DARK: m_colorBackground = C'20,20,20'; m_colorBorder = clrDimGray; m_colorText = clrWhiteSmoke; m_colorHeader = clrGold; m_colorSuccess = clrLime; m_colorDanger = clrRed; m_colorWarning = clrOrange; m_colorInfo = clrDodgerBlue; break; case DASH_THEME_LIGHT: m_colorBackground = clrWhite; m_colorBorder = clrLightGray; m_colorText = clrBlack; m_colorHeader = clrNavy; m_colorSuccess = clrGreen; m_colorDanger = clrCrimson; m_colorWarning = clrDarkOrange; m_colorInfo = clrRoyalBlue; break; case DASH_THEME_CONTRAST: m_colorBackground = clrBlack; m_colorBorder = clrWhite; m_colorText = clrWhite; m_colorHeader = clrYellow; m_colorSuccess = clrLime; m_colorDanger = clrRed; m_colorWarning = clrMagenta; m_colorInfo = clrCyan; break; case DASH_THEME_MATRIX: m_colorBackground = clrBlack; m_colorBorder = clrDarkGreen; m_colorText = clrLightGreen; m_colorHeader = clrLime; m_colorSuccess = clrLightGreen; m_colorDanger = clrDarkRed; m_colorWarning = clrYellow; m_colorInfo = clrSpringGreen; break; case DASH_THEME_OCEAN: m_colorBackground = C'10,25,40'; m_colorBorder = clrSteelBlue; m_colorText = clrLightCyan; m_colorHeader = clrAqua; m_colorSuccess = clrAquamarine; m_colorDanger = clrCoral; m_colorWarning = clrGold; m_colorInfo = clrDeepSkyBlue; break; default: ApplyTheme(DASH_THEME_DARK); break; } } //+------------------------------------------------------------------+ //| Get Risk Color Based on Percentage | //+------------------------------------------------------------------+ color CDashboardSelfContained::GetRiskColor(double riskPercent) { if(riskPercent <= 1.0) return m_colorSuccess; else if(riskPercent <= 2.0) return m_colorWarning; else return m_colorDanger; } //+------------------------------------------------------------------+ //| Get P&L Color | //+------------------------------------------------------------------+ color CDashboardSelfContained::GetPnLColor(double value) { if(value > 0) return m_colorSuccess; else if(value < 0) return m_colorDanger; else return m_colorText; } //+------------------------------------------------------------------+ //| Format Money Value | //+------------------------------------------------------------------+ string CDashboardSelfContained::FormatMoney(double value) { string sign = value < 0 ? "-$" : "$"; value = MathAbs(value); if(value >= 1000000) return sign + DoubleToString(value/1000000, 2) + "M"; else if(value >= 10000) return sign + DoubleToString(value/1000, 1) + "K"; else return sign + DoubleToString(value, 2); } //+------------------------------------------------------------------+ //| Format Percentage | //+------------------------------------------------------------------+ string CDashboardSelfContained::FormatPercent(double value) { return DoubleToString(value, 2) + "%"; } //+------------------------------------------------------------------+ //| Update Label | //+------------------------------------------------------------------+ void CDashboardSelfContained::UpdateLabel(string suffix, string text, color clr) { string objName = m_prefix + suffix; if(ObjectExists(objName)) { // Only update if changed if(ObjectGetString(0, objName, OBJPROP_TEXT) != text) ObjectSetString(0, objName, OBJPROP_TEXT, text); // Update color if specified if(clr != clrNONE) { if((color)ObjectGetInteger(0, objName, OBJPROP_COLOR) != clr) ObjectSetInteger(0, objName, OBJPROP_COLOR, clr); } } } //+------------------------------------------------------------------+ //| Check if Object Exists | //+------------------------------------------------------------------+ bool CDashboardSelfContained::ObjectExists(string name) { return ObjectFind(0, name) >= 0; } //+------------------------------------------------------------------+ //| Add Object to Management Array | //+------------------------------------------------------------------+ void CDashboardSelfContained::AddObject(string name) { if(m_objCount < ArraySize(m_objects)) { m_objects[m_objCount++] = name; } } //+------------------------------------------------------------------+ //| Destroy Dashboard | //+------------------------------------------------------------------+ void CDashboardSelfContained::Destroy() { // Delete all objects for(int i = 0; i < m_objCount; i++) { if(ObjectExists(m_objects[i])) { ObjectDelete(0, m_objects[i]); } } // Reset counter m_objCount = 0; ChartRedraw(); } #endif // DASHBOARD_SELF_CONTAINED_MQH