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
}
}