mirror of
https://github.com/ppy/osu.git
synced 2026-05-23 15:40:35 +08:00
Add sheared dropdown
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
// 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.
|
||||
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics.UserInterfaceV2;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Tests.Visual.UserInterface
|
||||
{
|
||||
public partial class TestSceneShearedDropdown : ThemeComparisonTestScene
|
||||
{
|
||||
public TestSceneShearedDropdown()
|
||||
: base(false)
|
||||
{
|
||||
}
|
||||
|
||||
protected override Drawable CreateContent() => new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = Color4.Black.Opacity(0.75f),
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
new ShearedDropdown<string>("Test")
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre,
|
||||
Y = 300f,
|
||||
Width = 140,
|
||||
Current = new Bindable<string>(),
|
||||
Items = new[] { "Global", "Friends", "Local", "Really lonnnnnnng option" },
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ namespace osu.Game.Graphics.UserInterface
|
||||
|
||||
#region OsuDropdownMenu
|
||||
|
||||
protected partial class OsuDropdownMenu : DropdownMenu
|
||||
public partial class OsuDropdownMenu : DropdownMenu
|
||||
{
|
||||
public override bool HandleNonPositionalInput => State == MenuState.Open;
|
||||
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
// 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.
|
||||
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Graphics.UserInterface;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Input.Bindings;
|
||||
using osu.Game.Overlays;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
namespace osu.Game.Graphics.UserInterfaceV2
|
||||
{
|
||||
public partial class ShearedDropdown<T> : Dropdown<T>, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
protected override DropdownHeader CreateHeader() => new ShearedDropdownHeader();
|
||||
|
||||
protected override DropdownMenu CreateMenu() => new ShearedDropdownMenu();
|
||||
|
||||
public ShearedDropdown(LocalisableString label)
|
||||
{
|
||||
if (Header is ShearedDropdownHeader osuHeader)
|
||||
{
|
||||
osuHeader.Dropdown = this;
|
||||
osuHeader.LeftSideLabel = label;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
var header = (ShearedDropdownHeader)Header;
|
||||
var menu = (ShearedDropdownMenu)Menu;
|
||||
|
||||
menu.Padding = new MarginPadding { Left = header.LabelContainer.DrawWidth - 15f };
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<GlobalAction> e)
|
||||
{
|
||||
if (e.Repeat) return false;
|
||||
|
||||
if (e.Action == GlobalAction.Back)
|
||||
return Back();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<GlobalAction> e)
|
||||
{
|
||||
}
|
||||
|
||||
protected partial class ShearedDropdownMenu : OsuDropdown<T>.OsuDropdownMenu
|
||||
{
|
||||
public new MarginPadding Padding
|
||||
{
|
||||
get => base.Padding;
|
||||
set => base.Padding = value;
|
||||
}
|
||||
|
||||
public ShearedDropdownMenu()
|
||||
{
|
||||
Margin = new MarginPadding { Top = 5f };
|
||||
}
|
||||
}
|
||||
|
||||
public partial class ShearedDropdownHeader : DropdownHeader
|
||||
{
|
||||
private LocalisableString label;
|
||||
|
||||
protected override LocalisableString Label
|
||||
{
|
||||
get => label;
|
||||
set
|
||||
{
|
||||
label = value;
|
||||
valueText.Text = value;
|
||||
}
|
||||
}
|
||||
|
||||
public LocalisableString LeftSideLabel
|
||||
{
|
||||
set => labelText.Text = value;
|
||||
}
|
||||
|
||||
private readonly OsuSpriteText labelText;
|
||||
private readonly OsuSpriteText valueText;
|
||||
private readonly Box labelBox;
|
||||
private readonly SpriteIcon chevron;
|
||||
|
||||
public Container LabelContainer { get; }
|
||||
|
||||
public ShearedDropdown<T> Dropdown = null!;
|
||||
private ShearedDropdownSearchBar searchBar = null!;
|
||||
|
||||
private readonly Vector2 shear = new Vector2(OsuGame.SHEAR, 0);
|
||||
|
||||
[Resolved]
|
||||
private OverlayColourProvider colourProvider { get; set; } = null!;
|
||||
|
||||
public ShearedDropdownHeader()
|
||||
{
|
||||
Shear = shear;
|
||||
CornerRadius = 5f;
|
||||
Masking = true;
|
||||
|
||||
Foreground.Children = new Drawable[]
|
||||
{
|
||||
new GridContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
RowDimensions = new[] { new Dimension(GridSizeMode.AutoSize) },
|
||||
ColumnDimensions = new[]
|
||||
{
|
||||
new Dimension(GridSizeMode.AutoSize),
|
||||
new Dimension()
|
||||
},
|
||||
Content = new[]
|
||||
{
|
||||
new[]
|
||||
{
|
||||
LabelContainer = new Container
|
||||
{
|
||||
AutoSizeAxes = Axes.Both,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
// required to fix colour bleeding around the edges of the dropdown on hover
|
||||
Padding = new MarginPadding { Vertical = -1f, Left = -1f },
|
||||
Child = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
CornerRadius = 5f,
|
||||
Masking = true,
|
||||
Child = labelBox = new Box
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
},
|
||||
},
|
||||
labelText = new OsuSpriteText
|
||||
{
|
||||
Margin = new MarginPadding { Horizontal = 10f, Vertical = 8f },
|
||||
Font = OsuFont.Torus.With(size: 16.8f, weight: FontWeight.SemiBold),
|
||||
Shear = -shear,
|
||||
},
|
||||
},
|
||||
},
|
||||
new Container
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Padding = new MarginPadding { Horizontal = 10f },
|
||||
Shear = -shear,
|
||||
Children = new Drawable[]
|
||||
{
|
||||
valueText = new TruncatingSpriteText
|
||||
{
|
||||
Anchor = Anchor.CentreLeft,
|
||||
Origin = Anchor.CentreLeft,
|
||||
Padding = new MarginPadding { Right = 15f },
|
||||
Font = OsuFont.Torus.With(size: 16.8f, weight: FontWeight.SemiBold),
|
||||
RelativeSizeAxes = Axes.X,
|
||||
},
|
||||
chevron = new SpriteIcon
|
||||
{
|
||||
Anchor = Anchor.CentreRight,
|
||||
Origin = Anchor.CentreRight,
|
||||
Y = 1f,
|
||||
Icon = FontAwesome.Solid.ChevronDown,
|
||||
Size = new Vector2(10f),
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
AddInternal(LabelContainer.CreateProxy());
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
labelBox.Colour = colourProvider.Background3;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
Dropdown.Menu.StateChanged += _ => updateChevron();
|
||||
SearchBar.State.ValueChanged += _ => updateColour();
|
||||
Enabled.BindValueChanged(_ => updateColour());
|
||||
updateColour();
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
searchBar.Padding = new MarginPadding { Left = LabelContainer.DrawWidth };
|
||||
}
|
||||
|
||||
protected override bool OnHover(HoverEvent e)
|
||||
{
|
||||
updateColour();
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void OnHoverLost(HoverLostEvent e)
|
||||
{
|
||||
updateColour();
|
||||
}
|
||||
|
||||
private void updateColour()
|
||||
{
|
||||
bool hovered = Enabled.Value && IsHovered;
|
||||
var hoveredColour = colourProvider.Light4;
|
||||
var unhoveredColour = colourProvider.Background5;
|
||||
|
||||
Colour = Color4.White;
|
||||
Alpha = Enabled.Value ? 1 : 0.3f;
|
||||
|
||||
if (SearchBar.State.Value == Visibility.Visible)
|
||||
{
|
||||
chevron.Colour = hovered ? hoveredColour.Lighten(0.5f) : Colour4.White;
|
||||
Background.Colour = unhoveredColour;
|
||||
}
|
||||
else
|
||||
{
|
||||
chevron.Colour = Color4.White;
|
||||
Background.Colour = hovered ? hoveredColour : unhoveredColour;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateChevron()
|
||||
{
|
||||
Debug.Assert(Dropdown != null);
|
||||
bool open = Dropdown.Menu.State == MenuState.Open;
|
||||
chevron.ScaleTo(open ? new Vector2(1f, -1f) : Vector2.One, 300, Easing.OutQuint);
|
||||
}
|
||||
|
||||
protected override DropdownSearchBar CreateSearchBar() => searchBar = new ShearedDropdownSearchBar();
|
||||
|
||||
private partial class ShearedDropdownSearchBar : DropdownSearchBar
|
||||
{
|
||||
protected override void PopIn() => this.FadeIn();
|
||||
|
||||
protected override void PopOut() => this.FadeOut();
|
||||
|
||||
protected override TextBox CreateTextBox() => new DropdownSearchTextBox
|
||||
{
|
||||
FontSize = OsuFont.Default.Size,
|
||||
};
|
||||
|
||||
private partial class DropdownSearchTextBox : OsuTextBox
|
||||
{
|
||||
private readonly Vector2 shear = new Vector2(OsuGame.SHEAR, 0);
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OverlayColourProvider? colourProvider)
|
||||
{
|
||||
TextContainer.Shear = -shear;
|
||||
BackgroundUnfocused = colourProvider?.Background5 ?? new Color4(10, 10, 10, 255);
|
||||
BackgroundFocused = colourProvider?.Background5 ?? new Color4(10, 10, 10, 255);
|
||||
}
|
||||
|
||||
protected override void OnFocus(FocusEvent e)
|
||||
{
|
||||
base.OnFocus(e);
|
||||
BorderThickness = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user