How to hide indicator plot - page 2

 
Jeepack #:

Thanks a lot! I will look at that in detail later today when I have more time. I thought about re-arranging the buffer mapping when I first ran into this issue but it seemed too complicated and I wasn't sure I could do it without getting confused. But looking at the way you did it, it seems pretty simple and logical, and less confusing than I imagined. I think this is going to help for some of the things I'm doing. Thanks again! Will update my reply later when I have time to do more tests.

Cool, please do. 

 

Alright so I checked everything, your code works fine. One thing that worried me though, which is one of the reasons I hesitated to try to find a method like this at first, was the concequence of dynamically changing the buffer mapping while the indicator had already been initialized. We need to add a way to reset the calculations, and to avoid the plots looking all messed up for a second before the new calculations take place I thought it'd be a nice touch to initialize all buffers before changing the mapping. Then I did some research and found that you could refresh the indicator calculations (without re-initializing it seems) by using the ChartSetSymbolPeriod command with the current period and symbol.

void ResetBuffers() {
	ArrayInitialize(middle_buffer1,EMPTY_VALUE);
	ArrayInitialize(middle_buffer2,EMPTY_VALUE);
	ArrayInitialize(upper_buffer1,EMPTY_VALUE);
	ArrayInitialize(upper_buffer2,EMPTY_VALUE);
	ArrayInitialize(lower_buffer1,EMPTY_VALUE);
	ArrayInitialize(lower_buffer2,EMPTY_VALUE);
	ChartSetSymbolPeriod(0,Symbol(),Period());
}

For the sake of running the test I added a white label on the top left corner that allows you to hide or show the middle band (mid band needs to be true in input settings). So I updated this line:

if(inpShowBufMiddle && Show_mid_band)

And added code to create the label and detect clicks on it.

After adding the modification to initialize all buffers first and then recalculate everything with the ChartSetSymbolPeriod command, all the issues dissapeared (the issues I would get from trying to update the buffer mapping once the indicator was already initialized).

If you want to do this with a label like in the example below, you need to create a hidden object (a simple text label with a "space" in the description will do) when you hide the plot and search for that object in OnInit, as this is the only way to have the value of Show_mid_band remembered when you change timeframes or symbols and the indicator reinitializes. That's pretty easy to do but it wasn't necessary for this example so I didn't add it. 

So after all this, I'll agree that using DRAW_NONE does a good job at getting rid of the mouse over pop-ups as you hide the plots, as long as you reset the buffer mapping everytime you do (if your plot uses more than one buffer and other plots are drawn after the one you are hiding), like you showed me, and as long as you reset the buffer calculations if you're doing it after the indicator is already initialized (see my modifications below).

So thanks again for the help! After this, the only improvement I could see adding is preventing calculations for a hidden plot from taking place, if not needed for other plots, so I added a simple line of code in the OnCalculate function.

So, I guess, that's it, seems like everything is fixed with this technique. And I prefer this method because it doesn't require duplicating all your buffers (allowing you to keep at least one buffer for the hidden plot in case the values are important for other calculations). I honestly don't see any issues with this approach and I hadn't found any posts discussing it in my previous research so I'm glad I asked the question! Thanks again.

The only downside is how all plots end up flickering for a fraction of a second as the recalculation takes place after the buffer mapping is reset. But I'm pretty sure this is going to be unavoidable unless you go with the first method of just changing the color to NONE (so it depends on if you prefer getting rid of mouse over pop-ups more than avoiding the flickering). *edit* there would be no flickering if we used the other method I discussed (filling buffers with empty_values, which requires duplicating all your buffers if you need the hidden plot's values for other buffer calculations). I know how to get this one to work so I don't have any questions, but I'll code an example just for the sake of this example and post it in another reply once I'm done.

Full code for final example (without the hidden object to remember settings when you change timeframes or symbols):

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 3
input bool inpShowBufLower=true;
input bool inpShowBufMiddle=true;
input bool inpShowBufUpper=true;
//---
int hnd_bb;
double middle_buffer1[], middle_buffer2[];
double upper_buffer1[], upper_buffer2[];
double lower_buffer1[], lower_buffer2[];

string LabelText="hide middle band";
bool Show_mid_band=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   CreateLabel();
   
   hnd_bb=iBands(_Symbol,_Period,50,0,2,PRICE_CLOSE);
   if(hnd_bb==INVALID_HANDLE)
      return INIT_FAILED;
//---
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
   PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
//--- plot labeling
   PlotIndexSetString(0,PLOT_LABEL,"buf0;buf1");
   PlotIndexSetString(1,PLOT_LABEL,"buf2;buf3");
   PlotIndexSetString(2,PLOT_LABEL,"buf4;buf5");

   AttachBuffers();

   if(inpShowBufMiddle)
     {
      PlotIndexSetInteger(0,PLOT_SHOW_DATA,true);
      PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
      PlotIndexSetInteger(0,PLOT_LINE_WIDTH,1);
      PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrYellow);
     }
   else
     {
      PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
      PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_NONE);
     }
   if(inpShowBufUpper)
     {
      PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID);
      PlotIndexSetInteger(1,PLOT_LINE_WIDTH,1);
      PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrGreen);
      PlotIndexSetInteger(1,PLOT_SHOW_DATA,true);
     }
   else
     {
      PlotIndexSetInteger(1,PLOT_SHOW_DATA,false);
      PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_NONE);
     }
   if(inpShowBufLower)
     {
      PlotIndexSetInteger(2,PLOT_SHOW_DATA,true);
      PlotIndexSetInteger(2,PLOT_LINE_STYLE,STYLE_SOLID);
      PlotIndexSetInteger(2,PLOT_LINE_WIDTH,1);
      PlotIndexSetInteger(2,PLOT_LINE_COLOR,clrRed);
     }
   else
     {
      PlotIndexSetInteger(2,PLOT_SHOW_DATA,false);
      PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_NONE);
     }
   ArraySetAsSeries(upper_buffer1,true);
   ArraySetAsSeries(lower_buffer1,true);
   ArraySetAsSeries(middle_buffer1,true);
   ArraySetAsSeries(upper_buffer2,true);
   ArraySetAsSeries(lower_buffer2,true);
   ArraySetAsSeries(middle_buffer2,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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 bb_low[1],bb_mid[1],bb_high[1];
//--- running indicator start formula
   int limit=rates_total-2-prev_calculated;
   for(int iBar = limit; iBar >= 0  && !IsStopped(); --iBar)
     {
      if (Show_mid_band) {
              CopyBuffer(hnd_bb,BASE_LINE,iBar,1,bb_mid);
              middle_buffer1[iBar]=middle_buffer2[iBar+1];
              middle_buffer2[iBar]=bb_mid[0];
      } else {
	      middle_buffer1[iBar]=EMPTY_VALUE;
	      middle_buffer2[iBar]=EMPTY_VALUE;      
      }
      CopyBuffer(hnd_bb,UPPER_BAND,iBar,1,bb_high);
      upper_buffer1[iBar]=upper_buffer2[iBar+1];
      upper_buffer2[iBar]=bb_high[0];
      CopyBuffer(hnd_bb,LOWER_BAND,iBar,1,bb_low);
      lower_buffer1[iBar]=lower_buffer2[iBar+1];
      lower_buffer2[iBar]=bb_low[0];
     }
//--- return value of prev_calculated for next call
   return(rates_total-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CreateLabel() {
        ObjectCreate(0,LabelText,OBJ_LABEL,0,0,0);
        ObjectSetString(0,LabelText,OBJPROP_TEXT,LabelText);
        ObjectSetInteger(0,LabelText,OBJPROP_COLOR,clrWhite);
        ObjectSetInteger(0,LabelText,OBJPROP_XDISTANCE,50);
        ObjectSetInteger(0,LabelText,OBJPROP_YDISTANCE,50);
        ChartRedraw();
}

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) {
        if (id==CHARTEVENT_OBJECT_CLICK) {      
                if (sparam==LabelText) {
                        if (Show_mid_band) {
                                // hide mid band
                                Show_mid_band=false;
                                ResetBuffers();
                                AttachBuffers();
                      PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
                      PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_NONE);
                        } else {
                                // show MA
                                Show_mid_band=true;
                                ResetBuffers();
                                AttachBuffers();        
                                PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
                      PlotIndexSetInteger(0,PLOT_SHOW_DATA,true);
                      PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
                      PlotIndexSetInteger(0,PLOT_LINE_WIDTH,1);
                      PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrYellow);
                        }
                }
        }
}

void ResetBuffers() {
        ArrayInitialize(middle_buffer1,EMPTY_VALUE);
        ArrayInitialize(middle_buffer2,EMPTY_VALUE);
        ArrayInitialize(upper_buffer1,EMPTY_VALUE);
        ArrayInitialize(upper_buffer2,EMPTY_VALUE);
        ArrayInitialize(lower_buffer1,EMPTY_VALUE);
        ArrayInitialize(lower_buffer2,EMPTY_VALUE);
        ChartSetSymbolPeriod(0,Symbol(),Period());
}

void AttachBuffers()
  {
   int buf_ind=0,buf_none=0;
//--- indicator buffers mapping
   SetIndexBuffer(buf_ind++,middle_buffer1,INDICATOR_DATA);
   if(inpShowBufMiddle && Show_mid_band)
      SetIndexBuffer(buf_ind++,middle_buffer2,INDICATOR_DATA);
   else
      SetIndexBuffer(indicator_buffers-(++buf_none),middle_buffer2,INDICATOR_DATA);
   SetIndexBuffer(buf_ind++,upper_buffer1,INDICATOR_DATA);
   if(inpShowBufUpper)
      SetIndexBuffer(buf_ind++,upper_buffer2,INDICATOR_DATA);
   else
      SetIndexBuffer(indicator_buffers-(++buf_none),upper_buffer2,INDICATOR_DATA);
   SetIndexBuffer(buf_ind++,lower_buffer1,INDICATOR_DATA);
   if(inpShowBufLower)
      SetIndexBuffer(buf_ind++,lower_buffer2,INDICATOR_DATA);
   else
      SetIndexBuffer(indicator_buffers-(++buf_none),lower_buffer2,INDICATOR_DATA);
  }
 
Here's the change with empty values used to hide the plots. Now that I know about the way to recalc all values with this line:
ChartSetSymbolPeriod(0,Symbol(),Period());

...it seems less complicated than I originally imagined. So because it gets rid of the flickering, I think that's the way I prefer doing it now. But it depends on the context. The issue is simply that if you need the buffer values even though the plot is hidden, then you need them stored on another buffer, so you would need to duplicate all your buffers and the dissadvantage is it uses more memory and might make the code a little slower to run, which might not be an issue if you're not using too many indicators.

So I'll post the code below, it's simple, less lines of code are needed. And it works a little better since it doesn't cause the plots to flicker when you try to hide one. But I think one thing is clear from this thread: you can change the color to clrNONE and keep the mouse over popups, you can change the draw type to DRAW_NONE but you then have to reset the buffer mapping which will make all plots flicker for a fraction of a second, or you can change all values to empty values to hide the plot but if you still need the values then you'll need to duplicate all your buffers and it might make the code less efficient. In other words, there's more than one way to hide a plot, and each has their advantages and dissadvantages so once you know them, you can choose what you prefer based on what's more important to you in the context of what you are doing.

Here's the code for hiding the plot using empty values:

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 3
//---
int hnd_bb;
double middle_buffer1[], middle_buffer2[];
double upper_buffer1[], upper_buffer2[];
double lower_buffer1[], lower_buffer2[];

string LabelText="hide middle band";
bool Show_mid_band=true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   CreateLabel();
   
   hnd_bb=iBands(_Symbol,_Period,50,0,2,PRICE_CLOSE);
   if(hnd_bb==INVALID_HANDLE)
      return INIT_FAILED;
//--- buffer mapping
   SetIndexBuffer(0,middle_buffer1,INDICATOR_DATA);
   SetIndexBuffer(1,middle_buffer2,INDICATOR_DATA);
   SetIndexBuffer(2,upper_buffer1,INDICATOR_DATA);
   SetIndexBuffer(3,upper_buffer2,INDICATOR_DATA);
   SetIndexBuffer(4,lower_buffer1,INDICATOR_DATA);
   SetIndexBuffer(5,lower_buffer2,INDICATOR_DATA);
//---
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
   PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
//--- plot labeling
   PlotIndexSetString(0,PLOT_LABEL,"buf0;buf1");
   PlotIndexSetString(1,PLOT_LABEL,"buf2;buf3");
   PlotIndexSetString(2,PLOT_LABEL,"buf4;buf5");

   PlotIndexSetInteger(0,PLOT_SHOW_DATA,true);
   PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(0,PLOT_LINE_WIDTH,1);
   PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrYellow);

   PlotIndexSetInteger(1,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(1,PLOT_LINE_WIDTH,1);
   PlotIndexSetInteger(1,PLOT_LINE_COLOR,clrGreen);
   PlotIndexSetInteger(1,PLOT_SHOW_DATA,true);

   PlotIndexSetInteger(2,PLOT_SHOW_DATA,true);
   PlotIndexSetInteger(2,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(2,PLOT_LINE_WIDTH,1);
   PlotIndexSetInteger(2,PLOT_LINE_COLOR,clrRed);

   ArraySetAsSeries(upper_buffer1,true);
   ArraySetAsSeries(lower_buffer1,true);
   ArraySetAsSeries(middle_buffer1,true);
   ArraySetAsSeries(upper_buffer2,true);
   ArraySetAsSeries(lower_buffer2,true);
   ArraySetAsSeries(middle_buffer2,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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 bb_low[1],bb_mid[1],bb_high[1];
//--- running indicator start formula
   int limit=rates_total-2-prev_calculated;
   for(int iBar = limit; iBar >= 0  && !IsStopped(); --iBar)
     {
      if (Show_mid_band) {
              CopyBuffer(hnd_bb,BASE_LINE,iBar,1,bb_mid);
              middle_buffer1[iBar]=middle_buffer2[iBar+1];
              middle_buffer2[iBar]=bb_mid[0];
      } else {
              middle_buffer1[iBar]=EMPTY_VALUE;
              middle_buffer2[iBar]=EMPTY_VALUE;      
      }
      CopyBuffer(hnd_bb,UPPER_BAND,iBar,1,bb_high);
      upper_buffer1[iBar]=upper_buffer2[iBar+1];
      upper_buffer2[iBar]=bb_high[0];
      CopyBuffer(hnd_bb,LOWER_BAND,iBar,1,bb_low);
      lower_buffer1[iBar]=lower_buffer2[iBar+1];
      lower_buffer2[iBar]=bb_low[0];
     }
//--- return value of prev_calculated for next call
   return(rates_total-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CreateLabel() {
        ObjectCreate(0,LabelText,OBJ_LABEL,0,0,0);
        ObjectSetString(0,LabelText,OBJPROP_TEXT,LabelText);
        ObjectSetInteger(0,LabelText,OBJPROP_COLOR,clrWhite);
        ObjectSetInteger(0,LabelText,OBJPROP_XDISTANCE,50);
        ObjectSetInteger(0,LabelText,OBJPROP_YDISTANCE,50);
        ChartRedraw();
}

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam) {
        if (id==CHARTEVENT_OBJECT_CLICK) {      
                if (sparam==LabelText) {
                        if (Show_mid_band) {
                                // hide mid band
                                Show_mid_band=false;
                                ArrayInitialize(middle_buffer1,EMPTY_VALUE);
                                ArrayInitialize(middle_buffer2,EMPTY_VALUE);
                                PlotIndexSetInteger(0,PLOT_SHOW_DATA,false);
                        } else {
                                // show MA
                                Show_mid_band=true;
                                PlotIndexSetInteger(0,PLOT_SHOW_DATA,true);
                                ChartSetSymbolPeriod(0,Symbol(),Period());
                        }
                }
        }
}
 

Ok, I do get what you talk about, it seems there is some delay after setting the plots using ChartSetSymbolPeriod(0,NULL,0) in relation to changing the parameter manually.

Anyway, this is for info purposes maybe, just some code optimization in case anyone query sometime

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 3
#include <ChartObjects\ChartObjectsTxtControls.mqh>

input bool inpShowBufLower=true;
input bool inpShowBufMiddle=true;
input bool inpShowBufUpper=true;
//---
CChartObjectButton mid_btn,up_btn,dn_btn;
int hnd_bb;
double middle_buffer1[], middle_buffer2[];
double upper_buffer1[], upper_buffer2[];
double lower_buffer1[], lower_buffer2[];

bool Show_mid_band=inpShowBufMiddle;
bool Show_up_band=inpShowBufUpper;
bool Show_dn_band=inpShowBufLower;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   hnd_bb=iBands(_Symbol,_Period,50,0,2,PRICE_CLOSE);
   if(hnd_bb==INVALID_HANDLE)
      return INIT_FAILED;

   up_btn.Create(ChartID(),"upbtn",0,50,50,50,50);
   up_btn.Description("upper");
   up_btn.BackColor(clrGreen);
   up_btn.Color(clrBlack);
   up_btn.State(true);

   mid_btn.Create(ChartID(),"midbtn",0,50,110,50,50);
   mid_btn.Description("middle");
   mid_btn.BackColor(clrYellow);
   mid_btn.Color(clrBlack);
   mid_btn.State(true);

   dn_btn.Create(ChartID(),"dnbtn",0,50,170,50,50);
   dn_btn.Description("lower");
   dn_btn.BackColor(clrRed);
   dn_btn.Color(clrBlack);
   dn_btn.State(true);

   AttachBuffers();

   ArraySetAsSeries(upper_buffer1,true);
   ArraySetAsSeries(lower_buffer1,true);
   ArraySetAsSeries(middle_buffer1,true);
   ArraySetAsSeries(upper_buffer2,true);
   ArraySetAsSeries(lower_buffer2,true);
   ArraySetAsSeries(middle_buffer2,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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 bb_low[1],bb_mid[1],bb_high[1];
//--- running indicator start formula
   int limit=rates_total-2-prev_calculated;
   for(int iBar = limit; iBar >= 0  && !IsStopped(); --iBar)
     {
      if(Show_mid_band)
        {
         CopyBuffer(hnd_bb,BASE_LINE,iBar,1,bb_mid);
         middle_buffer1[iBar]=middle_buffer2[iBar+1];
         middle_buffer2[iBar]=bb_mid[0];
        }
      if(Show_up_band)
        {
         CopyBuffer(hnd_bb,UPPER_BAND,iBar,1,bb_high);
         upper_buffer1[iBar]=upper_buffer2[iBar+1];
         upper_buffer2[iBar]=bb_high[0];
        }
      if(Show_dn_band)
        {
         CopyBuffer(hnd_bb,LOWER_BAND,iBar,1,bb_low);
         lower_buffer1[iBar]=lower_buffer2[iBar+1];
         lower_buffer2[iBar]=bb_low[0];
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void AttachBuffers()
  {
   int buf_ind=0,buf_none=0;
//---
   PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
   PlotIndexSetInteger(1,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
   PlotIndexSetInteger(2,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
//--- plot labeling
   PlotIndexSetString(0,PLOT_LABEL,"buf0;buf1");
   PlotIndexSetString(1,PLOT_LABEL,"buf2;buf3");
   PlotIndexSetString(2,PLOT_LABEL,"buf4;buf5");
//--- indicator buffers mapping
   SetIndexBuffer(buf_ind++,middle_buffer1,INDICATOR_DATA);
   if(Show_mid_band)
     {
      SetIndexBuffer(buf_ind++,middle_buffer2,INDICATOR_DATA);
      ShowPlot(0,clrYellow);
     }
   else
     {
      SetIndexBuffer(indicator_buffers-(++buf_none),middle_buffer2,INDICATOR_DATA);
      HidePlot(0);
     }
   SetIndexBuffer(buf_ind++,upper_buffer1,INDICATOR_DATA);
   if(Show_up_band)
     {
      SetIndexBuffer(buf_ind++,upper_buffer2,INDICATOR_DATA);
      ShowPlot(1,clrGreen);
     }
   else
     {
      SetIndexBuffer(indicator_buffers-(++buf_none),upper_buffer2,INDICATOR_DATA);
      HidePlot(1);
     }
   SetIndexBuffer(buf_ind++,lower_buffer1,INDICATOR_DATA);
   if(Show_dn_band)
     {
      SetIndexBuffer(buf_ind++,lower_buffer2,INDICATOR_DATA);
      ShowPlot(2,clrRed);
     }
   else
     {
      SetIndexBuffer(indicator_buffers-(++buf_none),lower_buffer2,INDICATOR_DATA);
      HidePlot(2);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ShowPlot(const int num,const color clr)
  {
   PlotIndexSetInteger(num,PLOT_SHOW_DATA,true);
   PlotIndexSetInteger(num,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(num,PLOT_LINE_WIDTH,1);
   PlotIndexSetInteger(num,PLOT_LINE_COLOR,clr);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void HidePlot(const int num)
  {
   PlotIndexSetInteger(num,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(num,PLOT_DRAW_TYPE,DRAW_NONE);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id!=CHARTEVENT_OBJECT_CLICK)
      return;
   if(sparam == "midbtn")
     {
      Show_up_band=!Show_up_band;
      ArrayInitialize(upper_buffer1,EMPTY_VALUE);
      ArrayInitialize(upper_buffer2,EMPTY_VALUE);
     }
   if(sparam == "upbtn")
     {
      Show_up_band=!Show_up_band;
      ArrayInitialize(upper_buffer1,EMPTY_VALUE);
      ArrayInitialize(upper_buffer2,EMPTY_VALUE);
     }
   if(sparam == "dnbtn")
     {
      Show_up_band=!Show_up_band;
      ArrayInitialize(lower_buffer1,EMPTY_VALUE);
      ArrayInitialize(lower_buffer2,EMPTY_VALUE);
     }
   if(sparam== "midbtn" || sparam == "upbtn" || sparam == "dnbtn")
     {
      AttachBuffers();
      ChartSetSymbolPeriod(0,NULL,0);
     }
  }
 
Amir Yacoby #:

Ok, I do get what you talk about, it seems there is some delay after setting the plots using ChartSetSymbolPeriod(0,NULL,0) in relation to changing the parameter manually.

Anyway, this is for info purposes maybe, just some code optimization in case anyone query sometime

cheers mate, thanks for giving this a bit of your time.

 
Jeepack #:

cheers mate, thanks for giving this a bit of your time.

@Jeepack Actually, I thought of a different method that does not cause flickering of buffers, or delay - because there are no dynamic buffer allocation. Instead, it plays with the plots. But that requires to rise up the number of plots in the indicator to the number of buffers, I don't think it costs any thing in performance.

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 6
#include <ChartObjects\ChartObjectsTxtControls.mqh>

input bool inpShowBufLower=true;
input bool inpShowBufMiddle=true;
input bool inpShowBufUpper=true;
//---
CChartObjectButton mid_btn,up_btn,dn_btn;
int hnd_bb;
double middle_buffer1[], middle_buffer2[];
double upper_buffer1[], upper_buffer2[];
double lower_buffer1[], lower_buffer2[];

bool Show_mid_band=inpShowBufMiddle;
bool Show_up_band=inpShowBufUpper;
bool Show_dn_band=inpShowBufLower;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   hnd_bb=iBands(_Symbol,_Period,50,0,2,PRICE_CLOSE);
   if(hnd_bb==INVALID_HANDLE)
      return INIT_FAILED;

   up_btn.Create(ChartID(),"upbtn",0,50,50,50,50);
   up_btn.Description("upper");
   up_btn.BackColor(clrGreen);
   up_btn.Color(clrBlack);
   up_btn.State(true);

   mid_btn.Create(ChartID(),"midbtn",0,50,110,50,50);
   mid_btn.Description("middle");
   mid_btn.BackColor(clrYellow);
   mid_btn.Color(clrBlack);
   mid_btn.State(true);

   dn_btn.Create(ChartID(),"dnbtn",0,50,170,50,50);
   dn_btn.Description("lower");
   dn_btn.BackColor(clrRed);
   dn_btn.Color(clrBlack);
   dn_btn.State(true);

//--- indicator buffers mapping
   SetIndexBuffer(0,middle_buffer1,INDICATOR_DATA);
   SetIndexBuffer(1,middle_buffer2,INDICATOR_DATA);
   SetIndexBuffer(2,upper_buffer1,INDICATOR_DATA);
   SetIndexBuffer(3,upper_buffer2,INDICATOR_DATA);
   SetIndexBuffer(4,lower_buffer1,INDICATOR_DATA);
   SetIndexBuffer(5,lower_buffer2,INDICATOR_DATA);

   SetUpPlotsDisplay();

   ArraySetAsSeries(upper_buffer1,true);
   ArraySetAsSeries(lower_buffer1,true);
   ArraySetAsSeries(middle_buffer1,true);
   ArraySetAsSeries(upper_buffer2,true);
   ArraySetAsSeries(lower_buffer2,true);
   ArraySetAsSeries(middle_buffer2,true);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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 bb_low[1],bb_mid[1],bb_high[1];
//--- running indicator start formula
   int limit=rates_total-2-prev_calculated;
   for(int iBar = limit; iBar >= 0  && !IsStopped(); --iBar)
     {
      if(Show_mid_band)
        {
         CopyBuffer(hnd_bb,BASE_LINE,iBar,1,bb_mid);
         middle_buffer1[iBar]=middle_buffer2[iBar+1];
         middle_buffer2[iBar]=bb_mid[0];
        }
      if(Show_up_band)
        {
         CopyBuffer(hnd_bb,UPPER_BAND,iBar,1,bb_high);
         upper_buffer1[iBar]=upper_buffer2[iBar+1];
         upper_buffer2[iBar]=bb_high[0];
        }
      if(Show_dn_band)
        {
         CopyBuffer(hnd_bb,LOWER_BAND,iBar,1,bb_low);
         lower_buffer1[iBar]=lower_buffer2[iBar+1];
         lower_buffer2[iBar]=bb_low[0];
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total-1);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void SetUpPlotsDisplay()
  {
   int plot_ind=0;
//---
   if(Show_mid_band)
     {
      PlotIndexSetInteger(plot_ind,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
      PlotIndexSetString(plot_ind,PLOT_LABEL,"buf0;buf1");
      ShowPlot(plot_ind++,clrYellow);
     }
   else
     {
      HidePlot(plot_ind++);
      HidePlot(plot_ind++);
     }
   if(Show_up_band)
     {
      PlotIndexSetInteger(plot_ind,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
      PlotIndexSetString(plot_ind,PLOT_LABEL,"buf2;buf3");
      ShowPlot(plot_ind++,clrGreen);
     }
   else
     {
      HidePlot(plot_ind++);
      HidePlot(plot_ind++);
     }
   if(Show_dn_band)
     {
      PlotIndexSetInteger(plot_ind,PLOT_DRAW_TYPE,DRAW_ZIGZAG);
      PlotIndexSetString(plot_ind,PLOT_LABEL,"buf4;buf5");
      ShowPlot(plot_ind++,clrRed);
     }
   else
     {
      HidePlot(plot_ind++);
      HidePlot(plot_ind++);
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ShowPlot(const int num,const color clr)
  {
   PlotIndexSetInteger(num,PLOT_SHOW_DATA,true);
   PlotIndexSetInteger(num,PLOT_LINE_STYLE,STYLE_SOLID);
   PlotIndexSetInteger(num,PLOT_LINE_WIDTH,1);
   PlotIndexSetInteger(num,PLOT_LINE_COLOR,clr);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void HidePlot(const int num)
  {
   PlotIndexSetInteger(num,PLOT_SHOW_DATA,false);
   PlotIndexSetInteger(num,PLOT_DRAW_TYPE,DRAW_NONE);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   if(id!=CHARTEVENT_OBJECT_CLICK)
      return;
   if(sparam == "midbtn")
      Show_mid_band=!Show_mid_band;
   if(sparam == "upbtn")
      Show_up_band=!Show_up_band;
   if(sparam == "dnbtn")
      Show_dn_band=!Show_dn_band;
   if(sparam== "midbtn" || sparam == "upbtn" || sparam == "dnbtn")
     {
      SetUpPlotsDisplay();
      ChartSetSymbolPeriod(0,NULL,0);
     }
  }
 
Amir Yacoby #:

@Jeepack Actually, I thought of a different method that does not cause flickering of buffers, or delay - because there are no dynamic buffer allocation. Instead, it plays with the plots. But that requires to rise up the number of plots in the indicator to the number of buffers, I don't think it costs any thing in performance.

Good job! I can see the difference and it's much better. I sometimes get a small flicker but I think it's something to do with the ZIGZAG draw type that glitches sometimes and not with you code. Luckily, this is not something we need to worry about in most cases but when I do come across this issue I now have a much better range of options to choose from. Nice coding again!