// Copyright (c) Craftwork Games. All rights reserved.
// Licensed under the MIT license.
// See LICENSE file in the project root for full license information.
using System;
using Microsoft.Xna.Framework;
namespace MonoGame.Extended.Graphics;
///
/// Represents a nine-patch texture.
///
///
///
/// A nine-patch texture is a specialized texture object used for rendering scalable graphical assets,
/// particularly user interface (UI) elements.It consists of a single texture region subdivided into nine
/// distinct subregions. When rendered, the four corner subregions remain unscaled, preserving their original
/// dimensions. The top and bottom edge subregions are stretched horizontally, while the left and right edge
/// subregions are stretched vertically. The central subregion is scaled along both axes to fill the desired
/// dimensions.
///
///
/// This approach is highly beneficial for UI components that require dynamic scaling, such as containers for
/// menus, dialog boxes, or other resizable elements. By leveraging the nine-patch texture, these graphical
/// assets can be seamlessly scaled to different sizes while maintaining their visual integrity and preventing
/// undesirable distortions or stretching artifacts.
///
///
public class NinePatch
{
/// The index representing the top-left patch.
public const int TopLeft = 0;
/// The index representing the top-middle patch.
public const int TopMiddle = 1;
/// The index representing the top-right patch.
public const int TopRight = 2;
/// The index representing the middle-left patch.
public const int MiddleLeft = 3;
/// The index representing the middle patch.
public const int Middle = 4;
/// The index representing the middle-right patch.
public const int MiddleRight = 5;
/// The index representing the bottom-left patch.
public const int BottomLeft = 6;
/// The index representing the bottom-middle patch.
public const int BottomMiddle = 7;
/// The index representing the bottom-right patch.
public const int BottomRight = 8;
private readonly Texture2DRegion[] _patches;
///
/// Gets the name assigned to this nine-patch.
///
public string Name { get; }
///
/// The size of the border patches around the middle patch.
///
public Thickness Padding { get; }
///
/// Gets a read-only span of the texture regions that make up the nine-patch.
///
///
/// Elements are in order of top-left, top-middle, top-right, middle-left, middle, middle-right, bottom-left,
/// bottom-middle, and bottom-right.
///
public ReadOnlySpan Patches => _patches;
///
/// Initializes a new instance of the class with the specified patches.
///
///
/// The array should contain the elements in the order of top-left, top-middle,
/// top-right, middle-left, middle, middle-right, bottom-left, bottom-middle, and bottom-right.
///
/// An array of nine objects.
/// Thrown if is null.
///
/// Thrown if does not contain exactly nine elements.
///
public NinePatch(Texture2DRegion[] patches) : this(patches, null) { }
///
/// Initializes a new instance of the class with the specified patches and name.
///
///
/// An array of nine objects.
/// The top, left, bottom and right regions must to be of exactly the same size.
/// Mid patches can be as small as 1x1.
///
///
/// The name of the nine-patch. If null or empty, a default name will be generated based on the texture name of the
/// top-left patch.
///
/// Thrown if is null.
///
/// Thrown if does not contain exactly nine elements.
///
public NinePatch(Texture2DRegion[] patches, string name)
{
ArgumentNullException.ThrowIfNull(patches);
if (patches.Length != 9)
{
throw new ArgumentException($"{nameof(patches)} must contain exactly 9 elements.", nameof(patches));
}
if (string.IsNullOrEmpty(name))
{
name = $"{patches[0].Texture.Name}-nine-patch";
}
_patches = patches;
Size topLeft = patches[NinePatch.TopLeft].OriginalSize;
Size bottomRight = patches[NinePatch.BottomRight].OriginalSize;
Padding = new Thickness(topLeft.Width, topLeft.Height, bottomRight.Width, bottomRight.Height);
Name = name;
}
}