Verb confirmation (#6137)
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
Name="ExpansionIndicator"
|
Name="ExpansionIndicator"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Stretch="KeepCentered"
|
Stretch="KeepCentered"
|
||||||
|
StyleClasses="contextMenuExpansionTexture"
|
||||||
TextureScale="0.5 0.5"
|
TextureScale="0.5 0.5"
|
||||||
SetWidth="{x:Static ui:ContextMenuElement.ElementHeight}"
|
SetWidth="{x:Static ui:ContextMenuElement.ElementHeight}"
|
||||||
SetHeight="{x:Static ui:ContextMenuElement.ElementHeight}"
|
SetHeight="{x:Static ui:ContextMenuElement.ElementHeight}"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace Content.Client.ContextMenu.UI
|
|||||||
public partial class ContextMenuElement : ContainerButton
|
public partial class ContextMenuElement : ContainerButton
|
||||||
{
|
{
|
||||||
public const string StyleClassContextMenuButton = "contextMenuButton";
|
public const string StyleClassContextMenuButton = "contextMenuButton";
|
||||||
|
public const string StyleClassContextMenuExpansionTexture = "contextMenuExpansionTexture";
|
||||||
|
|
||||||
public const float ElementMargin = 2;
|
public const float ElementMargin = 2;
|
||||||
public const float ElementHeight = 32;
|
public const float ElementHeight = 32;
|
||||||
@@ -45,7 +46,7 @@ namespace Content.Client.ContextMenu.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convenience property to set label text.
|
/// Convenience property to set label text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Text { set => Label.SetMessage(FormattedMessage.FromMarkupPermissive(value.Trim())); }
|
public virtual string Text { set => Label.SetMessage(FormattedMessage.FromMarkupPermissive(value.Trim())); }
|
||||||
|
|
||||||
public ContextMenuElement(string? text = null)
|
public ContextMenuElement(string? text = null)
|
||||||
{
|
{
|
||||||
@@ -55,9 +56,6 @@ namespace Content.Client.ContextMenu.UI
|
|||||||
|
|
||||||
if (text != null)
|
if (text != null)
|
||||||
Text = text;
|
Text = text;
|
||||||
|
|
||||||
ExpansionIndicator.Texture = IoCManager.Resolve<IResourceCache>()
|
|
||||||
.GetTexture("/Textures/Interface/VerbIcons/group.svg.192dpi.png");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
@@ -95,7 +93,8 @@ namespace Content.Client.ContextMenu.UI
|
|||||||
if (_subMenu?.Visible ?? true)
|
if (_subMenu?.Visible ?? true)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RemoveStylePseudoClass(StylePseudoClassHover);
|
if (HasStylePseudoClass(StylePseudoClassHover))
|
||||||
|
RemoveStylePseudoClass(StylePseudoClassHover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -446,6 +446,9 @@ namespace Content.Client.Stylesheets
|
|||||||
};
|
};
|
||||||
insetBack.SetPatchMargin(StyleBox.Margin.All, 10);
|
insetBack.SetPatchMargin(StyleBox.Margin.All, 10);
|
||||||
|
|
||||||
|
var contextMenuExpansionTexture = resCache.GetTexture("/Textures/Interface/VerbIcons/group.svg.192dpi.png");
|
||||||
|
var verbMenuConfirmationTexture = resCache.GetTexture("/Textures/Interface/VerbIcons/group.svg.192dpi.png");
|
||||||
|
|
||||||
Stylesheet = new Stylesheet(BaseRules.Concat(new[]
|
Stylesheet = new Stylesheet(BaseRules.Concat(new[]
|
||||||
{
|
{
|
||||||
// Window title.
|
// Window title.
|
||||||
@@ -623,6 +626,32 @@ namespace Content.Client.Stylesheets
|
|||||||
Element<RichTextLabel>().Class(VerbMenuElement.StyleClassVerbOtherText)
|
Element<RichTextLabel>().Class(VerbMenuElement.StyleClassVerbOtherText)
|
||||||
.Prop(Label.StylePropertyFont, notoSans12),
|
.Prop(Label.StylePropertyFont, notoSans12),
|
||||||
|
|
||||||
|
Element<TextureRect>().Class(ContextMenuElement.StyleClassContextMenuExpansionTexture)
|
||||||
|
.Prop(TextureRect.StylePropertyTexture, contextMenuExpansionTexture),
|
||||||
|
|
||||||
|
Element<TextureRect>().Class(VerbMenuElement.StyleClassVerbMenuConfirmationTexture)
|
||||||
|
.Prop(TextureRect.StylePropertyTexture, verbMenuConfirmationTexture),
|
||||||
|
|
||||||
|
// Context menu confirm buttons
|
||||||
|
Element<ContextMenuElement>().Class(ConfirmationMenuElement.StyleClassConfirmationContextMenuButton)
|
||||||
|
.Prop(ContainerButton.StylePropertyStyleBox, buttonContext),
|
||||||
|
|
||||||
|
Element<ContextMenuElement>().Class(ConfirmationMenuElement.StyleClassConfirmationContextMenuButton)
|
||||||
|
.Pseudo(ContainerButton.StylePseudoClassNormal)
|
||||||
|
.Prop(Control.StylePropertyModulateSelf, ButtonColorCautionDefault),
|
||||||
|
|
||||||
|
Element<ContextMenuElement>().Class(ConfirmationMenuElement.StyleClassConfirmationContextMenuButton)
|
||||||
|
.Pseudo(ContainerButton.StylePseudoClassHover)
|
||||||
|
.Prop(Control.StylePropertyModulateSelf, ButtonColorCautionHovered),
|
||||||
|
|
||||||
|
Element<ContextMenuElement>().Class(ConfirmationMenuElement.StyleClassConfirmationContextMenuButton)
|
||||||
|
.Pseudo(ContainerButton.StylePseudoClassPressed)
|
||||||
|
.Prop(Control.StylePropertyModulateSelf, ButtonColorCautionPressed),
|
||||||
|
|
||||||
|
Element<ContextMenuElement>().Class(ConfirmationMenuElement.StyleClassConfirmationContextMenuButton)
|
||||||
|
.Pseudo(ContainerButton.StylePseudoClassDisabled)
|
||||||
|
.Prop(Control.StylePropertyModulateSelf, ButtonColorCautionDisabled),
|
||||||
|
|
||||||
// Thin buttons (No padding nor vertical margin)
|
// Thin buttons (No padding nor vertical margin)
|
||||||
Element<EntityContainerButton>().Class(StyleClassStorageButton)
|
Element<EntityContainerButton>().Class(StyleClassStorageButton)
|
||||||
.Prop(ContainerButton.StylePropertyStyleBox, buttonStorage),
|
.Prop(ContainerButton.StylePropertyStyleBox, buttonStorage),
|
||||||
|
|||||||
34
Content.Client/Verbs/UI/ConfirmationMenuElement.cs
Normal file
34
Content.Client/Verbs/UI/ConfirmationMenuElement.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using Content.Client.ContextMenu.UI;
|
||||||
|
using Content.Shared.Verbs;
|
||||||
|
using Robust.Shared.Maths;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Client.Verbs.UI;
|
||||||
|
|
||||||
|
public partial class ConfirmationMenuElement : ContextMenuElement
|
||||||
|
{
|
||||||
|
public const string StyleClassConfirmationContextMenuButton = "confirmationContextMenuButton";
|
||||||
|
|
||||||
|
public readonly Verb Verb;
|
||||||
|
public readonly VerbType Type;
|
||||||
|
|
||||||
|
public override string Text
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var message = new FormattedMessage();
|
||||||
|
message.PushColor(Color.White);
|
||||||
|
message.AddMarkupPermissive(value.Trim());
|
||||||
|
Label.SetMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfirmationMenuElement(Verb verb, string? text, VerbType type) : base(text)
|
||||||
|
{
|
||||||
|
Verb = verb;
|
||||||
|
Type = type;
|
||||||
|
Icon.Visible = false;
|
||||||
|
|
||||||
|
SetOnlyStyleClass(StyleClassConfirmationContextMenuButton);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ namespace Content.Client.Verbs.UI
|
|||||||
public const string StyleClassVerbActivationText = "ActivationVerb";
|
public const string StyleClassVerbActivationText = "ActivationVerb";
|
||||||
public const string StyleClassVerbAlternativeText = "AlternativeVerb";
|
public const string StyleClassVerbAlternativeText = "AlternativeVerb";
|
||||||
public const string StyleClassVerbOtherText = "OtherVerb";
|
public const string StyleClassVerbOtherText = "OtherVerb";
|
||||||
|
public const string StyleClassVerbMenuConfirmationTexture = "verbMenuConfirmationTexture";
|
||||||
|
|
||||||
public const float VerbTooltipDelay = 0.5f;
|
public const float VerbTooltipDelay = 0.5f;
|
||||||
|
|
||||||
@@ -62,6 +63,12 @@ namespace Content.Client.Verbs.UI
|
|||||||
TooltipDelay = VerbTooltipDelay;
|
TooltipDelay = VerbTooltipDelay;
|
||||||
Disabled = verb.Disabled;
|
Disabled = verb.Disabled;
|
||||||
Verb = verb;
|
Verb = verb;
|
||||||
|
|
||||||
|
if (verb.ConfirmationPopup)
|
||||||
|
{
|
||||||
|
ExpansionIndicator.SetOnlyStyleClass(StyleClassVerbMenuConfirmationTexture);
|
||||||
|
ExpansionIndicator.Visible = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public VerbMenuElement(VerbCategory category, VerbType verbType) : this(category.Text, category.Icon, verbType) { }
|
public VerbMenuElement(VerbCategory category, VerbType verbType) : this(category.Text, category.Icon, verbType) { }
|
||||||
|
|||||||
@@ -170,7 +170,14 @@ namespace Content.Client.Verbs.UI
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (element is not VerbMenuElement verbElement)
|
if (element is not VerbMenuElement verbElement)
|
||||||
|
{
|
||||||
|
if (element is not ConfirmationMenuElement confElement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.Handle();
|
||||||
|
ExecuteVerb(confElement.Verb, confElement.Type);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
args.Handle();
|
args.Handle();
|
||||||
var verb = verbElement.Verb;
|
var verb = verbElement.Verb;
|
||||||
@@ -178,25 +185,45 @@ namespace Content.Client.Verbs.UI
|
|||||||
if (verb == null)
|
if (verb == null)
|
||||||
{
|
{
|
||||||
// The user probably clicked on a verb category.
|
// The user probably clicked on a verb category.
|
||||||
// We will act as if they clicked on the first verb in that category.
|
// If there's only one verb in the category, then it will act as if they clicked on that verb.
|
||||||
|
// Otherwise it opens the category menu.
|
||||||
|
|
||||||
if (verbElement.SubMenu == null || verbElement.SubMenu.ChildCount == 0)
|
if (verbElement.SubMenu == null || verbElement.SubMenu.ChildCount == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (verbElement.SubMenu.MenuBody.ChildCount != 1
|
if (verbElement.SubMenu.MenuBody.ChildCount != 1
|
||||||
|| verbElement.SubMenu.MenuBody.Children.First() is not VerbMenuElement verbCategoryElement)
|
|| verbElement.SubMenu.MenuBody.Children.First() is not VerbMenuElement verbMenuElement)
|
||||||
{
|
{
|
||||||
OpenSubMenu(verbElement);
|
OpenSubMenu(verbElement);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
verb = verbCategoryElement.Verb;
|
verb = verbMenuElement.Verb;
|
||||||
|
|
||||||
if (verb == null)
|
if (verb == null)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_verbSystem.ExecuteVerb(CurrentTarget, verb, verbElement.Type);
|
if (verb.ConfirmationPopup)
|
||||||
|
{
|
||||||
|
if (verbElement.SubMenu == null)
|
||||||
|
{
|
||||||
|
var popupElement = new ConfirmationMenuElement(verb, "Confirm", verbElement.Type);
|
||||||
|
verbElement.SubMenu = new ContextMenuPopup(this, verbElement);
|
||||||
|
AddElement(verbElement.SubMenu, popupElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenSubMenu(verbElement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ExecuteVerb(verb, verbElement.Type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExecuteVerb(Verb verb, VerbType verbType)
|
||||||
|
{
|
||||||
|
_verbSystem.ExecuteVerb(CurrentTarget, verb, verbType);
|
||||||
if (verb.CloseMenu)
|
if (verb.CloseMenu)
|
||||||
_verbSystem.CloseAllMenus();
|
_verbSystem.CloseAllMenus();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ namespace Content.Server.Administration
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
verb.Impact = LogImpact.Extreme; // if you're just outright killing a person, I guess that deserves to be extreme?
|
verb.Impact = LogImpact.Extreme; // if you're just outright killing a person, I guess that deserves to be extreme?
|
||||||
|
verb.ConfirmationPopup = true;
|
||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,6 +137,7 @@ namespace Content.Server.Administration
|
|||||||
verb.IconTexture = "/Textures/Interface/VerbIcons/delete_transparent.svg.192dpi.png";
|
verb.IconTexture = "/Textures/Interface/VerbIcons/delete_transparent.svg.192dpi.png";
|
||||||
verb.Act = () => EntityManager.DeleteEntity(args.Target);
|
verb.Act = () => EntityManager.DeleteEntity(args.Target);
|
||||||
verb.Impact = LogImpact.Medium;
|
verb.Impact = LogImpact.Medium;
|
||||||
|
verb.ConfirmationPopup = true;
|
||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,6 +168,7 @@ namespace Content.Server.Administration
|
|||||||
player.ContentData()?.Mind?.TransferTo(args.Target, ghostCheckOverride: true);
|
player.ContentData()?.Mind?.TransferTo(args.Target, ghostCheckOverride: true);
|
||||||
};
|
};
|
||||||
verb.Impact = LogImpact.High;
|
verb.Impact = LogImpact.High;
|
||||||
|
verb.ConfirmationPopup = true;
|
||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,6 +135,11 @@ namespace Content.Shared.Verbs
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
public LogImpact Impact = LogImpact.Low;
|
public LogImpact Impact = LogImpact.Low;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether this verb requires confirmation before being executed.
|
||||||
|
/// </summary>
|
||||||
|
public bool ConfirmationPopup = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compares two verbs based on their <see cref="Priority"/>, <see cref="Category"/>, <see cref="Text"/>,
|
/// Compares two verbs based on their <see cref="Priority"/>, <see cref="Category"/>, <see cref="Text"/>,
|
||||||
/// and <see cref="IconTexture"/>.
|
/// and <see cref="IconTexture"/>.
|
||||||
|
|||||||
Reference in New Issue
Block a user