/// <summary> /// Create empty keymap based on parent keymap /// </summary> public KeyMap(KeyMap parent, string title = null, string help = null) { this.title = title; this.help = help; this.parent = parent ?? throw new ArgumentNullException(nameof(parent)); items = new List <KeyMapItem>(); }
/// <summary> /// Construct with parent node /// </summary> public Mode(Mode parentMode, string name, string help = null, KeyMap keyMap = null) { this.parentMode = parentMode; this.name = name; this.help = help; this.keyMap = keyMap; }
// =============================================================================================== // Define menu map // =============================================================================================== /// <summary>Define list of key-strings. This way used for defining menu</summary> public KeyMap CreateMenu(string path, string title, string help) { var menu = new KeyMap(title, help); var sequence = path.Split('/'); var newSequence = Kbd.ParsePseudo(sequence); Define(newSequence, menu); return(menu); }
/// <summary>Define sequence with given binding</summary> public virtual bool Define(Event [] sequence, object value) { if (sequence == null) { throw new ArgumentNullException(nameof(sequence)); } var currentMap = this; var lastIndex = sequence.Length - 1; for (var i = 0; i < sequence.Length; i++) { var key = sequence[i]; var tmp = currentMap.GetLocal(key); // do not allow defaults if (tmp == null) { // there is no this binding // N.B. Do not look at the parent one! if (i == lastIndex) { // the currentMap is the target map and it does not have definition currentMap.SetLocal(key, value); return(true); } else { // the currentMap is the map in the sequence and it does not have definition var newMap = new KeyMap(); currentMap.SetLocal(key, newMap); currentMap = newMap; } } else { // we found binding in currentMap if (i == lastIndex) { // currentMap is target map, it has binding but we have to redefine it currentMap.SetLocal(key, value); } else { // the currentMap is the map in the sequence and it has definition var map = tmp.value as KeyMap; if (map != null) { currentMap = map; } else { throw new Exception($"Expect KeyMap at '{sequence[i]}' found: '{tmp}' in: '{sequence}'"); } } } } throw new Exception("We can\'t be here"); }
/// <summary> /// Copy this keymap to target one /// </summary> public virtual void CopyTo(KeyMap target) { target.title = title; target.title = help; target.parent = parent; foreach (var item in items) { target.SetLocal(item.key, item.value); } }
public static string RenderMenu(KeyMap menu, int selected, MenuOptions options = MenuOptions.Default) { stringBuilder.Clear(); var count = menu.Count; var txtItems = new string[count]; var valItems = new string[count]; var txtWidth = 0; var valWidth = 0; var txt = string.Empty; var val = string.Empty; for (var i = 0; i < count; i++) { var line = menu[i].value; if (line is MenuLine) { var item = line as MenuLine; txt = item.Text; val = item.Shorcut; } if (txt != null) { txtWidth = Math.Max(txtWidth, txt.Length); } if (val != null) { valWidth = Math.Max(valWidth, val.Length); } txtItems[i] = txt; valItems[i] = val; } var itemWidth = txtWidth + valWidth + SPACE.Length; var lineWidth = itemWidth + SUFFIX.Length + PREFIX.Length; string spaceLine = null; string dashedLine = null; string singleLine = null; string justLine = new string(CHAR_LIGHT_HORIZONTAL, lineWidth); stringBuilder.AppendLine(string.Format(upperLineFormat, justLine)); string itemFormat1 = $"{{0}}{{1,-{itemWidth}}}{{2}}"; string itemFormat2 = $"{{0}}{{1,-{txtWidth}}}{SPACE}{{2,-{valWidth}}}{{3}}"; for (var i = 0; i < count; i++) { var line = menu[i].value; var isSelected = i == selected; if (line is MenuSeparator) { var item = line as MenuSeparator; switch (item.type) { case MenuSeparator.Type.NoLine: break; case MenuSeparator.Type.Space: if (spaceLine == null) { spaceLine = string.Format(menuLineFormat, new string(' ', lineWidth)); } stringBuilder.AppendLine(spaceLine); break; case MenuSeparator.Type.SingleLine: if (singleLine == null) { singleLine = string.Format(middleLineFormat, justLine); } stringBuilder.AppendLine(singleLine); break; case MenuSeparator.Type.DashedLine: if (dashedLine == null) { dashedLine = string.Format(middleLineFormat, new string(CHAR_DASHED_LINE, lineWidth)); } stringBuilder.AppendLine(dashedLine); break; default: throw new Exception(); } } else { var prefix = isSelected ? PREFIX_SELECTED : PREFIX; string item; if (valItems[i] == null) { item = string.Format(itemFormat1, prefix, txtItems[i], SUFFIX); } else if (txtItems[i] != null) { item = string.Format(itemFormat2, prefix, txtItems[i], valItems[i], SUFFIX); } else { throw new ArgumentOutOfRangeException(); } stringBuilder.AppendLine(string.Format(menuLineFormat, item)); } } stringBuilder.AppendLine(string.Format(bottomLineFormat, justLine)); return(stringBuilder.ToString()); }
/// <summary> /// Constructor without parent /// </summary> public Mode(string name, string help = null, KeyMap keyMap = null) { this.name = name; this.help = help; this.keyMap = keyMap; }
/// <summary> /// Create empty keymap based on parent keymap /// </summary> /// <param name="parent"></param> /// <param name="title"></param> public FullKeymap(KeyMap parent, string title = null) : base(parent, title) { }