Files
barotrauma-localmods/Quick Interactions/CSharp/Client/CrabUI/Components/CUIMultiButton.cs

146 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Barotrauma;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;
namespace QICrabUI
{
/// <summary>
/// Button with multiple options
/// which are rotating when you click
/// </summary>
public class CUIMultiButton : CUIButton
{
private List<string> options = new List<string>();
/// <summary>
/// Options are just strings
/// </summary>
[CUISerializable]
public IEnumerable<string> Options
{
get => options;
set => options = value.ToList();
}
public event Action<string> OnSelect;
public Action<string> AddOnSelect { set { OnSelect += value; } }
public bool CycleOnClick { get; set; } = true;
public int SelectedIndex
{
get => options.IndexOf(Selected);
set
{
if (options.Count == 0)
{
Selected = "";
}
else
{
Selected = options.ElementAtOrDefault(value % options.Count) ?? "";
}
}
}
[CUISerializable]
public string Selected
{
get => Text;
set
{
Text = value;
OnSelect?.Invoke(value);
}
}
public void Add(string option) => options.Add(option);
public void Remove(string option)
{
int i = options.IndexOf(option);
options.Remove(option);
if (option == Selected) Select(i);
}
public void Select(int i) => SelectedIndex = i;
public void Select(string option) => Selected = option;
public void SelectNext() => SelectedIndex++;
public void SelectPrev() => SelectedIndex--;
public CUIMultiButton() : base()
{
Text = "MultiButton";
OnMouseDown += (e) =>
{
if (CycleOnClick)
{
SelectNext();
if (Command != null) DispatchUp(new CUICommand(Command, Selected));
}
};
}
/// <summary>
/// CUITextBlock DoWrapFor but for all text
/// </summary>
/// <param name="size"></param>
/// <returns></returns>
protected override Vector2 DoWrapFor(Vector2 size)
{
if ((!WrappedForThisSize.HasValue || size == WrappedForThisSize.Value) && !TextPropChanged) return WrappedSize;
TextPropChanged = false;
WrappedForThisSize = size;
if (Vertical) size = new Vector2(0, size.Y);
IEnumerable<string> WrappedTexts;
if (Wrap || Vertical)
{
WrappedText = Font.WrapText(Text, size.X / TextScale - Padding.X * 2).Trim('\n');
WrappedTexts = options.Select(o => Font.WrapText(o, size.X / TextScale - Padding.X * 2).Trim('\n'));
}
else
{
WrappedText = Text;
WrappedTexts = options;
}
IEnumerable<Vector2> RealTextSizes = WrappedTexts.Select(t => Font.MeasureString(t) * TextScale);
float maxX = 0;
float maxY = 0;
foreach (Vector2 s in RealTextSizes)
{
if (s.X > maxX) maxX = s.X;
if (s.Y > maxY) maxY = s.Y;
}
Vector2 MaxTextSize = new Vector2(maxX, maxY);
RealTextSize = Font.MeasureString(WrappedText) * TextScale;
if (WrappedText == "") RealTextSize = new Vector2(0, 0);
RealTextSize = new Vector2((float)Math.Round(RealTextSize.X), (float)Math.Round(RealTextSize.Y));
Vector2 minSize = MaxTextSize + Padding * 2;
if (!Wrap || Vertical)
{
SetForcedMinSize(new CUINullVector2(minSize));
}
WrappedSize = new Vector2(Math.Max(size.X, minSize.X), Math.Max(size.Y, minSize.Y));
return WrappedSize;
}
internal override Vector2 AmIOkWithThisSize(Vector2 size)
{
return DoWrapFor(size);
}
}
}