2019-10-28 14:33:08 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2021-10-14 04:32:54 +08:00
#nullable enable
2019-10-28 14:33:08 +08:00
using osu.Framework.Allocation ;
2020-03-11 09:18:41 +08:00
using osu.Framework.Extensions.Color4Extensions ;
2019-10-28 14:33:08 +08:00
using osu.Framework.Graphics ;
using osu.Framework.Graphics.Containers ;
using osu.Framework.Graphics.Shapes ;
2021-10-31 00:50:13 +08:00
using osu.Framework.Localisation ;
2019-10-28 14:33:08 +08:00
using osu.Game.Graphics.Containers ;
2021-10-14 04:32:54 +08:00
using osu.Game.Overlays ;
2019-10-28 14:33:08 +08:00
using osuTK ;
namespace osu.Game.Graphics.UserInterfaceV2
{
public abstract class LabelledDrawable < T > : CompositeDrawable
where T : Drawable
{
2021-06-08 22:33:56 +08:00
private float? fixedLabelWidth ;
/// <summary>
/// The fixed width of the label of this <see cref="LabelledDrawable{T}"/>.
/// If <c>null</c>, the label portion will auto-size to its content.
/// Can be used in layout scenarios where several labels must match in length for the components to be aligned properly.
/// </summary>
public float? FixedLabelWidth
{
get = > fixedLabelWidth ;
set
{
if ( fixedLabelWidth = = value )
return ;
fixedLabelWidth = value ;
updateLabelWidth ( ) ;
}
}
2019-10-28 14:33:08 +08:00
protected const float CONTENT_PADDING_VERTICAL = 10 ;
protected const float CONTENT_PADDING_HORIZONTAL = 15 ;
2022-05-20 13:34:33 +08:00
public const float CORNER_RADIUS = 15 ;
2019-10-28 14:33:08 +08:00
/// <summary>
/// The component that is being displayed.
/// </summary>
protected readonly T Component ;
2021-10-14 04:32:54 +08:00
private readonly Box background ;
2021-06-08 22:33:56 +08:00
private readonly GridContainer grid ;
2019-10-28 14:33:08 +08:00
private readonly OsuTextFlowContainer labelText ;
private readonly OsuTextFlowContainer descriptionText ;
/// <summary>
/// Creates a new <see cref="LabelledComponent{T, U}"/>.
/// </summary>
/// <param name="padded">Whether the component should be padded or should be expanded to the bounds of this <see cref="LabelledComponent{T, U}"/>.</param>
protected LabelledDrawable ( bool padded )
{
RelativeSizeAxes = Axes . X ;
AutoSizeAxes = Axes . Y ;
CornerRadius = CORNER_RADIUS ;
Masking = true ;
InternalChildren = new Drawable [ ]
{
2021-10-14 04:32:54 +08:00
background = new Box
2019-10-28 14:33:08 +08:00
{
RelativeSizeAxes = Axes . Both ,
} ,
new FillFlowContainer
{
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y ,
Direction = FillDirection . Vertical ,
Padding = padded
? new MarginPadding { Horizontal = CONTENT_PADDING_HORIZONTAL , Vertical = CONTENT_PADDING_VERTICAL }
: new MarginPadding { Left = CONTENT_PADDING_HORIZONTAL } ,
Spacing = new Vector2 ( 0 , 12 ) ,
Children = new Drawable [ ]
{
2021-06-08 22:33:56 +08:00
grid = new GridContainer
2019-10-28 14:33:08 +08:00
{
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y ,
Content = new [ ]
{
new Drawable [ ]
{
labelText = new OsuTextFlowContainer ( s = > s . Font = OsuFont . GetFont ( weight : FontWeight . Bold ) )
{
Anchor = Anchor . CentreLeft ,
Origin = Anchor . CentreLeft ,
AutoSizeAxes = Axes . Both ,
2021-06-08 22:33:56 +08:00
Padding = new MarginPadding
{
Right = 20 ,
// ensure that the label is always vertically padded even if the component itself isn't.
// this may become an issue if the label is taller than the component.
Vertical = padded ? 0 : CONTENT_PADDING_VERTICAL
}
2019-10-28 14:33:08 +08:00
} ,
new Container
{
2020-10-19 15:02:39 +08:00
// top right works better when the vertical height of the component changes smoothly (avoids weird layout animations).
2020-09-25 03:52:42 +08:00
Anchor = Anchor . TopRight ,
Origin = Anchor . TopRight ,
2019-10-28 14:33:08 +08:00
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y ,
Child = Component = CreateComponent ( ) . With ( d = >
{
d . Anchor = Anchor . CentreRight ;
d . Origin = Anchor . CentreRight ;
} )
}
} ,
} ,
RowDimensions = new [ ] { new Dimension ( GridSizeMode . AutoSize ) } ,
} ,
descriptionText = new OsuTextFlowContainer ( s = > s . Font = OsuFont . GetFont ( size : 12 , weight : FontWeight . Bold , italics : true ) )
{
RelativeSizeAxes = Axes . X ,
AutoSizeAxes = Axes . Y ,
Padding = new MarginPadding { Bottom = padded ? 0 : CONTENT_PADDING_VERTICAL } ,
Alpha = 0 ,
}
}
}
} ;
2021-06-08 22:33:56 +08:00
updateLabelWidth ( ) ;
}
private void updateLabelWidth ( )
{
if ( fixedLabelWidth = = null )
{
grid . ColumnDimensions = new [ ] { new Dimension ( GridSizeMode . AutoSize ) } ;
labelText . RelativeSizeAxes = Axes . None ;
labelText . AutoSizeAxes = Axes . Both ;
}
else
{
grid . ColumnDimensions = new [ ] { new Dimension ( GridSizeMode . Absolute , fixedLabelWidth . Value ) } ;
labelText . AutoSizeAxes = Axes . Y ;
labelText . RelativeSizeAxes = Axes . X ;
}
2019-10-28 14:33:08 +08:00
}
2021-10-14 04:32:54 +08:00
[BackgroundDependencyLoader(true)]
private void load ( OverlayColourProvider ? colourProvider , OsuColour osuColour )
2019-10-28 14:33:08 +08:00
{
2021-10-14 04:32:54 +08:00
background . Colour = colourProvider ? . Background4 ? ? Color4Extensions . FromHex ( @"1c2125" ) ;
2019-10-28 14:33:08 +08:00
descriptionText . Colour = osuColour . Yellow ;
}
2021-10-31 00:50:13 +08:00
public LocalisableString Label
2019-10-28 14:33:08 +08:00
{
set = > labelText . Text = value ;
}
2021-10-31 00:50:13 +08:00
public LocalisableString Description
2019-10-28 14:33:08 +08:00
{
set
{
descriptionText . Text = value ;
2021-11-05 04:38:01 +08:00
if ( ! string . IsNullOrEmpty ( value . ToString ( ) ) )
2019-10-28 14:33:08 +08:00
descriptionText . Show ( ) ;
else
descriptionText . Hide ( ) ;
}
}
/// <summary>
/// Creates the component that should be displayed.
/// </summary>
/// <returns>The component.</returns>
protected abstract T CreateComponent ( ) ;
}
}