//+------------------------------------------------------------------+
//|                                       Forex Market Hours GMT.mq4 |
//|                      Copyright ? 2008, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright 2008, MetaQuotes Software Corp.; Mods by B. D'Rion 2016"
#property link      "http: //www.metaquotes.net, 4XLA.org"
// v1.8 bug fixed re TimeX2, Session and Misc. tweaks, TimeBarColor
// v1.9 loops to reduce size BD
// v 2.0 more loops to reduce size RH, tweaks RH BD
// v 2.1 more precise colored session lines re start and stop times BD Mar. 2016
// v 2.3  4 sessions modes available

#property indicator_chart_window
//#import "kernel32.dll"
//int GetTimeZoneInformation(int& a0[]);
//#import

extern string season      = "S is Summer, W is Winter.";
extern string note1       = "Sessions are local 8-5, except Tokyo 9-6";

extern string season2     = "Set 'isSummerDST' False in Winter, True in Summer.";
input bool    isSummerDST = false;
extern string ffsyd       = "Forex Factory & Oanda.com put Sydney at end of NY:";
extern string note2       = "If Match_FF is true Sydney starts at 7[S] or 9[W]";
input bool    Match_FF    = false;
// input bool    FF_Sydney_Summer = false;
extern int Shift_Horiz    = 0;  // -158; //700;
extern int Shift_Vert     = 40; //-165; //400;

input color TimeBarColor  = Red;

int companion = 0;

input ENUM_BASE_CORNER InpCorner    = CORNER_LEFT_UPPER; // Chart corner for anchoring
extern string          corn         = "Coded for upper corners only.";
extern string          corn2        = "When on the right corner it reads right to left!";

extern string          bord         = "===BORDER===";
input ENUM_BORDER_TYPE InpBorder    = BORDER_FLAT;       // Border type
input color            InpBorderColor= clrDarkBlue;       // Flat border color (Flat)
input ENUM_LINE_STYLE  InpStyle     = STYLE_SOLID;       // Flat border style (Flat)
input int              InpLineWidth = 2;                 // Flat border width (Flat)


extern string          bckbx         = "===BACKGROUND BOX===";
input bool             InpBack      = false;             // Background object 
//input 
string                 InpName      = "RectLabel";       // Label name
input color            InpBackColor = clrDimGray;        //clrSkyBlue;     // Background color
extern string rect = "The following 4 settings are in case adjustment is needed.";
extern int RectWidth           = 390;
extern int RectHeight          = 116;
extern int RectX               = 0;
extern int RectY               = 0;

extern string Note1 = "Some session times are incorrect during DST transition weeks."; // or DST overlap times
extern string Note2 = "Mods by B. D'Rion, Feb.-April 2016, 4XLA in Meetup or 4xLosAngeles club";
extern string Note3 = "Further cleanup by MrPipForex, Feb. 2016, 4XLA in Meetup or 4xLosAngeles club";

int Shift_X, Shift_Y;
//input 
bool             InpSelection = false;              // Highlight to move //true;
//input 
bool             InpHidden    = false;              // Hidden in the object list //true;
//input 
long             InpZOrder    = 0;                 // Priority for mouse click

string myObjectID = "MarketHours_";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
//----
        deinit();
//----    
                
        RectX = RectX + Shift_Horiz;
        if(InpCorner == CORNER_RIGHT_UPPER) RectX += RectWidth;
        RectY = RectY + Shift_Vert;
        Shift_X = Shift_Horiz -158;
        Shift_Y = Shift_Vert  -195;
      //  Comment(" Shift_X ",Shift_X, " Shift_Y ",Shift_Y);   
      
        RectLabelCreate(companion, InpName, 0, RectX, RectY, RectWidth, RectHeight, InpBackColor, InpBorder, InpCorner,
                        InpBorderColor, InpStyle, InpLineWidth, InpBack, InpSelection, InpHidden, InpZOrder);

       
        market_hours_box_VERTS();     
        market_hours_box_HORIZ(); 
        trading_session();
        timer();     
//----
    return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
//----
    DeleteMyObjects();
    RectLabelDelete(0,InpName);
//----
    return(0);
}


//+------------------------------------------------------------------+
//| Create rectangle label                                           |
//+------------------------------------------------------------------+
bool RectLabelCreate(const long chart_ID = 0,                           // chart's ID
                     const string name = "RectLabel",                   // label name
                     const int sub_window = 0,                          // subwindow index
                     int x = 50,                                        // X coordinate
                     int y = 130,                                       // Y coordinate
                     int width = 307,                                   // RectWidth
                     int height = 150,                                  // RectHeight
                     color back_clr = C'236,233,216',                  // background color
                     const ENUM_BORDER_TYPE border = BORDER_SUNKEN,     // border type
                     const ENUM_BASE_CORNER corner = CORNER_LEFT_UPPER, // chart corner for anchoring
                     color clr = clrRed,                                // flat border color (Flat)
                     const ENUM_LINE_STYLE style = STYLE_SOLID,         // flat border style
                     const int line_width = 1,                          // flat border width
                     const bool back = TRUE,                            //false,       // in the background
                     const bool selection = false,                      // highlight to move
                     const bool hidden = false,                         //true,      // hidden in the object list
                     const long z_order = 0)                            // priority for mouse click
{
//--- reset the error value
    ResetLastError();
//--- create a rectangle label
    if (!ObjectCreate(chart_ID, name, OBJ_RECTANGLE_LABEL, sub_window, 0, 0))
    {
        Print(__FUNCTION__,
              ": failed to create a rectangle label! Error code = ", GetLastError());
        return(false);
    }
//--- set label coordinates
    ObjectSetInteger(chart_ID, name, OBJPROP_XDISTANCE, x);
    ObjectSetInteger(chart_ID, name, OBJPROP_YDISTANCE, y);
//--- set label size
    ObjectSetInteger(chart_ID, name, OBJPROP_XSIZE, width);
    ObjectSetInteger(chart_ID, name, OBJPROP_YSIZE, height);
//--- set background color
    ObjectSetInteger(chart_ID, name, OBJPROP_BGCOLOR, back_clr);
//--- set border type
    ObjectSetInteger(chart_ID, name, OBJPROP_BORDER_TYPE, border);
//--- set the chart's corner, relative to which point coordinates are defined
    ObjectSetInteger(chart_ID, name, OBJPROP_CORNER, corner);
//--- set flat border color (in Flat mode)
    ObjectSetInteger(chart_ID, name, OBJPROP_COLOR, clr);
//--- set flat border line style
    ObjectSetInteger(chart_ID, name, OBJPROP_STYLE, style);
//--- set flat border width
    ObjectSetInteger(chart_ID, name, OBJPROP_WIDTH, line_width);
//--- display in the foreground (false) or background (true)
    ObjectSetInteger(chart_ID, name, OBJPROP_BACK, back);
//--- enable (true) or disable (false) the mode of moving the label by mouse
    ObjectSetInteger(chart_ID, name, OBJPROP_SELECTABLE, selection);
    ObjectSetInteger(chart_ID, name, OBJPROP_SELECTED, selection);
//--- hide (true) or display (false) graphical object name in the object list
    ObjectSetInteger(chart_ID, name, OBJPROP_HIDDEN, hidden);
//--- set the priority for receiving the event of a mouse click in the chart
    ObjectSetInteger(chart_ID, name, OBJPROP_ZORDER, z_order);
//--- successful execution
    return(true);
}
//+------------------------------------------------------------------+ 
//| Delete the rectangle label                                       | 
//+------------------------------------------------------------------+ 
bool RectLabelDelete(const long   chart_ID=0,       // chart's ID 
                     const string name="RectLabel") // label name 
  { 
//--- reset the error value 
   ResetLastError(); 
//--- delete the label 
   if(!ObjectDelete(chart_ID,name)) 
     { 
      Print(__FUNCTION__, 
            ": failed to delete a rectangle label! Error code = ",GetLastError()); 
      return(false); 
     } 
//--- successful execution 
   return(true); 
  } 


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{

    timer();
    
    return(0);
}

void DrawSessionLines(int i, int xPos, int yPos, string  msg, color clr, int size)
{
   string ObjectID = myObjectID + "session_time_Line" + i;
   
    if (ObjectFind(ObjectID) == -1)
    {
        ObjectCreate(ObjectID, OBJ_LABEL, companion, 0, 0);
        ObjectSet(ObjectID, OBJPROP_BACK, 0);
        ObjectSet(ObjectID, OBJPROP_CORNER, InpCorner);
    }
    ObjectSet(ObjectID, OBJPROP_XDISTANCE, xPos + Shift_X);
    ObjectSet(ObjectID, OBJPROP_YDISTANCE, yPos + Shift_Y);
    ObjectSetText(ObjectID, msg, size, "Times New Roman", clr);


}

void DrawSessionLabel(int i, int xPos, int yPos, string msg, int size)
{
   string Object_ID =  myObjectID + "session_time_Label" + i;
   if (ObjectFind(Object_ID) == -1)
    {
        ObjectCreate(Object_ID, OBJ_LABEL, companion, 0, 0);
        ObjectSet(Object_ID, OBJPROP_BACK, 0);
        ObjectSet(Object_ID, OBJPROP_CORNER, InpCorner);
    }
    ObjectSet(Object_ID, OBJPROP_XDISTANCE, xPos + Shift_X); // 195
    ObjectSet(Object_ID, OBJPROP_YDISTANCE, yPos + Shift_Y);
    ObjectSetText(Object_ID, msg, size, "Tahoma", White);
}

void DisplayHours(int i, int xPos, int yPos, string msg, int size, color colr)
{
   string Object_ID = myObjectID + "session_time_hour_" + i;
   
    if (ObjectFind(Object_ID) == -1)
    {
        ObjectCreate(Object_ID, OBJ_LABEL, companion, 0, 0);
        ObjectSet(Object_ID, OBJPROP_BACK, 0);
        ObjectSet(Object_ID, OBJPROP_CORNER, InpCorner);
    }
    ObjectSet(Object_ID, OBJPROP_XDISTANCE, xPos + Shift_X);
    ObjectSet(Object_ID, OBJPROP_YDISTANCE, yPos + Shift_Y);
    ObjectSetText(Object_ID, msg, size, "Times New Roman", colr);
}

//+------------------------------------------------------------------+

string Full = "__________________________________";
// string Eur   = "______________________";

void trading_session()
{

    int i = 1, j;
    int x = 170,  y = 252; // 169, 249;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, Full, Magenta, 6);
      y += 2;
    } 
    
    DrawSessionLabel(1, 210, 259, "Tokyo GMT", 9); // 260   

//////////////////
  
    i = 9;
    if(isSummerDST == true)  x = 261;
    else x = 276;
    y = 266; //263; //265;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, Full, C'0,0,205', 6); // Blue  C'30,70,190'    33,78,209  49,92,223 Eur DarkBlue RoyalBlue
      y += 2;
    }
    
    DrawSessionLabel(2, 308, 273 , "Frankfurt GMT", 9);  /*276*/       

///////////////////

    i = 17;
    if(isSummerDST == true)  x = 276;
    else x = 291;
    y = 210; //207;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, Full,  Lime, 6); // Eur
      y += 2;
    }
     
    DrawSessionLabel(3, 320, 217, "London GMT", 9); 

///////////////////
    i = 25;
    if(isSummerDST == true)  x = 351;
    else x = 366;
    //x = 366; //365;
    y = 224; //221;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, Full,  Red, 6); // Eur
      y += 2;
    }
     
    DrawSessionLabel(4, 392, 231, "New York GMT", 9); 

///////////////////
 if(Match_FF == false)
 {
  if(isSummerDST != true) // == true)
  {
    i = 33;
    x = 486; //516; 501;
    y = 238; //235;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "____________",  Aqua, 6);
      y += 2;
    }
    
    i = 41;
    x = 171;
    y = 238; //218;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "______________________",  Aqua, 6); 
      y += 2;
    }
     
    DrawSessionLabel(5, 175, 245, "Sydney GMT", 9); //195
  }
  //else // Winter
  else  if(isSummerDST == true)
  {
    i = 33;
    x = 501;
    y = 238; //235;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "________",  Aqua, 6);
      y += 2;
    }
    
    i = 41;
    x = 171;
    y = 238; //218;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "__________________________",  Aqua, 6); 
      y += 2;
    }
     
    DrawSessionLabel(5, 195, 245, "Sydney GMT", 9); 
  }
 } // if(Match_FF == false)
 
 else // if(Match_FF == true)
 {
  if(isSummerDST != true) // == true)
  {
    i = 33;
    x = 501; // 486; //516; 
    y = 238; //235;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "________",  Aqua, 6);
      y += 2;
    }
    DrawSessionLabel(6, 503, 245, "(FF)", 9);  
    i = 41;
    x = 171;
    y = 238; //218;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "__________________________",  Aqua, 6); 
      y += 2;
    }
     
    DrawSessionLabel(5, 188, 245, "Sydney GMT", 9); //195
  }
  //else // Winter
  else  if(isSummerDST == true)
  {
    i = 33;
    x = 486; //501;
    y = 238; //235;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "____________",  Aqua, 6);
      y += 2;
    }
    DrawSessionLabel(6, 490, 245, "(FF)", 9);   
    
         
    i = 41;
    x = 171;
    y = 238; //218;
    
    for (j = i; j < i+6; j++)
    {
      DrawSessionLines(j, x, y, "______________________",  Aqua, 6); 
      y += 2;
    }
     
    DrawSessionLabel(5, 180, 245, "Sydney GMT", 9); // 195
  }
 } // if(Match_FF == true)
 
/////////////////// 0-23, W ////
    x = 170;
    y = 200;
    for (i = 0; i <= 24; i++)
    {
       if (i == 9) x = 307;
       if (i == 10) x = 315;
       if (i == 24)
       {
          if(isSummerDST == true)
          {
          DisplayHours(i, x+7, y, "S", 10, Yellow);
          x = 530;
          }
          else  // Winter
          {
          DisplayHours(i, x+6, y, "W", 10, LightBlue);
          x = 530;
          }
       }
       else
          DisplayHours(i, x, y, DoubleToStr(i, 0),8, Gainsboro);
       x+=15;
    }
    

}

void timer()
{
   string Object_ID_1 = myObjectID + "timer_bar";
   string Object_ID_2 = myObjectID + "timer_bar2"; //session_time_current2
   string Object_ID_3 = myObjectID + "timer_clock"; //time2

    // Bar
    if (ObjectFind(Object_ID_1) == -1)
    {
        ObjectCreate(Object_ID_1, OBJ_LABEL, companion, 0, 0);
        ObjectSet(Object_ID_1, OBJPROP_BACK, 0);
        ObjectSet(Object_ID_1, OBJPROP_CORNER, InpCorner);

    ObjectSet(Object_ID_1, OBJPROP_YDISTANCE, 207 + Shift_Y);
    ObjectSetText(Object_ID_1, "|", 34, "Times New Roman", TimeBarColor); // Red
    }
     
    if (ObjectFind(Object_ID_2) == -1)
    {
        ObjectCreate(Object_ID_2, OBJ_LABEL, companion, 0, 0);
        ObjectSet(Object_ID_2, OBJPROP_BACK, 0);
        ObjectSet(Object_ID_2, OBJPROP_CORNER, InpCorner);
        
    ObjectSet(Object_ID_2, OBJPROP_YDISTANCE, 241 + Shift_Y);
    ObjectSetText(Object_ID_2, "|", 34, "Times New Roman", TimeBarColor); // Red
    }
    
    // Clock
    if (ObjectFind(Object_ID_3) == -1)
    {
        ObjectCreate(Object_ID_3, OBJ_LABEL, companion, 0, 0);
        ObjectSet(Object_ID_3, OBJPROP_BACK, 0);
        ObjectSet(Object_ID_3, OBJPROP_CORNER, InpCorner);

    ObjectSet(Object_ID_3, OBJPROP_YDISTANCE, 294 + Shift_Y);
    }    

    string GMTtime = TimeToStr(TimeGMT(), TIME_MINUTES | TIME_SECONDS);
    int    GMTm    = TimeMinute(TimeGMT() );
    int    GMTh    = TimeHour(TimeGMT() );
        
    ObjectSetText(Object_ID_3, "" + GMTtime + "", 8, "Times New Roman", Gainsboro);
        //Comment(" GMTtime ",GMTtime, " GMTh ", GMTh, " GMTm ",GMTm);

    // Shift_X = -158 default //
    int PixelRange = 360; //358;
    double gmtm = GMTm; double gmth = GMTh;
    
    double TimeX;
    //gmth = 10; gmtm= 40; // for testing
    TimeX =   9 + Shift_X+158 + ((gmth+ (gmtm/60.0) )/24.0) * PixelRange;
    int TimeX2 = TimeX;
    
   if(GMTh >= 22) TimeX2 =  9 + Shift_X+158 + (22.0/24.0) * PixelRange; // 22/24 gives 0 // 10+
   // int test = 22;
   //  if(test >= 22) TimeX2 = 10+ Shift_X+158 + (22.0/24.0) * PixelRange;
      //  Comment(" Shift_X ",Shift_X," GMTh ", gmth/24, " GMTm ",gmtm/60," TimeX ",TimeX, " TimeX2 ",TimeX2); 
     //   Comment(" GMTh ",GMTh," TimeX2 ",TimeX2," ((gmth+ (gmtm/60)+.1 )/24) ",((gmth+ (gmtm/60)+.1 )/24) );
      //  Comment(" GMTh ",GMTh," TimeX ",TimeX," TimeX2 ",TimeX2," ((gmth+ (gmtm/60)+.1 )) ",((gmth+ (gmtm/60)+.1 )), " 22/24 ",22.0/24.0 );        

    ObjectSet(Object_ID_1, OBJPROP_XDISTANCE, TimeX);  // Bar
    ObjectSet(Object_ID_2, OBJPROP_XDISTANCE, TimeX);  // Bar
    ObjectSet(Object_ID_3, OBJPROP_XDISTANCE, TimeX2); // clock
}


void market_hours_box_HORIZ()
{
    int Fontsz = 10;

    for(int y=203;y<=280;)
    {
        for(int x=170;x<= 530;)
        {
            string on = myObjectID + "Horiz_"+x+","+y;
            
           // Comment(" on ",on);
            if (ObjectFind(on) == -1)
            {
                ObjectCreate(on, OBJ_LABEL, companion, 0, 0);
                ObjectSet(on, OBJPROP_BACK, 0);
                ObjectSet(on, OBJPROP_CORNER, InpCorner);
            }
            ObjectSet(on, OBJPROP_XDISTANCE, x + Shift_X);// 168
            ObjectSet(on, OBJPROP_YDISTANCE, y + Shift_Y);
            ObjectSetText(on, "_", Fontsz, "Times New Roman", Gainsboro); //Silver Yellow DarkGray
            x+=6;
        }
        y+=14;
    }
}

void market_hours_box_VERTS()
{
int Fontsz = 10;

for(int y=215;y<=280;)
    {
        for(int x=170;x<= 530;)
        {
            string on = myObjectID + "Vert_"+x+","+y;
            
           // Comment(" on ",on);
            if (ObjectFind(on) == -1)
            {
                ObjectCreate(on, OBJ_LABEL, companion, 0, 0);
                ObjectSet(on, OBJPROP_BACK, 0);
                ObjectSet(on, OBJPROP_CORNER, InpCorner);
            }
            ObjectSet(on, OBJPROP_XDISTANCE, x + Shift_X);// 168
            ObjectSet(on, OBJPROP_YDISTANCE, y + Shift_Y);
            ObjectSetText(on, "|", Fontsz, "Times New Roman", Silver); //Silver Yellow DarkGray
            x+=15;
        }
        y+=12;
    }
}

//
void DeleteMyObjects()
{

   int i, tot;
   string object_name;

   tot = ObjectsTotal();
   
   for (i = tot; i>=0;i--)
   {
    object_name = ObjectName(i);
    if (StringFind(object_name, myObjectID) > -1 ) ObjectDelete(object_name);
   }
}

//////////////////////////////////////////////////////////////////////////////////////////////////////