FastReport

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

8
namespace FastReport
9
{
10
    /// <summary>
11
    /// Specifies the style of a border line.
12
    /// </summary>
13
    public enum LineStyle
14
    {
15
        /// <summary>
16
        /// Specifies a solid line. 
17
        /// </summary>
18
        Solid,
19

20
        /// <summary>
21
        /// Specifies a line consisting of dashes.
22
        /// </summary>
23
        Dash,
24

25
        /// <summary>
26
        /// Specifies a line consisting of dots. 
27
        /// </summary>
28
        Dot,
29

30
        /// <summary>
31
        /// Specifies a line consisting of a repeating pattern of dash-dot. 
32
        /// </summary>
33
        DashDot,
34

35
        /// <summary>
36
        /// Specifies a line consisting of a repeating pattern of dash-dot-dot. 
37
        /// </summary>
38
        DashDotDot,
39

40
        /// <summary>
41
        /// Specifies a double line. 
42
        /// </summary>
43
        Double,
44

45
        /// <summary>
46
        /// Specifies a custom line. 
47
        /// </summary>
48
        Custom
49
    }
50

51
    /// <summary>
52
    /// Specifies the sides of a border.
53
    /// </summary>
54
    [Flags]
55
    public enum BorderLines
56
    {
57
        /// <summary>
58
        /// Specifies no border lines.
59
        /// </summary>
60
        None = 0,
61

62
        /// <summary>
63
        /// Specifies the left border line.
64
        /// </summary>
65
        Left = 1,
66

67
        /// <summary>
68
        /// Specifies the right border line.
69
        /// </summary>
70
        Right = 2,
71

72
        /// <summary>
73
        /// Specifies the top border line.
74
        /// </summary>
75
        Top = 4,
76

77
        /// <summary>
78
        /// Specifies the bottom border line.
79
        /// </summary>
80
        Bottom = 8,
81

82
        /// <summary>
83
        /// Specifies all border lines.
84
        /// </summary>
85
        All = 15
86
    }
87

88
    /// <summary>
89
    /// Represents a single border line.
90
    /// </summary>
91
    [TypeConverter(typeof(FastReport.TypeConverters.FRExpandableObjectConverter))]
92
    public class BorderLine
93
    {
94
        #region Fields
95
        private Color color;
96
        private LineStyle style;
97
        private float width;
98
        #endregion
99

100
        #region Properties
101
        /// <summary>
102
        /// Gets or sets a color of the line.
103
        /// </summary>
104
        [Editor("FastReport.TypeEditors.ColorEditor, FastReport", typeof(UITypeEditor))]
105
        public Color Color
106
        {
107
            get { return color; }
108
            set { color = value; }
109
        }
110

111
        /// <summary>
112
        /// Gets or sets a style of the line.
113
        /// </summary>
114
        [DefaultValue(LineStyle.Solid)]
115
        [Editor("FastReport.TypeEditors.LineStyleEditor, FastReport", typeof(UITypeEditor))]
116
        public LineStyle Style
117
        {
118
            get { return style; }
119
            set { style = value; }
120
        }
121

122
        /// <summary>
123
        /// Gets or sets a width of the line, in pixels.
124
        /// </summary>
125
        [DefaultValue(1f)]
126
        public float Width
127
        {
128
            get { return width; }
129
            set { width = value; }
130
        }
131

132
        internal DashStyle DashStyle
133
        {
134
            get
135
            {
136
                DashStyle[] styles = new DashStyle[] {
137
          DashStyle.Solid, DashStyle.Dash, DashStyle.Dot, DashStyle.DashDot, DashStyle.DashDotDot, DashStyle.Solid };
138
                return styles[(int)Style];
139
            }
140
        }
141
        #endregion
142

143
        #region Private Methods
144
        private bool ShouldSerializeColor()
145
        {
146
            return Color != Color.Black;
147
        }
148

149
        internal bool ShouldSerialize()
150
        {
151
            return Width != 1 || Style != LineStyle.Solid || Color != Color.Black;
152
        }
153
        #endregion
154

155
        #region Public Methods
156
        internal BorderLine Clone()
157
        {
158
            BorderLine result = new BorderLine();
159
            result.Assign(this);
160
            return result;
161
        }
162

163
        internal void Assign(BorderLine src)
164
        {
165
            Color = src.Color;
166
            Style = src.Style;
167
            Width = src.Width;
168
        }
169

170
        /// <inheritdoc/>
171
        public override bool Equals(object obj)
172
        {
173
            BorderLine line = obj as BorderLine;
174
            return line != null && Width == line.Width && Color == line.Color && Style == line.Style;
175
        }
176

177
        /// <inheritdoc/>
178
        public override int GetHashCode()
179
        {
180
            return Color.GetHashCode() ^ Style.GetHashCode() ^ Width.GetHashCode();
181
        }
182

183
        internal void Draw(FRPaintEventArgs e, float x, float y, float x1, float y1,
184
          bool reverseGaps, bool gap1, bool gap2)
185
        {
186
            IGraphics g = e.Graphics;
187

188
            int penWidth = (int)Math.Round(Width * e.ScaleX);
189
            if (penWidth <= 0)
190
                penWidth = 1;
191
            using (Pen pen = new Pen(Color, penWidth))
192
            {
193
                pen.DashStyle = DashStyle;
194
                pen.StartCap = LineCap.Square;
195
                pen.EndCap = LineCap.Square;
196
                if (pen.DashStyle != DashStyle.Solid)
197
                {
198
                    float patternWidth = 0;
199
                    foreach (float w in pen.DashPattern)
200
                        patternWidth += w * pen.Width;
201
                    if (y == y1)
202
                        pen.DashOffset = (x - ((int)(x / patternWidth)) * patternWidth) / pen.Width;
203
                    else
204
                        pen.DashOffset = (y - ((int)(y / patternWidth)) * patternWidth) / pen.Width;
205
                }
206

207
                if (Style != LineStyle.Double)
208
                    g.DrawLine(pen, x, y, x1, y1);
209
                else
210
                {
211
                    // we have to correctly draw inner and outer lines of a double line
212
                    float g1 = gap1 ? pen.Width : 0;
213
                    float g2 = gap2 ? pen.Width : 0;
214
                    float g3 = -g1;
215
                    float g4 = -g2;
216

217
                    if (reverseGaps)
218
                    {
219
                        g1 = -g1;
220
                        g2 = -g2;
221
                        g3 = -g3;
222
                        g4 = -g4;
223
                    }
224

225
                    if (x == x1)
226
                    {
227
                        g.DrawLine(pen, x - pen.Width, y + g1, x1 - pen.Width, y1 - g2);
228
                        g.DrawLine(pen, x + pen.Width, y + g3, x1 + pen.Width, y1 - g4);
229
                    }
230
                    else
231
                    {
232
                        g.DrawLine(pen, x + g1, y - pen.Width, x1 - g2, y1 - pen.Width);
233
                        g.DrawLine(pen, x + g3, y + pen.Width, x1 - g4, y1 + pen.Width);
234
                    }
235
                }
236
            }
237
        }
238

239
        internal void Serialize(FRWriter writer, string prefix, BorderLine c)
240
        {
241
            if (Color != c.Color)
242
                writer.WriteValue(prefix + ".Color", Color);
243
            if (Style != c.Style)
244
                writer.WriteValue(prefix + ".Style", Style);
245
            if (Width != c.Width)
246
                writer.WriteFloat(prefix + ".Width", Width);
247
        }
248

249
        public BorderLine()
250
        {
251
            color = Color.Black;
252
            width = 1;
253
        }
254
        #endregion
255
    }
256

257
    /// <summary>
258
    /// Represents a border around the report object.
259
    /// </summary>
260
    /// <remarks>
261
    /// Border consists of four lines. Each line has own color, style and width. Lines are accessible through
262
    /// <see cref="LeftLine"/>, <see cref="RightLine"/>, <see cref="TopLine"/>, <see cref="BottomLine"/> properties.
263
    /// <para/>
264
    /// To turn on and off the lines, use the <see cref="Lines"/> property. To set the same color, style or width
265
    /// for each line, use <see cref="Color"/>, <see cref="Style"/>, <see cref="Width"/> properties of the <b>Border</b>.
266
    /// </remarks>
267
    [TypeConverter(typeof(FastReport.TypeConverters.FRExpandableObjectConverter))]
268
    [Editor("FastReport.TypeEditors.BorderEditor, FastReport", typeof(UITypeEditor))]
269
    public class Border
270
    {
271
        #region Fields
272
        private bool shadow;
273
        private float shadowWidth;
274
        private Color shadowColor;
275
        private BorderLines lines;
276
        private BorderLine leftLine;
277
        private BorderLine topLine;
278
        private BorderLine rightLine;
279
        private BorderLine bottomLine;
280
        private bool simpleBorder;
281
        #endregion
282

283
        #region Properties
284
        /// <summary>
285
        /// Gets or sets a color of the border.
286
        /// </summary>
287
        /// <remarks>
288
        /// This property actually returns a color of the <see cref="LeftLine"/>. When you assign a value 
289
        /// to this property, the value will be set to each border line.
290
        /// </remarks>
291
        [Editor("FastReport.TypeEditors.ColorEditor, FastReport", typeof(UITypeEditor))]
292
        public Color Color
293
        {
294
            get { return leftLine.Color; }
295
            set
296
            {
297
                leftLine.Color = value;
298
                rightLine.Color = value;
299
                topLine.Color = value;
300
                bottomLine.Color = value;
301
            }
302
        }
303

304
        /// <summary>
305
        /// Gets or sets a value determines whether to draw a shadow.
306
        /// </summary>
307
        [DefaultValue(false)]
308
        public bool Shadow
309
        {
310
            get { return shadow; }
311
            set { shadow = value; }
312
        }
313

314
        /// <summary>
315
        /// Gets or sets a shadow width, in pixels.
316
        /// </summary>
317
        [DefaultValue(4f)]
318
        public float ShadowWidth
319
        {
320
            get { return shadowWidth; }
321
            set { shadowWidth = value; }
322
        }
323

324
        /// <summary>
325
        /// Gets or sets a shadow color.
326
        /// </summary>
327
        [Editor("FastReport.TypeEditors.ColorEditor, FastReport", typeof(UITypeEditor))]
328
        public Color ShadowColor
329
        {
330
            get { return shadowColor; }
331
            set { shadowColor = value; }
332
        }
333

334
        /// <summary>
335
        /// Gets or sets a style of the border.
336
        /// </summary>
337
        /// <remarks>
338
        /// This property actually returns a style of the <see cref="LeftLine"/>. When you assign a value 
339
        /// to this property, the value will be set to each border line.
340
        /// </remarks>
341
        [DefaultValue(LineStyle.Solid)]
342
        [Editor("FastReport.TypeEditors.LineStyleEditor, FastReport", typeof(UITypeEditor))]
343
        public LineStyle Style
344
        {
345
            get { return leftLine.Style; }
346
            set
347
            {
348
                leftLine.Style = value;
349
                rightLine.Style = value;
350
                topLine.Style = value;
351
                bottomLine.Style = value;
352
            }
353
        }
354

355
        /// <summary>
356
        /// Gets or sets a visible lines of a border.
357
        /// </summary>
358
        [DefaultValue(BorderLines.None)]
359
        [Editor("FastReport.TypeEditors.BorderLinesEditor, FastReport", typeof(UITypeEditor))]
360
        public BorderLines Lines
361
        {
362
            get { return lines; }
363
            set { lines = value; }
364
        }
365

366
        /// <summary>
367
        /// Gets or sets a width of the border, in pixels.
368
        /// </summary>
369
        /// <remarks>
370
        /// This property actually returns a width of the <see cref="LeftLine"/>. When you assign a value 
371
        /// to this property, the value will be set to each border line.
372
        /// </remarks>
373
        [DefaultValue(1f)]
374
        public float Width
375
        {
376
            get { return leftLine.Width; }
377
            set
378
            {
379
                leftLine.Width = value;
380
                rightLine.Width = value;
381
                topLine.Width = value;
382
                bottomLine.Width = value;
383
            }
384
        }
385

386
        /// <summary>
387
        /// Gets or sets the left line of the border.
388
        /// </summary>
389
        public BorderLine LeftLine
390
        {
391
            get { return leftLine; }
392
            set { leftLine = value; }
393
        }
394

395
        /// <summary>
396
        /// Gets or sets the top line of the border.
397
        /// </summary>
398
        public BorderLine TopLine
399
        {
400
            get { return topLine; }
401
            set { topLine = value; }
402
        }
403

404
        /// <summary>
405
        /// Gets or sets the right line of the border.
406
        /// </summary>
407
        public BorderLine RightLine
408
        {
409
            get { return rightLine; }
410
            set { rightLine = value; }
411
        }
412

413
        /// <summary>
414
        /// Gets or sets the bottom line of the border.
415
        /// </summary>
416
        public BorderLine BottomLine
417
        {
418
            get { return bottomLine; }
419
            set { bottomLine = value; }
420
        }
421

422
        /// <summary>
423
        /// Gets or sets a value determines that <b>Border</b> must serialize only one line.
424
        /// </summary>
425
        /// <remarks>
426
        /// This property is for internal use only.
427
        /// </remarks>
428
        [Browsable(false)]
429
        public bool SimpleBorder
430
        {
431
            get { return simpleBorder; }
432
            set { simpleBorder = value; }
433
        }
434

435
        internal DashStyle DashStyle
436
        {
437
            get { return leftLine.DashStyle; }
438
        }
439
        #endregion
440

441
        #region Private Methods
442
        private bool ShouldSerializeLeftLine()
443
        {
444
            return LeftLine.ShouldSerialize();
445
        }
446

447
        private bool ShouldSerializeTopLine()
448
        {
449
            return TopLine.ShouldSerialize();
450
        }
451

452
        private bool ShouldSerializeRightLine()
453
        {
454
            return RightLine.ShouldSerialize();
455
        }
456

457
        private bool ShouldSerializeBottomLine()
458
        {
459
            return BottomLine.ShouldSerialize();
460
        }
461

462
        private bool ShouldSerializeColor()
463
        {
464
            return Color != Color.Black;
465
        }
466

467
        private bool ShouldSerializeShadowColor()
468
        {
469
            return ShadowColor != Color.Black;
470
        }
471
        #endregion
472

473
        #region Internal Methods
474

475
        internal void ZoomBorder(float zoom)
476
        {
477
            LeftLine.Width *= zoom;
478
            if (leftLine.Width > 0 && leftLine.Width < 1)
479
                LeftLine.Width = 1;
480

481
            RightLine.Width *= zoom;
482
            if (rightLine.Width > 0 && rightLine.Width < 1)
483
                RightLine.Width = 1;
484

485
            TopLine.Width *= zoom;
486
            if (topLine.Width > 0 && topLine.Width < 1)
487
                TopLine.Width = 1;
488

489
            BottomLine.Width *= zoom;
490
            if (bottomLine.Width > 0 && bottomLine.Width < 1)
491
                BottomLine.Width = 1;
492
        }
493

494
        #endregion
495

496
        #region Public Methods
497
        /// <summary>
498
        /// Creates the exact copy of this <b>Border</b>.
499
        /// </summary>
500
        /// <returns>A copy of this border.</returns>
501
        public Border Clone()
502
        {
503
            Border result = new Border(this);
504
            return result;
505
        }
506

507
        /// <inheritdoc/>
508
        public override bool Equals(object obj)
509
        {
510
            Border b = obj as Border;
511
            return b != null && Lines == b.Lines &&
512
              LeftLine.Equals(b.LeftLine) && TopLine.Equals(b.TopLine) &&
513
              RightLine.Equals(b.RightLine) && BottomLine.Equals(b.BottomLine) &&
514
              Shadow == b.Shadow && ShadowColor == b.ShadowColor && ShadowWidth == b.ShadowWidth;
515
        }
516

517
        /// <inheritdoc/>
518
        public override int GetHashCode()
519
        {
520
            return Lines.GetHashCode() ^ (Shadow.GetHashCode() + 16) ^ ShadowColor.GetHashCode() ^
521
              (ShadowWidth.GetHashCode() + 32) ^ (LeftLine.GetHashCode() << 1) ^ (TopLine.GetHashCode() << 2) ^
522
              (RightLine.GetHashCode() << 3) ^ (BottomLine.GetHashCode() << 4);
523
        }
524

525
        /// <summary>
526
        /// Serializes the border.
527
        /// </summary>
528
        /// <param name="writer">Writer object.</param>
529
        /// <param name="prefix">Border property name.</param>
530
        /// <param name="c">Another Border to compare with.</param>
531
        /// <remarks>
532
        /// This method is for internal use only.
533
        /// </remarks>
534
        public void Serialize(FRWriter writer, string prefix, Border c)
535
        {
536
            if (Shadow != c.Shadow)
537
                writer.WriteBool(prefix + ".Shadow", Shadow);
538
            if (ShadowWidth != c.ShadowWidth)
539
                writer.WriteFloat(prefix + ".ShadowWidth", ShadowWidth);
540
            if (ShadowColor != c.ShadowColor)
541
                writer.WriteValue(prefix + ".ShadowColor", ShadowColor);
542
            if (!SimpleBorder)
543
            {
544
                if (Lines != c.Lines)
545
                    writer.WriteValue(prefix + ".Lines", Lines);
546
                if (Lines != BorderLines.None || Color != Color.Black)
547
                {
548
                    if (LeftLine.Equals(RightLine) && LeftLine.Equals(TopLine) && LeftLine.Equals(BottomLine) &&
549
                      c.LeftLine.Equals(c.RightLine) && c.LeftLine.Equals(c.TopLine) && c.LeftLine.Equals(c.BottomLine))
550
                        LeftLine.Serialize(writer, prefix, c.LeftLine);
551
                    else
552
                    {
553
                        LeftLine.Serialize(writer, prefix + ".LeftLine", c.LeftLine);
554
                        TopLine.Serialize(writer, prefix + ".TopLine", c.TopLine);
555
                        RightLine.Serialize(writer, prefix + ".RightLine", c.RightLine);
556
                        BottomLine.Serialize(writer, prefix + ".BottomLine", c.BottomLine);
557
                    }
558
                }
559
            }
560
            else
561
                LeftLine.Serialize(writer, prefix, c.LeftLine);
562
        }
563

564
        /// <summary>
565
        /// Draw the border using draw event arguments and specified bounding rectangle.
566
        /// </summary>
567
        /// <param name="e">Draw event arguments.</param>
568
        /// <param name="rect">Bounding rectangle.</param>
569
        /// <remarks>
570
        /// This method is for internal use only.
571
        /// </remarks>
572
        public void Draw(FRPaintEventArgs e, RectangleF rect)
573
        {
574
            IGraphics g = e.Graphics;
575
            rect.X *= e.ScaleX;
576
            rect.Y *= e.ScaleY;
577
            rect.Width *= e.ScaleX;
578
            rect.Height *= e.ScaleY;
579

580
            if (Shadow)
581
            {
582
                //int d = (int)Math.Round(ShadowWidth * e.ScaleX);
583
                //Pen pen = e.Cache.GetPen(ShadowColor, d, DashStyle.Solid);
584
                //g.DrawLine(pen, rect.Right + d / 2, rect.Top + d, rect.Right + d / 2, rect.Bottom);
585
                //g.DrawLine(pen, rect.Left + d, rect.Bottom + d / 2, rect.Right + d, rect.Bottom + d / 2);
586

587
                float d = ShadowWidth * e.ScaleX;
588
                Brush brush = e.Cache.GetBrush(ShadowColor);
589
                g.FillRectangle(brush, rect.Left + d, rect.Bottom, rect.Width, d);
590
                g.FillRectangle(brush, rect.Right, rect.Top + d, d, rect.Height);
591
            }
592

593
            if (Lines != BorderLines.None)
594
            {
595
                // draw full frame as a rectangle with solid line only. Non-solid lines
596
                // should be drawn separately to avoid overlapping effect
597
                if (Lines == BorderLines.All && LeftLine.Equals(TopLine) && LeftLine.Equals(RightLine) &&
598
                  LeftLine.Equals(BottomLine) && LeftLine.Style == LineStyle.Solid)
599
                {
600
                    Pen pen = e.Cache.GetPen(LeftLine.Color, (int)Math.Round(LeftLine.Width * e.ScaleX), LeftLine.DashStyle);
601
                    g.DrawRectangle(pen, rect.Left, rect.Top, rect.Width, rect.Height);
602
                }
603
                else
604
                {
605
                    if ((Lines & BorderLines.Left) != 0)
606
                        LeftLine.Draw(e, rect.Left, rect.Top, rect.Left, rect.Bottom,
607
                          true, (Lines & BorderLines.Top) != 0, (Lines & BorderLines.Bottom) != 0);
608
                    if ((Lines & BorderLines.Right) != 0)
609
                        RightLine.Draw(e, rect.Right, rect.Top, rect.Right, rect.Bottom,
610
                          false, (Lines & BorderLines.Top) != 0, (Lines & BorderLines.Bottom) != 0);
611
                    if ((Lines & BorderLines.Top) != 0)
612
                        TopLine.Draw(e, rect.Left, rect.Top, rect.Right, rect.Top,
613
                          true, (Lines & BorderLines.Left) != 0, (Lines & BorderLines.Right) != 0);
614
                    if ((Lines & BorderLines.Bottom) != 0)
615
                        BottomLine.Draw(e, rect.Left, rect.Bottom, rect.Right, rect.Bottom,
616
                          false, (Lines & BorderLines.Left) != 0, (Lines & BorderLines.Right) != 0);
617
                }
618
            }
619
        }
620
        #endregion
621

622
        /// <summary>
623
        /// Initializes a new instance of the <see cref="Border"/> class with default settings. 
624
        /// </summary>
625
        public Border()
626
        {
627
            leftLine = new BorderLine();
628
            topLine = new BorderLine();
629
            rightLine = new BorderLine();
630
            bottomLine = new BorderLine();
631
            shadowWidth = 4;
632
            shadowColor = Color.Black;
633
        }
634

635
        private Border(Border src)
636
        {
637
            lines = src.Lines;
638
            shadow = src.Shadow;
639
            shadowColor = src.ShadowColor;
640
            shadowWidth = src.ShadowWidth;
641
            leftLine = src.LeftLine.Clone();
642
            topLine = src.TopLine.Clone();
643
            rightLine = src.RightLine.Clone();
644
            bottomLine = src.BottomLine.Clone();
645
            //Fix 1513
646
            //Width = src.Width;
647
            //1513
648
        }
649
    }
650
}

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

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

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

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