123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- using FastReport;
- using FastReport.Utils;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Windows;
- using System.Windows.Forms;
- using HorizontalAlignment = System.Windows.HorizontalAlignment;
- namespace InABox.Wpf.Reports.CustomObjects
- {
- public enum DisplayType
- {
- /// <summary>
- /// Display as a grid of images
- /// </summary>
- Grid,
- /// <summary>
- /// Display as a list, which breaks onto new rows if necessary
- /// </summary>
- List
- }
- public abstract class MultiItemObject : ReportComponentBase
- {
- [Category("Layout")]
- public Padding Padding { get; set; }
- [Category("Layout")]
- public float Gap { get; set; }
- /// <summary>
- /// Sets the number of columns in the object. If it is 0, generates the number automatically. Ignored if <see cref="DisplayType"/> is <see cref="DisplayType.List"/>.
- /// </summary>
- [Category("Layout")]
- public int Columns { get; set; }
- /// <summary>
- /// Sets the number of rows in the object. If it is 0, generates the number automatically.
- /// Ignored if <see cref="DisplayType"/> is <see cref="DisplayType.Grid"/>
- /// </summary>
- [Category("Layout")]
- public int Rows { get; set; }
- /// <summary>
- /// If <see cref="ReportComponentBase.CanGrow"/> is <c>true</c>, or <see cref="Rows"/> is 0 and not ignored,
- /// sets the height of the row. Otherwise, this property is ignored.
- /// </summary>
- [Category("Layout")]
- public float RowHeight { get; set; }
- /// <summary>
- /// The horizontal alignment of the images within their cells, if their width does not fill the cell.
- /// Ignored if <see cref="DisplayType"/> is <see cref="DisplayType.List"/>.
- /// </summary>
- [Category("Layout")]
- public HorizontalAlignment HorizontalAlignment { get; set; }
- /// <summary>
- /// The vertical alignment of the images within their cells, if their height does not fill the cell.
- /// Ignored if <see cref="DisplayType"/> is <see cref="DisplayType.List"/>.
- /// </summary>
- [Category("Layout")]
- public VerticalAlignment VerticalAlignment { get; set; }
- /// <summary>
- /// The display type of the image object
- /// </summary>
- [Category("Layout")]
- public DisplayType DisplayType { get; set; }
- protected interface Item
- {
- float Width { get; }
- float Height { get; }
- }
- public MultiItemObject()
- {
- Padding = Padding.Empty;
- Columns = 3;
- Rows = 1;
- RowHeight = 100;
- CanGrow = true;
- HorizontalAlignment = HorizontalAlignment.Center;
- VerticalAlignment = VerticalAlignment.Top;
- DisplayType = DisplayType.Grid;
- }
- #region Serialization
- public override void Serialize(FRWriter writer)
- {
- base.Serialize(writer);
- MultiItemObject c = writer.DiffObject as MultiItemObject;
- if (Padding != c.Padding)
- writer.WriteValue("Padding", Padding);
- if (Gap != c.Gap)
- writer.WriteValue("Gap", Gap);
- if (Columns != c.Columns)
- writer.WriteValue("Columns", Columns);
- if (Rows != c.Rows)
- writer.WriteValue("Rows", Rows);
- if (RowHeight != c.RowHeight)
- writer.WriteValue("RowHeight", RowHeight);
- if (HorizontalAlignment != c.HorizontalAlignment)
- writer.WriteValue("HorizontalAlignment", HorizontalAlignment);
- if (VerticalAlignment != c.VerticalAlignment)
- writer.WriteValue("VerticalAlignment", VerticalAlignment);
- if (DisplayType != c.DisplayType)
- writer.WriteValue("DisplayType", DisplayType);
- }
- #endregion
- public override void Assign(Base source)
- {
- base.Assign(source);
- if (source is MultiItemObject src)
- {
- Padding = src.Padding;
- Gap = src.Gap;
- Columns = src.Columns;
- Rows = src.Rows;
- RowHeight = src.RowHeight;
- HorizontalAlignment = src.HorizontalAlignment;
- VerticalAlignment = src.VerticalAlignment;
- DisplayType = src.DisplayType;
- }
- }
- #region Drawing
- protected abstract IList<Item>? LoadItems();
- protected abstract void DrawItem(FRPaintEventArgs e, Item item, float x, float y, float w, float h);
- public override void Draw(FRPaintEventArgs e)
- {
- base.Draw(e);
- DrawItems(e);
- DrawMarkers(e);
- Border.Draw(e, new RectangleF(AbsLeft, AbsTop, Width, Height));
- //DrawDesign(e);
- }
- private void DrawGrid(FRPaintEventArgs e, IList<Item> items)
- {
- IGraphics g = e.Graphics;
- float drawLeft = AbsLeft + Padding.Left;
- float drawTop = AbsTop + Padding.Top;
- float drawWidth = Width - Padding.Horizontal;
- float drawHeight = Height - Padding.Vertical;
- int numColumns, numRows;
- if (Columns == 0)
- {
- double rows;
- if (CanGrow)
- {
- rows = Math.Ceiling(Math.Sqrt(items.Count));
- numRows = Convert.ToInt32(rows);
- drawHeight = numRows * RowHeight;
- numColumns = Convert.ToInt32(Math.Ceiling(items.Count / rows));
- }
- else
- {
- var cols = Math.Ceiling(Math.Sqrt(items.Count));
- numColumns = Convert.ToInt32(cols);
- numRows = Convert.ToInt32(Math.Ceiling(Math.Ceiling(items.Count / cols)));
- }
- }
- else
- {
- numColumns = Columns;
- numRows = Convert.ToInt32(Math.Ceiling(items.Count / (double)Columns));
- if (CanGrow)
- {
- drawHeight = numRows * RowHeight;
- }
- }
- Width = drawWidth + Padding.Horizontal;
- Height = drawHeight + Padding.Vertical;
- RectangleF drawRect = new RectangleF(drawLeft * e.ScaleX, drawTop * e.ScaleY, drawWidth * e.ScaleX, drawHeight * e.ScaleY);
- //if (Config.IsRunningOnMono) // strange behavior of mono - we need to reset clip before we set new one
- g.ResetClip();
- g.SetClip(drawRect);
- Report report = Report;
- if (report != null && report.SmoothGraphics)
- {
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.SmoothingMode = SmoothingMode.AntiAlias;
- }
- var imageWidth = (drawWidth + Gap) / numColumns - Gap;
- var imageHeight = CanGrow ? RowHeight : (drawHeight + Gap) / numRows - Gap;
- int column = 0;
- int row = 0;
- for (int i = 0; i < items.Count; i++)
- {
- var image = items[i];
- var aspectRatio = image.Width / image.Height;
- float width, height;
- if (aspectRatio <= imageWidth / imageHeight)
- {
- height = imageHeight;
- width = height * aspectRatio;
- }
- else
- {
- width = imageWidth;
- height = width / aspectRatio;
- }
- float x = column * (imageWidth + Gap) + Padding.Left + drawLeft;
- float y = row * (imageHeight + Gap) + Padding.Top + drawTop;
- switch (HorizontalAlignment)
- {
- case HorizontalAlignment.Center:
- x += imageWidth / 2 - width / 2;
- break;
- case HorizontalAlignment.Right:
- x += imageWidth - width;
- break;
- case HorizontalAlignment.Stretch:
- width = imageWidth;
- break;
- }
- switch (VerticalAlignment)
- {
- case VerticalAlignment.Center:
- y += imageHeight / 2 - height / 2;
- break;
- case VerticalAlignment.Bottom:
- y += imageHeight - height;
- break;
- case VerticalAlignment.Stretch:
- height = imageHeight;
- break;
- }
- DrawItem(e, image, x, y, width, height);
- if (++column >= numColumns)
- {
- column = 0;
- row++;
- }
- }
- }
- private void DrawList(FRPaintEventArgs e, IList<Item> items)
- {
- IGraphics g = e.Graphics;
- float drawLeft = AbsLeft + Padding.Left;
- float drawTop = AbsTop + Padding.Top;
- float drawWidth = Width - Padding.Horizontal;
- float drawHeight = Height - Padding.Vertical;
- float rowHeight;
- if (Rows == 0)
- {
- rowHeight = RowHeight;
- }
- else
- {
- if (CanGrow)
- {
- rowHeight = RowHeight;
- }
- else
- {
- rowHeight = drawHeight / Rows;
- }
- }
- RectangleF drawRect = new RectangleF(drawLeft * e.ScaleX, drawTop * e.ScaleY, drawWidth * e.ScaleX, drawHeight * e.ScaleY);
- //if (Config.IsRunningOnMono) // strange behavior of mono - we need to reset clip before we set new one
- g.ResetClip();
- g.SetClip(drawRect);
- Report report = Report;
- if (report != null && report.SmoothGraphics)
- {
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.SmoothingMode = SmoothingMode.AntiAlias;
- }
- float pointX = 0f;
- float pointY = 0f;
- for (int i = 0; i < items.Count; i++)
- {
- var image = items[i];
- var aspectRatio = image.Width / image.Height;
- float height = rowHeight;
- float width = rowHeight * aspectRatio;
- float x;
- if (pointX + width > drawWidth)
- {
- if (pointX > 0.001f)
- {
- pointY += rowHeight + Gap;
- }
- pointX = 0;
- x = 0;
- }
- else
- {
- x = pointX;
- }
- float y = pointY;
- x += Padding.Left + drawLeft;
- y += Padding.Top + drawTop;
- DrawItem(e, image, x * e.ScaleX, y * e.ScaleY, width * e.ScaleX, height * e.ScaleY);
- pointX += width + Gap;
- }
- float totalHeight = pointY + rowHeight + Padding.Vertical;
- if ((CanGrow && totalHeight > Height) || (CanShrink && totalHeight < Height))
- {
- Height = totalHeight;
- }
- }
- protected void DrawItems(FRPaintEventArgs e)
- {
- IGraphics g = e.Graphics;
- var items = LoadItems();
- if (items == null)
- {
- return;
- }
- IGraphicsState state = g.Save();
- try
- {
- switch (DisplayType)
- {
- case DisplayType.Grid:
- DrawGrid(e, items);
- break;
- case DisplayType.List:
- DrawList(e, items);
- break;
- }
- }
- finally
- {
- g.Restore(state);
- }
- if (IsPrinting)
- {
- //DisposeImage();
- }
- }
- #endregion
- }
- }
|