123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using FastReport.Utils;
- using System.Drawing.Design;
- namespace FastReport
- {
- /// <summary>
- /// Represents a zip code object.
- /// </summary>
- /// <remarks>
- /// This object is mainly used in Russia to print postal index on envelopes. It complies with the
- /// GOST R 51506-99.
- /// </remarks>
- public partial class ZipCodeObject : ReportComponentBase
- {
- #region Fields
- private float segmentWidth;
- private float segmentHeight;
- private float spacing;
- private int segmentCount;
- private bool showMarkers;
- private bool showGrid;
- private string dataColumn;
- private string expression;
- private string text;
- private static List<Point[]> FDigits;
- #endregion
- #region Properties
- /// <summary>
- /// Gets or sets the width of a single zipcode segment, in pixels.
- /// </summary>
- [Category("Layout")]
- [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
- public float SegmentWidth
- {
- get { return segmentWidth; }
- set { segmentWidth = value; }
- }
- /// <summary>
- /// Gets or sets the height of a single zipcode segment, in pixels.
- /// </summary>
- [Category("Layout")]
- [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
- public float SegmentHeight
- {
- get { return segmentHeight; }
- set { segmentHeight = value; }
- }
- /// <summary>
- /// Gets or sets the spacing between origins of segments, in pixels.
- /// </summary>
- [Category("Layout")]
- [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")]
- public float Spacing
- {
- get { return spacing; }
- set { spacing = value; }
- }
- /// <summary>
- /// Gets or sets the number of segments in zipcode.
- /// </summary>
- [Category("Layout")]
- [DefaultValue(6)]
- public int SegmentCount
- {
- get { return segmentCount; }
- set { segmentCount = value; }
- }
- /// <summary>
- /// Gets or sets a value indicating whether the reference markers should be drawn.
- /// </summary>
- /// <remarks>
- /// Reference markers are used by postal service to automatically read the zipcode.
- /// </remarks>
- [Category("Behavior")]
- [DefaultValue(true)]
- public bool ShowMarkers
- {
- get { return showMarkers; }
- set { showMarkers = value; }
- }
- /// <summary>
- /// Gets or sets a value indicating whether the segment grid should be drawn.
- /// </summary>
- [Category("Behavior")]
- [DefaultValue(true)]
- public bool ShowGrid
- {
- get { return showGrid; }
- set { showGrid = value; }
- }
- /// <summary>
- /// Gets or sets a data column name bound to this control.
- /// </summary>
- /// <remarks>
- /// Value must be in the form "Datasource.Column".
- /// </remarks>
- [Category("Data")]
- [Editor("FastReport.TypeEditors.DataColumnEditor, FastReport", typeof(UITypeEditor))]
- public string DataColumn
- {
- get { return dataColumn; }
- set { dataColumn = value; }
- }
- /// <summary>
- /// Gets or sets an expression that contains the zip code.
- /// </summary>
- [Category("Data")]
- [Editor("FastReport.TypeEditors.ExpressionEditor, FastReport", typeof(UITypeEditor))]
- public string Expression
- {
- get { return expression; }
- set { expression = value; }
- }
- /// <summary>
- /// Gets or sets the zip code.
- /// </summary>
- [Category("Data")]
- public string Text
- {
- get { return text; }
- set { text = value; }
- }
- #endregion
- #region Private Methods
- private void DrawSegmentGrid(FRPaintEventArgs e, float offsetX, float offsetY)
- {
- IGraphics g = e.Graphics;
- SmoothingMode saveSmoothing = g.SmoothingMode;
- g.SmoothingMode = SmoothingMode.AntiAlias;
- Brush b = e.Cache.GetBrush(Border.Color);
- int[] grid = new int[] { 111111, 110001, 101001, 100101, 100011, 111111, 110001, 101001, 100101, 100011, 111111 };
- float ratioX = segmentWidth / (Units.Centimeters * 0.5f);
- float ratioY = segmentHeight / (Units.Centimeters * 1);
- float pointSize = Units.Millimeters * 0.25f;
- float y = AbsTop;
- foreach (int gridRow in grid)
- {
- int row = gridRow;
- float x = AbsLeft;
- while (row > 0)
- {
- if (row % 10 == 1)
- g.FillEllipse(b, (x + offsetX - pointSize / 2) * e.ScaleX, (y + offsetY - pointSize / 2) * e.ScaleY,
- pointSize * e.ScaleX, pointSize * e.ScaleY);
- row /= 10;
- x += Units.Millimeters * 1 * ratioX;
- }
- y += Units.Millimeters * 1 * ratioY;
- }
- g.SmoothingMode = saveSmoothing;
- }
- private void DrawReferenceLine(FRPaintEventArgs e, float offsetX)
- {
- IGraphics g = e.Graphics;
- Brush b = e.Cache.GetBrush(Border.Color);
- g.FillRectangle(b,
- new RectangleF((AbsLeft + offsetX) * e.ScaleX, AbsTop * e.ScaleY,
- Units.Millimeters * 7 * e.ScaleX, Units.Millimeters * 2 * e.ScaleY));
- // draw start line
- if (offsetX == 0)
- {
- g.FillRectangle(b,
- new RectangleF((AbsLeft + offsetX) * e.ScaleX, (AbsTop + Units.Millimeters * 3) * e.ScaleY,
- Units.Millimeters * 7 * e.ScaleX, Units.Millimeters * 1 * e.ScaleY));
- }
- }
- private void DrawSegment(FRPaintEventArgs e, int symbol, float offsetX)
- {
- IGraphics g = e.Graphics;
- float offsetY = 0;
- // draw marker
- if (showMarkers)
- {
- DrawReferenceLine(e, offsetX);
- if (offsetX == 0)
- return;
- offsetX += Units.Millimeters * 1;
- offsetY = Units.Millimeters * 4;
- }
- else
- {
- // draw inside the object's area - important when you export the object
- offsetX += Border.Width / 2;
- offsetY += Border.Width / 2;
- }
- // draw grid
- if (showGrid)
- DrawSegmentGrid(e, offsetX, offsetY);
- // draw symbol
- if (symbol != -1)
- {
- Point[] digit = FDigits[symbol];
- PointF[] path = new PointF[digit.Length];
- float ratioX = segmentWidth / (Units.Centimeters * 0.5f);
- float ratioY = segmentHeight / (Units.Centimeters * 1);
- for (int i = 0; i < digit.Length; i++)
- {
- path[i] = new PointF((AbsLeft + digit[i].X * Units.Millimeters * ratioX + offsetX) * e.ScaleX,
- (AbsTop + digit[i].Y * Units.Millimeters * ratioY + offsetY) * e.ScaleY);
- }
- using (Pen pen = new Pen(Border.Color, Border.Width * e.ScaleX))
- {
- pen.StartCap = LineCap.Round;
- pen.EndCap = LineCap.Round;
- pen.LineJoin = LineJoin.Round;
- g.DrawLines(pen, path);
- }
- }
- }
- #endregion
- #region Public Methods
- /// <inheritdoc/>
- public override void Assign(Base source)
- {
- base.Assign(source);
- ZipCodeObject src = source as ZipCodeObject;
- SegmentWidth = src.SegmentWidth;
- SegmentHeight = src.SegmentHeight;
- Spacing = src.Spacing;
- SegmentCount = src.SegmentCount;
- ShowMarkers = src.ShowMarkers;
- ShowGrid = src.ShowGrid;
- DataColumn = src.DataColumn;
- Expression = src.Expression;
- Text = src.Text;
- }
- /// <inheritdoc/>
- public override void Draw(FRPaintEventArgs e)
- {
- Width = ((showMarkers ? 1 : 0) + segmentCount) * spacing;
- Height = (showMarkers ? segmentHeight + Units.Millimeters * 4 : segmentHeight) + Border.Width;
- base.Draw(e);
- float offsetX = 0;
- if (showMarkers)
- {
- // draw starting marker
- DrawSegment(e, -1, 0);
- offsetX += spacing;
- }
- string text = Text.PadLeft(segmentCount, '0');
- text = text.Substring(0, segmentCount);
- foreach (char ch in text)
- {
- int symbol = -1;
- if (ch >= '0' && ch <= '9')
- symbol = (int)ch - (int)'0';
- DrawSegment(e, symbol, offsetX);
- offsetX += spacing;
- }
- }
- /// <inheritdoc/>
- public override void Serialize(FRWriter writer)
- {
- ZipCodeObject c = writer.DiffObject as ZipCodeObject;
- Border.SimpleBorder = true;
- base.Serialize(writer);
- if (FloatDiff(SegmentWidth, c.SegmentWidth))
- writer.WriteFloat("SegmentWidth", SegmentWidth);
- if (FloatDiff(SegmentHeight, c.SegmentHeight))
- writer.WriteFloat("SegmentHeight", SegmentHeight);
- if (FloatDiff(Spacing, c.Spacing))
- writer.WriteFloat("Spacing", Spacing);
- if (SegmentCount != c.SegmentCount)
- writer.WriteInt("SegmentCount", SegmentCount);
- if (ShowMarkers != c.ShowMarkers)
- writer.WriteBool("ShowMarkers", ShowMarkers);
- if (ShowGrid != c.ShowGrid)
- writer.WriteBool("ShowGrid", ShowGrid);
- if (DataColumn != c.DataColumn)
- writer.WriteStr("DataColumn", DataColumn);
- if (Expression != c.Expression)
- writer.WriteStr("Expression", Expression);
- if (Text != c.Text)
- writer.WriteStr("Text", Text);
- }
- #endregion
- #region Report Engine
- /// <inheritdoc/>
- public override string[] GetExpressions()
- {
- List<string> expressions = new List<string>();
- expressions.AddRange(base.GetExpressions());
- if (!String.IsNullOrEmpty(DataColumn))
- expressions.Add(DataColumn);
- if (!String.IsNullOrEmpty(Expression))
- expressions.Add(Expression);
- return expressions.ToArray();
- }
- /// <inheritdoc/>
- public override void GetData()
- {
- base.GetData();
- if (!String.IsNullOrEmpty(DataColumn))
- {
- object value = Report.GetColumnValue(DataColumn);
- Text = value == null ? "" : value.ToString();
- }
- else if (!String.IsNullOrEmpty(Expression))
- {
- object value = Report.Calc(Expression);
- Text = value == null ? "" : value.ToString();
- }
- }
- #endregion
- /// <summary>
- /// Initializes a new instance of the <see cref="ZipCodeObject"/> with the default settings.
- /// </summary>
- public ZipCodeObject()
- {
- segmentWidth = Units.Centimeters * 0.5f;
- segmentHeight = Units.Centimeters * 1;
- spacing = Units.Centimeters * 0.9f;
- segmentCount = 6;
- showMarkers = true;
- showGrid = true;
- text = "123456";
- dataColumn = "";
- expression = "";
- FlagSimpleBorder = true;
- Border.Width = 3;
- SetFlags(Flags.HasSmartTag, true);
- }
- static ZipCodeObject()
- {
- FDigits = new List<Point[]>();
- FDigits.Add(new Point[] { new Point(0, 0), new Point(5, 0), new Point(5, 10), new Point(0, 10), new Point(0, 0) });
- FDigits.Add(new Point[] { new Point(0, 5), new Point(5, 0), new Point(5, 10) });
- FDigits.Add(new Point[] { new Point(0, 0), new Point(5, 0), new Point(5, 5), new Point(0, 10), new Point(5, 10) });
- FDigits.Add(new Point[] { new Point(0, 0), new Point(5, 0), new Point(0, 5), new Point(5, 5), new Point(0, 10) });
- FDigits.Add(new Point[] { new Point(0, 0), new Point(0, 5), new Point(5, 5), new Point(5, 0), new Point(5, 10) });
- FDigits.Add(new Point[] { new Point(5, 0), new Point(0, 0), new Point(0, 5), new Point(5, 5), new Point(5, 10), new Point(0, 10) });
- FDigits.Add(new Point[] { new Point(5, 0), new Point(0, 5), new Point(0, 10), new Point(5, 10), new Point(5, 5), new Point(0, 5) });
- FDigits.Add(new Point[] { new Point(0, 0), new Point(5, 0), new Point(0, 5), new Point(0, 10) });
- FDigits.Add(new Point[] { new Point(0, 5), new Point(0, 0), new Point(5, 0), new Point(5, 10), new Point(0, 10), new Point(0, 5), new Point(5, 5) });
- FDigits.Add(new Point[] { new Point(5, 5), new Point(0, 5), new Point(0, 0), new Point(5, 0), new Point(5, 5), new Point(0, 10) });
- }
- }
- }
|