//+------------------------------------------------------------------+
//|                                            SynchroChart_Line.mq4 |
//|                                                   Copyright 2019 |
//|                                            http://www.fxnav.net/ |
//+------------------------------------------------------------------+

/********************************************************************
著作権は「株式会社キーストン」が有しております。
無断再配布、再編を禁止します。
使用した事によって発生した損害は、一切補償しません。
*********************************************************************/

#property copyright "FXナビ"
#property link      "http://www.fxnav.net/"
#property description "使ってみた感想などお聞かせください。"
#property description "www.fxnav.net"
#property version   "1.11"
#property strict
#property indicator_chart_window

enum sync{

   allChart = 1,     //全ての時間足で同期
   lowerChart = 2,   //下位足限定で同期
   upperChart = 3    //上位足限定で同期
};

input sync setting1 = 1;  //同期する時間足を指定

bool OneClick = false;

int OnInit(){
     
   ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
   ChartSetInteger(0, CHART_EVENT_OBJECT_CREATE, true);
   ChartSetInteger(0, CHART_EVENT_OBJECT_DELETE, true);
   
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason){

}

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[]){
   
   return(rates_total);
}

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam){

   if(id == CHARTEVENT_MOUSE_MOVE){
   
      if((uint)sparam == 1) OneClick = true;
   }
   
   if(id == CHARTEVENT_OBJECT_CREATE && OneClick){
   
      string objName = sparam;
      
      if(!objNameCheck(objName)) return;
      
      long objChartID = ChartID();
      
      ENUM_OBJECT objType = (ENUM_OBJECT)ObjectGetInteger(objChartID, objName, OBJPROP_TYPE);
      int objColor = (int)ObjectGetInteger(objChartID, objName, OBJPROP_COLOR);
      int objStyle = (int)ObjectGetInteger(objChartID, objName, OBJPROP_STYLE);
      int objWidth = (int)ObjectGetInteger(objChartID, objName, OBJPROP_WIDTH);
      bool objBack = ObjectGetInteger(objChartID, objName, OBJPROP_BACK);
      bool objRayRight = ObjectGetInteger(objChartID, objName, OBJPROP_RAY_RIGHT);
      
      int objFontSize=0;
      int objArrowCode=0;
      double objAngle=0.0, objDeviation=0.0, objScale=0.0;
      
      string objText = ObjectGetString(objChartID, objName, OBJPROP_TEXT);
      string objFont;
      
      int objX=0, objY=0, objAnchor=0;
      
      int objLevels=0;
      int objLevelColor = clrNONE;
      int objLevelStyle = 0;
      int objLevelWidth = 0;
      //double objLevelValue = 0.0;
      //string objLevelText = "";
      bool objFill = false;
      
      double objLevelValue[];
      string objLevelText[];
      
      if(objType == OBJ_TRENDBYANGLE || objType == OBJ_LABEL || objType == OBJ_TEXT){
         objAngle = ObjectGetDouble(objChartID, objName, OBJPROP_ANGLE);
      }
      
      if(objType == OBJ_STDDEVCHANNEL){
         objDeviation = ObjectGetDouble(objChartID, objName, OBJPROP_DEVIATION);
      }
      
      if(objType == OBJ_GANNFAN || objType == OBJ_GANNGRID || objType == OBJ_GANNLINE || objType == OBJ_FIBOARC){
         objScale = ObjectGetDouble(objChartID, objName, OBJPROP_SCALE);
      }
      
      if(objType == OBJ_LABEL || objType == OBJ_TEXT){
         
         objFont = ObjectGetString(objChartID, objName, OBJPROP_FONT);
         objFontSize = (int)ObjectGetInteger(objChartID, objName, OBJPROP_FONTSIZE);
      }
      
      if(objType == OBJ_LABEL){
         
         objX = (int)ObjectGetInteger(objChartID, objName, OBJPROP_XDISTANCE);
         objY = (int)ObjectGetInteger(objChartID, objName, OBJPROP_YDISTANCE);
         objAnchor = (int)ObjectGetInteger(objChartID, objName, OBJPROP_ANCHOR);
      }
      
      if(objType == OBJ_ARROW){
         objArrowCode = (int)ObjectGetInteger(objChartID, objName, OBJPROP_ARROWCODE);
      }
      
      if(objType == OBJ_FIBO || objType == OBJ_FIBOTIMES || objType == OBJ_FIBOFAN || objType == OBJ_FIBOARC || objType == OBJ_FIBOCHANNEL || objType == OBJ_EXPANSION){
      
         objLevels = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELS);
         
         ArrayResize(objLevelValue, objLevels);
         ArrayResize(objLevelText, objLevels);
         
         objLevelColor = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELCOLOR);
         objLevelStyle = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELSTYLE);
         objLevelWidth = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELWIDTH);
         //objLevelValue = ObjectGetDouble(objChartID, objName, OBJPROP_LEVELVALUE);
         //objLevelText = ObjectGetString(objChartID, objName, OBJPROP_LEVELTEXT);

         for(int i=0; i<objLevels; i++){
         
            ObjectGetDouble(objChartID, objName, OBJPROP_LEVELVALUE, i, objLevelValue[i]);
            ObjectGetString(objChartID, objName, OBJPROP_LEVELTEXT, i, objLevelText[i]);          
         }
      }

      if(objType == OBJ_RECTANGLE || objType == OBJ_TRIANGLE || objType == OBJ_ELLIPSE || objType == OBJ_CHANNEL || objType == OBJ_STDDEVCHANNEL || objType == OBJ_REGRESSION){
         objFill = ObjectGetInteger(objChartID, objName, OBJPROP_FILL);
      }
            
            
      datetime time1 = (datetime)ObjectGetInteger(objChartID, objName, OBJPROP_TIME, 0);
      double price1 = ObjectGetDouble(objChartID, objName, OBJPROP_PRICE, 0);
      datetime time2 = (datetime)ObjectGetInteger(objChartID, objName, OBJPROP_TIME, 1);
      double price2 = ObjectGetDouble(objChartID, objName, OBJPROP_PRICE, 1);
      datetime time3 = (datetime)ObjectGetInteger(objChartID, objName, OBJPROP_TIME, 2);
      double price3 = ObjectGetDouble(objChartID, objName, OBJPROP_PRICE, 2);
      
      long currChart = ChartFirst();
      
      while(true){     
      
         if(ChartSymbol(currChart) == _Symbol && currChart != ChartID() && 
            (setting1 == 1 || 
            (setting1 == 2 && _Period>=ChartPeriod(currChart)) || 
            (setting1 == 3 && _Period<=ChartPeriod(currChart)))){
            
            if(ObjectFind(currChart, objName) < 0){
            
               ObjectCreate(currChart, objName, objType, 0, time1, price1, time2, price2, time3, price3);
               
               ObjectSetInteger(currChart, objName, OBJPROP_COLOR, objColor);
               ObjectSetInteger(currChart, objName, OBJPROP_STYLE, objStyle);
               ObjectSetInteger(currChart, objName, OBJPROP_WIDTH, objWidth);
               ObjectSetInteger(currChart, objName, OBJPROP_BACK, objBack);
               ObjectSetInteger(currChart, objName, OBJPROP_RAY_RIGHT, objRayRight);
               ObjectSetString(currChart, objName, OBJPROP_TEXT, objText);

               ObjectSetInteger(currChart, objName, OBJPROP_SELECTABLE, true);
               ObjectSetInteger(currChart, objName, OBJPROP_SELECTED, false);
               
               if(objType == OBJ_TRENDBYANGLE || objType == OBJ_TEXT){
                  ObjectSetDouble(currChart, objName, OBJPROP_ANGLE, objAngle);
               }
               
               if(objType == OBJ_STDDEVCHANNEL) ObjectSetDouble(currChart, objName, OBJPROP_DEVIATION, objDeviation);
               
               if(objType == OBJ_GANNFAN || objType == OBJ_GANNGRID || objType == OBJ_GANNLINE || objType == OBJ_FIBOARC){
                  ObjectSetDouble(currChart, objName, OBJPROP_SCALE, objScale);
               }
               
               if(objType == OBJ_LABEL || objType == OBJ_TEXT){
                  ObjectSetString(currChart, objName, OBJPROP_FONT, objFont);
                  ObjectSetInteger(currChart, objName, OBJPROP_FONTSIZE, objFontSize);
               }
               
               if(objType == OBJ_LABEL){
                  ObjectSetInteger(currChart, objName, OBJPROP_XDISTANCE, objX);
                  ObjectSetInteger(currChart, objName, OBJPROP_YDISTANCE, objY);
                  ObjectSetInteger(currChart, objName, OBJPROP_ANCHOR, objAnchor);
               }
               
               if(objType == OBJ_ARROW){
                  ObjectSetInteger(currChart, objName, OBJPROP_ARROWCODE, objArrowCode);
               }
               
               if(objType == OBJ_FIBO || objType == OBJ_FIBOTIMES || objType == OBJ_FIBOFAN || objType == OBJ_FIBOARC || objType == OBJ_FIBOCHANNEL || objType == OBJ_EXPANSION){
               
                  for(int i=0; i<objLevels; i++){
                     ObjectSetInteger(currChart, objName, OBJPROP_LEVELCOLOR, i, objLevelColor);
                     ObjectSetInteger(currChart, objName, OBJPROP_LEVELSTYLE, i, objLevelStyle);
                     ObjectSetInteger(currChart, objName, OBJPROP_LEVELWIDTH, i, objLevelWidth);                  
                     ObjectSetDouble(currChart, objName, OBJPROP_LEVELVALUE, i, objLevelValue[i]);
                     ObjectSetString(currChart, objName, OBJPROP_LEVELTEXT, i, objLevelText[i]);
                  }
               }
               
               if(objType == OBJ_RECTANGLE || objType == OBJ_TRIANGLE || objType == OBJ_ELLIPSE || objType == OBJ_CHANNEL || objType == OBJ_STDDEVCHANNEL || objType == OBJ_REGRESSION){
                  ObjectSetInteger(currChart, objName, OBJPROP_FILL, objFill);
               }
            }
            
            ChartRedraw(currChart);
         }
         
         if(ChartNext(currChart) < 0) break;
         else currChart = ChartNext(currChart);
         //ChartSymbol(currChart);
      }
      
      OneClick = false;
   }

   if(id == CHARTEVENT_OBJECT_CHANGE || id == CHARTEVENT_OBJECT_DRAG){
   
      string objName = sparam;
      
      long objChartID = ChartID();
      
      int objType = (int)ObjectGetInteger(objChartID, objName, OBJPROP_TYPE);
      int objColor = (int)ObjectGetInteger(objChartID, objName, OBJPROP_COLOR);
      int objStyle = (int)ObjectGetInteger(objChartID, objName, OBJPROP_STYLE);
      int objWidth = (int)ObjectGetInteger(objChartID, objName, OBJPROP_WIDTH);
      bool objBack = ObjectGetInteger(objChartID, objName, OBJPROP_BACK);
      bool objRayRight = ObjectGetInteger(objChartID, objName, OBJPROP_RAY_RIGHT);
      
      int objFontSize=0;
      int objArrowCode=0;
      double objAngle=0.0, objDeviation=0.0, objScale=0.0;
      string objText = ObjectGetString(objChartID, objName, OBJPROP_TEXT);
      string objFont;
      int objX=0, objY=0, objAnchor=0;

      int objLevels=0;
      int objLevelColor = clrNONE;
      int objLevelStyle = 0;
      int objLevelWidth = 0;
      //double objLevelValue = 0.0;
      //string objLevelText = "";
      bool objFill = false;
      
      double objLevelValue[];
      string objLevelText[];

      if(objType == OBJ_TRENDBYANGLE || objType == OBJ_TEXT){
         objAngle = ObjectGetDouble(objChartID, objName, OBJPROP_ANGLE);
      }
      
      if(objType == OBJ_STDDEVCHANNEL){
         objDeviation = ObjectGetDouble(objChartID, objName, OBJPROP_DEVIATION);
      }
      
      if(objType == OBJ_GANNFAN || objType == OBJ_GANNGRID || objType == OBJ_GANNLINE || objType == OBJ_FIBOARC){
         objScale = ObjectGetDouble(objChartID, objName, OBJPROP_SCALE);
      }
      
      if(objType == OBJ_LABEL || objType == OBJ_TEXT){
         
         objFont = ObjectGetString(objChartID, objName, OBJPROP_FONT);
         objFontSize = (int)ObjectGetInteger(objChartID, objName, OBJPROP_FONTSIZE);
      }

      if(objType == OBJ_LABEL){
         
         objX = (int)ObjectGetInteger(objChartID, objName, OBJPROP_XDISTANCE);
         objY = (int)ObjectGetInteger(objChartID, objName, OBJPROP_YDISTANCE);
         objAnchor = (int)ObjectGetInteger(objChartID, objName, OBJPROP_ANCHOR);
      }

      if(objType == OBJ_ARROW){
         objArrowCode = (int)ObjectGetInteger(objChartID, objName, OBJPROP_ARROWCODE);
      }

      if(objType == OBJ_FIBO || objType == OBJ_FIBOTIMES || objType == OBJ_FIBOFAN || objType == OBJ_FIBOARC || objType == OBJ_FIBOCHANNEL || objType == OBJ_EXPANSION){
         
         objLevels = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELS);
         
         ArrayResize(objLevelValue, objLevels);
         ArrayResize(objLevelText, objLevels);         
         
         objLevelColor = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELCOLOR);
         objLevelStyle = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELSTYLE);
         objLevelWidth = (int)ObjectGetInteger(objChartID, objName, OBJPROP_LEVELWIDTH);
         //objLevelValue = ObjectGetDouble(objChartID, objName, OBJPROP_LEVELVALUE);
         //objLevelText = ObjectGetString(objChartID, objName, OBJPROP_LEVELTEXT);
      
         for(int i=0; i<objLevels; i++){
         
            ObjectGetDouble(objChartID, objName, OBJPROP_LEVELVALUE, i, objLevelValue[i]);
            ObjectGetString(objChartID, objName, OBJPROP_LEVELTEXT, i, objLevelText[i]);  
         
         }      
      }

      if(objType == OBJ_RECTANGLE || objType == OBJ_TRIANGLE || objType == OBJ_ELLIPSE || objType == OBJ_CHANNEL || objType == OBJ_STDDEVCHANNEL || objType == OBJ_REGRESSION){
         objFill = ObjectGetInteger(objChartID, objName, OBJPROP_FILL);
      } 
            
      datetime time1 = (datetime)ObjectGetInteger(objChartID, objName, OBJPROP_TIME, 0);
      double price1 = ObjectGetDouble(objChartID, objName, OBJPROP_PRICE, 0);
      datetime time2 = (datetime)ObjectGetInteger(objChartID, objName, OBJPROP_TIME, 1);
      double price2 = ObjectGetDouble(objChartID, objName, OBJPROP_PRICE, 1);
      datetime time3 = (datetime)ObjectGetInteger(objChartID, objName, OBJPROP_TIME, 2);
      double price3 = ObjectGetDouble(objChartID, objName, OBJPROP_PRICE, 2);
      
      long currChart = ChartFirst();
      
      while(true){

         if(ChartSymbol(currChart) == _Symbol && currChart != ChartID() &&
            (setting1 == 1 || 
            (setting1 == 2 && _Period>=ChartPeriod(currChart)) || 
            (setting1 == 3 && _Period<=ChartPeriod(currChart)))){
            
            ObjectSetInteger(currChart, objName, OBJPROP_TIME, 0, time1);
            ObjectSetDouble(currChart, objName, OBJPROP_PRICE, 0, price1);
            ObjectSetInteger(currChart, objName, OBJPROP_TIME, 1, time2);
            ObjectSetDouble(currChart, objName, OBJPROP_PRICE, 1, price2);
            ObjectSetInteger(currChart, objName, OBJPROP_TIME, 2, time3);
            ObjectSetDouble(currChart, objName, OBJPROP_PRICE, 2, price3);
               
            //ObjectCreate(prevChart, objName+"_"+(string)prevChart, objType, 0, time1, price1, time2, price2, time3, price3);
            ObjectSetInteger(currChart, objName, OBJPROP_COLOR, objColor);
            ObjectSetInteger(currChart, objName, OBJPROP_STYLE, objStyle);
            ObjectSetInteger(currChart, objName, OBJPROP_WIDTH, objWidth);
            ObjectSetInteger(currChart, objName, OBJPROP_BACK, objBack);
            ObjectSetInteger(currChart, objName, OBJPROP_RAY_RIGHT, objRayRight);
            ObjectSetString(currChart, objName, OBJPROP_TEXT, objText);
            
            if(objType == OBJ_TRENDBYANGLE || objType == OBJ_TEXT){
               ObjectSetDouble(currChart, objName, OBJPROP_ANGLE, objAngle);
            }
            
            if(objType == OBJ_STDDEVCHANNEL) ObjectSetDouble(currChart, objName, OBJPROP_DEVIATION, objDeviation);
            
            if(objType == OBJ_GANNFAN || objType == OBJ_GANNGRID || objType == OBJ_GANNLINE || objType == OBJ_FIBOARC){
               ObjectSetDouble(currChart, objName, OBJPROP_SCALE, objScale);
            }
            
            if(objType == OBJ_LABEL || objType == OBJ_TEXT){
               ObjectSetString(currChart, objName, OBJPROP_FONT, objFont);
               ObjectSetInteger(currChart, objName, OBJPROP_FONTSIZE, objFontSize);
            }

            if(objType == OBJ_LABEL){
               ObjectSetInteger(currChart, objName, OBJPROP_XDISTANCE, objX);
               ObjectSetInteger(currChart, objName, OBJPROP_YDISTANCE, objY);
               ObjectSetInteger(currChart, objName, OBJPROP_ANCHOR, objAnchor);
            }

            if(objType == OBJ_ARROW){
               ObjectSetInteger(currChart, objName, OBJPROP_ARROWCODE, objArrowCode);
            }

            if(objType == OBJ_FIBO || objType == OBJ_FIBOTIMES || objType == OBJ_FIBOFAN || objType == OBJ_FIBOARC || objType == OBJ_FIBOCHANNEL || objType == OBJ_EXPANSION){
            
               for(int i=0; i<objLevels; i++){

                  //ObjectSetInteger(currChart, objName, OBJPROP_LEVELS, objLevels);
                  ObjectSetInteger(currChart, objName, OBJPROP_LEVELCOLOR, i, objLevelColor);
                  ObjectSetInteger(currChart, objName, OBJPROP_LEVELSTYLE, i, objLevelStyle);
                  ObjectSetInteger(currChart, objName, OBJPROP_LEVELWIDTH, i, objLevelWidth);
                  ObjectSetDouble(currChart, objName, OBJPROP_LEVELVALUE, i, objLevelValue[i]);
                  ObjectSetString(currChart, objName, OBJPROP_LEVELTEXT, i, objLevelText[i]);
               }            
            }

            if(objType == OBJ_RECTANGLE || objType == OBJ_TRIANGLE || objType == OBJ_ELLIPSE || objType == OBJ_CHANNEL || objType == OBJ_STDDEVCHANNEL || objType == OBJ_REGRESSION){
               ObjectSetInteger(currChart, objName, OBJPROP_FILL, objFill);
            }
            
            ChartRedraw(currChart);
         }
         
         if(ChartNext(currChart) < 0) break;
         else currChart = ChartNext(currChart);
         //ChartSymbol(currChart);
      }
   }
   
   if(id == CHARTEVENT_OBJECT_DELETE){
   
      string objName = sparam;
      long currChart = ChartFirst();
      int i = 0;
      
      while(true){

         if(ChartSymbol(currChart) == _Symbol && currChart != ChartID() &&
            (setting1 == 1 || 
            (setting1 == 2 && _Period>=ChartPeriod(currChart)) || 
            (setting1 == 3 && _Period<=ChartPeriod(currChart)))){
            
            ObjectDelete(currChart, objName);
            ChartRedraw(currChart);
            
         }
         
         //ObjectDelete(currChart, objName);
                  
         if(ChartNext(currChart) < 0) break;
         else currChart = ChartNext(currChart);
      }
   }

   if(id == CHARTEVENT_OBJECT_CLICK){

      string objName = sparam;      
      long objChartID = ChartID();

      bool objSelectable = ObjectGetInteger(objChartID, objName, OBJPROP_SELECTABLE);
      bool objSelected = ObjectGetInteger(objChartID, objName, OBJPROP_SELECTED);

      long currChart = ChartFirst();

      while(true){

         if(ChartSymbol(currChart) == _Symbol && currChart != ChartID() &&
            (setting1 == 1 || 
            (setting1 == 2 && _Period>=ChartPeriod(currChart)) || 
            (setting1 == 3 && _Period<=ChartPeriod(currChart)))){
            
            ObjectSetInteger(currChart, objName, OBJPROP_SELECTABLE, objSelectable);
            ObjectSetInteger(currChart, objName, OBJPROP_SELECTED, objSelected);
            
            ChartRedraw(currChart);
         }
         
         if(ChartNext(currChart) < 0) break;
         else currChart = ChartNext(currChart);
         //ChartSymbol(currChart);
      }
   }
}


bool objNameCheck(string name){

   if(StringFind(name, "Vertical Line") == 0 ||
      StringFind(name, "Horizontal Line") == 0 ||
      StringFind(name, "Trendline") == 0 ||
      StringFind(name, "Trend By Angle") == 0 ||
      StringFind(name, "Cycle Lines") == 0 ||
      StringFind(name, "Channel") == 0 ||
      StringFind(name, "Equidistant Channel") == 0 ||
      StringFind(name, "StdDev Channel") == 0 ||
      StringFind(name, "Regression Channel") == 0 ||
      StringFind(name, "Andrews Pitchfork") == 0 ||
      StringFind(name, "Gann") == 0 ||
      StringFind(name, "Fibo") == 0 ||
      StringFind(name, "Expansion") == 0 ||
      StringFind(name, "Rectangle") == 0 ||
      StringFind(name, "Triangle") == 0 ||
      StringFind(name, "Ellipse") == 0 ||
      StringFind(name, "Arrow") == 0 ||
      StringFind(name, "Text") == 0 ||
      StringFind(name, "Label") == 0) return(true);
   else return(false);
}