using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using FastReport.Design;
using System.Drawing;
using System.Collections;
using FastReport.Utils;
namespace FastReport
{
///
/// Holds the list of objects currently selected in the designer.
///
///
/// This class is used by the "Alignment" toolbar. Use methods of this class to perform some
/// operations on the selected objects.
/// Note: after calling any method in this class, call the
/// Designer.SetModified method to reflect changes.
/// Note: this list contains only objects of type. If you want to access all
/// selected objects, use the property.
///
public class SelectedComponents
{
private List list;
private Designer designer;
///
/// Gets the first selected object.
///
public ComponentBase First
{
get { return list.Count > 0 ? list[0] : null; }
}
///
/// Gets the number of selected objects.
///
public int Count
{
get { return list.Count; }
}
private List MoveList
{
get { return list.FindAll(CanMove); }
}
private List ResizeList
{
get { return list.FindAll(CanResize); }
}
private bool CanMove(ComponentBase c)
{
return c.HasFlag(Flags.CanMove) && !c.HasRestriction(Restrictions.DontMove);
}
private bool CanResize(ComponentBase c)
{
return c.HasFlag(Flags.CanResize) && !c.HasRestriction(Restrictions.DontResize);
}
internal void Update()
{
list.Clear();
if (designer.SelectedObjects != null)
{
foreach (Base c in designer.SelectedObjects)
{
if (c is ComponentBase)
list.Add(c as ComponentBase);
}
}
}
///
/// Aligns left edges of the selected objects.
///
public void AlignLeft(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in MoveList)
{
c.Left = First.Left;
}
designer.SetModified();
}
///
/// Aligns right edges of the selected objects.
///
public void AlignRight(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in MoveList)
{
c.Left = First.Right - c.Width;
}
designer.SetModified();
}
///
/// Aligns centers of the selected objects.
///
public void AlignCenter(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in MoveList)
{
c.Left = First.Left + (First.Width - c.Width) / 2;
}
designer.SetModified();
}
///
/// Aligns top edges of the selected objects.
///
public void AlignTop(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in MoveList)
{
c.Top = First.Top;
}
designer.SetModified();
}
///
/// Aligns bottom edges of the selected objects.
///
public void AlignBottom(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in MoveList)
{
c.Top = First.Bottom - c.Height;
}
designer.SetModified();
}
///
/// Aligns middles of the selected objects.
///
public void AlignMiddle(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in MoveList)
{
c.Top = First.Top + (First.Height - c.Height) / 2;
}
designer.SetModified();
}
///
/// Makes the selected objects the same width as the first object.
///
public void SameWidth(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in ResizeList)
{
c.Width = First.Width;
}
designer.SetModified();
}
///
/// Makes the selected objects the same height as the first object.
///
public void SameHeight(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in ResizeList)
{
c.Height = First.Height;
}
designer.SetModified();
}
///
/// Makes the selected objects the same size as the first object.
///
public void SameSize(object sender = null, EventArgs e = null)
{
foreach (ComponentBase c in ResizeList)
{
c.Width = First.Width;
c.Height = First.Height;
}
designer.SetModified();
}
///
/// Centers the selected objects horizontally.
///
public void CenterHorizontally(object sender = null, EventArgs e = null)
{
if (!(First.Parent is ComponentBase))
return;
float min = 100000;
float max = -100000;
foreach (ComponentBase c in MoveList)
{
if (c.Left < min)
min = c.Left;
if (c.Right > max)
max = c.Right;
}
float parentWidth = (First.Parent as ComponentBase).ClientSize.Width;
float dx = (parentWidth - (max - min)) / 2;
foreach (ComponentBase c in MoveList)
{
c.Left += dx - min;
}
designer.SetModified();
}
///
/// Centers the selected objects vertically.
///
public void CenterVertically(object sender = null, EventArgs e = null)
{
if (!(First.Parent is ComponentBase))
return;
float min = 100000;
float max = -100000;
foreach (ComponentBase c in MoveList)
{
if (c.Top < min)
min = c.Top;
if (c.Bottom > max)
max = c.Bottom;
}
float parentHeight = (First.Parent as ComponentBase).ClientSize.Height;
float dy = (parentHeight - (max - min)) / 2;
foreach (ComponentBase c in MoveList)
{
c.Top += dy - min;
}
designer.SetModified();
}
///
/// Aligns the selected objects to the grid.
///
public void AlignToGrid(object sender = null, EventArgs e = null)
{
SizeF snapSize = First.Page.SnapSize;
foreach (ComponentBase c in MoveList)
{
c.Left = (int)Math.Round(c.Left / snapSize.Width) * snapSize.Width;
c.Top = (int)Math.Round(c.Top / snapSize.Height) * snapSize.Height;
}
designer.SetModified();
}
///
/// Adjusts the size of selected objects to the grid.
///
public void SizeToGrid(object sender = null, EventArgs e = null)
{
SizeF snapSize = First.Page.SnapSize;
foreach (ComponentBase c in list)
{
if (c.HasFlag(Flags.CanMove) && !c.HasRestriction(Restrictions.DontMove))
{
c.Left = (int)Math.Round(c.Left / snapSize.Width) * snapSize.Width;
c.Top = (int)Math.Round(c.Top / snapSize.Height) * snapSize.Height;
}
if (c.HasFlag(Flags.CanResize) && !c.HasRestriction(Restrictions.DontResize))
{
c.Width = (int)Math.Round(c.Width / snapSize.Width) * snapSize.Width;
c.Height = (int)Math.Round(c.Height / snapSize.Height) * snapSize.Height;
}
}
designer.SetModified();
}
///
/// Spaces the selected objects horizontally.
///
public void SpaceHorizontally(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Left, c));
}
list.Sort();
if (list.Count < 3)
return;
float dx = list[list.Count - 1].obj.Left - list[0].obj.Right;
float actualSize = 0;
for (int i = 1; i < list.Count - 1; i++)
{
actualSize += list[i].obj.Width;
}
float sizeBetweenObj = actualSize < dx ? (dx - actualSize) / (list.Count - 1) : 0;
float count = sizeBetweenObj > 0 ? list.Count - 1 : list.Count;
for (int i = 1; i < count; i++)
{
list[i].obj.Left = list[i - 1].obj.Right + sizeBetweenObj;
}
designer.SetModified();
}
///
/// Increases horizontal spacing between the selected objects.
///
public void IncreaseHorizontalSpacing(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Left, c));
}
list.Sort();
SizeF snapSize = First.Page.SnapSize;
for (int i = 1; i < list.Count; i++)
{
list[i].obj.Left += snapSize.Width * i;
}
designer.SetModified();
}
///
/// Decreases horizontal spacing between the selected objects.
///
public void DecreaseHorizontalSpacing(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Left, c));
}
list.Sort();
SizeF snapSize = First.Page.SnapSize;
for (int i = 1; i < list.Count; i++)
{
list[i].obj.Left -= snapSize.Width * i;
}
designer.SetModified();
}
///
/// Removes horizontal spacing between the selected objects.
///
public void RemoveHorizontalSpacing(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Left, c));
}
list.Sort();
for (int i = 1; i < list.Count; i++)
{
list[i].obj.Left = list[i - 1].obj.Right;
}
designer.SetModified();
}
///
/// Spaces the selected objects vertically.
///
public void SpaceVertically(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Top, c));
}
list.Sort();
if (list.Count < 3)
return;
float dy = list[list.Count - 1].obj.Top - list[0].obj.Bottom;
float actualSize = 0;
for (int i = 1; i < list.Count - 1; i++)
{
actualSize += list[i].obj.Height;
}
float sizeBetweenObj = actualSize < dy ? (dy - actualSize) / (list.Count - 1) : 0;
float count = sizeBetweenObj > 0 ? list.Count - 1 : list.Count;
for (int i = 1; i < count; i++)
{
list[i].obj.Top = list[i - 1].obj.Bottom + sizeBetweenObj;
}
designer.SetModified();
}
///
/// Increases vertical spacing between the selected objects.
///
public void IncreaseVerticalSpacing(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Top, c));
}
list.Sort();
SizeF snapSize = First.Page.SnapSize;
for (int i = 1; i < list.Count; i++)
{
list[i].obj.Top += snapSize.Height * i;
}
designer.SetModified();
}
///
/// Decreases vertical spacing between the selected objects.
///
public void DecreaseVerticalSpacing(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Top, c));
}
list.Sort();
SizeF snapSize = First.Page.SnapSize;
for (int i = 1; i < list.Count; i++)
{
list[i].obj.Top -= snapSize.Height * i;
}
designer.SetModified();
}
///
/// Removes vertical spacing between the selected objects.
///
public void RemoveVerticalSpacing(object sender = null, EventArgs e = null)
{
List list = new List();
foreach (ComponentBase c in MoveList)
{
list.Add(new ObjItem(c.Left, c));
}
list.Sort();
for (int i = 1; i < list.Count; i++)
{
list[i].obj.Top = list[i - 1].obj.Bottom;
}
designer.SetModified();
}
internal SelectedComponents(Designer designer)
{
this.designer = designer;
list = new List();
}
private class ObjItem : IComparable
{
public float coord;
public ComponentBase obj;
public int CompareTo(object obj)
{
if (coord < (obj as ObjItem).coord)
return -1;
if (coord > (obj as ObjItem).coord)
return 1;
return 0;
}
public ObjItem(float coord, ComponentBase obj)
{
this.coord = coord;
this.obj = obj;
}
}
}
}