2022-12-21 18:54:25 +01:00
using System ;
2019-08-09 22:04:26 +02:00
using Microsoft.Xna.Framework ;
using Microsoft.Xna.Framework.Graphics ;
2022-04-25 15:25:58 +02:00
using MLEM.Graphics ;
2021-10-30 15:33:38 +02:00
using MLEM.Misc ;
2019-08-09 22:04:26 +02:00
using MLEM.Textures ;
2019-08-10 21:37:10 +02:00
using MLEM.Ui.Style ;
2019-08-09 22:04:26 +02:00
namespace MLEM.Ui.Elements {
2020-05-22 17:02:24 +02:00
/// <summary>
/// A button element for use inside of a <see cref="UiSystem"/>.
/// A button element can be pressed, hovered over and that can be disabled.
/// </summary>
2019-08-09 22:04:26 +02:00
public class Button : Element {
2020-05-22 17:02:24 +02:00
/// <summary>
/// The button's texture
/// </summary>
2019-10-14 21:28:12 +02:00
public StyleProp < NinePatch > Texture ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// The color that the button draws its texture with
/// </summary>
2019-12-06 21:18:43 +01:00
public StyleProp < Color > NormalColor = Color . White ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// The texture that the button uses while being moused over.
/// If this is null, it uses its default <see cref="Texture"/>.
/// </summary>
2019-10-14 21:28:12 +02:00
public StyleProp < NinePatch > HoveredTexture ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// The color that the button uses for drawing while being moused over
/// </summary>
2019-10-14 21:28:12 +02:00
public StyleProp < Color > HoveredColor ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// The texture that the button uses when it <see cref="IsDisabled"/>.
/// If this is null, it uses its default <see cref="Texture"/>.
/// </summary>
2020-01-15 17:05:28 +01:00
public StyleProp < NinePatch > DisabledTexture ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// The color that the button uses for drawing when it <see cref="IsDisabled"/>
/// </summary>
2020-01-15 17:05:28 +01:00
public StyleProp < Color > DisabledColor ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// The <see cref="Paragraph"/> of text that is displayed on the button.
/// Note that this is only nonnull by default if the constructor was passed a nonnull text.
/// </summary>
2019-08-13 21:23:20 +02:00
public Paragraph Text ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// The <see cref="Tooltip"/> that is displayed when hovering over the button.
/// Note that this is only nonnull by default if the constructor was passed a nonnull tooltip text.
/// </summary>
2019-08-13 23:54:29 +02:00
public Tooltip Tooltip ;
2020-05-22 17:02:24 +02:00
/// <summary>
/// Set this property to true to mark the button as disabled.
/// A disabled button cannot be moused over, selected or pressed.
2022-12-21 21:47:49 +01:00
/// If this value changes often, consider using <see cref="AutoDisableCondition"/>.
2020-05-22 17:02:24 +02:00
/// </summary>
2022-12-21 18:54:25 +01:00
public virtual bool IsDisabled {
2022-12-21 21:47:49 +01:00
get = > this . isDisabled | | this . AutoDisableCondition ? . Invoke ( this ) = = true ;
2022-12-21 18:54:25 +01:00
set = > this . isDisabled = value ;
}
2021-05-18 16:47:38 +02:00
/// <summary>
/// Whether this button's <see cref="Text"/> should be truncated if it exceeds this button's width.
/// Defaults to false.
/// </summary>
public bool TruncateTextIfLong {
get = > this . Text ? . TruncateIfLong ? ? false ;
set {
if ( this . Text ! = null )
this . Text . TruncateIfLong = value ;
}
}
2022-04-05 14:20:38 +02:00
/// <summary>
/// Whether this button should be able to be selected even if it <see cref="IsDisabled"/>.
/// If this is true, <see cref="CanBeSelected"/> will be able to return true even if <see cref="IsDisabled"/> is true.
/// </summary>
public bool CanSelectDisabled ;
2022-12-21 18:54:25 +01:00
/// <summary>
2022-12-21 21:47:49 +01:00
/// An optional function that can be used to modify the result of <see cref="IsDisabled"/> automatically based on a user-defined condition. This removes the need to disable a button based on a condition in <see cref="Element.OnUpdated"/> or manually.
2023-04-15 15:11:50 +02:00
/// Note that, if <see cref="IsDisabled"/>'s underlying value is set to <see langword="true"/> using <see cref="IsDisabled"/>, this function's result will be ignored.
2022-12-21 18:54:25 +01:00
/// </summary>
public Func < Button , bool > AutoDisableCondition ;
2020-01-15 17:05:28 +01:00
2022-03-11 13:25:18 +01:00
/// <inheritdoc />
2022-04-05 14:20:38 +02:00
public override bool CanBeSelected = > base . CanBeSelected & & ( this . CanSelectDisabled | | ! this . IsDisabled ) ;
2022-03-11 13:25:18 +01:00
/// <inheritdoc />
public override bool CanBePressed = > base . CanBePressed & & ! this . IsDisabled ;
2021-10-30 15:01:04 +02:00
2022-12-21 18:54:25 +01:00
private bool isDisabled ;
2023-12-28 17:16:31 +01:00
/// <summary>
/// Creates a new button with the given settings and no text or tooltip.
/// </summary>
/// <param name="anchor">The button's anchor</param>
/// <param name="size">The button's size</param>
public Button ( Anchor anchor , Vector2 size ) : base ( anchor , size ) { }
2020-05-22 17:02:24 +02:00
/// <summary>
/// Creates a new button with the given settings
/// </summary>
/// <param name="anchor">The button's anchor</param>
/// <param name="size">The button's size</param>
/// <param name="text">The text that should be displayed on the button</param>
/// <param name="tooltipText">The text that should be displayed in a <see cref="Tooltip"/> when hovering over this button</param>
2023-12-28 17:16:31 +01:00
public Button ( Anchor anchor , Vector2 size , string text = null , string tooltipText = null ) : this ( anchor , size ) {
2019-08-09 22:04:26 +02:00
if ( text ! = null ) {
2021-10-30 15:33:38 +02:00
this . Text = new Paragraph ( Anchor . Center , 1 , text , true ) ;
2021-12-21 11:54:32 +01:00
this . Text . Padding = this . Text . Padding . OrStyle ( new Padding ( 1 ) , 1 ) ;
2019-08-09 22:04:26 +02:00
this . AddChild ( this . Text ) ;
}
2019-08-24 20:45:40 +02:00
if ( tooltipText ! = null )
2021-10-29 23:33:15 +02:00
this . Tooltip = this . AddTooltip ( tooltipText ) ;
2019-08-09 22:04:26 +02:00
}
2023-12-28 17:16:31 +01:00
/// <summary>
/// Creates a new button with the given settings
/// </summary>
/// <param name="anchor">The button's anchor</param>
/// <param name="size">The button's size</param>
/// <param name="textCallback">The text that should be displayed on the button</param>
/// <param name="tooltipTextCallback">The text that should be displayed in a <see cref="Tooltip"/> when hovering over this button</param>
public Button ( Anchor anchor , Vector2 size , Paragraph . TextCallback textCallback = null , Paragraph . TextCallback tooltipTextCallback = null ) : this ( anchor , size ) {
if ( textCallback ! = null ) {
this . Text = new Paragraph ( Anchor . Center , 1 , textCallback , true ) ;
this . Text . Padding = this . Text . Padding . OrStyle ( new Padding ( 1 ) , 1 ) ;
this . AddChild ( this . Text ) ;
}
if ( tooltipTextCallback ! = null )
this . Tooltip = this . AddTooltip ( tooltipTextCallback ) ;
}
2020-05-22 17:02:24 +02:00
/// <inheritdoc />
2022-04-25 15:25:58 +02:00
public override void Draw ( GameTime time , SpriteBatch batch , float alpha , SpriteBatchContext context ) {
2019-08-09 22:04:26 +02:00
var tex = this . Texture ;
2019-12-06 21:18:43 +01:00
var color = ( Color ) this . NormalColor * alpha ;
2020-01-15 17:05:28 +01:00
if ( this . IsDisabled ) {
tex = this . DisabledTexture . OrDefault ( tex ) ;
color = ( Color ) this . DisabledColor * alpha ;
} else if ( this . IsMouseOver ) {
2019-11-05 13:28:41 +01:00
tex = this . HoveredTexture . OrDefault ( tex ) ;
2019-10-14 21:28:12 +02:00
color = ( Color ) this . HoveredColor * alpha ;
2019-08-09 22:04:26 +02:00
}
2019-09-04 17:19:31 +02:00
batch . Draw ( tex , this . DisplayArea , color , this . Scale ) ;
2022-04-25 15:25:58 +02:00
base . Draw ( time , batch , alpha , context ) ;
2019-08-09 22:04:26 +02:00
}
2020-05-22 17:02:24 +02:00
/// <inheritdoc />
2019-08-10 21:37:10 +02:00
protected override void InitStyle ( UiStyle style ) {
base . InitStyle ( style ) ;
2021-12-21 11:54:32 +01:00
this . Texture = this . Texture . OrStyle ( style . ButtonTexture ) ;
this . HoveredTexture = this . HoveredTexture . OrStyle ( style . ButtonHoveredTexture ) ;
this . HoveredColor = this . HoveredColor . OrStyle ( style . ButtonHoveredColor ) ;
this . DisabledTexture = this . DisabledTexture . OrStyle ( style . ButtonDisabledTexture ) ;
this . DisabledColor = this . DisabledColor . OrStyle ( style . ButtonDisabledColor ) ;
2019-08-10 21:37:10 +02:00
}
2019-08-09 22:04:26 +02:00
}
2022-06-17 18:23:47 +02:00
}