mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
331 lines
9.1 KiB
C#
331 lines
9.1 KiB
C#
using System;
|
|
using SS14.Client.Graphics;
|
|
using SS14.Client.Graphics.Drawing;
|
|
using SS14.Client.Utility;
|
|
using SS14.Shared.Maths;
|
|
|
|
namespace SS14.Client.UserInterface.Controls
|
|
{
|
|
[ControlWrap(typeof(Godot.Button))]
|
|
public class Button : BaseButton
|
|
{
|
|
public const string StylePropertyStyleBox = "stylebox";
|
|
public const string StylePseudoClassNormal = "normal";
|
|
public const string StylePseudoClassHover = "hover";
|
|
public const string StylePseudoClassDisabled = "disabled";
|
|
public const string StylePseudoClassPressed = "pressed";
|
|
private int? _textWidthCache;
|
|
|
|
public Button()
|
|
{
|
|
}
|
|
|
|
public Button(string name) : base(name)
|
|
{
|
|
}
|
|
|
|
internal Button(Godot.Button button) : base(button)
|
|
{
|
|
}
|
|
|
|
private protected override Godot.Control SpawnSceneControl()
|
|
{
|
|
return new Godot.Button();
|
|
}
|
|
|
|
private AlignMode _textAlign;
|
|
public AlignMode TextAlign
|
|
{
|
|
get => GameController.OnGodot ? (AlignMode)SceneControl.Get("align") : _textAlign;
|
|
set
|
|
{
|
|
if (GameController.OnGodot)
|
|
{
|
|
SceneControl.Set("align", (Godot.Button.TextAlign) value);
|
|
}
|
|
else
|
|
{
|
|
_textAlign = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool _clipText;
|
|
public bool ClipText
|
|
{
|
|
get => GameController.OnGodot ? (bool)SceneControl.Get("clip_text") : _clipText;
|
|
set
|
|
{
|
|
if (GameController.OnGodot)
|
|
{
|
|
SceneControl.Set("clip_text", value);
|
|
}
|
|
else
|
|
{
|
|
_clipText = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
private string _text;
|
|
public string Text
|
|
{
|
|
get => GameController.OnGodot ? (string)SceneControl.Get("text") : _text;
|
|
set
|
|
{
|
|
if (GameController.OnGodot)
|
|
{
|
|
SceneControl.Set("text", value);
|
|
}
|
|
else
|
|
{
|
|
_text = value;
|
|
_textWidthCache = null;
|
|
MinimumSizeChanged();
|
|
}
|
|
}
|
|
}
|
|
|
|
private StyleBox ActualStyleBox
|
|
{
|
|
get
|
|
{
|
|
if (TryGetStyleProperty(StylePropertyStyleBox, out StyleBox box))
|
|
{
|
|
return box;
|
|
}
|
|
|
|
return UserInterfaceManager.ThemeDefaults.ButtonStyle;
|
|
}
|
|
}
|
|
|
|
public Font ActualFont
|
|
{
|
|
get
|
|
{
|
|
if (TryGetStyleProperty("font", out Font font))
|
|
{
|
|
return font;
|
|
}
|
|
|
|
return UserInterfaceManager.ThemeDefaults.DefaultFont;
|
|
}
|
|
}
|
|
|
|
public Color ActualFontColor
|
|
{
|
|
get
|
|
{
|
|
if (TryGetStyleProperty("font-color", out Color fontColor))
|
|
{
|
|
return fontColor;
|
|
}
|
|
|
|
return _fontColorOverride ?? Color.White;
|
|
}
|
|
}
|
|
|
|
private Color? _fontColorOverride;
|
|
|
|
public Color? FontColorOverride
|
|
{
|
|
get => _fontColorOverride ?? GetColorOverride("font_color");
|
|
set => SetColorOverride("font_color", _fontColorOverride = value);
|
|
}
|
|
|
|
private Color? _fontColorDisabledOverride;
|
|
|
|
public Color? FontColorDisabledOverride
|
|
{
|
|
get => _fontColorDisabledOverride ?? GetColorOverride("font_color_disabled");
|
|
set => SetColorOverride("font_color_disabled", _fontColorDisabledOverride = value);
|
|
}
|
|
|
|
private Color? _fontColorHoverOverride;
|
|
|
|
public Color? FontColorHoverOverride
|
|
{
|
|
get => _fontColorHoverOverride ?? GetColorOverride("font_color_hover");
|
|
set => SetColorOverride("font_color_hover", _fontColorHoverOverride = value);
|
|
}
|
|
|
|
private Color? _fontColorPressedOverride;
|
|
|
|
public Color? FontColorPressedOverride
|
|
{
|
|
get => _fontColorPressedOverride ?? GetColorOverride("font_color_pressed");
|
|
set => SetColorOverride("font_color_pressed", _fontColorPressedOverride = value);
|
|
}
|
|
|
|
public enum AlignMode
|
|
{
|
|
Left = 0,
|
|
Center = 1,
|
|
Right = 2,
|
|
}
|
|
|
|
protected internal override void Draw(DrawingHandleScreen handle)
|
|
{
|
|
base.Draw(handle);
|
|
|
|
if (GameController.OnGodot)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var uiTheme = UserInterfaceManager.ThemeDefaults;
|
|
var style = ActualStyleBox;
|
|
var font = ActualFont;
|
|
var drawBox = SizeBox;
|
|
style.Draw(handle, drawBox);
|
|
|
|
if (_text == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var width = _ensureWidthCache();
|
|
var contentBox = style.GetContentBox(drawBox);
|
|
int drawOffset;
|
|
|
|
switch (TextAlign)
|
|
{
|
|
case AlignMode.Left:
|
|
drawOffset = 0;
|
|
break;
|
|
case AlignMode.Center:
|
|
drawOffset = (int)(contentBox.Width - width) / 2;
|
|
break;
|
|
case AlignMode.Right:
|
|
drawOffset = (int)(contentBox.Width - width);
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
|
|
var color = ActualFontColor;
|
|
var offsetY = (int) (contentBox.Height - font.Height) / 2;
|
|
var baseLine = new Vector2i(drawOffset, offsetY+font.Ascent) + contentBox.TopLeft;
|
|
|
|
foreach (var chr in _text)
|
|
{
|
|
if (!font.TryGetCharMetrics(chr, out var metrics))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!(ClipText && (baseLine.X < contentBox.Left || baseLine.X + metrics.Advance > contentBox.Right)))
|
|
{
|
|
font.DrawChar(handle, chr, baseLine, color);
|
|
}
|
|
baseLine += (metrics.Advance, 0);
|
|
}
|
|
}
|
|
|
|
protected override Vector2 CalculateMinimumSize()
|
|
{
|
|
if (GameController.OnGodot)
|
|
{
|
|
return base.CalculateMinimumSize();
|
|
}
|
|
|
|
var uiTheme = UserInterfaceManager.ThemeDefaults;
|
|
var style = ActualStyleBox;
|
|
var font = ActualFont;
|
|
|
|
var fontHeight = font.Height;
|
|
|
|
if (ClipText)
|
|
{
|
|
return (0, fontHeight) + style.MinimumSize;
|
|
}
|
|
|
|
var width = _ensureWidthCache();
|
|
|
|
return new Vector2(width, fontHeight) + style.MinimumSize;
|
|
}
|
|
|
|
protected override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
DrawModeChanged();
|
|
}
|
|
|
|
protected override void DrawModeChanged()
|
|
{
|
|
switch (DrawMode)
|
|
{
|
|
case DrawModeEnum.Normal:
|
|
StylePseudoClass = StylePseudoClassNormal;
|
|
break;
|
|
case DrawModeEnum.Pressed:
|
|
StylePseudoClass = StylePseudoClassPressed;
|
|
break;
|
|
case DrawModeEnum.Hover:
|
|
StylePseudoClass = StylePseudoClassHover;
|
|
break;
|
|
case DrawModeEnum.Disabled:
|
|
StylePseudoClass = StylePseudoClassDisabled;
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
private int _ensureWidthCache()
|
|
{
|
|
if (_textWidthCache.HasValue)
|
|
{
|
|
return _textWidthCache.Value;
|
|
}
|
|
|
|
if (_text == null)
|
|
{
|
|
_textWidthCache = 0;
|
|
return 0;
|
|
}
|
|
|
|
var uiTheme = UserInterfaceManager.ThemeDefaults;
|
|
var font = ActualFont;
|
|
|
|
var textWidth = 0;
|
|
foreach (var chr in _text)
|
|
{
|
|
var metrics = font.GetCharMetrics(chr);
|
|
if (metrics == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
textWidth += metrics.Value.Advance;
|
|
}
|
|
|
|
_textWidthCache = textWidth;
|
|
return textWidth;
|
|
}
|
|
|
|
protected override void StylePropertiesChanged()
|
|
{
|
|
_textWidthCache = null;
|
|
|
|
base.StylePropertiesChanged();
|
|
}
|
|
|
|
private protected override void SetGodotProperty(string property, object value, GodotAssetScene context)
|
|
{
|
|
base.SetGodotProperty(property, value, context);
|
|
|
|
if (property == "text")
|
|
{
|
|
Text = (string) value;
|
|
}
|
|
|
|
if (property == "align")
|
|
{
|
|
TextAlign = (AlignMode) (long) value;
|
|
}
|
|
}
|
|
}
|
|
}
|