UltimateZoneBuilder/Source/Core/Actions/HintsManager.cs
MaxED 0369c969d1 According to dotnetperls.com, "new Dictionary<string, [anything]>(StringComparer.Ordinal)" works 17% faster than "new Dictionary<string, [anything]>()", so let's stick that everywhere and see what happens :)
Draw Curve Mode: added settings panel.
Sectors mode: added "Make Door" button to the toolbar.
Swapped Side panel and Info panel z-order. 
Interface: split toolbar into 3 separate toolbars. All toolbar buttons are now viewable at 1024x768.
Interface: grouped stuff in "Modes" menu a bit better.
Interface: added "Draw [stuff]" buttons to modes toolbar.
Interface: reorganized main menu. Hope it makes more sense now.
API: added General.Interface.AddModesButton() and General.Interface.AddModesMenu(), which can be used to add buttons to specific group in "Modes" toolbar and menu items to specific group in "Modes" menu, so actions, which behave like an editing mode, but are not part of one can be added there.
2014-02-26 14:11:06 +00:00

151 lines
4.6 KiB
C#

#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?
if(rn.EndsWith(HINTS_RESOURCE, StringComparison.InvariantCultureIgnoreCase)) {
string line;
string classname = string.Empty;
string groupname = string.Empty;
List<string> lines = new List<string>(2);
// Get a stream from the resource
using(Stream data = asm.GetManifestResourceStream(rn)) {
using(StreamReader reader = new StreamReader(data, Encoding.ASCII)) {
while (!reader.EndOfStream) {
lines.Add(reader.ReadLine());
}
}
}
Dictionary<string, List<string>> group = new Dictionary<string, List<string>>(StringComparer.Ordinal);
foreach(string s in lines) {
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));
break;
}
}
}
private 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
Console.WriteLine("WARNING: Unable to get hints for class '" + fullname + "', group '" + groupname + "'");
#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
}
}