123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- 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
- {
- /// <summary>
- /// Holds the list of <see cref="ComponentBase"/> objects currently selected in the designer.
- /// </summary>
- /// <remarks>
- /// This class is used by the "Alignment" toolbar. Use methods of this class to perform some
- /// operations on the selected objects.
- /// <para/>Note: after calling any method in this class, call the
- /// <see cref="Designer.SetModified()">Designer.SetModified</see> method to reflect changes.
- /// <para/>Note: this list contains only objects of <see cref="ComponentBase"/> type. If you want to access all
- /// selected objects, use the <see cref="Designer.SelectedObjects"/> property.
- /// </remarks>
- public class SelectedComponents
- {
- private List<ComponentBase> list;
- private Designer designer;
- /// <summary>
- /// Gets the first selected object.
- /// </summary>
- public ComponentBase First
- {
- get { return list.Count > 0 ? list[0] : null; }
- }
- /// <summary>
- /// Gets the number of selected objects.
- /// </summary>
- public int Count
- {
- get { return list.Count; }
- }
- private List<ComponentBase> MoveList
- {
- get { return list.FindAll(CanMove); }
- }
- private List<ComponentBase> 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);
- }
- }
- }
- /// <summary>
- /// Aligns left edges of the selected objects.
- /// </summary>
- public void AlignLeft(object sender = null, EventArgs e = null)
- {
- foreach (ComponentBase c in MoveList)
- {
- c.Left = First.Left;
- }
- designer.SetModified();
- }
- /// <summary>
- /// Aligns right edges of the selected objects.
- /// </summary>
- public void AlignRight(object sender = null, EventArgs e = null)
- {
- foreach (ComponentBase c in MoveList)
- {
- c.Left = First.Right - c.Width;
- }
- designer.SetModified();
- }
- /// <summary>
- /// Aligns centers of the selected objects.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Aligns top edges of the selected objects.
- /// </summary>
- public void AlignTop(object sender = null, EventArgs e = null)
- {
- foreach (ComponentBase c in MoveList)
- {
- c.Top = First.Top;
- }
- designer.SetModified();
- }
- /// <summary>
- /// Aligns bottom edges of the selected objects.
- /// </summary>
- public void AlignBottom(object sender = null, EventArgs e = null)
- {
- foreach (ComponentBase c in MoveList)
- {
- c.Top = First.Bottom - c.Height;
- }
- designer.SetModified();
- }
- /// <summary>
- /// Aligns middles of the selected objects.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Makes the selected objects the same width as the first object.
- /// </summary>
- public void SameWidth(object sender = null, EventArgs e = null)
- {
- foreach (ComponentBase c in ResizeList)
- {
- c.Width = First.Width;
- }
- designer.SetModified();
- }
- /// <summary>
- /// Makes the selected objects the same height as the first object.
- /// </summary>
- public void SameHeight(object sender = null, EventArgs e = null)
- {
- foreach (ComponentBase c in ResizeList)
- {
- c.Height = First.Height;
- }
- designer.SetModified();
- }
- /// <summary>
- /// Makes the selected objects the same size as the first object.
- /// </summary>
- public void SameSize(object sender = null, EventArgs e = null)
- {
- foreach (ComponentBase c in ResizeList)
- {
- c.Width = First.Width;
- c.Height = First.Height;
- }
- designer.SetModified();
- }
- /// <summary>
- /// Centers the selected objects horizontally.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Centers the selected objects vertically.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Aligns the selected objects to the grid.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Adjusts the size of selected objects to the grid.
- /// </summary>
- 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();
- }
- /// <summary>
- /// Spaces the selected objects horizontally.
- /// </summary>
- public void SpaceHorizontally(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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();
- }
- /// <summary>
- /// Increases horizontal spacing between the selected objects.
- /// </summary>
- public void IncreaseHorizontalSpacing(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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();
- }
- /// <summary>
- /// Decreases horizontal spacing between the selected objects.
- /// </summary>
- public void DecreaseHorizontalSpacing(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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();
- }
- /// <summary>
- /// Removes horizontal spacing between the selected objects.
- /// </summary>
- public void RemoveHorizontalSpacing(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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();
- }
- /// <summary>
- /// Spaces the selected objects vertically.
- /// </summary>
- public void SpaceVertically(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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();
- }
- /// <summary>
- /// Increases vertical spacing between the selected objects.
- /// </summary>
- public void IncreaseVerticalSpacing(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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();
- }
- /// <summary>
- /// Decreases vertical spacing between the selected objects.
- /// </summary>
- public void DecreaseVerticalSpacing(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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();
- }
- /// <summary>
- /// Removes vertical spacing between the selected objects.
- /// </summary>
- public void RemoveVerticalSpacing(object sender = null, EventArgs e = null)
- {
- List<ObjItem> list = new List<ObjItem>();
- 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<ComponentBase>();
- }
- 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;
- }
- }
- }
- }
|