using System; using System.Collections.Generic; using System.Text; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using FastReport.Utils; namespace FastReport { /// /// Represents a line object. /// /// /// Use the Border.Width, Border.Style and Border.Color properties to set /// the line width, style and color. Set the property to true /// if you want to show a diagonal line. /// public partial class LineObject : ReportComponentBase { #region Fields private bool diagonal; private CapSettings startCap; private CapSettings endCap; #endregion #region Properties /// /// Gets or sets a value indicating that the line is diagonal. /// /// /// If this property is false, the line can be only horizontal or vertical. /// [DefaultValue(false)] [Category("Appearance")] public bool Diagonal { get { return diagonal; } set { diagonal = value; } } /// /// Gets or sets the start cap settings. /// [Category("Appearance")] public CapSettings StartCap { get { return startCap; } set { startCap = value; } } /// /// Gets or sets the end cap settings. /// [Category("Appearance")] public CapSettings EndCap { get { return endCap; } set { endCap = value; } } #endregion #region Public Methods /// public override void Assign(Base source) { base.Assign(source); LineObject src = source as LineObject; Diagonal = src.Diagonal; StartCap.Assign(src.StartCap); EndCap.Assign(src.EndCap); } /// public override void Draw(FRPaintEventArgs e) { IGraphics g = e.Graphics; // draw marker when inserting a line if (Width == 0 && Height == 0) { g.DrawLine(Pens.Black, AbsLeft * e.ScaleX - 6, AbsTop * e.ScaleY, AbsLeft * e.ScaleX + 6, AbsTop * e.ScaleY); g.DrawLine(Pens.Black, AbsLeft * e.ScaleX, AbsTop * e.ScaleY - 6, AbsLeft * e.ScaleX, AbsTop * e.ScaleY + 6); return; } Report report = Report; if (report != null && report.SmoothGraphics) { g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.SmoothingMode = SmoothingMode.AntiAlias; } Pen pen = e.Cache.GetPen(Border.Color, Border.Width * e.ScaleX, Border.DashStyle); float width = Width; float height = Height; if (!Diagonal) { if (Math.Abs(width) > Math.Abs(height)) height = 0; else width = 0; } float x1 = AbsLeft * e.ScaleX; float y1 = AbsTop * e.ScaleY; float x2 = (AbsLeft + width) * e.ScaleX; float y2 = (AbsTop + height) * e.ScaleY; if (StartCap.Style == CapStyle.None && EndCap.Style == CapStyle.None) { g.DrawLine(pen, x1, y1, x2, y2); } else { // draw line caps manually. It is necessary for correct svg rendering float angle = (float)(Math.Atan2(x2 - x1, y2 - y1) / Math.PI * 180); float len = (float)Math.Sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); float scale = Border.Width * e.ScaleX; IGraphicsState state = g.Save(); g.TranslateTransform(x1, y1); g.RotateTransform(-angle); float y = 0; GraphicsPath startCapPath = null; GraphicsPath endCapPath = null; float inset = 0; if (StartCap.Style != CapStyle.None) { StartCap.GetCustomCapPath(out startCapPath, out inset); y += inset * scale; } if (EndCap.Style != CapStyle.None) { EndCap.GetCustomCapPath(out endCapPath, out inset); len -= inset * scale; } g.DrawLine(pen, 0, y, 0, len); g.Restore(state); pen = e.Cache.GetPen(Border.Color, 1, Border.DashStyle); if (StartCap.Style != CapStyle.None) { state = g.Save(); g.TranslateTransform(x1, y1); g.RotateTransform(180 - angle); g.ScaleTransform(scale, scale); g.DrawPath(pen, startCapPath); g.Restore(state); } if (EndCap.Style != CapStyle.None) { state = g.Save(); g.TranslateTransform(x2, y2); g.RotateTransform(-angle); g.ScaleTransform(scale, scale); g.DrawPath(pen, endCapPath); g.Restore(state); } } if (report != null && report.SmoothGraphics && Diagonal) { g.InterpolationMode = InterpolationMode.Default; g.SmoothingMode = SmoothingMode.Default; } } /// public override List Validate() { List listError = new List(); if (IsIntersectingWithOtherObject && !(Parent is ReportComponentBase && !Validator.RectContainInOtherRect((Parent as ReportComponentBase).AbsBounds, this.AbsBounds))) listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Warning, Res.Get("Messages,Validator,IntersectedObjects"), this)); if ((Height < 0 || Width < 0) && diagonal || (Height <= 0 && Width <= 0)) listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,IncorrectSize"), this)); if (Name == "") listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,UnnamedObject"), this)); if (Parent is ReportComponentBase && !Validator.RectContainInOtherRect((Parent as ReportComponentBase).AbsBounds, this.AbsBounds)) listError.Add(new ValidationError(Name, ValidationError.ErrorLevel.Error, Res.Get("Messages,Validator,OutOfBounds"), this)); return listError; } /// public override void Serialize(FRWriter writer) { Border.SimpleBorder = true; base.Serialize(writer); LineObject c = writer.DiffObject as LineObject; if (Diagonal != c.Diagonal) writer.WriteBool("Diagonal", Diagonal); StartCap.Serialize("StartCap", writer, c.StartCap); EndCap.Serialize("EndCap", writer, c.EndCap); } #endregion /// /// Initializes a new instance of the class with default settings. /// public LineObject() { startCap = new CapSettings(); endCap = new CapSettings(); FlagSimpleBorder = true; FlagUseFill = false; } } }