Profile Picture

INPaintCallBack.OnBeforePaint interfering with NChartControl.ImageExporter

Posted By Kevin Harrison 7 Years Ago
Author
Message
Kevin Harrison
Problem Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)

Group: Forum Members
Last Active: 3 Years Ago
Posts: 176, Visits: 1,865
This is a behaviour change between 16.8.8.12 and 17.3.6.12

On your helpful recommendation we added an INPaintCallBack and use OnBeforePaint to allow the user to change the symbol sizes on chart lines by turning the mouse wheel. This works fine in 16.8.8.12 and 17.3.6.12. However, we have found that the OnBeforePaint code affects chart export in 17.3.612 - the chart is not resized in the export when the export size is changed form the default size.

I have tracked this to these lines of code:

this.chartControl.document.Calculate();
this.chartControl.RecalcLayout();

If they are removed the export is the correct size but the symbol resizing has not been applied to the export.

Is there a different way to achieve this in 17.3.6.12?

I also notice that previously I could reorganise panel layout; e.g. moving the legend panel from right to left and the chart would redraw. Now I have to explicitly call NChartControl.Refresh().

Some general advice on the changes and recommended strategies would be much appreciated.

Thanks

Kevin

Nevron Support
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)

Group: Forum Members
Last Active: Last Year
Posts: 3,039, Visits: 3,746
Hi Kevin,
Can you share some code that replicates this - or at least a some general guidelines - it is not clear which properties of the chart you modify on BeforePaint, the sequence of export etc.


Best Regards,
Nevron Support Team



Kevin Harrison
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)

Group: Forum Members
Last Active: 3 Years Ago
Posts: 176, Visits: 1,865
Here is an extract from the code in the INPaintCallback.OnBeforePaint method, which shows what I am changing. Basically, I am restricting the maximum size of line and point symbols.

If I comment out the last two ChartControl calls, then the exported chart resizes correctly (it is set to Dock.Fill) but the symbol size isn't restricted. If I leave them in everything works correctly in 16.8.8.12, but in 17.3.6.12 (and 17.3.28.12), the chart does not "fill" in the exported image.

foreach (NSeries series in chart.Series)
{
NPointSeries pointSeries = series as NPointSeries;
NLineSeries lineSeries = series as NLineSeries;
if (pointSeries != null || lineSeries != null)
{
ChartLine chartLine = chartDefinition.ChartSeriesSet.HavingId((int) series.Tag) as ChartLine;
Debug.Assert(chartLine != null);
ChartSymbol symbol = chartLine.RenderedSymbol;
Debug.Assert(symbol != null);
if (symbol.SymbolSizeStyle == ChartSymbolSizeStyle.PercentageWithMaximum && !chartLine.SymbolUserResized)
{
requiresRecalculate = true; // triggered by any resize
double percentageSize = symbol.SymbolSize;
double maximumSize = symbol.MaximumSymbolSize;
NLength requiredMarkerSize = new NLength(Math.Min((float) maximumSize, (float) (percentageScaling*percentageSize)), NGraphicsUnit.Pixel);

if (pointSeries != null)
pointSeries.Size = requiredMarkerSize;
else
{
lineSeries.MarkerStyle.Width = requiredMarkerSize;
lineSeries.MarkerStyle.Height = requiredMarkerSize;
}
}
}
}

// Recalculate the layout only if necessary
// TODO: In Nevron 17.3.6.12 this code prevents an exported image resizing. But removing the code doesn't action the symbol size changes.
if (requiresRecalculate)
{
this.chartControl.document.Calculate();
this.chartControl.RecalcLayout();
}


Nevron Support
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)

Group: Forum Members
Last Active: Last Year
Posts: 3,039, Visits: 3,746

Hi Kevin,

We were not able to replicate the problem - we tested with the following code:

using Nevron.Chart;
using Nevron.Chart.WinForm;
using Nevron.GraphicsCore;
using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
 public partial class Form1 : Form
 {
  public Form1()
  {
   InitializeComponent();
  }

  class MyPaintCallback : INPaintCallback
  {
   public MyPaintCallback(NChartControl chartControl)
   {
    m_ChartControl = chartControl;
   }
   public void OnAfterPaint(NPanel panel, NPanelPaintEventArgs eventArgs)
   {
    throw new NotImplementedException();
   }

   public void OnBeforePaint(NPanel panel, NPanelPaintEventArgs eventArgs)
   {
    bool requiresRecalculate = true;

    foreach (NSeries series in m_ChartControl.Charts[0].Series)
    {
     NPointSeries pointSeries = series as NPointSeries;
     if (pointSeries != null)
     {
      pointSeries.Size = new NLength(4, NGraphicsUnit.Pixel);
     }
    }

    if (requiresRecalculate)
    {
     m_ChartControl.document.Calculate();
     m_ChartControl.RecalcLayout();
    }
   }

   NChartControl m_ChartControl;
  }


  private void Form1_Load(object sender, EventArgs e)
  {
   NChart chart = nChartControl1.Charts[0];
   chart.DockMode = PanelDockMode.Fill;

   NPointSeries point = new NPointSeries();
   chart.Series.Add(point);
   Random rand = new Random();

   for (int i = 0; i < 20; i++)
   {
    point.Values.Add(rand.Next(100));
   }

   chart.PaintCallback = new MyPaintCallback(nChartControl1);

   nChartControl1.ImageExporter.SaveToFile("c:\\temp\\check.bmp", new NBitmapImageFormat());
  }
 }
}

And both the chart on the form and the exported image looked correct.



Best Regards,
Nevron Support Team



Kevin Harrison
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)

Group: Forum Members
Last Active: 3 Years Ago
Posts: 176, Visits: 1,865
"the chart is not resized in the export when the export size is changed from the default size."

You are using the default size.

Nevron Support
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)

Group: Forum Members
Last Active: Last Year
Posts: 3,039, Visits: 3,746
Hi Kevin,
The control works properly - when you call nChartControl.RecalcLayout it will use the default view context which has different size than the one in the view context that currently serves for image export - that's why you get the same size in the
chart rendered to bitmap as the one on the screen. The solution is to pass the view context of the current paint:

   public void OnBeforePaint(NPanel panel, NPanelPaintEventArgs eventArgs)
   {
    bool requiresRecalculate = true;

    foreach (NSeries series in m_ChartControl.Charts[0].Series)
    {
     NPointSeries pointSeries = series as NPointSeries;
     if (pointSeries != null)
     {
      pointSeries.Size = new NLength(4, NGraphicsUnit.Pixel);
     }
    }

    if (requiresRecalculate)
    {
     m_ChartControl.document.Calculate();
     m_ChartControl.document.RecalcLayout(eventArgs.Context);
    }
   }

We tested this approach and it was working OK. Let us know if you meet any problems.




Best Regards,
Nevron Support Team



Kevin Harrison
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)

Group: Forum Members
Last Active: 3 Years Ago
Posts: 176, Visits: 1,865
Thanks guys, that works. It really was a simple fix in the end.
Is there some documentation which gives an overview of this  context mechanism and how to use it?
Kind regards
Kevin

Nevron Support
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)

Group: Forum Members
Last Active: Last Year
Posts: 3,039, Visits: 3,746
Hi Kevin,
It is not documented but the general idea is that the context holds information about the current render surface (like render technology, size, resolution) as well as some means to paint on it - graphics, length conversion and other small classes. It in this particular case the size of the current view context differed than the size of the image export context and that messed up with the RecalcLayout.


Best Regards,
Nevron Support Team



Kevin Harrison
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)Supreme Being (79 reputation)

Group: Forum Members
Last Active: 3 Years Ago
Posts: 176, Visits: 1,865
Hi guys

I have found an issue with the suggested code relating to 3D charts.
The chart area is blank; i.e. not rendered, if cartesianChart.Enable3D is set to true.
Cabn you suggest a solution pelase?

Thanks

Kevin

Nevron Support
Posted 7 Years Ago
View Quick Profile
Supreme Being

Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)Supreme Being (4,329 reputation)

Group: Forum Members
Last Active: Last Year
Posts: 3,039, Visits: 3,746
Hi Kevin,
Indeed there is a problem in the 3D case - we just released a new SP of the control that fixes this issue. Also the code that recalculates the layout should be changed to:
m_ChartControl.document.RecalcLayout(m_ChartControl.document.CurrentRenderingContext);
Let us know if you meet any problems.


Best Regards,
Nevron Support Team





Similar Topics


Reading This Topic