Skip to content

Commit

Permalink
1.5.0 (#16)
Browse files Browse the repository at this point in the history
- Configuration dialog and file
- Configurable key to start block search
- Remembering block search text (optional)
- Remembering profile search text (optional)
  • Loading branch information
viktor-ferenczi authored Apr 26, 2024
1 parent 9533356 commit bbe3bb8
Show file tree
Hide file tree
Showing 10 changed files with 371 additions and 54 deletions.
67 changes: 67 additions & 0 deletions ToolbarManager/Config.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.IO;
using System.Xml.Serialization;
using VRage.FileSystem;
using VRage.Input;
using VRage.Utils;

namespace ToolbarManager
{
public class PluginConfig
{
public bool KeepProfileSearchText = false;
public string LatestProfileSearchText = "";

public bool KeepBlockSearchText = false;
public string LatestBlockSearchText = "";

public MyKeys BlockSearchKey = MyKeys.OemPipe;
}

public static class Config
{
public static PluginConfig Data { get; private set; } = new PluginConfig();

private static readonly string ConfigPath = Path.Combine(MyFileSystem.UserDataPath, "Storage", "ToolbarManager.cfg");
private static readonly XmlSerializer ConfigSerializer = new XmlSerializer(typeof(PluginConfig));

public static bool Save()
{
try
{
using (var writer = File.CreateText(ConfigPath))
{
ConfigSerializer.Serialize(writer, Data);
}
}
catch (Exception e)
{
MyLog.Default.Error($"Could not save config: {ConfigPath} | {e}");
return false;
}

return true;
}

public static void Load()
{
if (!File.Exists(ConfigPath))
{
MyLog.Default.Error($"Could not find config file: {ConfigPath}");
return;
}

try
{
using (var reader = new StreamReader(ConfigPath))
{
Data = (PluginConfig) ConfigSerializer.Deserialize(reader);
}
}
catch (Exception e)
{
MyLog.Default.Error($"Failed to load config file: {ConfigPath} | {e}");
}
}
}
}
46 changes: 44 additions & 2 deletions ToolbarManager/Gui/CustomToolbarConfigScreen.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using HarmonyLib;
using Sandbox.Game.Entities;
using Sandbox.Game.Gui;
using Sandbox.Game.Screens.Helpers;
Expand All @@ -14,6 +16,9 @@ namespace ToolbarManager.Gui
[SuppressMessage("ReSharper", "UnusedMember.Global")]
public class CustomToolbarConfigScreen : MyGuiScreenCubeBuilder
{
private static readonly MethodInfo SearchItemTextboxTextChangedMethod = AccessTools.Method(typeof(MyGuiScreenToolbarConfigBase), "searchItemTexbox_TextChanged");
private static readonly FieldInfo FramesBeforeSearchEnabledField = AccessTools.Field(typeof(MyGuiScreenToolbarConfigBase), "m_framesBeforeSearchEnabled");

private readonly CustomSearchCondition customSearchCondition = new CustomSearchCondition();
private MyGuiControlLabel searchInfoLabel;

Expand All @@ -25,12 +30,49 @@ public CustomToolbarConfigScreen(int scrollOffset, MyCubeBlock owner, string sel
{
}

public void SetSearchText(string text)
protected override void OnClosed()
{
if (Config.Data.KeepBlockSearchText)
{
Config.Data.LatestBlockSearchText = SearchText;
Config.Save();
}

base.OnClosed();
}

public override void LoadContent()
{
base.LoadContent();

if (!Config.Data.KeepBlockSearchText)
return;

var searchText = Config.Data.LatestBlockSearchText.Trim();
if (searchText.Length == 0)
return;

SetSearchText(Config.Data.LatestBlockSearchText.Trim());
}

private void SetSearchText(string text)
{
var framesBeforeSearchEnabledField = (int) FramesBeforeSearchEnabledField.GetValue(this);
if (framesBeforeSearchEnabledField > 0)
{
MyEntities.InvokeLater(() => SetSearchText(text));
}

m_searchBox.SearchText = text;
m_searchBox.TextBox.MoveCarriageToEnd();
// m_searchBox.TextBox.MoveCarriageToEnd();
m_searchBox.TextBox.SelectAll();

// KEEN!!! This method works only if m_framesBeforeSearchEnabled <= 0
SearchItemTextboxTextChangedMethod.Invoke(this, new object[] { text });
}

private string SearchText => m_searchBox.SearchText ?? "";

protected override void AddToolsAndAnimations(IMySearchCondition searchCondition)
{
if (searchCondition == m_nameSearchCondition)
Expand Down
14 changes: 12 additions & 2 deletions ToolbarManager/Gui/NameDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,21 @@ public class NameDialog : MyGuiScreenDebugBase
private readonly string caption;
private readonly string defaultName;
private readonly int maxLength;
private readonly bool moveCursorToEnd;

public NameDialog(
Action<string> callBack,
string caption,
string defaultName,
int maxLength = 40)
int maxLength = 40,
bool moveCursorToEnd = false)
: base(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.28f), MyGuiConstants.SCREEN_BACKGROUND_COLOR * MySandboxGame.Config.UIBkOpacity, true)
{
this.callBack = callBack;
this.caption = caption;
this.defaultName = defaultName;
this.maxLength = maxLength;
this.moveCursorToEnd = moveCursorToEnd;

RecreateControls(true);

Expand Down Expand Up @@ -65,7 +68,14 @@ public override void RecreateControls(bool constructor)
Text = defaultName,
Size = new Vector2(0.385f, 1f)
};
nameBox.SelectAll();
if (moveCursorToEnd)
{
nameBox.MoveCarriageToEnd();
}
else
{
nameBox.SelectAll();
}
Controls.Add(nameBox);

okButton = new MyGuiControlButton(originAlign: MyGuiDrawAlignEnum.HORISONTAL_RIGHT_AND_VERTICAL_CENTER, text: MyTexts.Get(MyCommonTexts.Ok), onButtonClick: OnOk);
Expand Down
206 changes: 206 additions & 0 deletions ToolbarManager/Gui/PluginConfigDialog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
using System;
using System.Reflection;
using System.Text;
using Sandbox;
using Sandbox.Game.Gui;
using Sandbox.Graphics.GUI;
using VRage;
using VRage.Game;
using VRage.Input;
using VRage.Utils;
using VRageMath;

namespace ToolbarManager.Gui
{
public class PluginConfigDialog : MyGuiScreenBase
{
private const string Caption = "Toolbar Manager Configuration";
public override string GetFriendlyName() => "ToolbarManagerConfigDialog";

private MyLayoutTable layoutTable;

private MyGuiControlLabel keepBlockSearchTextLabel;
private MyGuiControlCheckbox keepBlockSearchTextCheckbox;

private MyGuiControlLabel keepProfileSearchTextLabel;
private MyGuiControlCheckbox keepProfileSearchTextCheckbox;

private MyControl blockSearchKeyControl;
private MyGuiControlLabel blockSearchKeyLabel;
private MyGuiControlButton blockSearchKeyButton;

private MyGuiControlButton closeButton;

public PluginConfigDialog() : base(new Vector2(0.5f, 0.5f), MyGuiConstants.SCREEN_BACKGROUND_COLOR, new Vector2(0.5f, 0.5f), false, null, MySandboxGame.Config.UIBkOpacity, MySandboxGame.Config.UIOpacity)
{
EnabledBackgroundFade = true;
m_closeOnEsc = true;
m_drawEvenWithoutFocus = true;
CanHideOthers = true;
CanBeHidden = true;
CloseButtonEnabled = true;
}

public override void LoadContent()
{
base.LoadContent();
RecreateControls(true);
}

public override void RecreateControls(bool constructor)
{
base.RecreateControls(constructor);

CreateControls();
LayoutControls();
}

private void CreateControls()
{
AddCaption(Caption);

CreateCheckbox(
out keepProfileSearchTextLabel,
out keepProfileSearchTextCheckbox,
Config.Data.KeepProfileSearchText,
value => { Config.Data.KeepProfileSearchText = value; },
"Keep profile search text",
"Keep the search text between subsequent uses of the Profile dialog.");

CreateCheckbox(
out keepBlockSearchTextLabel,
out keepBlockSearchTextCheckbox,
Config.Data.KeepBlockSearchText,
value => { Config.Data.KeepBlockSearchText = value; },
"Keep block search text",
"Keep the search text between subsequent uses of the block search.");

blockSearchKeyControl = new MyControl(
MyStringId.GetOrCompute("ToolbarManagerBlockSearch"),
MyStringId.GetOrCompute("Key to start block search"),
MyGuiControlTypeEnum.General,
null,
Config.Data.BlockSearchKey,
MyStringId.GetOrCompute("Key to open the G menu and activate block search"),
null,
MyStringId.GetOrCompute("Key to open the G menu and activate block search"));

CreateControlButton(out blockSearchKeyLabel, out blockSearchKeyButton, blockSearchKeyControl, "Key to start block search");

closeButton = new MyGuiControlButton(originAlign: MyGuiDrawAlignEnum.HORISONTAL_RIGHT_AND_VERTICAL_CENTER, text: MyTexts.Get(MyCommonTexts.Ok), onButtonClick: OnOk);
}

private class ControlButtonData
{
public readonly MyControl Control;
public readonly MyGuiInputDeviceEnum Device;

public ControlButtonData(MyControl control, MyGuiInputDeviceEnum device)
{
Control = control;
Device = device;
}
}

private void CreateControlButton(out MyGuiControlLabel label, out MyGuiControlButton button, MyControl control, string labelText, bool enabled = true)
{
label = new MyGuiControlLabel
{
Text = labelText,
OriginAlign = MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_TOP,
Enabled = enabled,
};

StringBuilder output = null;
control.AppendBoundButtonNames(ref output, MyGuiInputDeviceEnum.Keyboard);
MyControl.AppendUnknownTextIfNeeded(ref output, MyTexts.GetString(MyCommonTexts.UnknownControl_None));
button = new MyGuiControlButton(text: output, onButtonClick: OnControlClick, onSecondaryButtonClick: OnSecondaryControlClick)
{
VisualStyle = MyGuiControlButtonStyleEnum.ControlSetting,
UserData = new ControlButtonData(control, MyGuiInputDeviceEnum.Keyboard),
};
}

private void OnControlClick(MyGuiControlButton button)
{
var userData = (ControlButtonData) button.UserData;
var messageText = MyCommonTexts.AssignControlKeyboard;
if (userData.Device == MyGuiInputDeviceEnum.Mouse)
messageText = MyCommonTexts.AssignControlMouse;

// KEEN!!! MyGuiScreenOptionsControls.MyGuiControlAssignKeyMessageBox is PRIVATE!
var screenClass = typeof(MyGuiScreenOptionsControls).GetNestedType("MyGuiControlAssignKeyMessageBox", BindingFlags.NonPublic);
var editBindingDialog = (MyGuiScreenBase) Activator.CreateInstance(screenClass, BindingFlags.CreateInstance, null, new object[] { userData.Device, userData.Control, messageText }, null);
editBindingDialog.Closed += (s, isUnloading) => StoreControlSelection(button);
MyGuiSandbox.AddScreen(editBindingDialog);
}

private static void StoreControlSelection(MyGuiControlButton button)
{
StringBuilder output = null;
var userData = (ControlButtonData) button.UserData;
userData.Control.AppendBoundButtonNames(ref output, userData.Device);

Config.Data.BlockSearchKey = userData.Control.GetKeyboardControl();

MyControl.AppendUnknownTextIfNeeded(ref output, MyTexts.GetString(MyCommonTexts.UnknownControl_None));
button.Text = output.ToString();
output.Clear();
}

private void OnSecondaryControlClick(MyGuiControlButton obj)
{
}

private void OnOk(MyGuiControlButton _) => CloseScreen();

private void CreateCheckbox(out MyGuiControlLabel labelControl, out MyGuiControlCheckbox checkboxControl, bool value, Action<bool> store, string label, string tooltip, bool enabled = true)
{
labelControl = new MyGuiControlLabel
{
Text = label,
OriginAlign = MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_TOP,
Enabled = enabled,
};

checkboxControl = new MyGuiControlCheckbox(toolTip: tooltip)
{
OriginAlign = MyGuiDrawAlignEnum.HORISONTAL_CENTER_AND_VERTICAL_TOP,
IsChecked = value,
Enabled = enabled,
CanHaveFocus = enabled
};
if (enabled)
{
checkboxControl.IsCheckedChanged += cb => store(cb.IsChecked);
}
else
{
checkboxControl.IsCheckedChanged += cb => { cb.IsChecked = value; };
}
}

private void LayoutControls()
{
layoutTable = new MyLayoutTable(this, new Vector2(-0.2f, -0.25f), new Vector2(0.20f, 0.25f));
layoutTable.SetColumnWidths(500f, 500f);
layoutTable.SetRowHeights(150f, 90f, 90f, 90f, 90f, 180f);

var row = 1;

layoutTable.Add(keepProfileSearchTextLabel, MyAlignH.Left, MyAlignV.Top, row, 0);
layoutTable.Add(keepProfileSearchTextCheckbox, MyAlignH.Left, MyAlignV.Top, row, 1);
row++;

layoutTable.Add(keepBlockSearchTextLabel, MyAlignH.Left, MyAlignV.Top, row, 0);
layoutTable.Add(keepBlockSearchTextCheckbox, MyAlignH.Left, MyAlignV.Top, row, 1);
row++;

layoutTable.Add(blockSearchKeyLabel, MyAlignH.Left, MyAlignV.Top, row, 0);
layoutTable.Add(blockSearchKeyButton, MyAlignH.Left, MyAlignV.Top, row, 1);
row++;

layoutTable.Add(closeButton, MyAlignH.Center, MyAlignV.Center, row, 0, colSpan: 2);
}
}
}
Loading

0 comments on commit bbe3bb8

Please sign in to comment.