Replace toggle button in parameter window with GuiToggle button?

Hello,

is there a way to make the guibutton replacing this parameter function toggle? So I dont have to right click and press the toggle button in the parameter window.

pardon me if the question is way too simple

thanks

here I attached a simple MA toggle from parameter window, can we change it to guibutton instead?

ma10dcolor = ParamColor("MA10daily Color",colorBlue);

Plotma10d=ParamToggle("Plot ma10d?","Yes|No",1);

if( Plotma10d == 0 ) 
{
MA10d=MA(Close,10);
Plot(MA10d,"MA10daily",ma10dcolor,styleLine|styleThick);
}

Moderator comment: Fundamental question is WHY on earth one would do that. Instead of writing one line of code spend time on re-inventing the wheel and spending time writing dozens of lines that do nothing else or nothing superior to existing feature?

Yes, it is possible. Searching the forum, you can find many example codes, which you can use:

There is even a computer game (I'm not talking about Cyberpunk 2077 :wink: ) making extensive use of all GuiButtons (also the equivalent of ParamToggle):

If Param functions are not enough for you, you should learn how to use GuiButton functions. You will benefit from it and won't have to ask others to code it for you.


Besides if you paste the code, you should format it properly:

1 Like

There is no thread using GuiToggle yet.

The shortest form of a GuiToggle button is this

Version( 6.25 ); 

text1 = "ON";
text2 = "OFF";
    
GuiToggle( text1, toggleID = 1, x = 0, y = 15, width = 40, height = 25, notifyflag = 1 );
guicheck = GuiGetCheck(toggleID); 
if( guicheck == 0 ) GuiSetText( text2, toggleID ); 

// ####################################################################################################

if( guicheck ) {
	_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} - {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%), Vol %g {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ), V ) );
	Plot( C, "Price", colorDefault, styleCandle );
}

But it doesn't preserve set toggle state when closing/restarting AmiBroker so you would have to add StaticVariables.

3 Likes

In the advent of the introduction of GUIButtons, just going by the old school for flexibility and pixel maneuvering sake :smiley::

//Coded by Lennon for https://forum.amibroker.com/t/replace-toggle-button-in-parameter-window-with-gui-button/6392
function GfxConvertValueToPixelY( Value ) 
{
	 //From http://www.amibroker.com/kb/2009/03/30/how-to-convert-from-bar-value-to-pixel-co-ordinates/
	 local Miny, Maxy, pxchartbottom, pxchartheight; 
	 Miny = Status("axisminy"); 
	 Maxy = Status("axismaxy"); 
	 pxchartbottom = Status("pxchartbottom"); 
	 pxchartheight = Status("pxchartheight"); 
	 return pxchartbottom - floor( 0.5 + ( Value - Miny ) * pxchartheight/ ( Maxy - Miny ) ); 
}
function DrawButton( _x1, _y1, _x2, _y2, RndRectBkClr, CirBkClr )
{
	 GfxSetZOrder( 5 );
     GfxSelectPen( RndRectBkClr );
     GfxSelectSolidBrush( RndRectBkClr );
     GfxSetBkColor( RndRectBkClr );
     _x3 = 15;
     _y3 = 15;
     GfxRoundRect( _x1, _y1, _x2, _y2, _x3, _y3 );
     GfxSelectPen( CirBkClr );
     GfxSelectSolidBrush( CirBkClr );
     GfxCircle( ( _x1 + _x2 ) / 2, ( _y1 + _y2 ) / 2, 3 );
}

_SECTION_BEGIN( "GFX Trigger Button" );
	 //Based on http://www.amibroker.org/userkb/2008/02/18/moving-low-level-graphics-gfx-objects-on-your-charts/
	 arr = ParamField( "Choose Array", 4 );
	 RectSize = Param( "BTN Size", 8, 8, 12, 1 );
	 
	 MouseState = GetCursorMouseButtons();
	 JustClkd = MouseState == 9;
	 MousePx  = Nz( GetCursorXPosition( 1 ) );
	 MousePy  = Nz( GetCursorYPosition( 1 ) );
	 
	 pxchartleft = Status( "pxchartleft" );
	 Miny = Status( "axisminy" );
	 Maxy = Status( "axismaxy" );
	 
	 //Drawing the button
	 pxBtnStrt = pxchartleft + RectSize;
	 pyBtnStrt = GfxConvertValueToPixelY( ( Maxy + Miny ) / 2 );
	 x1 = pxBtnStrt - RectSize;
	 y1 = pyBtnStrt - RectSize;
	 x2 = pxBtnStrt + RectSize;
	 y2 = pyBtnStrt + RectSize;
	 BtnBkClr = Nz( StaticVarGet( "#BtnBkClr" + Name(), False ), ColorRGB( 191, 206, 230 ) );
	 InBtnBkClr = Nz( StaticVarGet( "#InBtnBkClr" + Name(), False ), colorWhite );
	 DrawButton( x1, y1, x2, y2, BtnBkClr, InBtnBkClr );
	 
	 //Applying Logic to the button on mouse clicks
	 CrsrInBTN = MousePx > x1 AND MousePx < x2 AND MousePy > y1 AND MousePy < y2;
	 mipBTN = Nz( StaticVarGet( "#mipBTN" + Name(), False ) );
	 FrstClick = NOT mipBTN AND CrsrInBTN AND JustClkd; //First Click on the button for "ON"
	 NxtClick = mipBTN AND CrsrInBTN AND JustClkd; //Next Click on the button for "OFF"
	 if( FrstClick )
	 {
		 StaticVarSet( "#yesPlot" + Name(), 1, False );
		 StaticVarSet( "#BtnBkClr" + Name(), ColorRGB( 191, 206, 230 ), False );
		 StaticVarSet( "#InBtnBkClr" + Name(), colorDarkBlue, False );
		 StaticVarSet( "#mipBTN" + Name(), True, False );
	 }
	 if( NxtClick )
	 {
		 StaticVarSet( "#yesPlot" + Name(), Null, False );
		 StaticVarSet( "#BtnBkClr" + Name(), ColorRGB( 191, 206, 230 ), False );
		 StaticVarSet( "#InBtnBkClr" + Name(), colorWhite, False );
		 StaticVarSet( "#mipBTN" + Name(), False, False );
	 }
	 
	 yesPlot = Nz( StaticVarGet( "#yesPlot" + Name(), False ), 0 );
	 if( yesPlot )
	 {
		 Plot( MA( arr, 10 ), "", colorWhite, styleLine );
	 }
	 Plot( C, "", colorDefault, styleCandle );
	 RequestTimedRefresh( 1 );
_SECTION_END();
4 Likes

Ahh thank you for the simple explanation, I already search the forum but strangely the examples are only to make sound "button clicked" or something like that, and still havent much practical example to use guibutton for non programmer like me...... and fxshat I am not smart enough to understand of your saying here:

quote:
"But it doesn't preserve set toggle state when closing/restarting AmiBroker so you would have to add StaticVariables."

what is that means if I may ask? but thanks again

1 Like

thx a lot Lennon,

its very long coding but I try to understand it now :slight_smile:

My Style :smiley:

_SECTION_BEGIN( "Button Click" );
//Coded by Fossil

procedure DrawCircle (x1, y1,rad1,Getcolor)
{
    GfxSetOverlayMode(0);
    GfxSetBkMode(1);
    GfxSelectPen( Getcolor, 2 );
    GfxSelectSolidBrush( Getcolor );
    GfxCircle( x1, y1, rad1 );
}

LeftClick = GetCursorMouseButtons() == 9;
MXpoint  = Nz(GetCursorXPosition(1));
MYpoint  = Nz(GetCursorYPosition(1));

OnoffLogic = Nz( StaticVarGet( "ClickToggle", False ) );
DrawCircle (50, 50,10,colorRed);

ClickArea     = MXpoint >= 40 AND MXpoint <= 60 AND MYpoint >= 40 AND MYpoint <= 60;
FirstClick     = NOT OnoffLogic AND ClickArea AND LeftClick;
NextClick     = OnoffLogic AND ClickArea AND LeftClick;

if (FirstClick) 
    {
    StaticVarSet( "ClickToggle",  True);
    }
    
if (NextClick) 
    {
    StaticVarSet( "ClickToggle", False);
    }
    
if(StaticVarGet("ClickToggle")==True)
    {
    DrawCircle (50, 50,10,colorGreen);
    //logic
    }
    
_SECTION_END();
3 Likes

This sounds as if you were searching specifically for the example showing how to conditionally Plot MA(C, 10) using GuiButtons(). No wonder you didn't find one, but if you modified one of those examples replacing "clicking with plotting", it should work for you.

Param functions are very easy to use even for the beginners. If you don't feel comfortable with coding, you may stick to them. GuiButtons need from you putting more effort. For this reason learning how to use them would be the best option - even if not to code everything from scratch but to modify one of the example codes that you can find on the forum. If you followed my second link, you would have found an example of using GuiButtons to replace ParamTrigger. Today I would probably code it in a slightly different way, for example like this:

id = GuiGetEvent( 0, 0 ); event = GuiGetEvent( 0, 1 );
MyChartID = GetChartID();
ToggleButton = Nz( StaticVarGet( "ToggleButton" + MyChartID ));
GuiButton( "Off", 1, 2, 20, 50, 25, 1 );

if( id == 1 AND event == 1 )  // If ToggleButton is clicked
{
    if( ToggleButton ) StaticVarSet( "ToggleButton" + MyChartID, ToggleButton = 0, 0 );
    else  StaticVarSet( "ToggleButton" + MyChartID, ToggleButton = 1, 0 );
}

if( ToggleButton ) { Plot( MA( Close, 10 ), "MA10daily", colorBlue, styleLine | styleThick );   GuiSetText( "On", 1 ); }

else GuiSetText( "Off", 1 );

Plot( C, "Close", colorDefault, styleCandle );

... but there are always many possible solutions. Today I would probably make use of GuiToggle() and GuiGetCheck() but I didn't use it in my above code because although this function was implemented in AB 6.25 it wasn't functioning 100% properly from the beginning (when I was coding that example). For the first time it was modified/fixed in AB 6.26 and recently for the second time in AB 6.28 --> DevLog. But from now on - if you are using one of the latest versions of AmiBroker I recommend using fxshrat's version which is simpler and shorter.

If you need to store the value of your variable when closing AB and reload automatically on the next startup, preserving it's value, you can use my upper code (with Persistency set to 1 or True), or modify fxshrat's code adding static variables. But I think you don't need to preserve the value after restarts - using the default value would be enough. Here you can read more about the Persistency parameter:

https://www.amibroker.com/guide/afl/staticvarset.html

1 Like

I do not know what is unsure to you. But I meant that if closing AB and you had toggle ON then on restart it would show Toggle OFF again. So to store state you would have to use static variables with persistency setting being ON.

Here is (Multi-)GuiToggleButton with persistency setting.

Version( 6.25 ); 

/// ###########################################################################################################
/// Multi-GuiToggleButtons preserving set ON/OFF state (e.g. after restart of AB), vrs.1.0
/// by fxshrat@gmail.com
/// @link https://forum.amibroker.com/t/replace-toggle-button-in-parameter-window-with-guitoggle-button/6392/8
/// ###########################################################################################################
numbuttons = 2; // number of toggle buttons
toggletext1 = "Plot OFF,Plot ON";
toggletext2 = "ColorDefault,ColorRed";
//toggletext3 = ...;
// etc
initial = 1;// intial toggle setting
persist = 1;// keep toggle state ON(1) / OFF(0)
ypos = 15;
width = 80;
height = 22;

// iterate number of toggle buttons
for ( toggleID = 1; toggleID <= numbuttons; toggleID++ ) {  
	toggletext = VarGetText( "toggletext" + toggleID );	
	GuiToggle( StrExtract(toggletext, 0), toggleID, x = 0, y = (toggleID-1)*(height-2) + ypos, width, height, notifyflag = 1 );

	staticname = StrFormat( "GuiParamToggle_%s_%g_%g", GetDatabaseName(), GetChartID(), toggleID );
	staticget = Nz(StaticVarGet( staticname ), initial);
	GuiSetCheck(toggleID, staticget);

	togglecheck = GuiGetCheck(toggleID); 
	VarSet( "toggle" + toggleID, togglecheck );

	if ( togglecheck ) GuiSetText( StrExtract(toggletext, 1), toggleID ); 

	if ( GuiGetEvent( 0, 0 ) == toggleID && GuiGetEvent( 0, 1 ) == 1 ) {
		StaticVarSet( staticname, 1-togglecheck, persist );	
		Say( "Toggle " + StrExtract(toggletext, 1-togglecheck) ); 
	} 
}
 
/// ###########################################################################################################
showPlot = toggle1;
showredcolor = VarGet("toggle2") == 1;	// if numbuttons is larger than 1 then better use VarGet 
										// to avoid error message if changing numbuttons to lower values
//
// Usage example 
if ( showPlot ) {
	_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} - {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%), Vol %g {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ), V ) );
	Plot( C, "", IIf( showredcolor, colorRed, colorDefault), styleLine );
}

853

2 Likes

@fxshrat thanks for the code!

I haven't analysed it thoroughly yet, but noticed, that after clicking one of the buttons, visual changes are applied from the next formula run. So one additional refresh would be beneficial (if the chart is not refreshed by plugin). A quick and simple solution could be adding RequestTimedRefresh(0.1) to refresh the chart only once after the button is clicked:

if ( GuiGetEvent( 0, 0 ) == toggleID && GuiGetEvent( 0, 1 ) == 1 ) {
		StaticVarSet( staticname, 1-togglecheck, persist );	
		Say( "Toggle " + StrExtract(toggletext, 1-togglecheck) ); 
		RequestTimedRefresh(0.1);
	} 

Now the changes are applied right after the click, but I think (maybe I'm wrong) that the same effect should be possible without resorting to using this additional refresh at all. I haven't recognized the reason of the delay yet. I'll give it another try ...

2 Likes

I'm on REALTIME DB and there you do not need RequestTimedRefresh.
But yeah, since GuiButtons are detached from chart pane selection (-> so button click does not trigger chart pane selection) on local DB you would need to add RequestTimedRefresh.

1 Like

The code should be restructured NOT to require additional run. Just do everything needed right after receiving an event from GUI, without waiting for "next" refresh. This way: a) you avoid additional refreshes, b) your code is faster, c) updates are immediate

1 Like

Hello @fxshrat thanks for the code, I tried it but it has a little glitch. When you press the second button, the first button also get "affected" somehow, vice versa...

here is my modified afl from you, can you take a look to see what went wrong? thanks

Version( 6.25 ); 
MA1=MA(Close,10);
MA2=MA(Close,20);
/// ###########################################################################################################
/// Multi-GuiToggleButtons preserving set ON/OFF state (e.g. after restart of AB), vrs.1.0
/// by fxshrat@gmail.com
/// @link https://forum.amibroker.com/t/replace-toggle-button-in-parameter-window-with-guitoggle-button/6392/8
/// ###########################################################################################################
numbuttons = 2; // number of toggle buttons
toggletext1 = "Plot MA1 OFF,Plot MA1 ON";
toggletext2 = "Plot MA2 OFF,Plot MA2 ON";
//toggletext3 = ...;
// etc
initial = 1;// intial toggle setting
persist = 1;// keep toggle state ON(1) / OFF(0)
ypos = 15;
width = 80;
height = 22;

// iterate number of toggle buttons
for ( toggleID = 1; toggleID <= numbuttons; toggleID++ ) {  
	toggletext = VarGetText( "toggletext" + toggleID );	
	GuiToggle( StrExtract(toggletext, 0), toggleID, x = 0, y = (toggleID-1)*(height-2) + ypos, width, height, notifyflag = 1 );

	staticname = StrFormat( "GuiParamToggle_%s_%g_%g", GetDatabaseName(), GetChartID(), toggleID );
	staticget = Nz(StaticVarGet( staticname ), initial);
	GuiSetCheck(toggleID, staticget);

	togglecheck = GuiGetCheck(toggleID); 
	VarSet( "toggle" + toggleID, togglecheck );

	if ( togglecheck ) GuiSetText( StrExtract(toggletext, 1), toggleID ); 

	if ( GuiGetEvent( 0, 0 ) == toggleID && GuiGetEvent( 0, 1 ) == 1 ) {
		StaticVarSet( staticname, 1-togglecheck, persist );	
		Say( "Toggle " + StrExtract(toggletext, 1-togglecheck) ); 
	} 
}
 
/// ###########################################################################################################
showPlot1 = toggle1;
showPlot2 = VarGet("toggle2") == 1;	// if numbuttons is larger than 1 then better use VarGet 
										// to avoid error message if changing numbuttons to lower values
//
// Usage example 
if ( showPlot1 ) {

Plot(MA1,"MA10daily",colorRed,styleLine|styleThick);
}

if ( showPlot2 ) {

Plot(MA2,"MA20daily",colorBlue,styleLine|styleThick);
}
1 Like

Hello @Fossil,

thanks for the code, I am beginning to understand how it works.
If you would be so kind, can you give example if there is two buttons? which part of the code I should change?

thank you in advance

@sikatgigi
If version above 6.2 you should use @Milosz or @fxshrat code..... and to make another Button… play with X & Y axis to create ClickArea2… & assign remaining logic.
Put your MA indicator here…
logic%20input%20area

2 Likes

Tomasz, I know that. There was already a long discussion about it in this thread (where I was against using regular refreshes in such codes) I have coded a lot of examples using GuiButtons (and have posted many of them on the forum) and none of them uses any regular or additional refreshes to work properly. That's why I wrote in my reply that in general it should be done without resorting to using this additional refresh to apply the changes right away. It was just a quick solution to fxshrat's code because up untill now I didn't have time to recode fxshrat's last example. I have already proposed my solution above which applies all the changes in the same formula run without any additional refresh, no matter if the user is on local DB or not.

2 Likes

@Milosz - I know that you know :slight_smile: My answer was addressed to person who wrote the original code, which of course wasn't you. And surely it is not your task to rewrite somebody's else code :wink: I am sorry if I did not make it clear enough to whom this was addressed.

2 Likes

Buttons don't affect each other. You seem to be on local DB so you have to add RequestTimedRefresh for current version as said few posts above.

But I am stopping here. Too many know-it-alls here speaking to 3rd person.

BTW, I know too...

And oh yeah, I don't have time too...

:roll_eyes:

1 Like

Nevertheless since I don't have time here is quick current version 1.1 not requiring RequestTimedRefresh after equally quick test.

Version( 6.25 ); 

/// ###########################################################################################################
/// Multi-GuiToggleButtons preserving set ON/OFF state (e.g. after restart of AB), vrs.1.1
/// by fxshrat@gmail.com
/// @link https://forum.amibroker.com/t/replace-toggle-button-in-parameter-window-with-guitoggle-button/6392/8
/// ###########################################################################################################
numbuttons = 2; // number of toggle buttons
toggletext1 = "Plot OFF,Plot ON";
toggletext2 = "ColorDefault,ColorRed";
//toggletext3 = ...;
// etc
initial = 1;// intial toggle setting
persist = 1;// keep toggle state ON(1) / OFF(0)
ypos = 15;
width = 80;
height = 22;

// iterate number of toggle buttons
for ( toggleID = 1; toggleID <= numbuttons; toggleID++ ) {  
	toggletext = VarGetText( "toggletext" + toggleID );	
	GuiToggle( StrExtract(toggletext, 0), toggleID, x = 0, y = (toggleID-1)*(height-2) + ypos, width, height, notifyflag = 1 );
	
	togglecheck = GuiGetCheck(toggleID); 
	VarSet( "toggle" + toggleID, togglecheck );

	if ( togglecheck ) GuiSetText( StrExtract(toggletext, 1), toggleID );	
	
	staticname = StrFormat( "GuiParamToggle_%s_%g_%g", GetDatabaseName(), GetChartID(), toggleID );
	staticget = Nz(StaticVarGet( staticname ), initial);
	if ( GuiGetEvent( 0, 0 ) == toggleID && GuiGetEvent( 0, 1 ) == 1 ) {		
		GuiSetCheck(toggleID, staticget);
		StaticVarSet( staticname, 1-togglecheck, persist );	
		Say( "Toggle " + StrExtract(toggletext, togglecheck) );		
	} 		
}

/// ###########################################################################################################
showPlot = toggle1;
showredcolor = VarGet("toggle2") == 1;	// if numbuttons is larger than 1 then better use VarGet 
										// to avoid error message if changing numbuttons to lower values
//
// Usage example 
if( showPlot ) {
	_N( Title = StrFormat( "{{NAME}} - {{INTERVAL}} - {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%), Vol %g {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ), V ) );
	Plot( C, "", IIf( showredcolor, colorRed, colorDefault), styleLine );
}

EDIT:
I does not seem to preserve previous setting after closing AB...
Have to go now...

3 Likes

Thank you for the codes guys, it really nice to have someone helping each others....

I tried the fxshrat code but still dont understand where is the mistakes, the code from Milosz is doing perfectly, but again because I am not a programmer I can not combine the 2 codes from fxshrat and Milosz to get multiple toggle button works perfectly.

Tomasz said that now I have to use this forum to learn together and cannot directly ask to amibroker suport for this kind of matter.... please help point out the logic to makes multiple toggle that works perfectly using gui button? I try to learn the logics from each coding you all been so kindly and so FAST share to us, but this guibutton is something new and I tried the help file in Amibroker but i think its not there yet.... so please help the unsmart me.... :slight_smile:

And by the way, can Amibroker now have input guibutton to input the numbers/text? If have, then I think I would never need to go to the parameter window again....

for example I want to draw line to alert me when the price reach 200. I have 2 button in my afl chart, the first is input button, I will input 200, then i will press the guibutton Draw, then its done, no need to right click and input it in parameter window..

thanks in advance for the help from all of you