forked from ppy/osu-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request ppy#4506 from bdach/hex-colour-picker
Add hex colour picker
- Loading branch information
Showing
3 changed files
with
307 additions
and
0 deletions.
There are no files selected for viewing
112 changes: 112 additions & 0 deletions
112
osu.Framework.Tests/Visual/UserInterface/TestSceneHexColourPicker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// 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.Linq; | ||
using NUnit.Framework; | ||
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.Testing; | ||
using osuTK; | ||
using osuTK.Input; | ||
|
||
namespace osu.Framework.Tests.Visual.UserInterface | ||
{ | ||
public class TestSceneHexColourPicker : ManualInputManagerTestScene | ||
{ | ||
private TestHexColourPicker hexColourPicker; | ||
private SpriteText currentText; | ||
private Box currentPreview; | ||
|
||
[SetUpSteps] | ||
public void SetUpSteps() | ||
{ | ||
AddStep("create content", () => | ||
{ | ||
Child = new FillFlowContainer | ||
{ | ||
RelativeSizeAxes = Axes.Both, | ||
Direction = FillDirection.Vertical, | ||
Spacing = new Vector2(0, 10), | ||
Children = new Drawable[] | ||
{ | ||
hexColourPicker = new TestHexColourPicker(), | ||
new FillFlowContainer | ||
{ | ||
RelativeSizeAxes = Axes.X, | ||
AutoSizeAxes = Axes.Y, | ||
Direction = FillDirection.Horizontal, | ||
Spacing = new Vector2(10, 0), | ||
Children = new Drawable[] | ||
{ | ||
currentText = new SpriteText(), | ||
new Container | ||
{ | ||
Width = 50, | ||
RelativeSizeAxes = Axes.Y, | ||
Child = currentPreview = new Box | ||
{ | ||
RelativeSizeAxes = Axes.Both | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
|
||
hexColourPicker.Current.BindValueChanged(colour => | ||
{ | ||
currentText.Text = $"Current.Value = {colour.NewValue.ToHex()}"; | ||
currentPreview.Colour = colour.NewValue; | ||
}, true); | ||
}); | ||
} | ||
|
||
[Test] | ||
public void TestExternalChange() | ||
{ | ||
Colour4 colour = Colour4.Yellow; | ||
|
||
AddStep("set current colour", () => hexColourPicker.Current.Value = colour); | ||
|
||
AddAssert("hex code updated", () => hexColourPicker.HexCodeTextBox.Text == colour.ToHex()); | ||
assertPreviewUpdated(colour); | ||
} | ||
|
||
[Test] | ||
public void TestTextBoxBehaviour() | ||
{ | ||
clickTextBox(); | ||
AddStep("insert valid colour", () => hexColourPicker.HexCodeTextBox.Text = "#ff00ff"); | ||
assertPreviewUpdated(Colour4.Magenta); | ||
AddAssert("current not changed yet", () => hexColourPicker.Current.Value == Colour4.White); | ||
|
||
AddStep("commit text", () => InputManager.Key(Key.Enter)); | ||
AddAssert("current updated", () => hexColourPicker.Current.Value == Colour4.Magenta); | ||
|
||
clickTextBox(); | ||
AddStep("insert invalid colour", () => hexColourPicker.HexCodeTextBox.Text = "c0d0"); | ||
AddStep("commit text", () => InputManager.Key(Key.Enter)); | ||
AddAssert("current not changed", () => hexColourPicker.Current.Value == Colour4.Magenta); | ||
AddAssert("old hex code restored", () => hexColourPicker.HexCodeTextBox.Text == "#FF00FF"); | ||
} | ||
|
||
private void clickTextBox() | ||
=> AddStep("click text box", () => | ||
{ | ||
InputManager.MoveMouseTo(hexColourPicker.HexCodeTextBox); | ||
InputManager.Click(MouseButton.Left); | ||
}); | ||
|
||
private void assertPreviewUpdated(Colour4 expected) | ||
=> AddAssert("preview colour updated", () => hexColourPicker.Preview.Current.Value == expected); | ||
|
||
private class TestHexColourPicker : BasicHexColourPicker | ||
{ | ||
public TextBox HexCodeTextBox => this.ChildrenOfType<TextBox>().Single(); | ||
public ColourPreview Preview => this.ChildrenOfType<ColourPreview>().Single(); | ||
} | ||
} | ||
} |
50 changes: 50 additions & 0 deletions
50
osu.Framework/Graphics/UserInterface/BasicHexColourPicker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// 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.Graphics.Shapes; | ||
|
||
namespace osu.Framework.Graphics.UserInterface | ||
{ | ||
public class BasicHexColourPicker : HexColourPicker | ||
{ | ||
public BasicHexColourPicker() | ||
{ | ||
Background.Colour = FrameworkColour.GreenDarker; | ||
|
||
Padding = new MarginPadding(20); | ||
Spacing = 10; | ||
} | ||
|
||
protected override TextBox CreateHexCodeTextBox() => new BasicTextBox | ||
{ | ||
Height = 40 | ||
}; | ||
|
||
protected override ColourPreview CreateColourPreview() => new BasicColourPreview(); | ||
|
||
private class BasicColourPreview : ColourPreview | ||
{ | ||
private readonly Box previewBox; | ||
|
||
public BasicColourPreview() | ||
{ | ||
InternalChild = previewBox = new Box | ||
{ | ||
RelativeSizeAxes = Axes.Both | ||
}; | ||
} | ||
|
||
protected override void LoadComplete() | ||
{ | ||
base.LoadComplete(); | ||
|
||
Current.BindValueChanged(_ => updatePreview(), true); | ||
} | ||
|
||
private void updatePreview() | ||
{ | ||
previewBox.Colour = Current.Value; | ||
} | ||
} | ||
} | ||
} |
145 changes: 145 additions & 0 deletions
145
osu.Framework/Graphics/UserInterface/HexColourPicker.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
// 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.Graphics.Containers; | ||
using osu.Framework.Graphics.Shapes; | ||
|
||
namespace osu.Framework.Graphics.UserInterface | ||
{ | ||
public abstract class HexColourPicker : CompositeDrawable, IHasCurrentValue<Colour4> | ||
{ | ||
private readonly BindableWithCurrent<Colour4> current = new BindableWithCurrent<Colour4>(); | ||
|
||
public Bindable<Colour4> Current | ||
{ | ||
get => current.Current; | ||
set => current.Current = value; | ||
} | ||
|
||
public new MarginPadding Padding | ||
{ | ||
get => content.Padding; | ||
set => content.Padding = value; | ||
} | ||
|
||
/// <summary> | ||
/// Sets the spacing between the hex input text box and the colour preview. | ||
/// </summary> | ||
public float Spacing | ||
{ | ||
get => spacer.Width; | ||
set => spacer.Width = value; | ||
} | ||
|
||
/// <summary> | ||
/// The background of the control. | ||
/// </summary> | ||
protected readonly Box Background; | ||
|
||
private readonly Container content; | ||
|
||
private readonly TextBox hexCodeTextBox; | ||
private readonly Drawable spacer; | ||
private readonly ColourPreview colourPreview; | ||
|
||
protected HexColourPicker() | ||
{ | ||
Current.Value = Colour4.White; | ||
|
||
Width = 300; | ||
AutoSizeAxes = Axes.Y; | ||
|
||
InternalChildren = new Drawable[] | ||
{ | ||
Background = new Box | ||
{ | ||
RelativeSizeAxes = Axes.Both | ||
}, | ||
content = new Container | ||
{ | ||
RelativeSizeAxes = Axes.X, | ||
AutoSizeAxes = Axes.Y, | ||
Child = new GridContainer | ||
{ | ||
RelativeSizeAxes = Axes.X, | ||
AutoSizeAxes = Axes.Y, | ||
ColumnDimensions = new[] | ||
{ | ||
new Dimension(), | ||
new Dimension(GridSizeMode.AutoSize), | ||
new Dimension() | ||
}, | ||
RowDimensions = new[] | ||
{ | ||
new Dimension(GridSizeMode.AutoSize) | ||
}, | ||
Content = new[] | ||
{ | ||
new[] | ||
{ | ||
hexCodeTextBox = CreateHexCodeTextBox().With(d => | ||
{ | ||
d.RelativeSizeAxes = Axes.X; | ||
d.CommitOnFocusLost = true; | ||
}), | ||
spacer = Empty(), | ||
colourPreview = CreateColourPreview().With(d => d.RelativeSizeAxes = Axes.Both) | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
|
||
/// <summary> | ||
/// Creates the text box to be used for specifying the hex code of the target colour. | ||
/// </summary> | ||
protected abstract TextBox CreateHexCodeTextBox(); | ||
|
||
/// <summary> | ||
/// Creates the control that will be used for displaying the preview of the target colour. | ||
/// </summary> | ||
protected abstract ColourPreview CreateColourPreview(); | ||
|
||
protected override void LoadComplete() | ||
{ | ||
base.LoadComplete(); | ||
|
||
Current.BindValueChanged(_ => updateState(), true); | ||
|
||
hexCodeTextBox.Current.BindValueChanged(_ => tryPreviewColour()); | ||
hexCodeTextBox.OnCommit += commitColour; | ||
} | ||
|
||
private void updateState() | ||
{ | ||
hexCodeTextBox.Text = Current.Value.ToHex(); | ||
colourPreview.Current.Value = Current.Value; | ||
} | ||
|
||
private void tryPreviewColour() | ||
{ | ||
if (!Colour4.TryParseHex(hexCodeTextBox.Text, out var colour) || colour.A < 1) | ||
return; | ||
|
||
colourPreview.Current.Value = colour; | ||
} | ||
|
||
private void commitColour(TextBox sender, bool newText) | ||
{ | ||
if (!Colour4.TryParseHex(sender.Text, out var colour) || colour.A < 1) | ||
{ | ||
Current.TriggerChange(); // restore previous value. | ||
return; | ||
} | ||
|
||
Current.Value = colour; | ||
} | ||
|
||
public abstract class ColourPreview : CompositeDrawable | ||
{ | ||
public Bindable<Colour4> Current = new Bindable<Colour4>(); | ||
} | ||
} | ||
} |