GfxSetZOrder and GfxSetOverlayMode

Hello. I would like to ask @Tomasz and/or other users about some GFX features.

For some time I've been trying to work out the best way of using charts to display only GFX stuff in codes similar to this one:

PrzechwytywaniePBP

Usually I use GfxSetOverlayMode(2) which allows to display only graphics (no charts, no grids, etc) and GfxSetBkMode(1) - transparent background (i.e. of the text) and it works properly, but the only problem is that in such case I cannot use GfxSetZOrder(). If I do so I get an Error: PrzechwytywanieError . Because of this, the only way in which I can decide which graphics elements are on top and which are are behind is the sequence in which they appear in the code. It is easy in simple cases, but as the code becomes complex it gets problematic and forces to move some parts of the code to (sometimes) distant locations. I find it especially challenging in case of custom functions or procedures - used to display some elements depending on many factors - which are declared at the beginning of the code. I would like to make sure if in such cases, moving some parts of the code is the only way?

I also ask, because some time ago I didn't know, that using GfxSetZOrder and GfxOverlayMode in the same code is not allowed (if GfxSetZOrder follows GfxOverlayMode, AFL Editor doesn't display any Error) and was experimenting with different ways of achieving my goal. I came to the solution which uses both above functions and seems to work properly except one element which I can't get rid of. It is the black vertical line which separates the chart and the scale area. I can't make it disappear (although I've tried many different ways) if there is GfxSetZOrder present in the code. Maybe there is an option allowing to do that, which I haven't found?

Przechwytywanie

BTW I understand, that GuiButtons are always on top and cannot be obscured by any other element (that is logical).

Thank you in advance for any suggestions.

1 Like

A very simle example without using GfxSetOverlayMode() and GfxSetBkMode():

Title = "";
XMax = Status( "pxwidth" );

GfxZOrderOn = ParamToggle( "GfxZOrder", "Off|On", 0 );

if( GfxZOrderOn == 0 )
{

    GfxGradientRect( 0, 0, XMax, 300, colorWhite, ColorBlend( colorBlack, colorWhite, 0.7 ) );
    GfxSelectFont( "Segoe UI", 10, 400, False, False, 0 );
    GfxTextOut( "Test text Test text Test text Test text Test text Test text Test text Test text Test text", 280, 160 );
    GfxGradientRect( 100, 70, 500, 250, colorWhite, ColorBlend( colorBlack, colorWhite, 0.4 ) );
}

else

{
    GfxSetZOrder( 1 );
    GfxGradientRect( 0, 0, XMax, 300, colorWhite, ColorBlend( colorBlack, colorWhite, 0.7 ) );
    GfxSelectFont( "Segoe UI", 10, 400, False, False, 0 );
    GfxSetZOrder( 2 );
    GfxTextOut( "Test text Test text Test text Test text Test text Test text Test text Test text Test text", 280, 160 );
    GfxSetZOrder( 1 );
    GfxGradientRect( 100, 70, 500, 250, colorWhite, ColorBlend( colorBlack, colorWhite, 0.4 ) );
}

GfxZOrder

1 Like

As editor message says you shouldn’t need GfxSetOverlayModeand GfxSetZOrder in same code. GfxSetZOrder is improved function of GfxSetOverlayMode and it is more flexible since it allows multiple calls by applying different z layers.

The z order range of GfxSetZOrder goes from -128 (bottom most) to 128 (top most).

GfxSetZOrder(128) applies the same as GfxSetOverlayMode(0).
GfxSetZOrder(-128) applies the same as GfxSetOverlayMode(1).

Following drawing will be placed above of default chart and also hides price axis line.

pxwidth  = Status( "pxwidth" );
pxheight = Status( "pxheight" );
	
GfxSetZOrder( 128 );
GfxGradientRect( pxWidth-200, 0, pxWidth, pxheight, colorBlack, colorBlack );

This one will place drawing at bottom most

pxwidth  = Status( "pxwidth" );
pxheight = Status( "pxheight" );
	
GfxSetZOrder( -128 );
GfxGradientRect( pxWidth-200, 0, pxWidth, pxheight, colorBlack, colorBlack );

If you just want to draw Gfx only then you should not use GfxSetZOrder (except for just using GfxSetZOrder(128) at the top).

Either use GfxSetOverlayMode(2) or place colored rectangle at top of script.

pxwidth  = Status( "pxwidth" );
pxheight = Status( "pxheight" );

GfxGradientRect( 0, 0, pxWidth, pxheight, colorBlack, colorBlack );

and all other Gfx follows below of it.

3 Likes

@fxshrat thanks for the reply.

I didn’t know that GfxSetZOrder ranges from -128 to 128 and in case of 128 it indeed covers/obscures this vertical line. It’s good to know that, but frankly in such case there’s no point in using GfxSetZOrder at all if we are limited to only one value. It would be very useful if I could use different Z layers. As I mentioned, I have been already using GfxSetOverlayMode(2) - which I have just learned (from you) is a synonym for GfxSetZOrder(128) but then I need to move some parts of the code (sometimes to distant locations) just to be able to display some things in desired order. In case of complex codes - for example displaying conditionally many different values/strings using loops, GuiButtons, and using custom functions/procedures for that (which are declared at the beginning of the code) it is sometimes a challenge for me. If I could use GfxSetZOrder it would be a piece of cake :wink:

https://www.amibroker.com/guide/h_zorder.html

Once again thanks for the help.

1 Like

The order of elements is defined by layer parameter, not by the sequence in code

Title = "";
GfxZOrderOn = Param( "GfxZOrder",0, 0, 3, 1);

if( GfxZOrderOn == 0 ) {
	Zred = 3;
	ZGreen = 2;
	ZOrange = 1;
} else if( GfxZOrderOn == 1 ) {
	Zred = 3;
	ZGreen = 1;
	ZOrange = 2;
} else if( GfxZOrderOn == 2 ) {
	Zred = 2;
	ZGreen = 1;
	ZOrange = 3;
} else {
	Zred = 1;
	ZGreen = 2;
	ZOrange = 3;
}
GfxSetZOrder( Zred );
GfxGradientRect( 110, 70, 250, 250, colorWhite, colorRed );
GfxSetZOrder( ZGreen );
GfxGradientRect( 120, 70, 300, 300, colorWhite, colorGreen );
GfxSetZOrder( ZOrange );
GfxGradientRect( 140, 70, 250, 350, colorWhite, colorOrange );

1 Like

Anderson, thanks for the replay.

I am of fourse aware of that that. I've been using GfxSetZOrder() for a long time, but as I have shown in my above examples, in such code I cannot get rid of the vertical line separating the chart area and scale area. Your example:

Przechwytywanie

So I want this (Here I use GfxSetOverlayMode(2) and GfxSetBkMode(1)) :

Przechwytywanie1

.. not this (different GfxSetZOrder() present in the code):

Przechwytywanie2

Summing up, if nobody shows a way how to disable displaying this line (when GfxSetZOrder() is present) I assume, that in such cases as above, the only solution is using GfxSetOverlayMode(2) or as fsxhrat has shown - GfxSetZOrder(128) and the only way which enables to determine which elements are displayed in front (foreground) and which are behind (background) is the order in which they appear in the code.

I just want to make it clear, because sometimes you can spend a lot of time making complex solutions when they can be easily simplified :wink:

1 Like
Title = "";
pxwidth  = Status( "pxwidth" );
pxheight = Status( "pxheight" );
	
GfxSetZOrder( 128 );
GfxGradientRect( pxWidth-200, 0, pxWidth, pxheight, colorwhite, colorwhite );

GfxZOrderOn = Param( "GfxZOrder",0, 0, 3, 1);

if( GfxZOrderOn == 0 ) {
	Zred = 3;
	ZGreen = 2;
	ZOrange = 1;
} else if( GfxZOrderOn == 1 ) {
	Zred = 3;
	ZGreen = 1;
	ZOrange = 2;
} else if( GfxZOrderOn == 2 ) {
	Zred = 2;
	ZGreen = 1;
	ZOrange = 3;
} else {
	Zred = 1;
	ZGreen = 2;
	ZOrange = 3;
}
GfxSetZOrder( Zred );
GfxGradientRect( 110, 70, 250, 250, colorWhite, colorRed );
GfxSetZOrder( ZGreen );
GfxGradientRect( 120, 70, 300, 300, colorWhite, colorGreen );
GfxSetZOrder( ZOrange );
GfxGradientRect( 140, 70, 250, 350, colorWhite, colorOrange );

ami

@Tomasz is the only one that can probably provide you the optimal solution… in a future version of AmiBroker!

I do not know anything about the internals of the application but I hope that disabling that vertical line programmatically will not be a too difficult task to implement.

I suggest posting the request also in the FeedBack Center.

1 Like

@awilson Thanks again for your efforts.

Nice try :slight_smile: At first I thought, that I have missed something, because at first glance your new code seemed to achieve what I want, but then I realised, that you have used a kind of trick to hide only this vertical line area :wink: I want to use 100% of the chart area - and as I have shown above - it’s doable! If I replace your line:

GfxSetZOrder( 128 );
GfxGradientRect( pxWidth-200, 0, pxWidth, pxheight, colorwhite, colorwhite );

with:

GfxSetZOrder( 128 );
GfxGradientRect( 0, 0, pxWidth, pxheight, colorwhite, colorwhite );
// Or simply GfxFillSolidRect (0, 0, pxWidth, pxheight, colorWhite);

… to extend the filled area, the white area covers all other drawings because 128 is the top layer. All others are behind it. So we are again “back to square one”. In this case also the only way of determining which elements are displayed in front and which are behind, is the order in which they appear in the code. And I have already been using similar solution via GfxSetOverlayMode(2). It is even a simpler one, because I don’t have to draw any rectangle to hide other elements.

Once again, thanks a lot :slight_smile:

1 Like

@beppe I agree. If Tomasz says that there is no other way apart from presented above, of course I will accept that. As I have shown - I already have properly working solutions. I am just looking for a way of simplyfing complex codes.

It would be very useful in such cases to be able to “switch off” this vertical line. Everything else seems to be working fine and using GfxSetZOrder() is so simple. I may suggest implementing such option/feature to the feedback centre. I would really appreciate hearing @Tomasz’s opinion about that.

Thanks a lot!

1 Like

The thing is that these two functions provide similar functionality (Z-ordering) and they are mutually exclusive as one would interfere with another. The thing is however that overlay mode 2 is in fact “special case” which means, don’t draw anything and I think it would be beneficial to treat it as “special” and allow it to be called in one and only allowed position - on top of the formula. Something to consider in next version.

1 Like

Tomasz, thank you for the reply!

Of course all new features are welcomed by the users :slight_smile: but I am not sure if I understood correctly. is it possible to allow users to take advantage of different GFxSetZOrder() and be able to “switch off” this vertical line which seems to be the only element which makes using ZOrders in such cases impossible?

Thank you

1 Like

Sure just add this:

SetChartOptions( 0, chartHideQuoteMarker ); 
1 Like

I've tried, but the vertical line still persists :disappointed_relieved: :wink: It is not a quote Marker.

Przechwytywanie

If it is crosshair you need to press Ctrl+H. But it may be also divider between Y axis area and the chart area. If that is the case you can’t control it using SetChartOptions at the moment.

1 Like

No it is not a crosshair. It is a line between the chart area and Y axis area.

Przechwytywanie

Would it be possible to allow users to switch off this line in such cases? It would be really useful. Will you consider implementing it? :wink: Should I submit it to the feedback centre?

1 Like

ami

Title = "";
pxwidth  = Status( "pxwidth" );
pxheight = Status( "pxheight" );
	
//GfxSetZOrder( 128 );
//GfxGradientRect( pxWidth-200, 0, pxWidth, pxheight, colorwhite, colorwhite );

GfxZOrderOn = Param( "GfxZOrder",0, 0, 3, 1);

if( GfxZOrderOn == 0 ) {
	Zred = 3;
	ZGreen = 2;
	ZOrange = 1;
} else if( GfxZOrderOn == 1 ) {
	Zred = 3;
	ZGreen = 1;
	ZOrange = 2;
} else if( GfxZOrderOn == 2 ) {
	Zred = 2;
	ZGreen = 1;
	ZOrange = 3;
} else {
	Zred = 1;
	ZGreen = 2;
	ZOrange = 3;
}
GfxSetZOrder( Zred );
GfxGradientRect( 110, 70, 250, 250, colorWhite, colorRed );
GfxSetZOrder( ZGreen );
GfxGradientRect( 120, 70, 300, 300, colorWhite, colorGreen );
GfxSetZOrder( ZOrange );
GfxGradientRect( 140, 70, 250, 350, colorWhite, colorOrange );

How to NOT draw the line of Y axis ?

1 Like

Try this:

SetChartOptions(GetChartID(),chartHideQuoteMarker);

Anthony

1 Like

Did you try and change the color of the axis line to the color of the chart area ?

1 Like

I already wrote what I would do in previous reply

1 Like