FirstVisibleIndex and LastVisibleIndex while zooming
FirstVisibleIndex and LastVisibleIndex while zooming
Hello.
I'm using TeeChart Pro 4.2019.8.8 and I need to determine indexes of the first and last point that are visible to user. I'm using line1.FirstVisibleIndex and line1.LastVisibleIndex, but it gives me strange values. I use non-historical horizontal zoom.
First zoom:
Second zoom:
Third Zoom:
Undone zoom:
Undone zoom again (values changed!!!):
I've uploaded test app here
I'm using TeeChart Pro 4.2019.8.8 and I need to determine indexes of the first and last point that are visible to user. I'm using line1.FirstVisibleIndex and line1.LastVisibleIndex, but it gives me strange values. I use non-historical horizontal zoom.
First zoom:
Second zoom:
Third Zoom:
Undone zoom:
Undone zoom again (values changed!!!):
I've uploaded test app here
Last edited by bairog on Tue Aug 13, 2019 6:14 am, edited 1 time in total.
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Hello!
rather than using the Zoomed and UndoneZoom events, have you tried using the AfterDraw events?
Here this works much better.
rather than using the Zoomed and UndoneZoom events, have you tried using the AfterDraw events?
Code: Select all
private void TChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
Text = $"FirstVisibleIndex: {line1.FirstVisibleIndex}, LastVisibleIndex: {line1.LastVisibleIndex}";
}
private void TChart1_Zoomed(object sender, EventArgs e)
{
//Text = $"FirstVisibleIndex: {line1.FirstVisibleIndex}, LastVisibleIndex: {line1.LastVisibleIndex}";
}
private void TChart1_UndoneZoom(object sender, EventArgs e)
{
//Text = $"FirstVisibleIndex: {line1.FirstVisibleIndex}, LastVisibleIndex: {line1.LastVisibleIndex}";
}
Best Regards,
Christopher Ireland / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Re: FirstVisibleIndex and LastVisibleIndex while zooming
For unzoomed chart both values are correct:Christopher wrote: ↑Fri Aug 09, 2019 8:28 amrather than using the Zoomed and UndoneZoom events, have you tried using the AfterDraw events?Here this works much better.
But for zoomed chart LastVisibleIndex returns correct_value + 1:
P. S. I'm drawing custom labels for bottom axis (label text is long - so I need to perform labels thinning). So I need to clear all current labels (30 for example) and add some custom labels (10 for example). And looks like AfterDraw event does't suitable for that -tChart.Axes.Labels.Items.Count in debugger doesn't correspond to number of labels that I see on a screen aftewards.
I've uploaded sample application here.
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Hello!
Okay - first off, LastVisibleIndex is one off in LIne series because the line itself is considered as belonging to the next point - so, for example, if you scroll the chart so there's only one point visible, the visible part of the line which continues to the next point (which isn't visible) causes LastVisibleIndex to be one and not zero.
As for the events, you can use BeforeDraw for the Labels and AfterDraw for the Text and this will save you having to zoom out twice to get the correct labels, e.g.
Okay - first off, LastVisibleIndex is one off in LIne series because the line itself is considered as belonging to the next point - so, for example, if you scroll the chart so there's only one point visible, the visible part of the line which continues to the next point (which isn't visible) causes LastVisibleIndex to be one and not zero.
As for the events, you can use BeforeDraw for the Labels and AfterDraw for the Text and this will save you having to zoom out twice to get the correct labels, e.g.
Code: Select all
private void TChart1_BeforeDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
//Text = $"FirstVisibleIndex: {line1.FirstVisibleIndex}, LastVisibleIndex: {line1.LastVisibleIndex}";
DrawLabels(maxDisplayedLabelsForBottomaAxis);
}
private void TChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
Text = $"FirstVisibleIndex: {line1.FirstVisibleIndex}, LastVisibleIndex: {line1.LastVisibleIndex}";
//DrawLabels(maxDisplayedLabelsForBottomaAxis);
}
Best Regards,
Christopher Ireland / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Ok, I got it.Christopher wrote: ↑Fri Aug 09, 2019 11:23 amOkay - first off, LastVisibleIndex is one off in LIne series because the line itself is considered as belonging to the next point - so, for example, if you scroll the chart so there's only one point visible, the visible part of the line which continues to the next point (which isn't visible) causes LastVisibleIndex to be one and not zero.
If I use BeforeDraw event - I have FirstVisibleIndex=0 and LastVisibleIndex=line1.Count after the first zoom. After the second zoom FirstVisibleIndex and LastVisibleIndex have values of the first zoom and so on. That makes impossible to calculate currently visible points inside DrawLabels function and it is working incorrectly.Christopher wrote: ↑Fri Aug 09, 2019 11:23 amAs for the events, you can use BeforeDraw for the Labels and AfterDraw for the Text and this will save you having to zoom out twice to get the correct labels
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: FirstVisibleIndex and LastVisibleIndex while zooming
I can't see that it's working incorrectly - using this slightly modified version of your example:bairog wrote: ↑Fri Aug 09, 2019 11:49 amIf I use BeforeDraw event - I have FirstVisibleIndex=0 and LastVisibleIndex=line1.Count after the first zoom. After the second zoom FirstVisibleIndex and LastVisibleIndex have values of the first zoom and so on. That makes impossible to calculate currently visible points inside DrawLabels function and it is working incorrectly.
Code: Select all
//DrawLabels(maxDisplayedLabelsForBottomaAxis);
tChart1.BeforeDraw += TChart1_BeforeDraw;
}
private void TChart1_BeforeDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
//Text = $"FirstVisibleIndex: {line1.FirstVisibleIndex}, LastVisibleIndex: {line1.LastVisibleIndex}";
DrawLabels(maxDisplayedLabelsForBottomaAxis);
}
private void TChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
Text = $"FirstVisibleIndex: {line1.FirstVisibleIndex}, LastVisibleIndex: {line1.LastVisibleIndex}";
//DrawLabels(maxDisplayedLabelsForBottomaAxis);
}
I can't see what is working incorrectly here.
Best Regards,
Christopher Ireland / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Re: FirstVisibleIndex and LastVisibleIndex while zooming
When you zoom in first time and number of currently displayed points is lower than 20 (in your gif from point 11 to point 19) every label on bottom axis should be drawn (because 19 - 11 < 20). In your gif every second label is drawn. That is because of incorrect FirstVisibleIndex and LasVisibleIndex values.
The logic is simple - labels are thinned to maximum 20 labels simultaneously visible.
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Once again: I want to avoid labels overlapping on bottom axis and ensure two adjacent labels have a free space between them. So labels are thinned to maximum 20 labels simultaneously visible.
As I can see from my experiments:
In BeforeDraw event FirstVisibleIndex/LastVisibleIndex have incorrect values (FirstVisibleIndex=0 and LastVisibleIndex=line1.Count after the first zoom; after the second zoom FirstVisibleIndex and LastVisibleIndex have values of the first zoom and so on) but I can manipulate labels.
In AfterDraw event FirstVisibleIndex/LastVisibleIndex have correct values but I cannot manipulate labels (clear/add has no effect).
So the only workaround that I see is the following (force redraw after initial draw + drawing custom labels on redraw):
That workaround archeives the goal but it's very bad (hits performance and maybe have some other side effects).
Moreover labels are not fully visible - chart isn't recalculating vertical space that is needed to draw bottom axis labels for some reason:
The only workaround is to use the following code (draw labels every time):
But it hits performance even worse because my custom labels are drawn on initial draw and on force redraw.
I've uploaded sample app here
BTW: long time ago in TeeChart V2 I was successfully using Zoomed/UndoneZoom/Scroll events to obtain FirstVisibleIndex/LastVisibleIndexand draw my custom labels. Now in TeeChart V4 inside that events FirstVisibleIndex/LastVisibleIndex have incorrect values.
To sum up: to draw custom labels depending on first and last visible points it is vital to have an event with correct FirstVisibleIndex/LastVisibleIndex and which allows to manipulate labels. Some time ago it was Zoomed/UndoneZoom/Scroll, but now it's not working. Maybe you can repair them?
P. S. If there is enother way to ensure two adjacent labels have a free space between them (e. g. tChart1.Axes.Bottom.Labels.Space = 10) - any help will be appreciated..
As I can see from my experiments:
In BeforeDraw event FirstVisibleIndex/LastVisibleIndex have incorrect values (FirstVisibleIndex=0 and LastVisibleIndex=line1.Count after the first zoom; after the second zoom FirstVisibleIndex and LastVisibleIndex have values of the first zoom and so on) but I can manipulate labels.
In AfterDraw event FirstVisibleIndex/LastVisibleIndex have correct values but I cannot manipulate labels (clear/add has no effect).
So the only workaround that I see is the following (force redraw after initial draw + drawing custom labels on redraw):
Code: Select all
private Boolean FirstAndLastVisibleIndexesAreCorrect = true;
private void TChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
if (!FirstAndLastVisibleIndexesAreCorrect)
tChart1.Refresh();
}
private void TChart1_BeforeDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
FirstAndLastVisibleIndexesAreCorrect = !FirstAndLastVisibleIndexesAreCorrect;
if (FirstAndLastVisibleIndexesAreCorrect)
DrawLabels(maxDisplayedLabelsForBottomaAxis);
}
Moreover labels are not fully visible - chart isn't recalculating vertical space that is needed to draw bottom axis labels for some reason:
The only workaround is to use the following code (draw labels every time):
Code: Select all
private Boolean FirstAndLastVisibleIndexesAreCorrect = true;
private void TChart1_AfterDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
if (!FirstAndLastVisibleIndexesAreCorrect)
tChart1.Refresh();
}
private void TChart1_BeforeDraw(object sender, Steema.TeeChart.Drawing.Graphics3D g)
{
FirstAndLastVisibleIndexesAreCorrect = !FirstAndLastVisibleIndexesAreCorrect;
DrawLabels(maxDisplayedLabelsForBottomaAxis);
}
I've uploaded sample app here
BTW: long time ago in TeeChart V2 I was successfully using Zoomed/UndoneZoom/Scroll events to obtain FirstVisibleIndex/LastVisibleIndexand draw my custom labels. Now in TeeChart V4 inside that events FirstVisibleIndex/LastVisibleIndex have incorrect values.
To sum up: to draw custom labels depending on first and last visible points it is vital to have an event with correct FirstVisibleIndex/LastVisibleIndex and which allows to manipulate labels. Some time ago it was Zoomed/UndoneZoom/Scroll, but now it's not working. Maybe you can repair them?
P. S. If there is enother way to ensure two adjacent labels have a free space between them (e. g. tChart1.Axes.Bottom.Labels.Space = 10) - any help will be appreciated..
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: FirstVisibleIndex and LastVisibleIndex while zooming
One alternative is this:
Code: Select all
public partial class Form1 : Form
{
//max visible labels
private const Int32 maxDisplayedLabelsForBottomaAxis = 20;
//list of customa labels
private List<String> Labels = new List<string>();
public Form1()
{
var rnd = new Random();
InitializeComponent();
tChart1.Axes.Bottom.GetAxisDrawLabel += Bottom_GetAxisDrawLabel;
tChart1.Axes.Bottom.Labels.Style = Steema.TeeChart.AxisLabelStyle.Text;
for (int i = 0; i < 30; i++)
{
//adding points
line1.Add(i, rnd.Next(5));
//adding custom labels
Labels.Add($"Point #{i}");
}
line1.Labels.AddRange(Labels);
}
private void Bottom_GetAxisDrawLabel(object sender, Steema.TeeChart.GetAxisDrawLabelEventArgs e)
{
if((line1.LastVisibleIndex - line1.FirstVisibleIndex) > maxDisplayedLabelsForBottomaAxis)
{
var label = int.Parse(e.Text.Last().ToString());
e.DrawLabel = label % 2 == 0;
}
else
{
e.DrawLabel = true;
}
}
}
Best Regards,
Christopher Ireland / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Looks like DrawAxisLabel event is forking fine.
But what is my labels are not like Point #{i}, but like First point, Second point, etc..
In that case i cannot rely on:
Code: Select all
var labelIndex = int.Parse(e.Text.Last().ToString())
BTW. At least Steema.TeeChart.NET nuget package (and I suppose all others too) doesn't have *.xml files inside. It's really hard to use your libraries on machines with no internet connection. Many developers prefer to have XML-comments right in their IDE. It's a real pain to guess what are the differences for example between CalcPosPoint or CalcPosValue or CalcXPosValue. Suppose it will not be a big problem to generate XML-documentation and add it to nuget package on every build automatically. Thank you in advance.
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Well, you could check the incoming Text with the Labels collection you already have, e.g.
Code: Select all
public partial class Form1 : Form
{
//max visible labels
private const Int32 maxDisplayedLabelsForBottomaAxis = 20;
//list of customa labels
private List<String> Labels = new List<string>();
public Form1()
{
var rnd = new Random();
InitializeComponent();
tChart1.Axes.Bottom.GetAxisDrawLabel += Bottom_GetAxisDrawLabel;
tChart1.Axes.Bottom.Labels.Style = Steema.TeeChart.AxisLabelStyle.Text;
for (int i = 0; i < 30; i++)
{
//adding points
line1.Add(i, rnd.Next(5));
//adding custom labels
Labels.Add($"Point NoClue #{rnd.Next()}");
}
line1.Labels.AddRange(Labels);
}
private void Bottom_GetAxisDrawLabel(object sender, Steema.TeeChart.GetAxisDrawLabelEventArgs e)
{
if((line1.LastVisibleIndex - line1.FirstVisibleIndex) > maxDisplayedLabelsForBottomaAxis)
{
var label = Labels.IndexOf(e.Text);
e.DrawLabel = label % 2 == 0;
}
else
{
e.DrawLabel = true;
}
}
}
Best Regards,
Christopher Ireland / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Well, not so elegant as I thought - I supposed I can use something likeChristopher wrote: ↑Mon Aug 12, 2019 8:56 amWell, you could check the incoming Text with the Labels collection you already have, e.g.
Code: Select all
(sender as Steema.TeeChart.Axis).CalcXXXXValue(e.X)
P. S. As I wrote above - missing *.XML files in your nuget packages is a real pain, add them please. If in addition you can also add offline variant for http://www.teechart.net/docs/TeeChartNETReference.htm - it will be even better (nuget package already has TeeChart_Pro_Net_Tutorials.chm, why not to add TeeChart_Pro_Net_Library_Reference.chm as well). Many thanks in advance.
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: FirstVisibleIndex and LastVisibleIndex while zooming
You don't have to use the Labels collection, unless you want to. I've also modded the code so scrolling doesn't draw every label when less than 20 labels are shown:
Code: Select all
public partial class Form1 : Form
{
//max visible labels
private const Int32 maxDisplayedLabelsForBottomaAxis = 20;
public Form1()
{
var rnd = new Random();
InitializeComponent();
tChart1.Axes.Bottom.GetAxisDrawLabel += Bottom_GetAxisDrawLabel;
tChart1.Axes.Bottom.Labels.Style = Steema.TeeChart.AxisLabelStyle.Text;
for (int i = 0; i < 30; i++)
{
//adding points
line1.Add(i, rnd.Next(5), $"Point NoClue #{rnd.Next()}");
}
}
private void Bottom_GetAxisDrawLabel(object sender, Steema.TeeChart.GetAxisDrawLabelEventArgs e)
{
if(tChart1.Zoom.Zoomed)
{
if ((line1.LastVisibleIndex - line1.FirstVisibleIndex) > maxDisplayedLabelsForBottomaAxis)
{
var label = line1.Labels.IndexOf(e.Text);
e.DrawLabel = label % 2 == 0;
}
else
{
e.DrawLabel = true;
}
}
else
{
var label = line1.Labels.IndexOf(e.Text);
e.DrawLabel = label % 2 == 0;
}
}
}
Okay, I've added this issue to our issue tracker with id=2225, which means your request will be considered for inclusion in future releases.
Best Regards,
Christopher Ireland / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Unfortunatelly I'm here again..
In fact instead of your code:
I'm using:
With it I draw every point if there are <=20 currently visible points; draw every 2nd point - if there are 20<x<=40 currently visible points; draw every 3rd point - if there are 40<x<=60 currently visible points, etc.
That code was working for 30 points in a line, but when I've tried to add 50 points - looks like chart started automatically performing thinning (I've commented Bottom_GetAxisDrawLabel function here):
So GetAxisDrawLabel fired not 50 times, but only 25 (only for visible labels).
And if I uncomment Bottom_GetAxisDrawLabel function - extra thinning is performed by it (it draws every 3rd label but among already thinned labels):
So how to deal with that? Is there a way to disable automatic thinning that is performed by chart itself?
In fact instead of your code:
Code: Select all
if ((line1.LastVisibleIndex - line1.FirstVisibleIndex) > maxDisplayedLabelsForBottomaAxis)
{
var label = line1.Labels.IndexOf(e.Text);
e.DrawLabel = label % 2 == 0;
}
Code: Select all
if ((line1.LastVisibleIndex - line1.FirstVisibleIndex) > maxDisplayedLabelsForBottomaAxis)
{
var drawEvery = ((line1.LastVisibleIndex - 1 - line1.FirstVisibleIndex) / maxDisplayedLabelsForBottomaAxis) + 1;
var label = line1.Labels.IndexOf(e.Text);
e.DrawLabel = label % drawEvery == 0;
}
That code was working for 30 points in a line, but when I've tried to add 50 points - looks like chart started automatically performing thinning (I've commented Bottom_GetAxisDrawLabel function here):
So GetAxisDrawLabel fired not 50 times, but only 25 (only for visible labels).
And if I uncomment Bottom_GetAxisDrawLabel function - extra thinning is performed by it (it draws every 3rd label but among already thinned labels):
So how to deal with that? Is there a way to disable automatic thinning that is performed by chart itself?
-
- Guru
- Posts: 1603
- Joined: Fri Nov 15, 2002 12:00 am
Re: FirstVisibleIndex and LastVisibleIndex while zooming
Try setting the Labels separation to zero, e.g.
Code: Select all
tChart1.Axes.Bottom.Labels.Separation = 0;
tChart1.Axes.Bottom.Labels.Style = Steema.TeeChart.AxisLabelStyle.Text;
Best Regards,
Christopher Ireland / Development & Support Steema Software Avinguda Montilivi 33, 17003 Girona, Catalonia Tel: 34 972 218 797 http://www.steema.com |
Instructions - How to post in this forum |