using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using RealTimeGraphX.EventArguments;
using RealTimeGraphX.WPF.DataSeries;
namespace RealTimeGraphX.WPF.Painters
{
///
/// Represents a WPF implementation for .
/// This painter provides a graph image of type .
///
///
///
public class WpfScrollingGraphPainter : GraphPainterBase
{
private WriteableBitmap _writeable_bitmap;
private Bitmap _gdi_bitmap;
private Graphics g;
///
/// Gets the current graph image.
///
public override BitmapSource Image { get; protected set; }
///
/// Called when the connected input invoked the method.
///
/// The series to draw.
/// The points to draw.
/// Specifies whether there is a need to reinitialize the image because surface size change.
protected override void OnDraw(IEnumerable seriesCollection, WpfDataSeries series, IEnumerable points, bool sizeChanged)
{
if (sizeChanged)
{
if (g != null)
{
g.Dispose();
}
_writeable_bitmap = new WriteableBitmap((int)Math.Max(Output.SurfaceWidth, 1), (int)Math.Max(Output.SurfaceHeight, 1), 96.0, 96.0, PixelFormats.Pbgra32, null);
if (_gdi_bitmap != null)
{
_gdi_bitmap.Dispose();
}
_gdi_bitmap = new Bitmap(_writeable_bitmap.PixelWidth, _writeable_bitmap.PixelHeight,
_writeable_bitmap.BackBufferStride,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb,
_writeable_bitmap.BackBuffer);
_writeable_bitmap.Lock();
}
bool isFirst = series == seriesCollection.First();
bool isLast = series == seriesCollection.Last();
if (isFirst)
{
if (!sizeChanged)
{
_writeable_bitmap.Lock();
}
g = Graphics.FromImage(_gdi_bitmap);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.Clear(System.Drawing.Color.Transparent);
//Apply zooming.
if (ZoomRect.Width > 0 && ZoomRect.Height > 0)
{
var scale_x = (float)(Output.SurfaceWidth / ZoomRect.Width);
var scale_y = (float)(Output.SurfaceHeight / ZoomRect.Height);
var translate_x = (float)-ZoomRect.Left * scale_x;
var translate_y = (float)-ZoomRect.Top * scale_y;
g.TranslateTransform(translate_x, translate_y);
g.ScaleTransform(scale_x, scale_y);
if (scale_x != Transform.ScaleX || scale_y != Transform.ScaleY || translate_x != Transform.TranslateX || translate_y != Transform.TranslateY)
{
OnTransformChanged(new TransformChangedEventArgs()
{
Transform = new GraphTransform()
{
ScaleX = scale_x,
ScaleY = scale_y,
TranslateX = translate_x,
TranslateY = translate_y,
}
});
OnVirtualRangeXChanged();
OnVirtualRangeYChanged();
}
}
}
OnDraw(seriesCollection, series, points, g);
if (isLast)
{
_writeable_bitmap.AddDirtyRect(new Int32Rect(0, 0, _writeable_bitmap.PixelWidth, _writeable_bitmap.PixelHeight));
_writeable_bitmap.Unlock();
var cloned = _writeable_bitmap.Clone();
cloned.Freeze();
OnPaintingCompleted(cloned);
g.Dispose();
}
}
///
/// Called when the connected input invoked the method.
///
/// The series collection.
/// The series.
/// The points.
/// The graphics object.
protected virtual void OnDraw(IEnumerable seriesCollection, WpfDataSeries series, IEnumerable points, Graphics g)
{
if (SurfaceWidth > 10 && SurfaceHeight > 10)
{
System.Drawing.Pen pen = new System.Drawing.Pen(series.GdiStroke, (float)series.StrokeThickness);
List gdiPoints = points.Select(x => new PointF((float)x.X, (float)x.Y)).ToList();
if (series.GdiFill != null)
{
if (series.GdiFill is System.Drawing.Drawing2D.LinearGradientBrush)
{
var gradient = (series.GdiFill as System.Drawing.Drawing2D.LinearGradientBrush);
gradient.ResetTransform();
gradient.ScaleTransform((float)(Output.SurfaceWidth / gradient.Rectangle.Width), (float)(Output.SurfaceHeight / gradient.Rectangle.Height));
}
g.FillPolygon(series.GdiFill, GetFillPoints(gdiPoints));
}
try
{
g.DrawCurve(pen, gdiPoints.ToArray());
}
catch { }
pen.Dispose();
}
}
///
/// Gets a closed polygon version of the specified points to use with FillPolygon().
///
/// The points.
///
protected virtual PointF[] GetFillPoints(List points)
{
List closed = points.ToList();
closed.Add(new PointF(points.Last().X, (float)SurfaceWidth));
closed.Add(new PointF(0, (float)SurfaceHeight));
return closed.ToArray();
}
}
}