// Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE using System.Collections.Generic; using osu.Framework.Allocation; using OpenTK.Graphics; using osu.Framework.Configuration; using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Graphics; using osu.Framework.Graphics.Colour; using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Sprites; using osu.Framework.Graphics.UserInterface; using osu.Framework.Input; using osu.Game.Graphics; using osu.Game.Graphics.Sprites; namespace osu.Game.Overlays.Settings { public abstract class SettingsItem : Container, IFilterable { protected abstract Drawable CreateControl(); protected Drawable Control { get; } private IHasCurrentValue controlWithCurrent => Control as IHasCurrentValue; protected override Container Content => FlowContent; protected readonly FillFlowContainer FlowContent; private SpriteText text; private readonly RestoreDefaultValueButton restoreDefaultValueButton = new RestoreDefaultValueButton(); public bool ShowsDefaultIndicator = true; private Color4? restoreDefaultValueColour; public Color4 RestoreDefaultValueColour { get { return restoreDefaultValueColour ?? Color4.White; } set { restoreDefaultValueColour = value; restoreDefaultValueButton?.SetButtonColour(RestoreDefaultValueColour); } } public virtual string LabelText { get { return text?.Text ?? string.Empty; } set { if (text == null) { // construct lazily for cases where the label is not needed (may be provided by the Control). Add(text = new OsuSpriteText { Depth = 1 }); } text.Text = value; } } // hold a reference to the provided bindable so we don't have to in every settings section. private Bindable bindable; public virtual Bindable Bindable { get { return bindable; } set { bindable = value; controlWithCurrent?.Current.BindTo(bindable); if (ShowsDefaultIndicator) { restoreDefaultValueButton.Bindable = bindable.GetBoundCopy(); restoreDefaultValueButton.Bindable.TriggerChange(); } } } public IEnumerable FilterTerms => new[] { LabelText }; public bool MatchingFilter { set { // probably needs a better transition. this.FadeTo(value ? 1 : 0); } } protected SettingsItem() { RelativeSizeAxes = Axes.X; AutoSizeAxes = Axes.Y; Padding = new MarginPadding { Right = SettingsOverlay.CONTENT_MARGINS }; FlowContent = new FillFlowContainer { RelativeSizeAxes = Axes.X, AutoSizeAxes = Axes.Y, Padding = new MarginPadding { Left = SettingsOverlay.CONTENT_MARGINS, Right = 5 }, }; if ((Control = CreateControl()) != null) { if (controlWithCurrent != null) controlWithCurrent.Current.DisabledChanged += disabled => { Colour = disabled ? Color4.Gray : Color4.White; }; FlowContent.Add(Control); } } [BackgroundDependencyLoader] private void load(OsuColour colours) { AddInternal(FlowContent); if (restoreDefaultValueButton != null) { if (!restoreDefaultValueColour.HasValue) restoreDefaultValueColour = colours.Yellow; restoreDefaultValueButton.SetButtonColour(RestoreDefaultValueColour); AddInternal(restoreDefaultValueButton); } } private class RestoreDefaultValueButton : Box, IHasTooltip { private Bindable bindable; public Bindable Bindable { get { return bindable; } set { bindable = value; bindable.ValueChanged += newValue => UpdateState(); bindable.DisabledChanged += disabled => UpdateState(); } } private Color4 buttonColour; private bool hovering; public RestoreDefaultValueButton() { RelativeSizeAxes = Axes.Y; Width = SettingsOverlay.CONTENT_MARGINS; Alpha = 0f; } public string TooltipText => "Revert to default"; public override bool HandleInput => true; protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true; protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => true; protected override bool OnClick(InputState state) { if (bindable != null && !bindable.Disabled) bindable.SetDefault(); return true; } protected override bool OnHover(InputState state) { hovering = true; UpdateState(); return true; } protected override void OnHoverLost(InputState state) { hovering = false; UpdateState(); } public void SetButtonColour(Color4 buttonColour) { this.buttonColour = buttonColour; UpdateState(); } public void UpdateState() { if (bindable == null) return; var colour = bindable.Disabled ? Color4.Gray : buttonColour; this.FadeTo(bindable.IsDefault ? 0f : hovering && !bindable.Disabled ? 1f : 0.5f, 200, Easing.OutQuint); this.FadeColour(ColourInfo.GradientHorizontal(colour.Opacity(0.8f), colour.Opacity(0)), 200, Easing.OutQuint); } } } }