ShapePresets.cs
//
// This code is part of GrapeCity Documents for Word samples.
// Copyright (c) GrapeCity, Inc. All rights reserved.
//
using System;
using System.IO;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using GrapeCity.Documents.Word;

namespace GcWordWeb.Samples
{
    // This sample demonstrates all available shape presets
    // that specify a shape's fill and outline.
    public class ShapePresets
    {
        public GcWordDocument CreateDocx()
        {
            var presets = typeof(ShapePreset).GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static)
                .Where(p_ => p_.FieldType == typeof(ShapePreset));
            int presetsCount = presets.Count();

            var doc = new GcWordDocument();

            // We will apply each preset to 2 consecutive shapes:
            var shapes = AddGeometryTypes(doc, new SizeF(100, 100), presetsCount * 2, true);

            doc.Body.Paragraphs.Insert($"Shape presets ({presetsCount})", doc.Styles[BuiltInStyleId.Title], InsertLocation.Start);

            if (shapes.Count() > presetsCount * 2)
                shapes.Skip(presetsCount).ToList().ForEach(s_ => s_.Delete());

            int presetIdx = 0;
            int flop = 0;
            foreach (var s in shapes)
            {
                var shape = s.GetRange().CopyTo(s.GetRange(), InsertLocation.After).ParentObject as Shape;
                var preset = presets.ElementAt((flop++ % 2 == 0) ? presetIdx : presetIdx++);
                shape.ApplyPreset((ShapePreset)preset.GetValue(null));
                shape.GetRange().Runs.Insert($"{preset.Name}:", InsertLocation.Before);
                shape.GetRange().Runs.Insert("\n", InsertLocation.After);
                //shape.GetRange().Texts.AddBreak(BreakType.TextWrapping);
            }

            return doc;
        }

        /// <summary>
        /// Adds a paragraph with a single empty run, and adds a shape for each available GeometryType.
        /// The fill and line colors of the shapes are varied.
        /// </summary>
        /// <param name="doc">The target document.</param>
        /// <param name="size">The size of shapes to create.</param>
        /// <param name="count">The maximum number of shapes to create (-1 for no limit).</param>
        /// <param name="skipUnfillable">Add only shapes that support fills.</param>
        /// <param name="noNames">Do not add geometry names as shape text frames.</param>
        /// <returns>The list of shapes added to the document.</returns>
        private static List<Shape> AddGeometryTypes(GcWordDocument doc, SizeF size, int count = -1, bool skipUnfillable = false, bool noNames = false)
        {
            // Line and fill colors:
            Color[] lines = new Color[] { Color.Blue, Color.SlateBlue, Color.Navy, Color.Indigo, Color.BlueViolet, Color.CadetBlue, };
            int line = 0;
            Color[] fills = new Color[] { Color.MistyRose, Color.BurlyWood, Color.Coral, Color.Goldenrod, Color.Orchid, Color.Orange, Color.PaleVioletRed, };
            int fill = 0;

            // The supported geometry types:
            var geoms = Enum.GetValues(typeof(GeometryType));

            // Add a paragraph and a run where the shapes will live:
            doc.Body.Paragraphs.Add("");

            var shapes = new List<Shape>();
            foreach (GeometryType g in geoms)
            {
                // Line geometries do not support fills:
                if (skipUnfillable && g.IsLineGeometry())
                    continue;

                if (count-- == 0)
                    break;

                float w = size.Width, h = size.Height;
                var shape = doc.Body.Runs.Last.GetRange().Shapes.Add(w, h, g);
                if (!g.IsLineGeometry())
                {
                    shape.Fill.Type = FillType.Solid;
                    shape.Fill.SolidFill.RGB = fills[fill < fills.Length - 1 ? ++fill : (fill = 0)];
                }
                shape.Line.Width = 3;
                shape.Line.Fill.SolidFill.RGB = lines[line < lines.Length - 1 ? ++line : (line = 0)];
                if (!noNames && g.TextFrameSupported())
                    shape.AddTextFrame(g.ToString());
                shape.AlternativeText = $"This is shape {g}";
                shape.Size.EffectExtent.AllEdges = 8;
                shapes.Add(shape);
            }
            return shapes;
        }
    }
}