2015-12-31 12:21:44 +00:00
|
|
|
|
#region ================== Namespaces
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
namespace CodeImp.DoomBuilder.Actions
|
|
|
|
|
{
|
|
|
|
|
public class HintsManager
|
|
|
|
|
{
|
|
|
|
|
#region ================== Public constants
|
|
|
|
|
|
|
|
|
|
public const string GENERAL = "general";
|
|
|
|
|
public const string MULTISELECTION = "multiselection";
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Constants
|
|
|
|
|
|
|
|
|
|
private const string HINTS_RESOURCE = "Hints.cfg";
|
|
|
|
|
private const string CLASS_MARKER = "class";
|
|
|
|
|
private const string GROUP_MARKER = "group";
|
|
|
|
|
private const string DEFAULT_HINT = "{\\rtf1 Press {\\b F1} to show help for current editing mode}";
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Variables
|
|
|
|
|
|
|
|
|
|
private readonly Dictionary<string, Dictionary<string, string>> hints; //<classname, <group, hints as rtf string>>
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Constructor
|
|
|
|
|
|
|
|
|
|
public HintsManager()
|
|
|
|
|
{
|
|
|
|
|
hints = new Dictionary<string, Dictionary<string, string>>(StringComparer.Ordinal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Hints
|
|
|
|
|
|
|
|
|
|
//Hints.cfg is dev-only stuff so bare minimum of boilerplate is present
|
|
|
|
|
//(e.g. create your Hints.cfg exactly the way it's done in the main project).
|
|
|
|
|
internal void LoadHints(Assembly asm)
|
|
|
|
|
{
|
|
|
|
|
// Find a resource named Hints.cfg
|
|
|
|
|
string[] resnames = asm.GetManifestResourceNames();
|
|
|
|
|
string asmname = asm.GetName().Name.ToLowerInvariant() + "_";
|
|
|
|
|
|
|
|
|
|
foreach(string rn in resnames)
|
|
|
|
|
{
|
|
|
|
|
// Found one?
|
2016-04-07 13:29:47 +00:00
|
|
|
|
if(rn.EndsWith(HINTS_RESOURCE, StringComparison.OrdinalIgnoreCase))
|
2015-12-31 12:21:44 +00:00
|
|
|
|
{
|
|
|
|
|
string classname = string.Empty;
|
|
|
|
|
string groupname = string.Empty;
|
|
|
|
|
List<string> lines = new List<string>(2);
|
|
|
|
|
|
|
|
|
|
// Get a stream from the resource
|
2016-03-18 12:52:12 +00:00
|
|
|
|
Stream data = asm.GetManifestResourceStream(rn);
|
|
|
|
|
if(data == null) return;
|
|
|
|
|
using(StreamReader reader = new StreamReader(data, Encoding.ASCII))
|
2015-12-31 12:21:44 +00:00
|
|
|
|
{
|
2016-03-18 12:52:12 +00:00
|
|
|
|
while(!reader.EndOfStream) lines.Add(reader.ReadLine());
|
2015-12-31 12:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Dictionary<string, List<string>> group = new Dictionary<string, List<string>>(StringComparer.Ordinal);
|
|
|
|
|
|
|
|
|
|
foreach(string s in lines)
|
|
|
|
|
{
|
|
|
|
|
string line = s.Trim();
|
|
|
|
|
if(string.IsNullOrEmpty(line) || line.StartsWith("//"))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//class declaration?
|
|
|
|
|
if(line.StartsWith(CLASS_MARKER))
|
|
|
|
|
{
|
|
|
|
|
if(!string.IsNullOrEmpty(classname))
|
|
|
|
|
{
|
|
|
|
|
hints.Add(asmname + classname, ProcessHints(group));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
classname = line.Substring(6, line.Length - 6);
|
|
|
|
|
groupname = string.Empty;
|
|
|
|
|
group.Clear();
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//group declaration?
|
|
|
|
|
if(line.StartsWith(GROUP_MARKER))
|
|
|
|
|
{
|
|
|
|
|
groupname = line.Substring(6, line.Length - 6);
|
|
|
|
|
group.Add(groupname, new List<string>());
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//regular lines
|
|
|
|
|
line = line.Replace("\"", string.Empty).Replace("<b>", "{\\b ").Replace("</b>", "}").Replace("<br>", "\\par ");
|
|
|
|
|
|
|
|
|
|
//replace action names with keys
|
|
|
|
|
int start = line.IndexOf("<k>");
|
|
|
|
|
while(start != -1)
|
|
|
|
|
{
|
|
|
|
|
int end = line.IndexOf("</k>");
|
|
|
|
|
string key = line.Substring(start + 3, end - start - 3);
|
|
|
|
|
line = line.Substring(0, start) + "{\\b " + Action.GetShortcutKeyDesc(key) + "}" + line.Substring(end + 4, line.Length - end - 4);
|
|
|
|
|
start = line.IndexOf("<k>");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
group[groupname].Add(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//add the last class
|
|
|
|
|
hints.Add(asmname + classname, ProcessHints(group));
|
2016-03-18 12:52:12 +00:00
|
|
|
|
return;
|
2015-12-31 12:21:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Dictionary<string, string> ProcessHints(Dictionary<string, List<string>> hintsgroup)
|
|
|
|
|
{
|
|
|
|
|
var result = new Dictionary<string, string>(StringComparer.Ordinal);
|
|
|
|
|
foreach(KeyValuePair<string, List<string>> group in hintsgroup)
|
|
|
|
|
{
|
|
|
|
|
result.Add(group.Key, "{\\rtf1" + string.Join("\\par\\par ", group.Value.ToArray()) + "}");
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ShowHints(Type type, string groupname)
|
|
|
|
|
{
|
|
|
|
|
string fullname = type.Assembly.GetName().Name.ToLowerInvariant() + "_" + type.Name;
|
|
|
|
|
|
|
|
|
|
if(!hints.ContainsKey(fullname) || !hints[fullname].ContainsKey(groupname))
|
|
|
|
|
{
|
|
|
|
|
General.Interface.ShowHints(DEFAULT_HINT);
|
|
|
|
|
#if DEBUG
|
2022-11-25 17:14:35 +00:00
|
|
|
|
Console.WriteLine("WARNING: Unable to get hints for class \"" + fullname + "\", group \"" + groupname + "\"");
|
2015-12-31 12:21:44 +00:00
|
|
|
|
#endif
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
General.Interface.ShowHints(hints[fullname][groupname]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Utility
|
|
|
|
|
|
|
|
|
|
public static string GetRtfString(string text)
|
|
|
|
|
{
|
|
|
|
|
text = text.Replace("<b>", "{\\b ").Replace("</b>", "}").Replace("<br>", "\\par\\par ");
|
|
|
|
|
return "{\\rtf1" + text + "}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
}
|
|
|
|
|
}
|