//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2018, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#define KEY_P       80

//+------------------------------------------------------------------+
//|  BUTTONS                                                         |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 0
#property strict

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
extern string  Symbols="AUDUSD;EURUSD;GBPUSD;USDCAD;USDJPY;USDCHF;XAUUSD;US500;AUDCAD;AUDCHF;AUDJPY;AUDNZD;CADCHF;CADJPY;CHFJPY;EURAUD;EURCAD;EURCHF;EURGBP;EURJPY;EURNZD;GBPAUD;GBPCAD;GBPCHF;GBPJPY;GBPNZD;NZDCAD;NZDCHF;NZDJPY;NZDUSD;USDCZK;USDSGD;XAUEUR;XTIUSD;BTCUSD;USDRUB"; // List of symbols (separated by ";")
extern string  UniqueID="changer";     // Indicator unique ID

extern int     ButtonsInARow = 8;      // Buttons in a horizontal row
extern int     Corner        = 1;      // Corner
extern int     XShift        = 1200;    // Horizontal shift
extern int     YShift        = 20;     // Vertical shift
extern int     XSize         = 100;     // Width of buttons
extern int     YSize         = 32;     // Height of buttons
extern int     FSize         = 8;     // Font size
extern string  FontType      = "Consolas" ; // Font
extern color   ButtonColor=clrWheat;        // Button color
extern color   OpenPositionColor=clrAquamarine;
extern color   PlacedOrderColor= clrBlueViolet;
extern color   PriceIsCloseColor= clrRed;
extern double DistanceInPoints = 500;



//+------------------------------------------------------------------+

string aSymbols[];
bool visible = false;
int tmpTickCounter = 0;

//+------------------------------------------------------------------+
int OnInit()
  {

   //color clr = StringToColor(clll + "," + clll + "," + clll);
   ChartSetInteger(0, CHART_FOREGROUND, false);
   ObjectSetInteger(0, "Spread", OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
   //LoadObjectsFromFile(Symbol() + "_saved_objs.txt");

   Symbols=StringTrimLeft(StringTrimRight(Symbols));
   if(StringSubstr(Symbols,StringLen(Symbols)-1,1)!=";")
      Symbols=StringConcatenate(Symbols,";");

   int s=0,i=StringFind(Symbols,";",s);
   string current;
   while(i>0)
     {
      current=StringSubstr(Symbols,s,i-s);
      ArrayResize(aSymbols,ArraySize(aSymbols)+1);
      aSymbols[ArraySize(aSymbols)-1]=current;
      s = i + 1;
      i = StringFind(Symbols,";",s);
     }


   int xpos=0,ypos=0,maxx=0,maxy=0;
   for(i=0; i<ArraySize(aSymbols); i++)
     {
      if(i>0 && MathMod(i,ButtonsInARow)==0)
        {
         xpos=0;
         ypos+=YSize+1;
        }
      createButton(UniqueID+":symbol:"+aSymbols[i],aSymbols[i],XShift-xpos,YShift+ypos);
      xpos+=XSize+1;
     }

   setSymbolButtonColor();
   setButtonsVisibility(false);

   return(0);
  }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

   //SaveObjectsToFile();
// destroys buttons
   string lookFor       = UniqueID+":";  // that contain this in the name
   int    lookForLength = StringLen(lookFor);
   for(int i=ObjectsTotal()-1; i>=0; i--)
     {
      string objectName=ObjectName(i);
      if(StringSubstr(objectName,0,lookForLength)==lookFor)
         ObjectDelete(objectName);
     }
  }
//+------------------------------------------------------------------+
void createButton(string name,string caption,int xpos,int ypos)
  {
   if(ObjectFind(name)!=0)
      ObjectCreate(name,OBJ_BUTTON,0,0,0);
   ObjectSet(name,OBJPROP_CORNER,0);
   ObjectSet(name,OBJPROP_XDISTANCE,xpos);
   ObjectSet(name,OBJPROP_YDISTANCE,ypos);
   ObjectSet(name,OBJPROP_XSIZE,XSize);
   ObjectSet(name,OBJPROP_YSIZE,YSize);
   ObjectSetText(name,caption,FSize,FontType,clrBlack);
   ObjectSet(name,OBJPROP_FONTSIZE,FSize);
   ObjectSet(name,OBJPROP_BORDER_TYPE,BORDER_FLAT);
   ObjectSet(name,OBJPROP_COLOR,clrBlack);
   
   //int clr = 125 + ypos / 1.5;
   //color button_clr = StringToColor(clr + "," + clr + "," + clr);
   
   
   ObjectSet(name,OBJPROP_BGCOLOR,ButtonColor);
   ObjectSet(name,OBJPROP_BORDER_COLOR,ButtonColor);
   ObjectSet(name,OBJPROP_STATE,false);
   ObjectSet(name,OBJPROP_HIDDEN,!visible);
   ObjectSet(name,OBJPROP_CORNER,Corner);
   ObjectSet(name,OBJPROP_BACK,false);

  }
//+------------------------------------------------------------------+
void setSymbolButtonColor()
  {
   string lookFor       = UniqueID+":symbol:";
   int    lookForLength = StringLen(lookFor);
   for(int i=ObjectsTotal()-1; i>=0; i--)
     {
      string objectName=ObjectName(i);
      if(StringSubstr(objectName,0,lookForLength)==lookFor)
         ObjectSet(objectName,OBJPROP_COLOR,clrBlack);
     }
  }
//+------------------------------------------------------------------+



//+------------------------------------------------------------------+
void updateSymbolButtonColor()
  {
   RefreshRates();
   setSymbolButtonColor();

   for(int i=(OrdersTotal()-1); i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)
        {
         Print("ERROR - Unable to select the order - ",GetLastError());
         continue;
        }

      int ordType = OrderType();

      if(ordType == OP_BUYSTOP || ordType == OP_SELLSTOP)
         continue;

      string tgOrderSymbol = OrderSymbol();
      string buttonName = UniqueID+":symbol:" + tgOrderSymbol;

      if(ordType == OP_BUY || ordType == OP_SELL)
        {
         ObjectSet(buttonName,OBJPROP_BGCOLOR,OpenPositionColor);
         ObjectSet(buttonName,OBJPROP_BORDER_COLOR,OpenPositionColor);
        }

      if(ordType == OP_BUYLIMIT || ordType == OP_SELLLIMIT)
        {
         ObjectSet(buttonName,OBJPROP_COLOR,PlacedOrderColor);
         ObjectSet(buttonName,OBJPROP_BORDER_COLOR,PlacedOrderColor);

         if(getDistanceToNearestPendingEntry(tgOrderSymbol) < DistanceInPoints)
           {
            ObjectSet(buttonName,OBJPROP_COLOR,PriceIsCloseColor);
            ObjectSet(buttonName,OBJPROP_BORDER_COLOR,PriceIsCloseColor);
           }

        }

     }
  }
//+------------------------------------------------------------------+




//+------------------------------------------------------------------+
void setButtonsVisibility(bool vis)
  {
   visible = vis;
   int    lookForLength = StringLen(UniqueID);
   for(int i=ObjectsTotal()-1; i>=0; i--)
     {
      string objectName=ObjectName(i);
      if(StringSubstr(objectName,0,lookForLength)==UniqueID)
        {
         string symbol=ObjectGetString(0,objectName,OBJPROP_TEXT);
         if(vis)
            ObjectSetInteger(0, objectName,OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);
         else
            ObjectSetInteger(0, objectName,OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
        }
     }
  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
long getChartIDFromSymbol(string sym)
  {
   long chartID=ChartFirst();
   while(chartID >= 0)
     {
      if(ChartSymbol(chartID) == sym)
         return chartID;
      chartID = ChartNext(chartID);
     }
   return -1;
  }



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double getDistanceToNearestPendingEntry(string sym)
  {
   double nearestDist = 999999999;

   for(int i=(OrdersTotal()-1); i>=0; i--)
     {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false)
        {
         Print("ERROR - Unable to select the order - ",GetLastError());
         continue;
        }

      if(OrderSymbol() != sym)
         continue;

      double curDist = MathAbs(OrderOpenPrice() - MarketInfo(sym,MODE_BID)) * MathPow(10, MarketInfo(sym,MODE_DIGITS));
      if(curDist < nearestDist)
         nearestDist = curDist;
     }
   return nearestDist;
  }



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
  {
   tmpTickCounter++;
   if(tmpTickCounter > 5)
     {
      tmpTickCounter = 0;
      if(visible)
         updateSymbolButtonColor();
     }
   return(rates_total);
  }


//+------------------------------------------------------------------+
void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
  {
   if(id==CHARTEVENT_KEYDOWN)
      if(lparam == 9)     // TAB - show buttons
        {
         if(visible)
            ObjectSetInteger(0, "Spread", OBJPROP_TIMEFRAMES,OBJ_NO_PERIODS);
         else
            ObjectSetInteger(0, "Spread", OBJPROP_TIMEFRAMES,OBJ_ALL_PERIODS);

         updateSymbolButtonColor();
         setButtonsVisibility(!visible);
        }


   if(id==CHARTEVENT_OBJECT_CLICK && ObjectGet(sparam,OBJPROP_TYPE)==OBJ_BUTTON)
     {
      if(StringFind(sparam,UniqueID+":symbol:",0)==0)    // pair button clicked
        {
         ObjectSet(sparam,OBJPROP_STATE,false);
         string pair_str = sparam;
         StringReplace(pair_str, UniqueID+":symbol:", "");  // get the pair name

         if(StringCompare(Symbol(), pair_str) != 0)    // ignore if it's the current pair
           {
            SaveObjectsToFile();

            for(int i=ObjectsTotal()-1; i>=0; i--)
               ObjectDelete(ObjectName(i));

            LoadObjectsFromFile(pair_str + "_saved_objs.txt");


            ChartSetSymbolPeriod(0, pair_str, Period());
            ChartRedraw(0);
           }


         setButtonsVisibility(false);
         fixChartMinMax();
        }
     }
  }


//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
void fixChartMinMax()
  {
   long m_shift = WindowBarsPerChart();
   if(WindowFirstVisibleBar() - WindowBarsPerChart() < 0)
      m_shift = WindowFirstVisibleBar();

   double lowest_price = iLow(NULL, 0, iLowest(NULL, 0, MODE_LOW, m_shift, MathMax(WindowFirstVisibleBar() - WindowBarsPerChart(), 0)));
   double highest_price = iHigh(NULL, 0, iHighest(NULL, 0, MODE_HIGH, m_shift, MathMax(WindowFirstVisibleBar() - WindowBarsPerChart(), 0)));

//ChartSetInteger(0,CHART_SCALEFIX,true);
   ChartSetDouble(0, CHART_FIXED_MIN, lowest_price - (highest_price-lowest_price) * 0.05);
   ChartSetDouble(0, CHART_FIXED_MAX, highest_price + (highest_price-lowest_price) * 0.05);
  }





//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SaveObjectsToFile()
  {
   int objCountToSave = 0;
   for(int i=0; i < ObjectsTotal(); i++)
     {
      string nm = ObjectName(i);
      if(StringFind(nm,UniqueID+":symbol:",0) == 0)
         continue;    // no need to save buttons
      if(StringFind(nm,"Spread",0) == 0)
         continue;               // neither spread
      if(StringFind(nm,"_SimulatonData",0) == 0)
         continue;

      objCountToSave++;
     }

// save chart objects
   int hndl = FileOpen(Symbol() + "_saved_objs.txt",FILE_WRITE|FILE_TXT);
   FileWriteString(hndl, objCountToSave + "\n");  // first string = objects count

   for(int i=0; i < ObjectsTotal(); i++)
     {

      string nm = ObjectName(i);
      
      if(StringFind(nm,UniqueID+":symbol:",0) == 0)
         continue;    // no need to save buttons
      if(StringFind(nm,"Spread",0) == 0)
         continue;               // neither spread
      if(StringFind(nm,"_SimulatonData",0) == 0)
         continue;


      string infoStr = nm + " ";
      infoStr = infoStr + ObjectType(nm)                + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_TIME1)  + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_PRICE1) + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_TIME2)  + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_PRICE2) + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_TIME3)  + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_PRICE3) + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_STYLE)  + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_WIDTH)  + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_COLOR)  + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_FILL)   + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_BACK)   + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_RAY_LEFT) + " ";
      infoStr = infoStr + ObjectGet(nm, OBJPROP_RAY_RIGHT) + " ";

      string txt = ObjectGetString(0, nm, OBJPROP_TEXT);
      StringReplace(txt, " ", "_");

      infoStr = infoStr + txt + " \n";


      FileWriteString(hndl,infoStr);
     
  }
FileClose(hndl);
//Print("Saved to file");

  }
//+------------------------------------------------------------------+


//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void LoadObjectsFromFile(string fileName)
  {

   int hndl = FileOpen(fileName,FILE_READ|FILE_TXT);

   int objsCount = FileReadString(hndl);
   //Print("O count " + objsCount);
   for(int i = 0; i < objsCount; i++)
     {
      string tmmk = FileReadString(hndl);
      string params[];
      StringSplit(tmmk, ' ', params);

      if(ArraySize(params) == 0) continue;
      string nm = params[0];

      ObjectCreate(0, nm, params[1], 0, params[2], params[3]);

      ObjectSet(nm, OBJPROP_TIME2, params[4]);
      ObjectSet(nm, OBJPROP_PRICE2, params[5]);
      ObjectSet(nm, OBJPROP_TIME3, params[6]);
      ObjectSet(nm, OBJPROP_PRICE3, params[7]);

      ObjectSet(nm, OBJPROP_STYLE, params[8]);
      ObjectSet(nm, OBJPROP_WIDTH, params[9]);
      ObjectSet(nm, OBJPROP_COLOR, params[10]);
      ObjectSet(nm, OBJPROP_FILL, params[11]);
      ObjectSet(nm, OBJPROP_BACK, params[12]);
      ObjectSet(nm, OBJPROP_RAY_LEFT, params[13]);
      ObjectSet(nm, OBJPROP_RAY_RIGHT, params[14]);

      string txt = params[15];

      StringReplace(txt, "_", " ");
      ObjectSetString(0, nm, OBJPROP_TEXT, txt);

     }
   FileClose(hndl);

  }
//+------------------------------------------------------------------+
