//+------------------------------------------------------------------+
//|                                              qwma_dashboard.mq5 |
//|                                      Generated by Gemini AI      |
//+------------------------------------------------------------------+
#property copyright "Dashboard based on mladen's qwma gradient"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0

//--- ENUMS (Must match the original indicator to pass to iCustom) ---
enum enPrices {
   pr_close, pr_open, pr_high, pr_low, pr_median, pr_typical, pr_weighted, 
   pr_average, pr_medianb, pr_tbiased, pr_tbiased2, pr_haclose, pr_haopen, 
   pr_hahigh, pr_halow, pr_hamedian, pr_hatypical, pr_haweighted, 
   pr_haaverage, pr_hamedianb, pr_hatbiased, pr_hatbiased2
};

enum chgColor {
   chg_onSlope, chg_onLevel, chg_onMiddle
};

//--- INPUTS: DASHBOARD SETTINGS ---
input string            InpIndName       = "qwma color candle gradient"; // Source Indicator File Name (Without .ex5)
input int               InpShift         = 1;                            // Bar Shift (0 = Current Open Candle, 1 = Last Closed Candle)
input int               InpCorner        = 1;                            // Corner (0=TopLeft, 1=TopRight, 2=BotLeft, 3=BotRight)
input int               InpXOffset       = 20;                           // X Offset
input int               InpYOffset       = 30;                           // Y Offset
input int               InpSpacing       = 60;                           // Spacing between blocks

//--- INPUTS: SOURCE INDICATOR SETTINGS ---
input int               MaPeriod         = 25;             // MA period
input double            MaSpeed          = 2.0;            // MA "speed"
input enPrices          MaPrice          = pr_close;       // Average price
input chgColor          ColorOn          = chg_onLevel;    // Color change on :
input int               FlPeriod         = 25;             // Period for finding floating levels
input double            FlUp             = 90;             // Upper level %
input double            FlDown           = 10;             // Lower level %
input bool              GradientColors   = true;           // Use gradient coloring?
input color             ColorUp          = clrLimeGreen;   // Up color
input color             ColorDn          = clrDarkOrange;  // Down color
input color             ColorMid         = clrDarkGray;    // Middle color
input bool              ColorCandles     = true;           // Color price candles?
input bool              Interpolate      = true;           // Interpolate when in MTF mode?

//--- GLOBALS ---
ENUM_TIMEFRAMES DashTFs[] = {PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1};
string          TfNames[] = {"M5", "M15", "M30", "H1", "H4", "D1", "W1"};
int             TfHandles[7];
string          Prefix = "qwma_dash_";

//+------------------------------------------------------------------+
//| Utility: Color Blending for Gradient                             |
//+------------------------------------------------------------------+
color mixColor(color c1, color c2, double fraction) {
    int r1 = c1 & 0xFF;         int g1 = (c1 >> 8) & 0xFF;  int b1 = (c1 >> 16) & 0xFF;
    int r2 = c2 & 0xFF;         int g2 = (c2 >> 8) & 0xFF;  int b2 = (c2 >> 16) & 0xFF;
    int r = (int)(r1 + (r2 - r1) * fraction);
    int g = (int)(g1 + (g2 - g1) * fraction);
    int b = (int)(b1 + (b2 - b1) * fraction);
    return (color)(r | (g << 8) | (b << 16));
}

//+------------------------------------------------------------------+
//| Utility: Get Exact Color mapped to Indicator's Buffer 4 Index    |
//+------------------------------------------------------------------+
color GetMappedColor(double bufferValue) {
    int i = (int)bufferValue;
    if(!GradientColors) {
        if(i == 1) return ColorUp;
        if(i == 2) return ColorDn;
        return ColorMid;
    } else {
        if (i < 0) i = 0;
        if (i > 63) i = 63;
        if (i < 32) return mixColor(ColorDn, ColorMid, i/31.0);
        else        return mixColor(ColorMid, ColorUp, (i-32)/31.0);
    }
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {
    int numTFs = ArraySize(DashTFs);
    
    for(int i = 0; i < numTFs; i++) {
        // Create Handle for each Timeframe. 
        // We set alert flags to 'false' so the dashboard doesn't spam alerts from background handles.
        TfHandles[i] = iCustom(_Symbol, DashTFs[i], InpIndName, 
                               PERIOD_CURRENT, MaPeriod, MaSpeed, MaPrice, ColorOn, 
                               FlPeriod, FlUp, FlDown, GradientColors, 
                               ColorUp, ColorDn, ColorMid, ColorCandles, 
                               false, false, false, false, false, false, Interpolate);
        
        if(TfHandles[i] == INVALID_HANDLE) {
            Print("Error: Failed to load indicator '", InpIndName, "' on TF ", EnumToString(DashTFs[i]));
            return(INIT_FAILED);
        }

        // --- Create Dashboard UI Panel Elements ---
        string bgName = Prefix + "bg_" + TfNames[i];
        ObjectCreate(0, bgName, OBJ_RECTANGLE_LABEL, 0, 0, 0);
        ObjectSetInteger(0, bgName, OBJPROP_CORNER, InpCorner);
        ObjectSetInteger(0, bgName, OBJPROP_XDISTANCE, InpXOffset + (i * InpSpacing));
        ObjectSetInteger(0, bgName, OBJPROP_YDISTANCE, InpYOffset);
        ObjectSetInteger(0, bgName, OBJPROP_XSIZE, 50);
        ObjectSetInteger(0, bgName, OBJPROP_YSIZE, 30);
        ObjectSetInteger(0, bgName, OBJPROP_BGCOLOR, clrDimGray); // default
        ObjectSetInteger(0, bgName, OBJPROP_COLOR, clrBlack); // border
        ObjectSetInteger(0, bgName, OBJPROP_BACK, false);
        
        string txtName = Prefix + "txt_" + TfNames[i];
        ObjectCreate(0, txtName, OBJ_LABEL, 0, 0, 0);
        ObjectSetInteger(0, txtName, OBJPROP_CORNER, InpCorner);
        ObjectSetInteger(0, txtName, OBJPROP_XDISTANCE, InpXOffset + (i * InpSpacing) + 25);
        ObjectSetInteger(0, txtName, OBJPROP_YDISTANCE, InpYOffset + 7);
        ObjectSetString(0, txtName, OBJPROP_TEXT, TfNames[i]);
        ObjectSetString(0, txtName, OBJPROP_FONT, "Arial");
        ObjectSetInteger(0, txtName, OBJPROP_FONTSIZE, 10);
        ObjectSetInteger(0, txtName, OBJPROP_COLOR, clrWhite);
        ObjectSetInteger(0, txtName, OBJPROP_ANCHOR, ANCHOR_TOP);
        ObjectSetInteger(0, txtName, OBJPROP_BACK, false);
    }
    
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
    ObjectsDeleteAll(0, Prefix);
    for(int i = 0; i < ArraySize(DashTFs); i++) {
        if(TfHandles[i] != INVALID_HANDLE) IndicatorRelease(TfHandles[i]);
    }
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]) 
{
    double colorIndexBuffer[1];
    
    for(int i = 0; i < ArraySize(DashTFs); i++) {
        // Buffer 4 is 'qwmac' (Color Index Buffer) in the source indicator
        if(CopyBuffer(TfHandles[i], 4, InpShift, 1, colorIndexBuffer) > 0) {
            
            // Calculate actual color based on buffer index
            color boxColor = GetMappedColor(colorIndexBuffer[0]);
            
            // Update Dashboard Box Color
            string bgName = Prefix + "bg_" + TfNames[i];
            ObjectSetInteger(0, bgName, OBJPROP_BGCOLOR, boxColor);
            
            // Optional: Adjust Text Color based on brightness for readability
            string txtName = Prefix + "txt_" + TfNames[i];
            ObjectSetInteger(0, txtName, OBJPROP_COLOR, clrWhite);
        }
    }
    
    return(rates_total);
}
//+------------------------------------------------------------------+