FastReport

Форк
0
638 строк · 24.2 Кб
1
using System;
2
using System.Drawing;
3
using System.Drawing.Drawing2D;
4
using System.ComponentModel;
5
using FastReport.Utils;
6

7
namespace FastReport.Gauge.Radial
8
{
9
    /// <summary>
10
    /// Represents a linear scale.
11
    /// </summary>
12
#if !DEBUG
13
    [DesignTimeVisible(false)]
14
#endif
15
    public class RadialScale : GaugeScale
16
    {
17
        #region Fields
18

19
        private float left;
20
        private float top;
21
        private float height;
22
        private float width;
23
        private float majorTicksOffset;
24
        private float minorTicksOffset;
25
        private PointF avrTick;
26
        private double stepValue;
27
        private PointF center;
28
        private double avrValue;
29
        private float majorStep;
30
        private float minorStep;
31
        private int sideTicksCount;
32
        private bool drawRight, drawLeft;
33

34
        #endregion // Fields
35

36
        #region Enums
37
        private enum HorAlign
38
        {
39
            Middle,
40
            Left,
41
            Right
42
        }
43
        private enum VertAlign
44
        {
45
            Bottom,
46
            Middle,
47
            Top
48
        }
49

50
        #endregion //Enums
51

52
        #region Properties
53

54
        [Browsable(false)]
55
        internal PointF AvrTick
56
        {
57
            get { return avrTick; }
58
        }
59

60
        [Browsable(false)]
61
        internal double StepValue
62
        {
63
            get { return stepValue; }
64
            set { stepValue = value; }
65
        }
66

67
        [Browsable(false)]
68
        internal double AverageValue
69
        {
70
            get { return avrValue; }
71
            set { avrValue = value; }
72
        }
73

74
        internal float MajorStep
75
        {
76
            get { return majorStep; }
77
            set { majorStep = value; }
78
        }
79
        #endregion // Properties
80

81
        #region Constructors
82

83
        /// <summary>
84
        /// Initializes a new instance of the <see cref="RadialScale"/> class.
85
        /// </summary>
86
        /// <param name="parent">The parent gauge object.</param>
87
        public RadialScale(RadialGauge parent) : base(parent)
88
        {
89
            MajorTicks = new ScaleTicks(5, 2, Color.Black, 11);
90
            MinorTicks = new ScaleTicks(2, 1, Color.Black, 4);
91
            majorStep = 27; //degree, 135/5
92
            minorStep = 5.4f; // degree, 27/5
93
            drawRight = true;
94
            drawLeft = true;
95
        }
96

97
        #endregion // Constructors
98

99
        #region Private Methods
100

101
        private bool isNegative(int i, bool isRightPart)
102
        {
103
            if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))
104
            {
105
                if (i <= sideTicksCount / 2)
106
                {
107
                    if (isRightPart)
108
                    {
109
                        if (RadialUtils.IsBottom(Parent) && RadialUtils.IsLeft(Parent))
110
                        {
111
                            return false;
112
                        }
113
                        else if (RadialUtils.IsBottom(Parent))
114
                            return false;
115
                        else if (RadialUtils.IsLeft(Parent))
116
                            return true;
117
                        else if (RadialUtils.IsRight(Parent))
118
                            return true; //!!!!!!!!!!!!!!!!!!
119
                        else return true; //Check!!!!
120
                    }
121
                    else
122
                    {
123
                        if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))
124
                        {
125
                            return true;
126
                        }
127
                        else if (RadialUtils.IsBottom(Parent))
128
                            return false;
129
                        else if (RadialUtils.IsLeft(Parent))
130
                            return false;
131
                        else if (RadialUtils.IsRight(Parent))
132
                            return false; //!!!!!!!!!!!!!!!!!!
133
                        else return true; //Check!!!!
134
                    }
135
                }
136
                return false; //shouldn't be reached
137
            }
138
            else if (i > sideTicksCount / 2)
139
                return false;
140
            else return true;
141
        }
142
        private void DrawText(FRPaintEventArgs e, string text, Brush brush, float x, float y, HorAlign hAlign, VertAlign vAlign)
143
        {
144
            IGraphics g = e.Graphics;
145
            Font font = RadialUtils.GetFont(e, Parent, Font);
146
            SizeF strSize = RadialUtils.GetStringSize(e, Parent, Font, text);
147
            float dx = 0;
148
            float dy = 0;
149
            if (hAlign == HorAlign.Middle)
150
                dx = -strSize.Width / 2;
151
            else if (hAlign == HorAlign.Left)
152
                dx = 0;
153
            else if (hAlign == HorAlign.Right)
154
                dx = -strSize.Width;
155

156
            if (vAlign == VertAlign.Bottom)
157
                dy = -strSize.Height;
158
            else if (vAlign == VertAlign.Middle)
159
                dy = -strSize.Height / 2;
160
            else if (vAlign == VertAlign.Top)
161
                dy = 0;
162
            g.DrawString(text, font, brush, x + dx, y + dy);
163
        }
164

165
        private PointF GetTextPoint(PointF[] tick, float txtOffset, bool negativ, bool isRight)
166
        {
167
            float dx = Math.Abs(tick[1].X - tick[0].X);
168
            float dy = Math.Abs(tick[1].Y - tick[0].Y);
169
            float absA = (float)Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)); //vectors length
170
            float sinAlpha = dy / absA;
171
            float cosAlpha = dx / absA;
172
            float absA1 = absA + txtOffset;
173
            float dx1 = Math.Abs(absA1 * cosAlpha);
174
            float dy1 = Math.Abs(absA1 * sinAlpha);
175
            float pointX;
176
            float pointY;
177
            if (negativ)
178
                pointY = tick[1].Y - dy1;
179
            else
180
                pointY = tick[1].Y + dy1;
181
            if (isRight)
182
                pointX = tick[1].X + dx1;
183
            else
184
                pointX = tick[1].X - dx1;
185
            return new PointF(pointX, pointY);
186
        }
187

188
        private void DrawMajorTicks(FRPaintEventArgs e)
189
        {
190
            center = (Parent as RadialGauge).Center;
191
            stepValue = (Parent.Maximum - Parent.Minimum) / (MajorTicks.Count - 1);
192
            if (RadialUtils.IsQuadrant(Parent))
193
                stepValue *= 2;
194

195
            avrValue = Parent.Minimum + (Parent.Maximum - Parent.Minimum) / 2;
196

197
            bool isRightPart = true;
198
            bool isLeftPart = false;
199
            PointF txtPoint;
200

201
            IGraphics g = e.Graphics;
202
            Pen pen = e.Cache.GetPen(MajorTicks.Color, MajorTicks.Width * e.ScaleX, DashStyle.Solid);
203
            Brush brush = TextFill.CreateBrush(new RectangleF(Parent.AbsLeft * e.ScaleX, Parent.AbsTop * e.ScaleY,
204
    Parent.Width * e.ScaleX, Parent.Height * e.ScaleY), e.ScaleX, e.ScaleY);
205
            sideTicksCount = (MajorTicks.Count - 1) / 2;
206
            MajorTicks.Length = width / 12;
207

208
            SizeF maxTxt = RadialUtils.GetStringSize(e, Parent, Font, Parent.Maximum.ToString());
209
            SizeF minTxt = RadialUtils.GetStringSize(e, Parent, Font, Parent.Minimum.ToString());
210
            float maxTxtOffset = maxTxt.Height > maxTxt.Width ? maxTxt.Height : maxTxt.Width;
211
            float minTxtOffset = minTxt.Height > minTxt.Width ? minTxt.Height : minTxt.Width;
212
            majorTicksOffset = maxTxtOffset > minTxtOffset ? maxTxtOffset : minTxtOffset;
213

214
            PointF[] tick0 = new PointF[2];
215
            avrTick = new PointF(left + width / 2, top + majorTicksOffset);
216
            //first tick
217
            tick0[0] = avrTick;
218
            tick0[1] = new PointF(tick0[0].X, tick0[0].Y + MajorTicks.Length);
219

220
            double angle = 0;
221
            HorAlign horAlign = HorAlign.Middle;
222
            VertAlign vertAlign = VertAlign.Bottom;
223
            double startValue = avrValue;
224
            if (RadialUtils.IsSemicircle(Parent))
225
            {
226
                drawRight = true;
227
                drawLeft = true;
228
                if (RadialUtils.IsBottom(Parent))
229
                {
230
                    angle = 180 * RadialGauge.Radians;
231
                    horAlign = HorAlign.Middle;
232
                    vertAlign = VertAlign.Top;
233
                    majorStep *= -1;
234
                    isRightPart = true;
235
                    isLeftPart = false;
236
                }
237
                else if (RadialUtils.IsLeft(Parent))
238
                {
239
                    angle = -90 * RadialGauge.Radians;
240
                    horAlign = HorAlign.Right;
241
                    vertAlign = VertAlign.Middle;
242
                    isRightPart = false;
243
                    isLeftPart = false;
244
                }
245
                else if (RadialUtils.IsRight(Parent))
246
                {
247
                    angle = 90 * RadialGauge.Radians;
248
                    horAlign = HorAlign.Left;
249
                    vertAlign = VertAlign.Middle;
250
                    majorStep *= -1;
251
                    isRightPart = true; //false
252
                    isLeftPart = true; // false
253
                }
254
            }
255

256

257
            else if (RadialUtils.IsQuadrant(Parent))
258
            {
259
                if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))
260
                {
261
                    startValue = Parent.Maximum;
262
                    //angle = 180 * RadialGauge.Radians;
263
                    horAlign = HorAlign.Middle;
264
                    vertAlign = VertAlign.Bottom;
265
                    //majorStep *= -1;
266
                    //isRightPart = true;
267
                    //isLeftPart = false;
268
                    drawRight = false;
269
                    drawLeft = true;
270

271
                    isRightPart = false;
272
                    isLeftPart = false;
273
                }
274
                else if (RadialUtils.IsBottom(Parent) && RadialUtils.IsLeft(Parent))
275
                {
276
                    startValue = Parent.Minimum;
277
                    angle = 180 * RadialGauge.Radians;
278
                    horAlign = HorAlign.Middle;
279
                    vertAlign = VertAlign.Top;
280
                    drawRight = true;
281
                    drawLeft = false;
282

283
                    isRightPart = false;
284
                    isLeftPart = false;
285
                }
286
                else if (RadialUtils.IsTop(Parent) && RadialUtils.IsRight(Parent))
287
                {
288
                    stepValue *= -1;
289
                    startValue = Parent.Maximum;
290
                    angle = 0;
291
                    horAlign = HorAlign.Middle;
292
                    vertAlign = VertAlign.Bottom;
293
                    drawRight = true;
294
                    drawLeft = false;
295

296
                    isRightPart = true;
297
                    isLeftPart = true;
298
                }
299
                else if (RadialUtils.IsBottom(Parent) && RadialUtils.IsRight(Parent))
300
                {
301
                    stepValue *= -1;
302
                    startValue = Parent.Minimum;
303
                    angle = 180 * RadialGauge.Radians;
304
                    horAlign = HorAlign.Middle;
305
                    vertAlign = VertAlign.Top;
306
                    drawRight = false;
307
                    drawLeft = true;
308

309
                    isRightPart = true;
310
                    isLeftPart = true;
311
                }
312
            }
313
            else
314
            {
315
                drawRight = true;
316
                drawLeft = true;
317
            }
318

319
            tick0 = RadialUtils.RotateVector(tick0, angle, center);
320

321
            g.DrawLine(pen, tick0[0].X, tick0[0].Y, tick0[1].X, tick0[1].Y);
322
            string text = startValue.ToString();
323
            DrawText(e, text, brush, tick0[0].X, tick0[0].Y, horAlign, vertAlign);
324

325
            //rest of ticks
326
            PointF[] tick = new PointF[2];
327
            angle = majorStep * RadialGauge.Radians;
328

329
            for (int i = 0; i < sideTicksCount; i++)
330
            {
331
                //right side
332
                if (drawRight)
333
                {
334
                    tick = RadialUtils.RotateVector(tick0, angle, center);
335
                    g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);
336
                    text = Convert.ToString(Math.Round(startValue + stepValue * (i + 1)));
337

338
                    if (i == sideTicksCount / 2)
339
                    {
340
                        if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))
341
                        {
342
                            if (RadialUtils.IsLeft(Parent) && RadialUtils.IsTop(Parent))
343
                            {
344
                                horAlign = HorAlign.Right;
345
                                vertAlign = VertAlign.Middle;
346
                            }
347
                            else if (RadialUtils.IsLeft(Parent) && RadialUtils.IsBottom(Parent))
348
                            {
349
                                horAlign = HorAlign.Right;
350
                                vertAlign = VertAlign.Middle;
351
                            }
352
                            else if (RadialUtils.IsRight(Parent) && RadialUtils.IsTop(Parent))
353
                            {
354
                                horAlign = HorAlign.Left;
355
                                vertAlign = VertAlign.Middle;
356
                            }
357
                            else if (RadialUtils.IsLeft(Parent))
358
                            {
359
                                horAlign = HorAlign.Middle;
360
                                vertAlign = VertAlign.Bottom;
361
                            }
362
                            else if (RadialUtils.IsRight(Parent))
363
                            {
364
                                horAlign = HorAlign.Middle;
365
                                vertAlign = VertAlign.Bottom;
366
                            }
367
                            else
368
                            {
369
                                horAlign = HorAlign.Left;
370
                                vertAlign = VertAlign.Middle;
371
                            }
372
                        }
373
                        else
374
                        {
375
                            horAlign = HorAlign.Left;
376
                            vertAlign = VertAlign.Middle;
377
                        }
378
                    }
379
                    else if (i < sideTicksCount / 2)
380
                    {
381
                        horAlign = HorAlign.Left;
382
                        if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))
383
                        {
384
                            if (RadialUtils.IsLeft(Parent) && RadialUtils.IsTop(Parent))
385
                            {
386
                                horAlign = HorAlign.Right;
387
                                vertAlign = VertAlign.Middle;
388
                            }
389
                            if (RadialUtils.IsLeft(Parent) && RadialUtils.IsBottom(Parent))
390
                            {
391
                                vertAlign = VertAlign.Top;
392
                                horAlign = HorAlign.Right;
393
                            }
394
                            else if (RadialUtils.IsBottom(Parent))
395
                                vertAlign = VertAlign.Top;
396
                            else if (RadialUtils.IsLeft(Parent))
397
                            {
398
                                horAlign = HorAlign.Right;
399
                                vertAlign = VertAlign.Bottom;
400
                            }
401
                            else if (RadialUtils.IsRight(Parent))
402
                            {
403
                                horAlign = HorAlign.Left;
404
                                vertAlign = VertAlign.Bottom;
405
                            }
406
                        }
407
                        else
408
                            vertAlign = VertAlign.Bottom;
409
                    }
410
                    else
411
                    {
412
                        horAlign = HorAlign.Left;
413
                        vertAlign = VertAlign.Top;
414
                    }
415
                    txtPoint = GetTextPoint(tick, -1 * e.ScaleX, isNegative(i, true), isRightPart);
416
                    DrawText(e, text, brush, txtPoint.X, txtPoint.Y, horAlign, vertAlign);
417
                }
418

419
                if (drawLeft)
420
                {
421
                    //left side
422
                    angle *= -1;
423
                    tick = RadialUtils.RotateVector(tick0, angle, center);
424
                    g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);
425
                    text = Convert.ToString(Math.Round(startValue - stepValue * (i + 1)));
426

427
                    if (i == sideTicksCount / 2)
428
                    {
429
                        if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))
430
                        {
431
                            if ((RadialUtils.IsTop(Parent) || RadialUtils.IsBottom(Parent)) && RadialUtils.IsSemicircle(Parent))
432
                            {
433
                                horAlign = HorAlign.Right;
434
                                vertAlign = VertAlign.Middle;
435
                            }
436
                            else if (RadialUtils.IsLeft(Parent) && RadialUtils.IsTop(Parent))
437
                            {
438
                                horAlign = HorAlign.Right;
439
                                vertAlign = VertAlign.Middle;
440
                            }
441
                            else if (RadialUtils.IsRight(Parent) && RadialUtils.IsBottom(Parent))
442
                            {
443
                                horAlign = HorAlign.Left;
444
                                vertAlign = VertAlign.Middle;
445
                            }
446
                            else if (RadialUtils.IsLeft(Parent))
447
                            {
448
                                horAlign = HorAlign.Middle;
449
                                vertAlign = VertAlign.Top;
450
                            }
451
                            else if (RadialUtils.IsRight(Parent))
452
                            {
453
                                horAlign = HorAlign.Middle;
454
                                vertAlign = VertAlign.Top;
455
                            }
456
                        }
457
                        else
458
                        {
459
                            horAlign = HorAlign.Right;
460
                            vertAlign = VertAlign.Middle;
461
                        }
462
                    }
463
                    else if (i < sideTicksCount / 2)
464
                    {
465
                        horAlign = HorAlign.Right;
466

467
                        if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))
468
                        {
469
                            if (RadialUtils.IsRight(Parent) && RadialUtils.IsBottom(Parent))
470
                            {
471
                                vertAlign = VertAlign.Top;
472
                                horAlign = HorAlign.Left;
473
                            }
474
                            else if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))
475
                            {
476
                                vertAlign = VertAlign.Bottom;
477
                                horAlign = HorAlign.Right;
478
                            }
479
                            else if (RadialUtils.IsBottom(Parent))
480
                                vertAlign = VertAlign.Top;
481
                            else if (RadialUtils.IsLeft(Parent))
482
                            {
483
                                horAlign = HorAlign.Right;
484
                                vertAlign = VertAlign.Top;
485
                            }
486
                            else if (RadialUtils.IsRight(Parent))
487
                            {
488
                                horAlign = HorAlign.Left;
489
                                vertAlign = VertAlign.Top;
490
                            }
491
                        }
492
                        else
493
                            vertAlign = VertAlign.Bottom;
494
                    }
495
                    else
496
                    {
497
                        horAlign = HorAlign.Right;
498
                        vertAlign = VertAlign.Top;
499
                    }
500
                    txtPoint = GetTextPoint(tick, -1 * e.ScaleX, isNegative(i, false), isLeftPart);
501
                    DrawText(e, text, brush, txtPoint.X, txtPoint.Y, horAlign, vertAlign);
502
                    angle *= -1;
503
                }
504

505
                angle += majorStep * RadialGauge.Radians;
506
            }
507
        }
508

509
        private void DrawMinorTicks(FRPaintEventArgs e)
510
        {
511
            IGraphics g = e.Graphics;
512
            Pen pen = e.Cache.GetPen(MinorTicks.Color, MinorTicks.Width * e.ScaleX, DashStyle.Solid);
513

514
            MinorTicks.Length = width / 24;
515
            minorTicksOffset = majorTicksOffset + MajorTicks.Length / 2 - MinorTicks.Length / 2;
516
            PointF center = new PointF(left + width / 2, top + height / 2);
517

518
            PointF[] tick0 = new PointF[2];
519
            //first tick
520
            tick0[0] = new PointF(left + width / 2, top + minorTicksOffset);
521
            tick0[1] = new PointF(tick0[0].X, tick0[0].Y + MinorTicks.Length);
522

523
            double angle = 0;
524
            if (RadialUtils.IsSemicircle(Parent) || RadialUtils.IsQuadrant(Parent))
525
            {
526
                if (RadialUtils.IsBottom(Parent) && RadialUtils.IsLeft(Parent))
527
                {
528
                    angle = -180 * RadialGauge.Radians;
529
                }
530
                else if (RadialUtils.IsTop(Parent) && RadialUtils.IsLeft(Parent))
531
                {
532
                    angle = 0;
533
                }
534
                else if (RadialUtils.IsTop(Parent) && RadialUtils.IsRight(Parent))
535
                {
536
                    angle = 0;
537
                }
538
                else if (RadialUtils.IsBottom(Parent))
539
                {
540
                    angle = 180 * RadialGauge.Radians;
541
                    majorStep *= -1;
542
                }
543
                else if (RadialUtils.IsLeft(Parent))
544
                {
545
                    angle = -90 * RadialGauge.Radians;
546
                }
547
                else if (RadialUtils.IsRight(Parent))
548
                {
549
                    angle = 90 * RadialGauge.Radians;
550
                    majorStep *= -1;
551
                }
552
            }
553
            tick0 = RadialUtils.RotateVector(tick0, angle, center);
554

555
            //rest of ticks
556
            PointF[] tick = new PointF[2];
557
            angle = minorStep * RadialGauge.Radians;
558
            for (int i = 0; i < MajorTicks.Count / 2 * (MinorTicks.Count + 1); i++)
559
            {
560
                if ((i + 1) % (MinorTicks.Count + 1) != 0)
561
                {
562
                    if (drawRight)
563
                    {
564
                        tick = RadialUtils.RotateVector(tick0, angle, center);
565
                        g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);
566
                    }
567
                    if (drawLeft)
568
                    {
569
                        angle *= -1;
570
                        tick = RadialUtils.RotateVector(tick0, angle, center);
571
                        g.DrawLine(pen, tick[0].X, tick[0].Y, tick[1].X, tick[1].Y);
572
                        angle *= -1;
573
                    }
574
                }
575
                angle += minorStep * RadialGauge.Radians;
576
            }
577
        }
578

579
        #endregion // Private Methods
580

581
        #region Public Methods
582

583
        /// <inheritdoc/>
584
        public override void Assign(GaugeScale src)
585
        {
586
            base.Assign(src);
587

588
            RadialScale s = src as RadialScale;
589
            MajorTicks.Assign(s.MajorTicks);
590
            MinorTicks.Assign(s.MinorTicks);
591
        }
592

593
        /// <inheritdoc/>
594
        public override void Draw(FRPaintEventArgs e)
595
        {
596
            base.Draw(e);
597
            if ((Parent as RadialGauge).Type == RadialGaugeType.Circle)
598
            {
599
                MajorTicks.Count = 11;
600
                MinorTicks.Count = 4;
601
                majorStep = 135f / 5;
602
                minorStep = 135f / 5f / 5f;
603
            }
604
            else if ((Parent as RadialGauge).Type == RadialGaugeType.Semicircle)
605
            {
606
                MajorTicks.Count = 5;
607
                MinorTicks.Count = 3;
608
                majorStep = 90f / 2;
609
                minorStep = 90f / 2 / 4;
610
            }
611
            else if ((Parent as RadialGauge).Type == RadialGaugeType.Quadrant)
612
            {
613
                MajorTicks.Count = 5;
614
                MinorTicks.Count = 3;
615
                majorStep = 90f / 2;
616
                minorStep = 90f / 2 / 4;
617
            }
618
            left = Parent.AbsLeft * e.ScaleX;
619
            top = Parent.AbsTop * e.ScaleY;
620
            height = Parent.Height * e.ScaleY;
621
            width = Parent.Width * e.ScaleX;
622
            DrawMajorTicks(e);
623
            DrawMinorTicks(e);
624
        }
625

626
        /// <inheritdoc/>
627
        public override void Serialize(FRWriter writer, string prefix, GaugeScale diff)
628
        {
629
            base.Serialize(writer, prefix, diff);
630

631
            RadialScale dc = diff as RadialScale;
632
            MajorTicks.Serialize(writer, prefix + ".MajorTicks", dc.MajorTicks);
633
            MinorTicks.Serialize(writer, prefix + ".MinorTicks", dc.MinorTicks);
634
        }
635

636
        #endregion // Public Methods
637
    }
638
}
639

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.