using System; using System.Collections.Generic; using System.Drawing; using System.ComponentModel; using System.Windows.Forms; using System.Drawing.Design; using FastReport.Utils; using FastReport.TypeEditors; using FastReport.TypeConverters; using FastReport.Design.PageDesigners.Page; using System.Threading; using System.Drawing.Drawing2D; namespace FastReport { /// /// The style of the report object markers. /// public enum MarkerStyle { /// /// Rectangle marker. /// Rectangle, /// /// Small markers at the object's corners. /// Corners } partial class ReportComponentBase { #region Properties /// [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")] public override float Left { get { return base.Left; } set { base.Left = value; } } /// [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")] public override float Top { get { return base.Top; } set { base.Top = value; } } /// [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")] public override float Width { get { return base.Width; } set { base.Width = value; } } /// [TypeConverter("FastReport.TypeConverters.UnitsConverter, FastReport")] public override float Height { get { return base.Height; } set { base.Height = value; } } #endregion #region Private Methods private bool ShouldSerializeHyperlink() { return !Hyperlink.Equals(new Hyperlink(null)); } private bool ShouldSerializeBorder() { return !Border.Equals(new Border()); } private bool ShouldSerializeCursor() { return Cursor != Cursors.Default; } private bool ShouldSerializeFill() { return !(Fill is SolidFill) || !Fill.IsTransparent; } #endregion #region Public Methods /// /// Assigns a format from another, similar object. /// /// Source object to assign a format from. public virtual void AssignFormat(ReportComponentBase source) { Border = source.Border.Clone(); Fill = source.Fill.Clone(); style = source.Style; } /// public override void HandleMouseDown(FRMouseEventArgs e) { base.HandleMouseDown(e); // we will use FSavedBounds to keep the delta while moving the object between bands savedBounds.X = 0; savedBounds.Y = 0; } /// public override void CheckParent(bool immediately) { if (!(Parent is ComponentBase) || !IsSelected || IsAncestor || Dock != DockStyle.None) return; if (immediately || Left < 0 || Left > (Parent as ComponentBase).Width || Top < 0 || Top > (Parent as ComponentBase).Height) { if (HasFlag(Flags.CanChangeParent)) { ObjectCollection list = Page.AllObjects; for (int i = list.Count - 1; i >= 0; i--) { ComponentBase c = list[i] as ComponentBase; if (c == null || c == this || !(c is IParent)) continue; if (c != null && (c as IParent).CanContain(this)) { bool inside; int bandGap = ReportWorkspace.ClassicView && IsDesigning ? BandBase.HeaderSize : 4; if (c is BandBase) inside = AbsTop > c.AbsTop - bandGap && AbsTop < c.AbsBottom - 1; else inside = AbsLeft > c.AbsLeft - 1e-4 && AbsLeft < c.AbsRight - 1e-4 && AbsTop > c.AbsTop - 1e-4 && AbsTop < c.AbsBottom - 1e-4; if (inside) { if (Parent != c) { float saveAbsTop = AbsTop; float saveAbsLeft = AbsLeft; // keep existing offsets if the object is not aligned to the grid float gridXOffset = Converter.DecreasePrecision(Left - (int)(Left / Page.SnapSize.Width + 1e-4) * Page.SnapSize.Width, 2); float gridYOffset = Converter.DecreasePrecision(Top - (int)(Top / Page.SnapSize.Height + 1e-4) * Page.SnapSize.Height, 2); // move the object to the new parent Left = (int)((AbsLeft - c.AbsLeft) / Page.SnapSize.Width + 1e-4) * Page.SnapSize.Width + gridXOffset; Top = (int)((AbsTop - c.AbsTop) / Page.SnapSize.Height + 1e-4) * Page.SnapSize.Height + gridYOffset; Parent = c; // correct the delta savedBounds.X += saveAbsLeft - AbsLeft; savedBounds.Y += saveAbsTop - AbsTop; // check delta if (Math.Abs(savedBounds.X) > Page.SnapSize.Width) { float delta = Math.Sign(savedBounds.X) * Page.SnapSize.Width; Left += delta; savedBounds.X -= delta; } if (Math.Abs(savedBounds.Y) > Page.SnapSize.Height) { float delta = Math.Sign(savedBounds.Y) * Page.SnapSize.Height; Top += delta; savedBounds.Y -= delta * 0.9f; } } break; } } } } else { if (Left < 0) Left = 0; if (Left > (Parent as ComponentBase).Width) Left = (Parent as ComponentBase).Width - 2; if (Top < 0) Top = 0; if (Top > (Parent as ComponentBase).Height) Top = (Parent as ComponentBase).Height - 2; } } } /// /// Draws the object's markers. /// /// Draw event arguments. public void DrawMarkers(FRPaintEventArgs e) { if (IsDesigning && Border.Lines != BorderLines.All) DrawMarkersInternal(e); } private void DrawMarkersInternal(FRPaintEventArgs e) { DrawMarkers(e, ReportWorkspace.MarkerStyle); } /// /// Draws the object's markers. /// /// Draw event arguments. /// Marker style public void DrawMarkers(FRPaintEventArgs e, MarkerStyle style) { IGraphics g = e.Graphics; float _1 = 1 * e.ScaleX; float _3 = 3 * e.ScaleX; if (style == MarkerStyle.Corners) { using (Pen p = new Pen(Color.Black, _1)) { int x = (int)Math.Round(AbsLeft * e.ScaleX); int y = (int)Math.Round(AbsTop * e.ScaleY); int x1 = (int)Math.Round(AbsRight * e.ScaleX); int y1 = (int)Math.Round(AbsBottom * e.ScaleY); g.DrawLine(p, x, y, x + _3, y); g.DrawLine(p, x, y, x, y + _3); g.DrawLine(p, x, y1, x + _3, y1); g.DrawLine(p, x, y1, x, y1 - _3); g.DrawLine(p, x1, y, x1 - _3, y); g.DrawLine(p, x1, y, x1, y + _3); g.DrawLine(p, x1, y1, x1 - _3, y1); g.DrawLine(p, x1, y1, x1, y1 - _3); } } else if (Math.Abs(Width) > 1 || Math.Abs(Height) > 1) { using (Pen p = new Pen(Color.Gainsboro, _1)) { g.DrawRectangle(p, AbsLeft * e.ScaleX, AbsTop * e.ScaleY, Width * e.ScaleX, Height * e.ScaleY); } } } /// /// Draws the intersection indicator. /// /// Draw event arguments. public void DrawIntersection(FRPaintEventArgs e) { RectangleF rect = new RectangleF(AbsBounds.Left * e.ScaleX, AbsBounds.Top * e.ScaleY, AbsBounds.Width * e.ScaleX, AbsBounds.Height * e.ScaleY); // normalize rect in case of diagonal lines if (rect.Width < 0) { rect.X = rect.Right; rect.Width = -rect.Width; } if (rect.Height < 0) { rect.Y = rect.Bottom; rect.Height = -rect.Height; } var backColor = (Fill is SolidFill fill) ? fill.Color : Color.Red; var contrastColor = backColor.GetBrightness() < 0.5f ? Color.White : Color.Black; using (HatchBrush brush = new HatchBrush(HatchStyle.ZigZag, Color.FromArgb(80, contrastColor), Color.Transparent)) { e.Graphics.FillRectangle(brush, rect.Left, rect.Top, rect.Width, rect.Height); } } /// public override ContextMenuBase GetContextMenu() { return new ReportComponentBaseMenu(Report.Designer); } /// public override SizeF GetPreferredSize() { if (Page is ReportPage && (Page as ReportPage).IsImperialUnitsUsed) return new SizeF(Units.Inches * 1, Units.Inches * 0.2f); return base.GetPreferredSize(); } /// public override void OnAfterInsert(InsertFrom source) { if (this is IHasEditor && source == InsertFrom.NewObject && ReportWorkspace.EditAfterInsert) (this as IHasEditor).InvokeEditor(); } #endregion } }