FastReport
638 строк · 24.2 Кб
1using System;2using System.Drawing;3using System.Drawing.Drawing2D;4using System.ComponentModel;5using FastReport.Utils;6
7namespace FastReport.Gauge.Radial8{
9/// <summary>10/// Represents a linear scale.11/// </summary>12#if !DEBUG13[DesignTimeVisible(false)]14#endif15public class RadialScale : GaugeScale16{17#region Fields18
19private float left;20private float top;21private float height;22private float width;23private float majorTicksOffset;24private float minorTicksOffset;25private PointF avrTick;26private double stepValue;27private PointF center;28private double avrValue;29private float majorStep;30private float minorStep;31private int sideTicksCount;32private bool drawRight, drawLeft;33
34#endregion // Fields35
36#region Enums37private enum HorAlign38{39Middle,40Left,41Right
42}43private enum VertAlign44{45Bottom,46Middle,47Top
48}49
50#endregion //Enums51
52#region Properties53
54[Browsable(false)]55internal PointF AvrTick56{57get { return avrTick; }58}59
60[Browsable(false)]61internal double StepValue62{63get { return stepValue; }64set { stepValue = value; }65}66
67[Browsable(false)]68internal double AverageValue69{70get { return avrValue; }71set { avrValue = value; }72}73
74internal float MajorStep75{76get { return majorStep; }77set { majorStep = value; }78}79#endregion // Properties80
81#region Constructors82
83/// <summary>84/// Initializes a new instance of the <see cref="RadialScale"/> class.85/// </summary>86/// <param name="parent">The parent gauge object.</param>87public RadialScale(RadialGauge parent) : base(parent)88{89MajorTicks = new ScaleTicks(5, 2, Color.Black, 11);90MinorTicks = new ScaleTicks(2, 1, Color.Black, 4);91majorStep = 27; //degree, 135/592minorStep = 5.4f; // degree, 27/593drawRight = true;94drawLeft = true;95}96
97#endregion // Constructors98
99#region Private Methods100
101private bool isNegative(int i, bool isRightPart)102{103if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))104{105if (i <= sideTicksCount / 2)106{107if (isRightPart)108{109if (RadialUtils.IsBottom(Parent) && RadialUtils.IsLeft(Parent))110{111return false;112}113else if (RadialUtils.IsBottom(Parent))114return false;115else if (RadialUtils.IsLeft(Parent))116return true;117else if (RadialUtils.IsRight(Parent))118return true; //!!!!!!!!!!!!!!!!!!119else return true; //Check!!!!120}121else122{123if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))124{125return true;126}127else if (RadialUtils.IsBottom(Parent))128return false;129else if (RadialUtils.IsLeft(Parent))130return false;131else if (RadialUtils.IsRight(Parent))132return false; //!!!!!!!!!!!!!!!!!!133else return true; //Check!!!!134}135}136return false; //shouldn't be reached137}138else if (i > sideTicksCount / 2)139return false;140else return true;141}142private void DrawText(FRPaintEventArgs e, string text, Brush brush, float x, float y, HorAlign hAlign, VertAlign vAlign)143{144IGraphics g = e.Graphics;145Font font = RadialUtils.GetFont(e, Parent, Font);146SizeF strSize = RadialUtils.GetStringSize(e, Parent, Font, text);147float dx = 0;148float dy = 0;149if (hAlign == HorAlign.Middle)150dx = -strSize.Width / 2;151else if (hAlign == HorAlign.Left)152dx = 0;153else if (hAlign == HorAlign.Right)154dx = -strSize.Width;155
156if (vAlign == VertAlign.Bottom)157dy = -strSize.Height;158else if (vAlign == VertAlign.Middle)159dy = -strSize.Height / 2;160else if (vAlign == VertAlign.Top)161dy = 0;162g.DrawString(text, font, brush, x + dx, y + dy);163}164
165private PointF GetTextPoint(PointF[] tick, float txtOffset, bool negativ, bool isRight)166{167float dx = Math.Abs(tick[1].X - tick[0].X);168float dy = Math.Abs(tick[1].Y - tick[0].Y);169float absA = (float)Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)); //vectors length170float sinAlpha = dy / absA;171float cosAlpha = dx / absA;172float absA1 = absA + txtOffset;173float dx1 = Math.Abs(absA1 * cosAlpha);174float dy1 = Math.Abs(absA1 * sinAlpha);175float pointX;176float pointY;177if (negativ)178pointY = tick[1].Y - dy1;179else180pointY = tick[1].Y + dy1;181if (isRight)182pointX = tick[1].X + dx1;183else184pointX = tick[1].X - dx1;185return new PointF(pointX, pointY);186}187
188private void DrawMajorTicks(FRPaintEventArgs e)189{190center = (Parent as RadialGauge).Center;191stepValue = (Parent.Maximum - Parent.Minimum) / (MajorTicks.Count - 1);192if (RadialUtils.IsQuadrant(Parent))193stepValue *= 2;194
195avrValue = Parent.Minimum + (Parent.Maximum - Parent.Minimum) / 2;196
197bool isRightPart = true;198bool isLeftPart = false;199PointF txtPoint;200
201IGraphics g = e.Graphics;202Pen pen = e.Cache.GetPen(MajorTicks.Color, MajorTicks.Width * e.ScaleX, DashStyle.Solid);203Brush brush = TextFill.CreateBrush(new RectangleF(Parent.AbsLeft * e.ScaleX, Parent.AbsTop * e.ScaleY,204Parent.Width * e.ScaleX, Parent.Height * e.ScaleY), e.ScaleX, e.ScaleY);205sideTicksCount = (MajorTicks.Count - 1) / 2;206MajorTicks.Length = width / 12;207
208SizeF maxTxt = RadialUtils.GetStringSize(e, Parent, Font, Parent.Maximum.ToString());209SizeF minTxt = RadialUtils.GetStringSize(e, Parent, Font, Parent.Minimum.ToString());210float maxTxtOffset = maxTxt.Height > maxTxt.Width ? maxTxt.Height : maxTxt.Width;211float minTxtOffset = minTxt.Height > minTxt.Width ? minTxt.Height : minTxt.Width;212majorTicksOffset = maxTxtOffset > minTxtOffset ? maxTxtOffset : minTxtOffset;213
214PointF[] tick0 = new PointF[2];215avrTick = new PointF(left + width / 2, top + majorTicksOffset);216//first tick217tick0[0] = avrTick;218tick0[1] = new PointF(tick0[0].X, tick0[0].Y + MajorTicks.Length);219
220double angle = 0;221HorAlign horAlign = HorAlign.Middle;222VertAlign vertAlign = VertAlign.Bottom;223double startValue = avrValue;224if (RadialUtils.IsSemicircle(Parent))225{226drawRight = true;227drawLeft = true;228if (RadialUtils.IsBottom(Parent))229{230angle = 180 * RadialGauge.Radians;231horAlign = HorAlign.Middle;232vertAlign = VertAlign.Top;233majorStep *= -1;234isRightPart = true;235isLeftPart = false;236}237else if (RadialUtils.IsLeft(Parent))238{239angle = -90 * RadialGauge.Radians;240horAlign = HorAlign.Right;241vertAlign = VertAlign.Middle;242isRightPart = false;243isLeftPart = false;244}245else if (RadialUtils.IsRight(Parent))246{247angle = 90 * RadialGauge.Radians;248horAlign = HorAlign.Left;249vertAlign = VertAlign.Middle;250majorStep *= -1;251isRightPart = true; //false252isLeftPart = true; // false253}254}255
256
257else if (RadialUtils.IsQuadrant(Parent))258{259if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))260{261startValue = Parent.Maximum;262//angle = 180 * RadialGauge.Radians;263horAlign = HorAlign.Middle;264vertAlign = VertAlign.Bottom;265//majorStep *= -1;266//isRightPart = true;267//isLeftPart = false;268drawRight = false;269drawLeft = true;270
271isRightPart = false;272isLeftPart = false;273}274else if (RadialUtils.IsBottom(Parent) && RadialUtils.IsLeft(Parent))275{276startValue = Parent.Minimum;277angle = 180 * RadialGauge.Radians;278horAlign = HorAlign.Middle;279vertAlign = VertAlign.Top;280drawRight = true;281drawLeft = false;282
283isRightPart = false;284isLeftPart = false;285}286else if (RadialUtils.IsTop(Parent) && RadialUtils.IsRight(Parent))287{288stepValue *= -1;289startValue = Parent.Maximum;290angle = 0;291horAlign = HorAlign.Middle;292vertAlign = VertAlign.Bottom;293drawRight = true;294drawLeft = false;295
296isRightPart = true;297isLeftPart = true;298}299else if (RadialUtils.IsBottom(Parent) && RadialUtils.IsRight(Parent))300{301stepValue *= -1;302startValue = Parent.Minimum;303angle = 180 * RadialGauge.Radians;304horAlign = HorAlign.Middle;305vertAlign = VertAlign.Top;306drawRight = false;307drawLeft = true;308
309isRightPart = true;310isLeftPart = true;311}312}313else314{315drawRight = true;316drawLeft = true;317}318
319tick0 = RadialUtils.RotateVector(tick0, angle, center);320
321g.DrawLine(pen, tick0[0].X, tick0[0].Y, tick0[1].X, tick0[1].Y);322string text = startValue.ToString();323DrawText(e, text, brush, tick0[0].X, tick0[0].Y, horAlign, vertAlign);324
325//rest of ticks326PointF[] tick = new PointF[2];327angle = majorStep * RadialGauge.Radians;328
329for (int i = 0; i < sideTicksCount; i++)330{331//right side332if (drawRight)333{334tick = RadialUtils.RotateVector(tick0, angle, center);335g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);336text = Convert.ToString(Math.Round(startValue + stepValue * (i + 1)));337
338if (i == sideTicksCount / 2)339{340if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))341{342if (RadialUtils.IsLeft(Parent) && RadialUtils.IsTop(Parent))343{344horAlign = HorAlign.Right;345vertAlign = VertAlign.Middle;346}347else if (RadialUtils.IsLeft(Parent) && RadialUtils.IsBottom(Parent))348{349horAlign = HorAlign.Right;350vertAlign = VertAlign.Middle;351}352else if (RadialUtils.IsRight(Parent) && RadialUtils.IsTop(Parent))353{354horAlign = HorAlign.Left;355vertAlign = VertAlign.Middle;356}357else if (RadialUtils.IsLeft(Parent))358{359horAlign = HorAlign.Middle;360vertAlign = VertAlign.Bottom;361}362else if (RadialUtils.IsRight(Parent))363{364horAlign = HorAlign.Middle;365vertAlign = VertAlign.Bottom;366}367else368{369horAlign = HorAlign.Left;370vertAlign = VertAlign.Middle;371}372}373else374{375horAlign = HorAlign.Left;376vertAlign = VertAlign.Middle;377}378}379else if (i < sideTicksCount / 2)380{381horAlign = HorAlign.Left;382if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))383{384if (RadialUtils.IsLeft(Parent) && RadialUtils.IsTop(Parent))385{386horAlign = HorAlign.Right;387vertAlign = VertAlign.Middle;388}389if (RadialUtils.IsLeft(Parent) && RadialUtils.IsBottom(Parent))390{391vertAlign = VertAlign.Top;392horAlign = HorAlign.Right;393}394else if (RadialUtils.IsBottom(Parent))395vertAlign = VertAlign.Top;396else if (RadialUtils.IsLeft(Parent))397{398horAlign = HorAlign.Right;399vertAlign = VertAlign.Bottom;400}401else if (RadialUtils.IsRight(Parent))402{403horAlign = HorAlign.Left;404vertAlign = VertAlign.Bottom;405}406}407else408vertAlign = VertAlign.Bottom;409}410else411{412horAlign = HorAlign.Left;413vertAlign = VertAlign.Top;414}415txtPoint = GetTextPoint(tick, -1 * e.ScaleX, isNegative(i, true), isRightPart);416DrawText(e, text, brush, txtPoint.X, txtPoint.Y, horAlign, vertAlign);417}418
419if (drawLeft)420{421//left side422angle *= -1;423tick = RadialUtils.RotateVector(tick0, angle, center);424g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);425text = Convert.ToString(Math.Round(startValue - stepValue * (i + 1)));426
427if (i == sideTicksCount / 2)428{429if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))430{431if ((RadialUtils.IsTop(Parent) || RadialUtils.IsBottom(Parent)) && RadialUtils.IsSemicircle(Parent))432{433horAlign = HorAlign.Right;434vertAlign = VertAlign.Middle;435}436else if (RadialUtils.IsLeft(Parent) && RadialUtils.IsTop(Parent))437{438horAlign = HorAlign.Right;439vertAlign = VertAlign.Middle;440}441else if (RadialUtils.IsRight(Parent) && RadialUtils.IsBottom(Parent))442{443horAlign = HorAlign.Left;444vertAlign = VertAlign.Middle;445}446else if (RadialUtils.IsLeft(Parent))447{448horAlign = HorAlign.Middle;449vertAlign = VertAlign.Top;450}451else if (RadialUtils.IsRight(Parent))452{453horAlign = HorAlign.Middle;454vertAlign = VertAlign.Top;455}456}457else458{459horAlign = HorAlign.Right;460vertAlign = VertAlign.Middle;461}462}463else if (i < sideTicksCount / 2)464{465horAlign = HorAlign.Right;466
467if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))468{469if (RadialUtils.IsRight(Parent) && RadialUtils.IsBottom(Parent))470{471vertAlign = VertAlign.Top;472horAlign = HorAlign.Left;473}474else if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))475{476vertAlign = VertAlign.Bottom;477horAlign = HorAlign.Right;478}479else if (RadialUtils.IsBottom(Parent))480vertAlign = VertAlign.Top;481else if (RadialUtils.IsLeft(Parent))482{483horAlign = HorAlign.Right;484vertAlign = VertAlign.Top;485}486else if (RadialUtils.IsRight(Parent))487{488horAlign = HorAlign.Left;489vertAlign = VertAlign.Top;490}491}492else493vertAlign = VertAlign.Bottom;494}495else496{497horAlign = HorAlign.Right;498vertAlign = VertAlign.Top;499}500txtPoint = GetTextPoint(tick, -1 * e.ScaleX, isNegative(i, false), isLeftPart);501DrawText(e, text, brush, txtPoint.X, txtPoint.Y, horAlign, vertAlign);502angle *= -1;503}504
505angle += majorStep * RadialGauge.Radians;506}507}508
509private void DrawMinorTicks(FRPaintEventArgs e)510{511IGraphics g = e.Graphics;512Pen pen = e.Cache.GetPen(MinorTicks.Color, MinorTicks.Width * e.ScaleX, DashStyle.Solid);513
514MinorTicks.Length = width / 24;515minorTicksOffset = majorTicksOffset + MajorTicks.Length / 2 - MinorTicks.Length / 2;516PointF center = new PointF(left + width / 2, top + height / 2);517
518PointF[] tick0 = new PointF[2];519//first tick520tick0[0] = new PointF(left + width / 2, top + minorTicksOffset);521tick0[1] = new PointF(tick0[0].X, tick0[0].Y + MinorTicks.Length);522
523double angle = 0;524if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))525{526if (RadialUtils.IsBottom(Parent) && RadialUtils.IsLeft(Parent))527{528angle = -180 * RadialGauge.Radians;529}530else if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))531{532angle = 0;533}534else if (RadialUtils.IsTop(Parent) && RadialUtils.IsRight(Parent))535{536angle = 0;537}538else if (RadialUtils.IsBottom(Parent))539{540angle = 180 * RadialGauge.Radians;541majorStep *= -1;542}543else if (RadialUtils.IsLeft(Parent))544{545angle = -90 * RadialGauge.Radians;546}547else if (RadialUtils.IsRight(Parent))548{549angle = 90 * RadialGauge.Radians;550majorStep *= -1;551}552}553tick0 = RadialUtils.RotateVector(tick0, angle, center);554
555//rest of ticks556PointF[] tick = new PointF[2];557angle = minorStep * RadialGauge.Radians;558for (int i = 0; i < MajorTicks.Count / 2 * (MinorTicks.Count + 1); i++)559{560if ((i + 1) % (MinorTicks.Count + 1) != 0)561{562if (drawRight)563{564tick = RadialUtils.RotateVector(tick0, angle, center);565g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);566}567if (drawLeft)568{569angle *= -1;570tick = RadialUtils.RotateVector(tick0, angle, center);571g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);572angle *= -1;573}574}575angle += minorStep * RadialGauge.Radians;576}577}578
579#endregion // Private Methods580
581#region Public Methods582
583/// <inheritdoc/>584public override void Assign(GaugeScale src)585{586base.Assign(src);587
588RadialScale s = src as RadialScale;589MajorTicks.Assign(s.MajorTicks);590MinorTicks.Assign(s.MinorTicks);591}592
593/// <inheritdoc/>594public override void Draw(FRPaintEventArgs e)595{596base.Draw(e);597if ((Parent as RadialGauge).Type == RadialGaugeType.Circle)598{599MajorTicks.Count = 11;600MinorTicks.Count = 4;601majorStep = 135f / 5;602minorStep = 135f / 5f / 5f;603}604else if ((Parent as RadialGauge).Type == RadialGaugeType.Semicircle)605{606MajorTicks.Count = 5;607MinorTicks.Count = 3;608majorStep = 90f / 2;609minorStep = 90f / 2 / 4;610}611else if ((Parent as RadialGauge).Type == RadialGaugeType.Quadrant)612{613MajorTicks.Count = 5;614MinorTicks.Count = 3;615majorStep = 90f / 2;616minorStep = 90f / 2 / 4;617}618left = Parent.AbsLeft * e.ScaleX;619top = Parent.AbsTop * e.ScaleY;620height = Parent.Height * e.ScaleY;621width = Parent.Width * e.ScaleX;622DrawMajorTicks(e);623DrawMinorTicks(e);624}625
626/// <inheritdoc/>627public override void Serialize(FRWriter writer, string prefix, GaugeScale diff)628{629base.Serialize(writer, prefix, diff);630
631RadialScale dc = diff as RadialScale;632MajorTicks.Serialize(writer, prefix + ".MajorTicks", dc.MajorTicks);633MinorTicks.Serialize(writer, prefix + ".MinorTicks", dc.MinorTicks);634}635
636#endregion // Public Methods637}638}
639