Move hotkey dialog logic into SettingsLogic, fix bugs and improve usability of the dialog
This commit is contained in:
committed by
reaperrr
parent
ed8abe9861
commit
be1f820674
@@ -24,10 +24,7 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
public int LeftMargin = 5;
|
public int LeftMargin = 5;
|
||||||
public int RightMargin = 5;
|
public int RightMargin = 5;
|
||||||
|
|
||||||
public Action OnTakeFocus = () => { };
|
|
||||||
public Action OnLoseFocus = () => { };
|
public Action OnLoseFocus = () => { };
|
||||||
public Action OnEscape = () => { };
|
|
||||||
public Action OnReturn = () => { };
|
|
||||||
|
|
||||||
public Func<bool> IsDisabled = () => false;
|
public Func<bool> IsDisabled = () => false;
|
||||||
public Func<bool> IsValid = () => false;
|
public Func<bool> IsValid = () => false;
|
||||||
@@ -49,7 +46,6 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
public override bool TakeKeyboardFocus()
|
public override bool TakeKeyboardFocus()
|
||||||
{
|
{
|
||||||
OnTakeFocus();
|
|
||||||
return base.TakeKeyboardFocus();
|
return base.TakeKeyboardFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +58,12 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
return base.YieldKeyboardFocus();
|
return base.YieldKeyboardFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ForceYieldKeyboardFocus()
|
||||||
|
{
|
||||||
|
OnLoseFocus();
|
||||||
|
return base.YieldKeyboardFocus();
|
||||||
|
}
|
||||||
|
|
||||||
public override bool HandleMouseInput(MouseInput mi)
|
public override bool HandleMouseInput(MouseInput mi)
|
||||||
{
|
{
|
||||||
if (IsDisabled())
|
if (IsDisabled())
|
||||||
@@ -95,15 +97,9 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
if (!HasKeyboardFocus || IgnoreKeys.Contains(e.Key))
|
if (!HasKeyboardFocus || IgnoreKeys.Contains(e.Key))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (e.Key != Keycode.ESCAPE && e.Key != Keycode.RETURN)
|
if (e.Key != Keycode.ESCAPE && e.Key != Keycode.RETURN && e.Key != Keycode.KP_ENTER)
|
||||||
Key = Hotkey.FromKeyInput(e);
|
Key = Hotkey.FromKeyInput(e);
|
||||||
|
|
||||||
if (e.Key == Keycode.ESCAPE)
|
|
||||||
OnEscape();
|
|
||||||
|
|
||||||
if (e.Key == Keycode.RETURN)
|
|
||||||
OnReturn();
|
|
||||||
|
|
||||||
YieldKeyboardFocus();
|
YieldKeyboardFocus();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
#region Copyright & License Information
|
|
||||||
/*
|
|
||||||
* Copyright 2007-2019 The OpenRA Developers (see AUTHORS)
|
|
||||||
* This file is part of OpenRA, which is free software. It is made
|
|
||||||
* available to you under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation, either version 3 of
|
|
||||||
* the License, or (at your option) any later version. For more
|
|
||||||
* information, see COPYING.
|
|
||||||
*/
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using OpenRA.Primitives;
|
|
||||||
using OpenRA.Widgets;
|
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
|
||||||
{
|
|
||||||
public class HotkeyDialogLogic : ChromeLogic
|
|
||||||
{
|
|
||||||
readonly Widget panel;
|
|
||||||
readonly ButtonWidget resetButton, clearButton, cancelButton;
|
|
||||||
readonly LabelWidget duplicateNotice, defaultNotice, originalNotice;
|
|
||||||
readonly Action onSave;
|
|
||||||
readonly HotkeyDefinition definition;
|
|
||||||
readonly HotkeyManager manager;
|
|
||||||
readonly HotkeyEntryWidget hotkeyEntry;
|
|
||||||
readonly bool isFirstValidation = true;
|
|
||||||
Hotkey currentHotkey;
|
|
||||||
HotkeyDefinition duplicateHotkey;
|
|
||||||
bool isValid = false;
|
|
||||||
bool isValidating = false;
|
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
|
||||||
public HotkeyDialogLogic(Widget widget, Action onSave, HotkeyDefinition hotkeyDefinition, HotkeyManager hotkeyManager)
|
|
||||||
{
|
|
||||||
panel = widget;
|
|
||||||
this.onSave = onSave;
|
|
||||||
definition = hotkeyDefinition;
|
|
||||||
manager = hotkeyManager;
|
|
||||||
currentHotkey = manager[definition.Name].GetValue();
|
|
||||||
hotkeyEntry = panel.Get<HotkeyEntryWidget>("HOTKEY_ENTRY");
|
|
||||||
resetButton = panel.Get<ButtonWidget>("RESET_BUTTON");
|
|
||||||
clearButton = panel.Get<ButtonWidget>("CLEAR_BUTTON");
|
|
||||||
cancelButton = panel.Get<ButtonWidget>("CANCEL_BUTTON");
|
|
||||||
duplicateNotice = panel.Get<LabelWidget>("DUPLICATE_NOTICE");
|
|
||||||
defaultNotice = panel.Get<LabelWidget>("DEFAULT_NOTICE");
|
|
||||||
originalNotice = panel.Get<LabelWidget>("ORIGINAL_NOTICE");
|
|
||||||
|
|
||||||
panel.Get<LabelWidget>("HOTKEY_LABEL").GetText = () => hotkeyDefinition.Description + ":";
|
|
||||||
|
|
||||||
duplicateNotice.TextColor = ChromeMetrics.Get<Color>("NoticeErrorColor");
|
|
||||||
duplicateNotice.GetText = () =>
|
|
||||||
{
|
|
||||||
return (duplicateHotkey != null) ? duplicateNotice.Text.F(duplicateHotkey.Description) : duplicateNotice.Text;
|
|
||||||
};
|
|
||||||
defaultNotice.TextColor = ChromeMetrics.Get<Color>("NoticeInfoColor");
|
|
||||||
originalNotice.TextColor = ChromeMetrics.Get<Color>("NoticeInfoColor");
|
|
||||||
originalNotice.Text = originalNotice.Text.F(hotkeyDefinition.Default.DisplayString());
|
|
||||||
|
|
||||||
resetButton.OnClick = Reset;
|
|
||||||
clearButton.OnClick = Clear;
|
|
||||||
cancelButton.OnClick = Cancel;
|
|
||||||
|
|
||||||
hotkeyEntry.Key = currentHotkey;
|
|
||||||
hotkeyEntry.IsValid = () => isValid;
|
|
||||||
hotkeyEntry.OnTakeFocus = OnHotkeyEntryTakeFocus;
|
|
||||||
hotkeyEntry.OnLoseFocus = OnHotkeyEntryLoseFocus;
|
|
||||||
hotkeyEntry.OnEscape = Cancel;
|
|
||||||
hotkeyEntry.OnReturn = Cancel;
|
|
||||||
hotkeyEntry.TakeKeyboardFocus();
|
|
||||||
|
|
||||||
Validate();
|
|
||||||
isFirstValidation = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnHotkeyEntryTakeFocus()
|
|
||||||
{
|
|
||||||
cancelButton.Disabled = manager.GetFirstDuplicate(definition.Name, currentHotkey, definition) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnHotkeyEntryLoseFocus()
|
|
||||||
{
|
|
||||||
cancelButton.Disabled = true;
|
|
||||||
if (!isValidating)
|
|
||||||
Validate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Validate()
|
|
||||||
{
|
|
||||||
isValidating = true;
|
|
||||||
|
|
||||||
duplicateHotkey = manager.GetFirstDuplicate(definition.Name, hotkeyEntry.Key, definition);
|
|
||||||
isValid = duplicateHotkey == null;
|
|
||||||
|
|
||||||
duplicateNotice.Visible = !isValid;
|
|
||||||
clearButton.Disabled = !hotkeyEntry.Key.IsValid();
|
|
||||||
|
|
||||||
if (hotkeyEntry.Key == definition.Default || (!hotkeyEntry.Key.IsValid() && !definition.Default.IsValid()))
|
|
||||||
{
|
|
||||||
defaultNotice.Visible = !duplicateNotice.Visible;
|
|
||||||
originalNotice.Visible = false;
|
|
||||||
resetButton.Disabled = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
defaultNotice.Visible = false;
|
|
||||||
originalNotice.Visible = !duplicateNotice.Visible;
|
|
||||||
resetButton.Disabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValid && !isFirstValidation)
|
|
||||||
{
|
|
||||||
currentHotkey = hotkeyEntry.Key;
|
|
||||||
hotkeyEntry.YieldKeyboardFocus();
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
hotkeyEntry.TakeKeyboardFocus();
|
|
||||||
|
|
||||||
isValidating = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Save()
|
|
||||||
{
|
|
||||||
manager.Set(definition.Name, hotkeyEntry.Key);
|
|
||||||
Game.Settings.Save();
|
|
||||||
onSave();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Cancel()
|
|
||||||
{
|
|
||||||
cancelButton.Disabled = true;
|
|
||||||
hotkeyEntry.Key = currentHotkey;
|
|
||||||
Validate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Reset()
|
|
||||||
{
|
|
||||||
hotkeyEntry.Key = definition.Default;
|
|
||||||
Validate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
hotkeyEntry.Key = Hotkey.Invalid;
|
|
||||||
Validate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -39,6 +39,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
SoundDevice soundDevice;
|
SoundDevice soundDevice;
|
||||||
PanelType settingsPanel = PanelType.Display;
|
PanelType settingsPanel = PanelType.Display;
|
||||||
|
|
||||||
|
ButtonWidget selectedHotkeyButton;
|
||||||
|
HotkeyEntryWidget hotkeyEntryWidget;
|
||||||
|
HotkeyDefinition duplicateHotkeyDefinition, selectedHotkeyDefinition;
|
||||||
|
bool isHotkeyValid;
|
||||||
|
bool isHotkeyDefault;
|
||||||
|
|
||||||
static SettingsLogic()
|
static SettingsLogic()
|
||||||
{
|
{
|
||||||
var original = Game.Settings;
|
var original = Game.Settings;
|
||||||
@@ -125,7 +131,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
ss.OnChange += x => field.SetValue(group, x);
|
ss.OnChange += x => field.SetValue(group, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BindHotkeyPref(HotkeyDefinition hd, HotkeyManager manager, Widget template, Widget parent, Widget remapDialogRoot, Widget remapDialogPlaceholder)
|
void BindHotkeyPref(HotkeyDefinition hd, Widget template, Widget parent)
|
||||||
{
|
{
|
||||||
var key = template.Clone() as Widget;
|
var key = template.Clone() as Widget;
|
||||||
key.Id = hd.Name;
|
key.Id = hd.Name;
|
||||||
@@ -134,50 +140,34 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
key.Get<LabelWidget>("FUNCTION").GetText = () => hd.Description + ":";
|
key.Get<LabelWidget>("FUNCTION").GetText = () => hd.Description + ":";
|
||||||
|
|
||||||
var remapButton = key.Get<ButtonWidget>("HOTKEY");
|
var remapButton = key.Get<ButtonWidget>("HOTKEY");
|
||||||
WidgetUtils.TruncateButtonToTooltip(remapButton, manager[hd.Name].GetValue().DisplayString());
|
WidgetUtils.TruncateButtonToTooltip(remapButton, modData.Hotkeys[hd.Name].GetValue().DisplayString());
|
||||||
|
|
||||||
if (manager.GetFirstDuplicate(hd.Name, manager[hd.Name].GetValue(), hd) != null)
|
remapButton.IsHighlighted = () => selectedHotkeyDefinition == hd;
|
||||||
remapButton.GetColor = () => ChromeMetrics.Get<Color>("HotkeyColorInvalid");
|
|
||||||
|
var hotkeyValidColor = ChromeMetrics.Get<Color>("HotkeyColor");
|
||||||
|
var hotkeyInvalidColor = ChromeMetrics.Get<Color>("HotkeyColorInvalid");
|
||||||
|
|
||||||
|
remapButton.GetColor = () =>
|
||||||
|
{
|
||||||
|
return modData.Hotkeys.GetFirstDuplicate(hd.Name, modData.Hotkeys[hd.Name].GetValue(), hd) != null ?
|
||||||
|
hotkeyInvalidColor :
|
||||||
|
hotkeyValidColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (selectedHotkeyDefinition == hd)
|
||||||
|
{
|
||||||
|
selectedHotkeyButton = remapButton;
|
||||||
|
hotkeyEntryWidget.Key = modData.Hotkeys[hd.Name].GetValue();
|
||||||
|
ValidateHotkey();
|
||||||
|
}
|
||||||
|
|
||||||
remapButton.OnClick = () =>
|
remapButton.OnClick = () =>
|
||||||
{
|
{
|
||||||
remapDialogRoot.RemoveChildren();
|
selectedHotkeyDefinition = hd;
|
||||||
|
selectedHotkeyButton = remapButton;
|
||||||
if (remapButton.IsHighlighted())
|
hotkeyEntryWidget.Key = modData.Hotkeys[hd.Name].GetValue();
|
||||||
{
|
ValidateHotkey();
|
||||||
remapButton.IsHighlighted = () => false;
|
hotkeyEntryWidget.TakeKeyboardFocus();
|
||||||
|
|
||||||
if (remapDialogPlaceholder != null)
|
|
||||||
remapDialogPlaceholder.Visible = true;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remapDialogPlaceholder != null)
|
|
||||||
remapDialogPlaceholder.Visible = false;
|
|
||||||
|
|
||||||
var siblings = parent.Children;
|
|
||||||
foreach (var sibling in siblings)
|
|
||||||
{
|
|
||||||
var button = sibling.GetOrNull<ButtonWidget>("HOTKEY");
|
|
||||||
if (button != null)
|
|
||||||
button.IsHighlighted = () => false;
|
|
||||||
}
|
|
||||||
|
|
||||||
remapButton.IsHighlighted = () => true;
|
|
||||||
|
|
||||||
Ui.LoadWidget("HOTKEY_DIALOG", remapDialogRoot, new WidgetArgs
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"onSave", () =>
|
|
||||||
{
|
|
||||||
WidgetUtils.TruncateButtonToTooltip(remapButton, manager[hd.Name].GetValue().DisplayString());
|
|
||||||
remapButton.GetColor = () => ChromeMetrics.Get<Color>("ButtonTextColor");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ "hotkeyDefinition", hd },
|
|
||||||
{ "hotkeyManager", manager },
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
parent.AddChild(key);
|
parent.AddChild(key);
|
||||||
@@ -463,6 +453,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
Action InitHotkeysPanel(Widget panel)
|
Action InitHotkeysPanel(Widget panel)
|
||||||
{
|
{
|
||||||
|
var hotkeyDialogRoot = panel.Get("HOTKEY_DIALOG_ROOT");
|
||||||
var hotkeyList = panel.Get<ScrollPanelWidget>("HOTKEY_LIST");
|
var hotkeyList = panel.Get<ScrollPanelWidget>("HOTKEY_LIST");
|
||||||
hotkeyList.Layout = new GridLayout(hotkeyList);
|
hotkeyList.Layout = new GridLayout(hotkeyList);
|
||||||
var hotkeyHeader = hotkeyList.Get<ScrollItemWidget>("HEADER");
|
var hotkeyHeader = hotkeyList.Get<ScrollItemWidget>("HEADER");
|
||||||
@@ -475,6 +466,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
MiniYaml hotkeyGroups;
|
MiniYaml hotkeyGroups;
|
||||||
if (logicArgs.TryGetValue("HotkeyGroups", out hotkeyGroups))
|
if (logicArgs.TryGetValue("HotkeyGroups", out hotkeyGroups))
|
||||||
{
|
{
|
||||||
|
InitHotkeyRemapDialog(panel);
|
||||||
|
|
||||||
foreach (var hg in hotkeyGroups.Nodes)
|
foreach (var hg in hotkeyGroups.Nodes)
|
||||||
{
|
{
|
||||||
var templateNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Template");
|
var templateNode = hg.Value.Nodes.FirstOrDefault(n => n.Key == "Template");
|
||||||
@@ -489,16 +482,28 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var types = FieldLoader.GetValue<string[]>("Types", typesNode.Value.Value);
|
var types = FieldLoader.GetValue<string[]>("Types", typesNode.Value.Value);
|
||||||
var added = new HashSet<HotkeyDefinition>();
|
var added = new HashSet<HotkeyDefinition>();
|
||||||
var template = templates.Get(templateNode.Value.Value);
|
var template = templates.Get(templateNode.Value.Value);
|
||||||
var remapDialogRoot = panel.Get("HOTKEY_DIALOG_ROOT");
|
|
||||||
var remapDialogPlaceholder = panel.GetOrNull("HOTKEY_DIALOG_PLACEHOLDER");
|
|
||||||
foreach (var t in types)
|
foreach (var t in types)
|
||||||
|
{
|
||||||
foreach (var hd in modData.Hotkeys.Definitions.Where(k => k.Types.Contains(t)))
|
foreach (var hd in modData.Hotkeys.Definitions.Where(k => k.Types.Contains(t)))
|
||||||
|
{
|
||||||
if (added.Add(hd))
|
if (added.Add(hd))
|
||||||
BindHotkeyPref(hd, modData.Hotkeys, template, hotkeyList, remapDialogRoot, remapDialogPlaceholder);
|
{
|
||||||
|
if (selectedHotkeyDefinition == null)
|
||||||
|
selectedHotkeyDefinition = hd;
|
||||||
|
|
||||||
|
BindHotkeyPref(hd, template, hotkeyList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => { };
|
return () =>
|
||||||
|
{
|
||||||
|
hotkeyEntryWidget.Key = modData.Hotkeys[selectedHotkeyDefinition.Name].GetValue();
|
||||||
|
hotkeyEntryWidget.ForceYieldKeyboardFocus();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Action ResetInputPanel(Widget panel)
|
Action ResetInputPanel(Widget panel)
|
||||||
@@ -532,7 +537,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
foreach (var hd in modData.Hotkeys.Definitions)
|
foreach (var hd in modData.Hotkeys.Definitions)
|
||||||
{
|
{
|
||||||
modData.Hotkeys.Set(hd.Name, hd.Default);
|
modData.Hotkeys.Set(hd.Name, hd.Default);
|
||||||
panel.Get(hd.Name).Get<HotkeyEntryWidget>("HOTKEY").Key = hd.Default;
|
WidgetUtils.TruncateButtonToTooltip(panel.Get(hd.Name).Get<ButtonWidget>("HOTKEY"), hd.Default.DisplayString());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -745,5 +750,68 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
else
|
else
|
||||||
Game.Renderer.ReleaseWindowMouseFocus();
|
Game.Renderer.ReleaseWindowMouseFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitHotkeyRemapDialog(Widget panel)
|
||||||
|
{
|
||||||
|
var label = new CachedTransform<HotkeyDefinition, string>(hd => hd.Description + ":");
|
||||||
|
panel.Get<LabelWidget>("HOTKEY_LABEL").GetText = () => label.Update(selectedHotkeyDefinition);
|
||||||
|
|
||||||
|
var duplicateNotice = panel.Get<LabelWidget>("DUPLICATE_NOTICE");
|
||||||
|
duplicateNotice.TextColor = ChromeMetrics.Get<Color>("NoticeErrorColor");
|
||||||
|
duplicateNotice.IsVisible = () => !isHotkeyValid;
|
||||||
|
var duplicateNoticeText = new CachedTransform<HotkeyDefinition, string>(hd => hd != null ? duplicateNotice.Text.F(hd.Description) : duplicateNotice.Text);
|
||||||
|
duplicateNotice.GetText = () => duplicateNoticeText.Update(duplicateHotkeyDefinition);
|
||||||
|
|
||||||
|
var defaultNotice = panel.Get<LabelWidget>("DEFAULT_NOTICE");
|
||||||
|
defaultNotice.TextColor = ChromeMetrics.Get<Color>("NoticeInfoColor");
|
||||||
|
defaultNotice.IsVisible = () => isHotkeyValid && isHotkeyDefault;
|
||||||
|
|
||||||
|
var originalNotice = panel.Get<LabelWidget>("ORIGINAL_NOTICE");
|
||||||
|
originalNotice.TextColor = ChromeMetrics.Get<Color>("NoticeInfoColor");
|
||||||
|
originalNotice.IsVisible = () => isHotkeyValid && !isHotkeyDefault;
|
||||||
|
var originalNoticeText = new CachedTransform<HotkeyDefinition, string>(hd => originalNotice.Text.F(hd.Default.DisplayString()));
|
||||||
|
originalNotice.GetText = () => originalNoticeText.Update(selectedHotkeyDefinition);
|
||||||
|
|
||||||
|
var resetButton = panel.Get<ButtonWidget>("RESET_HOTKEY_BUTTON");
|
||||||
|
resetButton.IsDisabled = () => isHotkeyDefault;
|
||||||
|
resetButton.OnClick = ResetHotkey;
|
||||||
|
|
||||||
|
var clearButton = panel.Get<ButtonWidget>("CLEAR_HOTKEY_BUTTON");
|
||||||
|
clearButton.IsDisabled = () => !hotkeyEntryWidget.Key.IsValid();
|
||||||
|
clearButton.OnClick = ClearHotkey;
|
||||||
|
|
||||||
|
hotkeyEntryWidget = panel.Get<HotkeyEntryWidget>("HOTKEY_ENTRY");
|
||||||
|
hotkeyEntryWidget.IsValid = () => isHotkeyValid;
|
||||||
|
hotkeyEntryWidget.OnLoseFocus = ValidateHotkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ValidateHotkey()
|
||||||
|
{
|
||||||
|
duplicateHotkeyDefinition = modData.Hotkeys.GetFirstDuplicate(selectedHotkeyDefinition.Name, hotkeyEntryWidget.Key, selectedHotkeyDefinition);
|
||||||
|
isHotkeyValid = duplicateHotkeyDefinition == null;
|
||||||
|
isHotkeyDefault = hotkeyEntryWidget.Key == selectedHotkeyDefinition.Default || (!hotkeyEntryWidget.Key.IsValid() && !selectedHotkeyDefinition.Default.IsValid());
|
||||||
|
|
||||||
|
if (isHotkeyValid)
|
||||||
|
SaveHotkey();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveHotkey()
|
||||||
|
{
|
||||||
|
WidgetUtils.TruncateButtonToTooltip(selectedHotkeyButton, hotkeyEntryWidget.Key.DisplayString());
|
||||||
|
modData.Hotkeys.Set(selectedHotkeyDefinition.Name, hotkeyEntryWidget.Key);
|
||||||
|
Game.Settings.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetHotkey()
|
||||||
|
{
|
||||||
|
hotkeyEntryWidget.Key = selectedHotkeyDefinition.Default;
|
||||||
|
hotkeyEntryWidget.YieldKeyboardFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearHotkey()
|
||||||
|
{
|
||||||
|
hotkeyEntryWidget.Key = Hotkey.Invalid;
|
||||||
|
hotkeyEntryWidget.YieldKeyboardFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
Background@HOTKEY_DIALOG:
|
|
||||||
Logic: HotkeyDialogLogic
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Background: panel-gray
|
|
||||||
Children:
|
|
||||||
Label@HOTKEY_LABEL:
|
|
||||||
X: 15
|
|
||||||
Y: 14
|
|
||||||
Width: PARENT_RIGHT - 40
|
|
||||||
Height: 25
|
|
||||||
Font: Bold
|
|
||||||
HotkeyEntry@HOTKEY_ENTRY:
|
|
||||||
X: 15
|
|
||||||
Y: 40
|
|
||||||
Width: 382
|
|
||||||
Height: 25
|
|
||||||
Container@NOTICES:
|
|
||||||
X: 15
|
|
||||||
Y: 65
|
|
||||||
Width: PARENT_RIGHT - 40
|
|
||||||
Height: 25
|
|
||||||
Children:
|
|
||||||
Label@DEFAULT_NOTICE:
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Font: Tiny
|
|
||||||
Align: Left
|
|
||||||
Text: This is the default hotkey.
|
|
||||||
Label@ORIGINAL_NOTICE:
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Font: Tiny
|
|
||||||
Align: Left
|
|
||||||
Text: The default is "{0}"
|
|
||||||
Label@DUPLICATE_NOTICE:
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Font: Tiny
|
|
||||||
Align: Left
|
|
||||||
Text: This hotkey is already used for "{0}"
|
|
||||||
Button@CLEAR_BUTTON:
|
|
||||||
X: PARENT_RIGHT - 65 - 15 - 2 * (WIDTH + 10)
|
|
||||||
Y: 40
|
|
||||||
Width: 25
|
|
||||||
Height: 25
|
|
||||||
TooltipText: Unbind the hotkey
|
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
|
||||||
TooltipTemplate: SIMPLE_TOOLTIP
|
|
||||||
Children:
|
|
||||||
Image:
|
|
||||||
ImageCollection: lobby-bits
|
|
||||||
ImageName: kick
|
|
||||||
X: 7
|
|
||||||
Y: 8
|
|
||||||
IgnoreMouseOver: True
|
|
||||||
Button@RESET_BUTTON:
|
|
||||||
X: PARENT_RIGHT - 65 - 15 - WIDTH - 10
|
|
||||||
Y: 40
|
|
||||||
Width: 25
|
|
||||||
Height: 25
|
|
||||||
TooltipText: Reset to default
|
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
|
||||||
TooltipTemplate: SIMPLE_TOOLTIP
|
|
||||||
Children:
|
|
||||||
Image@IMAGE_RELOAD:
|
|
||||||
X: 5
|
|
||||||
Y: 5
|
|
||||||
Width: 16
|
|
||||||
Height: 16
|
|
||||||
ImageCollection: reload-icon
|
|
||||||
ImageName: enabled
|
|
||||||
IgnoreMouseOver: True
|
|
||||||
Button@CANCEL_BUTTON:
|
|
||||||
X: PARENT_RIGHT - WIDTH - 15
|
|
||||||
Y: 40
|
|
||||||
Width: 65
|
|
||||||
Height: 25
|
|
||||||
Text: Cancel
|
|
||||||
TooltipText: Cancel the operation
|
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
|
||||||
TooltipTemplate: SIMPLE_TOOLTIP
|
|
||||||
TooltipContainer@TOOLTIP_CONTAINER:
|
|
||||||
@@ -480,7 +480,7 @@ Container@SETTINGS_PANEL:
|
|||||||
Width: PARENT_RIGHT - 15
|
Width: PARENT_RIGHT - 15
|
||||||
TopBottomSpacing: 4
|
TopBottomSpacing: 4
|
||||||
ItemSpacing: 4
|
ItemSpacing: 4
|
||||||
Height: 210
|
Height: 242
|
||||||
Children:
|
Children:
|
||||||
ScrollItem@HEADER:
|
ScrollItem@HEADER:
|
||||||
Width: 528
|
Width: 528
|
||||||
@@ -526,23 +526,80 @@ Container@SETTINGS_PANEL:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Align: Left
|
Align: Left
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
Background@HOTKEY_DIALOG_PLACEHOLDER:
|
Background@HOTKEY_DIALOG_ROOT:
|
||||||
Y: 225
|
Y: 255
|
||||||
Width: PARENT_RIGHT - 15
|
Width: PARENT_RIGHT - 15
|
||||||
Height: 105
|
Height: 75
|
||||||
Background: panel-gray
|
Background: panel-gray
|
||||||
Children:
|
Children:
|
||||||
Label@HOTKEY_DIALOG_HELPTEXT:
|
Label@HOTKEY_LABEL:
|
||||||
Y: PARENT_BOTTOM / 2 - 12
|
X: 15
|
||||||
Width: PARENT_RIGHT
|
Y: 14
|
||||||
|
Width: 220 - 15 - 10
|
||||||
Height: 25
|
Height: 25
|
||||||
Font: Tiny
|
Font: Bold
|
||||||
Align: Center
|
Align: Right
|
||||||
Text: Click on a hotkey to start rebinding
|
HotkeyEntry@HOTKEY_ENTRY:
|
||||||
Container@HOTKEY_DIALOG_ROOT:
|
X: 220
|
||||||
Y: 225
|
Y: 15
|
||||||
Width: PARENT_RIGHT - 15
|
Width: 254
|
||||||
Height: 105
|
Height: 25
|
||||||
|
Container@NOTICES:
|
||||||
|
X: 220
|
||||||
|
Y: 40
|
||||||
|
Width: 254
|
||||||
|
Height: 25
|
||||||
|
Children:
|
||||||
|
Label@DEFAULT_NOTICE:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Font: Tiny
|
||||||
|
Align: Left
|
||||||
|
Text: This is the default
|
||||||
|
Label@ORIGINAL_NOTICE:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Font: Tiny
|
||||||
|
Align: Left
|
||||||
|
Text: The default is "{0}"
|
||||||
|
Label@DUPLICATE_NOTICE:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Font: Tiny
|
||||||
|
Align: Left
|
||||||
|
Text: This is already used for "{0}"
|
||||||
|
Button@CLEAR_HOTKEY_BUTTON:
|
||||||
|
X: PARENT_RIGHT - 25 - 15 - WIDTH - 10
|
||||||
|
Y: 15
|
||||||
|
Width: 25
|
||||||
|
Height: 25
|
||||||
|
TooltipText: Unbind the hotkey
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipTemplate: SIMPLE_TOOLTIP
|
||||||
|
Children:
|
||||||
|
Image:
|
||||||
|
ImageCollection: lobby-bits
|
||||||
|
ImageName: kick
|
||||||
|
X: 7
|
||||||
|
Y: 8
|
||||||
|
IgnoreMouseOver: True
|
||||||
|
Button@RESET_HOTKEY_BUTTON:
|
||||||
|
X: PARENT_RIGHT - WIDTH - 15
|
||||||
|
Y: 15
|
||||||
|
Width: 25
|
||||||
|
Height: 25
|
||||||
|
TooltipText: Reset to default
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipTemplate: SIMPLE_TOOLTIP
|
||||||
|
Children:
|
||||||
|
Image@IMAGE_RELOAD:
|
||||||
|
X: 5
|
||||||
|
Y: 5
|
||||||
|
Width: 16
|
||||||
|
Height: 16
|
||||||
|
ImageCollection: reload-icon
|
||||||
|
ImageName: enabled
|
||||||
|
IgnoreMouseOver: True
|
||||||
Container@ADVANCED_PANEL:
|
Container@ADVANCED_PANEL:
|
||||||
Width: PARENT_RIGHT
|
Width: PARENT_RIGHT
|
||||||
Height: PARENT_BOTTOM
|
Height: PARENT_BOTTOM
|
||||||
|
|||||||
@@ -128,7 +128,6 @@ ChromeLayout:
|
|||||||
cnc|chrome/assetbrowser.yaml
|
cnc|chrome/assetbrowser.yaml
|
||||||
cnc|chrome/missionbrowser.yaml
|
cnc|chrome/missionbrowser.yaml
|
||||||
cnc|chrome/editor.yaml
|
cnc|chrome/editor.yaml
|
||||||
cnc|chrome/dialog-hotkey.yaml
|
|
||||||
|
|
||||||
Voices:
|
Voices:
|
||||||
cnc|audio/voices.yaml
|
cnc|audio/voices.yaml
|
||||||
|
|||||||
@@ -1,69 +0,0 @@
|
|||||||
Background@HOTKEY_DIALOG:
|
|
||||||
Logic: HotkeyDialogLogic
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Background: dialog3
|
|
||||||
Children:
|
|
||||||
Label@HOTKEY_LABEL:
|
|
||||||
X: 20
|
|
||||||
Y: 14
|
|
||||||
Width: PARENT_RIGHT - 40
|
|
||||||
Height: 25
|
|
||||||
Font: Bold
|
|
||||||
HotkeyEntry@HOTKEY_ENTRY:
|
|
||||||
X: 20
|
|
||||||
Y: 40
|
|
||||||
Width: 280
|
|
||||||
Height: 25
|
|
||||||
Container@NOTICES:
|
|
||||||
X: 20
|
|
||||||
Y: 65
|
|
||||||
Width: PARENT_RIGHT - 40
|
|
||||||
Height: 25
|
|
||||||
Children:
|
|
||||||
Label@DEFAULT_NOTICE:
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Font: Tiny
|
|
||||||
Align: Left
|
|
||||||
Text: This is the default
|
|
||||||
Label@ORIGINAL_NOTICE:
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Font: Tiny
|
|
||||||
Align: Left
|
|
||||||
Text: The default is "{0}"
|
|
||||||
Label@DUPLICATE_NOTICE:
|
|
||||||
Width: PARENT_RIGHT
|
|
||||||
Height: PARENT_BOTTOM
|
|
||||||
Font: Tiny
|
|
||||||
Align: Left
|
|
||||||
Text: This hotkey is already used for "{0}"
|
|
||||||
Button@CLEAR_BUTTON:
|
|
||||||
X: PARENT_RIGHT - 3 * WIDTH - 40
|
|
||||||
Y: 41
|
|
||||||
Width: 65
|
|
||||||
Height: 25
|
|
||||||
Text: Clear
|
|
||||||
TooltipText: Unbind the hotkey
|
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
|
||||||
TooltipTemplate: SIMPLE_TOOLTIP
|
|
||||||
Button@RESET_BUTTON:
|
|
||||||
X: PARENT_RIGHT - 2 * WIDTH - 30
|
|
||||||
Y: 41
|
|
||||||
Width: 65
|
|
||||||
Height: 25
|
|
||||||
Text: Reset
|
|
||||||
TooltipText: Reset to default
|
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
|
||||||
TooltipTemplate: SIMPLE_TOOLTIP
|
|
||||||
Button@CANCEL_BUTTON:
|
|
||||||
X: PARENT_RIGHT - WIDTH - 20
|
|
||||||
Y: 41
|
|
||||||
Width: 65
|
|
||||||
Height: 25
|
|
||||||
Text: Cancel
|
|
||||||
TooltipText: Cancel the operation
|
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
|
||||||
TooltipTemplate: SIMPLE_TOOLTIP
|
|
||||||
TooltipContainer@TOOLTIP_CONTAINER:
|
|
||||||
@@ -482,7 +482,7 @@ Background@SETTINGS_PANEL:
|
|||||||
Width: PARENT_RIGHT - 30
|
Width: PARENT_RIGHT - 30
|
||||||
TopBottomSpacing: 4
|
TopBottomSpacing: 4
|
||||||
ItemSpacing: 4
|
ItemSpacing: 4
|
||||||
Height: 183
|
Height: 222
|
||||||
Children:
|
Children:
|
||||||
ScrollItem@HEADER:
|
ScrollItem@HEADER:
|
||||||
BaseName: scrollheader
|
BaseName: scrollheader
|
||||||
@@ -539,25 +539,69 @@ Background@SETTINGS_PANEL:
|
|||||||
Height: 25
|
Height: 25
|
||||||
Align: Left
|
Align: Left
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
Background@HOTKEY_DIALOG_PLACEHOLDER:
|
Background@HOTKEY_DIALOG_ROOT:
|
||||||
X: 15
|
X: 15
|
||||||
Y: 232
|
Y: 270
|
||||||
Width: PARENT_RIGHT - 30
|
Width: PARENT_RIGHT - 30
|
||||||
Height: 108
|
Height: 73
|
||||||
Background: dialog3
|
Background: dialog3
|
||||||
Children:
|
Children:
|
||||||
Label@HOTKEY_DIALOG_HELPTEXT:
|
Label@HOTKEY_LABEL:
|
||||||
Y: PARENT_BOTTOM / 2 - 12
|
X: 15
|
||||||
Width: PARENT_RIGHT
|
Y: 19
|
||||||
|
Width: 219 - 15 - 10
|
||||||
Height: 25
|
Height: 25
|
||||||
Font: Tiny
|
Font: Bold
|
||||||
Align: Center
|
Align: Right
|
||||||
Text: Click on a hotkey to start rebinding
|
HotkeyEntry@HOTKEY_ENTRY:
|
||||||
Container@HOTKEY_DIALOG_ROOT:
|
X: 219
|
||||||
X: 15
|
Y: 20
|
||||||
Y: 232
|
Width: 170
|
||||||
Width: PARENT_RIGHT - 30
|
Height: 25
|
||||||
Height: 108
|
Container@NOTICES:
|
||||||
|
X: 219
|
||||||
|
Y: 42
|
||||||
|
Width: 170
|
||||||
|
Height: 25
|
||||||
|
Children:
|
||||||
|
Label@DEFAULT_NOTICE:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Font: Tiny
|
||||||
|
Align: Left
|
||||||
|
Text: This is the default
|
||||||
|
Label@ORIGINAL_NOTICE:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Font: Tiny
|
||||||
|
Align: Left
|
||||||
|
Text: The default is "{0}"
|
||||||
|
Label@DUPLICATE_NOTICE:
|
||||||
|
Width: PARENT_RIGHT
|
||||||
|
Height: PARENT_BOTTOM
|
||||||
|
Font: Tiny
|
||||||
|
Align: Left
|
||||||
|
Text: This is already used for "{0}"
|
||||||
|
Button@CLEAR_HOTKEY_BUTTON:
|
||||||
|
X: PARENT_RIGHT - 2 * WIDTH - 30
|
||||||
|
Y: 20
|
||||||
|
Width: 65
|
||||||
|
Height: 25
|
||||||
|
Text: Clear
|
||||||
|
Font: Bold
|
||||||
|
TooltipText: Unbind the hotkey
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipTemplate: SIMPLE_TOOLTIP
|
||||||
|
Button@RESET_HOTKEY_BUTTON:
|
||||||
|
X: PARENT_RIGHT - WIDTH - 20
|
||||||
|
Y: 20
|
||||||
|
Width: 65
|
||||||
|
Height: 25
|
||||||
|
Text: Reset
|
||||||
|
Font: Bold
|
||||||
|
TooltipText: Reset to default
|
||||||
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
|
TooltipTemplate: SIMPLE_TOOLTIP
|
||||||
Container@ADVANCED_PANEL:
|
Container@ADVANCED_PANEL:
|
||||||
X: 5
|
X: 5
|
||||||
Y: 50
|
Y: 50
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ ChromeLayout:
|
|||||||
common|chrome/replaybrowser.yaml
|
common|chrome/replaybrowser.yaml
|
||||||
common|chrome/gamesave-browser.yaml
|
common|chrome/gamesave-browser.yaml
|
||||||
common|chrome/gamesave-loading.yaml
|
common|chrome/gamesave-loading.yaml
|
||||||
common|chrome/dialog-hotkey.yaml
|
|
||||||
|
|
||||||
Weapons:
|
Weapons:
|
||||||
d2k|weapons/debris.yaml
|
d2k|weapons/debris.yaml
|
||||||
|
|||||||
@@ -124,7 +124,6 @@ ChromeLayout:
|
|||||||
common|chrome/confirmation-dialogs.yaml
|
common|chrome/confirmation-dialogs.yaml
|
||||||
common|chrome/editor.yaml
|
common|chrome/editor.yaml
|
||||||
common|chrome/playerprofile.yaml
|
common|chrome/playerprofile.yaml
|
||||||
common|chrome/dialog-hotkey.yaml
|
|
||||||
|
|
||||||
Weapons:
|
Weapons:
|
||||||
ra|weapons/explosions.yaml
|
ra|weapons/explosions.yaml
|
||||||
|
|||||||
@@ -172,7 +172,6 @@ ChromeLayout:
|
|||||||
common|chrome/missionbrowser.yaml
|
common|chrome/missionbrowser.yaml
|
||||||
common|chrome/confirmation-dialogs.yaml
|
common|chrome/confirmation-dialogs.yaml
|
||||||
common|chrome/editor.yaml
|
common|chrome/editor.yaml
|
||||||
common|chrome/dialog-hotkey.yaml
|
|
||||||
|
|
||||||
Voices:
|
Voices:
|
||||||
ts|audio/voices.yaml
|
ts|audio/voices.yaml
|
||||||
|
|||||||
Reference in New Issue
Block a user