Page 1 of 1

Change panel margins based on visible axis

Posted: Tue Jun 12, 2012 2:49 pm
by 15660409
I'm working on implementing automatic adjustment of left margin on the panel based on which axes are shown.

I've stared with this piece of code:

Code: Select all

        private void tChart1_BeforeDrawSeries(object sender, Graphics3D g)
        {
            var sizeOfAxes = 30;
            var visibleAxes = 0;
            if (tChart1.Axes.Left.Visible)
                visibleAxes++;
            foreach (Axes axes in tChart1.Axes.Custom)
                if (axes.Visible) 
                    visibleAxes++;
            tChart1.Panel.MarginLeft = sizeOfAxes * visibleAxes;
        }


The big issue is that the chart only shows the big red cross all over when there exists a custom axes so that the foreach loop activates:

Code: Select all

            foreach (Axes axes in tChart1.Axes.Custom)
                if (axes.Visible) 
                    visibleAxes++;
What may cause this behaviour of the whole chart? As far as I know, I do not change any data in this code except the local variable 'visibleAxes'.

When there's some error in the chart so that the red cross appears, is there any way to programatically detect this state of the chart and reset it?
Cause

Code: Select all

tChart1.Series.Clear();
or

Code: Select all

tChart1.Clear();
is not enough to validate the chart again when red cross has appeared.

Is there some way to calculate the needed horisontal space for each axes including labels and values? Perferably an in parameter to add in the sum
instead of multiplying visible axes with a fix space value (sizeOfAxes).

Re: Change panel margins based on visible axis

Posted: Tue Jun 12, 2012 3:18 pm
by 10050769
Hello Simon Dahlquist SP,

Can you please, send me a simple project because we can try to reproduce your problem here?

Thanks,

Re: Change panel margins based on visible axis

Posted: Wed Jun 13, 2012 8:40 am
by 15660409
Here is a slolution with the problem.

Instructions:

Start application

Press Settings button and add a custom axis.

Press Refresh button.

Check the Include checkbox.

Press Refresh button - the problem occurs.

Regards,

Simon

Re: Change panel margins based on visible axis

Posted: Wed Jun 13, 2012 9:45 am
by 15660409
I found what causes the error in the chart.

Code: Select all

            foreach (Axes axes in tChart1.Axes.Custom)
                if (axes.Visible) 
                    visibleAxes++;
is wrong. The correct is

Code: Select all

            foreach (Axis axis in tChart1.Axes.Custom)
                if (axis.Visible) 
                    visibleAxes++;
Somehow I do not get this error as an unhandled exception in this solution but if I replace tChart1 with a new TChart in designer then this unhandled exception occurs.

But the question how to check the red cross occurance programatically remains and when it has occured, if there's a way to reset the chart without replace it with a new instance.

Is there any way to get how much horizontal space a vertical axis need to be shown correctly, to be used in setting the Panel margins.

What I want is a way to set the margins similar to what original left and right axis do, just more axis added. (Margin changed if all series that's connected to a certain axis are invisible)

Re: Change panel margins based on visible axis

Posted: Wed Jun 13, 2012 1:43 pm
by 10050769
Hello Simon Dahlquist SP,
Somehow I do not get this error as an unhandled exception in this solution but if I replace tChart1 with a new TChart in designer then this unhandled exception occurs.

But the question how to check the red cross occurance programatically remains and when it has occured, if there's a way to reset the chart without replace it with a new instance.
I can reproduce your problem here, but you can remove the file Licenses.licx from properties folder and rebuild the application to try to solve the problem.
Is there any way to get how much horizontal space a vertical axis need to be shown correctly, to be used in setting the Panel margins.

What I want is a way to set the margins similar to what original left and right axis do, just more axis added. (Margin changed if all series that's connected to a certain axis are invisible)
I recomend you use method MaxLabelsWidht() of Axes, the Axes Position property and AfterDraw event to control where the axis is drawn in a correct position and what size margin you need. You can do something as next :

Code: Select all

 i public Form1()
        {
            InitializeComponent();
           
           InitializeChart();
        }
        Steema.TeeChart.Axis custom1;
        Steema.TeeChart.Styles.Line line1, line2;
        private void InitializeChart()
        {
            line1 = new Steema.TeeChart.Styles.Line(tChart1.Chart);
            line1.FillSampleValues();
            line2 = new Steema.TeeChart.Styles.Line(tChart1.Chart);
            line2.FillSampleValues();
            tChart1.BeforeDrawSeries += new PaintChartEventHandler(tChart1_BeforeDrawSeries);
            custom1 = new Axis(tChart1.Chart);
            tChart1.Axes.Custom.Add(custom1);
            custom1.Horizontal = false;
            custom1.AxisPen.Color = Color.Red;
            line2.CustomVertAxis = custom1;
            tChart1.AfterDraw += new PaintChartEventHandler(tChart1_AfterDraw);
            tChart1.UndoneZoom += new EventHandler(tChart1_UndoneZoom);
            tChart1.Draw();
            tChart1.Draw();
            
        }

        void tChart1_UndoneZoom(object sender, EventArgs e)
        {
            tChart1.Draw();
        }
        int visibleAxes; 
        void tChart1_AfterDraw(object sender, Graphics3D g)
        {
            int Maxlabels = tChart1.Axes.Left.MaxLabelsWidth();
            custom1.PositionUnits = PositionUnits.Pixels;
            tChart1.Axes.Left.PositionUnits = PositionUnits.Pixels;
            custom1.RelativePosition = ((tChart1.Panel.MarginLeft + Maxlabels) - tChart1.Axes.Left.Position)/visibleAxes;
         
        }
        void tChart1_BeforeDrawSeries(object sender, Graphics3D g)
        {
            int sizeOfAxes = 10;
            visibleAxes = 0;
            if (tChart1.Axes.Left.Visible)
                visibleAxes++;
            if (cbxIncludeLoop.Checked)
            {
                // Axis not Axes.
                foreach (Axis axis in tChart1.Axes.Custom)
                    if (axis.Visible)
                        visibleAxes++;
            }

            tChart1.Panel.MarginLeft =  sizeOfAxes* visibleAxes;
         
        }
        private void BtnSettingsClick(object sender, EventArgs e)
        {
            tChart1.ShowEditor();
        }

        private void BtnRefreshClick(object sender, EventArgs e)
        {
            tChart1.Draw();
        }
Can you tell us if previous code help you to achieve as you want?

Thanks,

Re: Change panel margins based on visible axis

Posted: Wed Jun 13, 2012 4:36 pm
by 15660409
Thanks a lot for the answer Sandra!

It solved parts of my problem. the MaxLabelsWidth is really good but I need to calculate the total horizontal space for the axis including title if visible.

Is there a way to do that?

if the title is rotated 90 degrees:

Code: Select all

tChart1.Axes.Left.MaxLabelsWidth() + tChart1.Axes.Left.Title.Height + extraSpaceBetweenTitleAndLabels
if the title is horizontal:

Code: Select all

tChart1.Axes.Left.MaxLabelsWidth() + tChart1.Axes.Left.Title.Width + extraSpaceBetweenTitleAndLabels
extraSpaceBetweenTitleAndLabels is preferable something applicable.

Regards,

Simon

Re: Change panel margins based on visible axis

Posted: Thu Jun 14, 2012 3:21 pm
by 10050769
Hello Simon Dahlquist SP,

Ok, I have modified your code and now it use a method PlaceAxes() to calculate the position of custom axes dinamically:

Code: Select all

  public Form1()
        {
            InitializeComponent();           
           InitializeChart();
        }

        private void InitializeChart()
        {
            tChart1.Aspect.View3D = false;
            tChart1.Header.Visible = false;
            tChart1.Legend.Alignment = LegendAlignments.Bottom;
            for (int i = 0; i < nSeries - 1; i++)
            {
                new Steema.TeeChart.Styles.Line(tChart1.Chart);
                tChart1.Axes.Custom.Add(new Steema.TeeChart.Axis(tChart1.Chart));
                tChart1[i].CustomVertAxis = tChart1.Axes.Custom[i];
                tChart1.Axes.Custom[i].AxisPen.Color = tChart1[i].Color;
                tChart1.Axes.Custom[i].Grid.Visible = false;
                tChart1.Axes.Custom[i].Title.Visible = true;
                tChart1.Axes.Custom[i].Title.Caption = "Series" + i.ToString();
                tChart1[i].FillSampleValues(20);
                tChart1.Axes.Custom[i].PositionUnits = PositionUnits.Pixels;
            }

            tChart1.Panel.MarginUnits = PanelMarginUnits.Pixels;
            tChart1.Draw();
            PlaceAxes(0, 0, 0, 0, 0);
            tChart1.Draw();
        }


        private void PlaceAxes(int nSeries, int NextXLeft, int NextXRight, int MargLeft, int MargRight)
        {
            const int extraPos = 12;
            const int extraMargin = 105;
            //Variable 
            int MaxLabelsWidth;
            int lenghtTicks;
            int extraSpaceBetweenTitleAndLabels;
            if (tChart1[nSeries].Active)
            {
                MaxLabelsWidth = tChart1.Axes.Custom[nSeries].MaxLabelsWidth();
                lenghtTicks = tChart1.Axes.Custom[nSeries].Ticks.Length;
                extraSpaceBetweenTitleAndLabels = (tChart1.Axes.Custom[nSeries].Title.Width);//- tChart1.Axes.Custom[nSeries].MaxLabelsWidth());
                if (tChart1.Axes.Custom[nSeries].OtherSide)
                {
                    tChart1.Axes.Custom[nSeries].RelativePosition = NextXRight;
                    NextXRight = NextXRight - (MaxLabelsWidth + lenghtTicks + extraSpaceBetweenTitleAndLabels + extraPos);
                    MargRight = MargRight + extraMargin;
                }

                else
                {
                    tChart1.Axes.Custom[nSeries].RelativePosition = NextXLeft;
                    NextXLeft = NextXLeft - (MaxLabelsWidth + lenghtTicks + extraSpaceBetweenTitleAndLabels + extraPos);
                    MargLeft = MargLeft + extraMargin;
                }

                tChart1.Panel.MarginLeft = MargLeft;
                tChart1.Panel.MarginRight = MargRight;

                nSeries++;

                if (nSeries <= tChart1.Series.Count - 1)
                {
                    PlaceAxes(nSeries, NextXLeft, NextXRight, MargLeft, MargRight);
                }
            }
        }
Can you tell us if previous code works as you want?

I hope will helps.

Thanks,

Re: Change panel margins based on visible axis

Posted: Thu Jun 14, 2012 5:22 pm
by 15660409
Hi Sandra,

I'm sorry to tell you that your solution is not what I want.

What I want is additional custom axis that acts like the standard left and right axes except from that the custom axis will
be placed outside the right and left axis.

The space for each axis will be adjusted to fit what's visible on that axis.

Every single axis will only be visible if there are any active series that uses that axis.

When legend checkboxes are available, visible axes will be adjusted when check/uncheck series.

Panel margins of the chart will be minimized to fit the visible axes.

Regards,

Simon

Re: Change panel margins based on visible axis

Posted: Fri Jun 15, 2012 1:54 pm
by 10050769
Hello Simon,

Ok, I have modified the code again to try achieve as you want:

Code: Select all

  private void InitializeChart()
        {
            tChart1.Aspect.View3D = false;
            tChart1.Header.Visible = false;
            tChart1.Legend.Alignment = LegendAlignments.Bottom;
            tChart1.Legend.CheckBoxes = true;
            for (int i = 0; i < 3; i++)
            {
                new Steema.TeeChart.Styles.Line(tChart1.Chart);
                tChart1.Axes.Custom.Add(new Steema.TeeChart.Axis(tChart1.Chart));
                tChart1[i].CustomVertAxis = tChart1.Axes.Custom[i];
                tChart1.Axes.Custom[i].AxisPen.Color = tChart1[i].Color;
                tChart1.Axes.Custom[i].Grid.Visible = false;
                tChart1.Axes.Custom[i].Title.Visible = true;
                if (i % 2 == 0)
                {
                    tChart1.Axes.Custom[i].Title.Caption = "Series" + i.ToString();
                }
                tChart1[i].FillSampleValues(20);
                tChart1.Axes.Custom[i].PositionUnits = PositionUnits.Pixels;
            }

            tChart1.Panel.MarginUnits = PanelMarginUnits.Pixels;
            tChart1.Draw();
             PlaceAxes(0, 0, 0, 0, 0);
            tChart1.AfterDraw += new PaintChartEventHandler(tChart1_AfterDraw);
            tChart1.ClickLegend += new MouseEventHandler(tChart1_ClickLegend);
            tChart1.Draw();
        }

        void tChart1_ClickLegend(object sender, MouseEventArgs e)
        {
            tChart1.Draw();
        }

        void tChart1_AfterDraw(object sender, Graphics3D g)
        {
            PlaceAxes(0, 0, 0, 0, 0);
        }

        private void PlaceAxes(int nSeries, int NextXLeft, int NextXRight, int MargLeft, int MargRight)
        {
            const int extraPos = 12;
            const int extraMargin = 105;
            //Variable 
            int MaxLabelsWidth;
            int lenghtTicks;
            int extraSpaceBetweenTitleAndLabels;
            foreach (Steema.TeeChart.Styles.Line s in tChart1.Series)
            {
                if (s.Active)
                {
                    s.CustomVertAxis.Visible = true;
                    MaxLabelsWidth = s.CustomVertAxis.MaxLabelsWidth();
                    lenghtTicks = s.CustomVertAxis.Ticks.Length;
                    extraSpaceBetweenTitleAndLabels = (s.CustomVertAxis.Title.Width);//- tChart1.Axes.Custom[nSeries].MaxLabelsWidth());
                    if (s.CustomVertAxis.Title.Visible)
                    {
                        s.CustomVertAxis.RelativePosition = NextXLeft;
                        NextXLeft = NextXLeft - (MaxLabelsWidth + lenghtTicks + extraSpaceBetweenTitleAndLabels + extraPos);
                        MargLeft = MargLeft + extraMargin;
                    }

                    else
                    {
                        s.CustomVertAxis.RelativePosition = NextXLeft;
                        NextXLeft = NextXLeft - (MaxLabelsWidth + lenghtTicks + extraPos);
                        MargLeft = MargLeft + extraMargin;
                    }

                    tChart1.Panel.MarginLeft = MargLeft;
                    tChart1.Panel.MarginRight = MargRight;
                }
                else
                {
                    s.CustomVertAxis.Visible = false;
                }
            }

        }
Can you tell us if previous code help you to achieve as you want? If my solution doesn't like you please let me know.

Thanks,