private static List <ButtonPrimitive> syn(string printBuffer) { var printString = printBuffer; var ret = new List <ButtonPrimitive>(); if (printString.Length == 0) { goto nonButton; } List <string> strs = null; if (!printString.Contains("[") || !printString.Contains("]")) { goto nonButton; } strs = lex(new StringStream(printString)); if (strs == null) { goto nonButton; } var beforeButton = false; //最初のボタン("[1]"とか)より前にテキストがある var afterButton = false; //最後のボタン("[1]"とか)より後にテキストがある var buttonCount = 0; long inpL = 0; for (var i = 0; i < strs.Count; i++) { if (strs[i].Length == 0) { continue; } var c = strs[i][0]; if (LexicalAnalyzer.IsWhiteSpace(c)) { //ただの空白 } //数値以外はボタン化しない方向にした。 //else if ((c == '[') && (!isSymbols(strArray[i]))) else if (isButtonCore(strs[i], ref inpL)) { //[]で囲まれた文字列。選択肢の核となるかどうかはこの段階では判定しない。 buttonCount++; afterButton = false; } else { //選択肢の説明になるかもしれない文字列 afterButton = true; if (buttonCount == 0) { beforeButton = true; } } } if (buttonCount <= 1) { var button = new ButtonPrimitive(); button.Str = printBuffer; button.CanSelect = buttonCount >= 1; button.Input = inpL; ret.Add(button); return(ret); } buttonCount = 0; var alignmentRight = !beforeButton && afterButton; //説明はボタンの右固定 var alignmentLeft = beforeButton && !afterButton; //説明はボタンの左固定 var alignmentEtc = !alignmentRight && !alignmentLeft; //臨機応変に var canSelect = false; long input = 0; var state = 0; var buffer = new StringBuilder(); VoidMethod reduce = delegate { if (buffer.Length == 0) { return; } var button = new ButtonPrimitive(); button.Str = buffer.ToString(); button.CanSelect = canSelect; button.Input = input; ret.Add(button); buffer.Remove(0, buffer.Length); canSelect = false; input = 0; }; for (var i = 0; i < strs.Count; i++) { if (strs[i].Length == 0) { continue; } var c = strs[i][0]; if (LexicalAnalyzer.IsWhiteSpace(c)) { //ただの空白 if ((state & 3) == 3 && alignmentEtc && strs[i].Length >= 2) { //核と説明を含んだものが完成していればボタン生成。 //一文字以下のスペースはキニシナイ。キャラ購入画面対策 reduce(); buffer.Append(strs[i]); state = 0; } else { buffer.Append(strs[i]); } continue; } if (isButtonCore(strs[i], ref inpL)) { buttonCount++; if ((state & 1) == 1 || alignmentRight) { //bufferが既に核を含んでいる、又は強制的に右配置 reduce(); buffer.Append(strs[i]); input = inpL; canSelect = true; state = 1; } //((state & 2) == 2) || else if (alignmentLeft) { //bufferが説明を含んでいる、又は強制的に左配置 buffer.Append(strs[i]); input = inpL; canSelect = true; reduce(); state = 0; } else { //bufferが空または空白文字列 buffer.Append(strs[i]); input = inpL; canSelect = true; state = 1; } continue; } //else //{//選択肢の説明になるかもしれない文字列 buffer.Append(strs[i]); state |= 2; //} } ; reduce(); return(ret); nonButton: ret = new List <ButtonPrimitive>(); var singleButton = new ButtonPrimitive(); singleButton.Str = printString; ret.Add(singleButton); return(ret); }
/// <summary> /// 物理行をボタン単位に分割。引数のcssListの内容は変更される場合がある。 /// </summary> /// <returns></returns> private ConsoleButtonString[] createButtons(List <AConsoleDisplayPart> cssList) { StringBuilder buf = new StringBuilder(); for (int i = 0; i < cssList.Count; i++) { buf.Append(cssList[i].Str); } List <ButtonPrimitive> bpList = ButtonStringCreator.SplitButton(buf.ToString()); ConsoleButtonString[] ret = new ConsoleButtonString[bpList.Count]; AConsoleDisplayPart[] cssArray = null; if (ret.Length == 1) { cssArray = new AConsoleDisplayPart[cssList.Count]; cssList.CopyTo(cssArray); if (bpList[0].CanSelect) { ret[0] = new ConsoleButtonString(parent, cssArray, bpList[0].Input); } else { ret[0] = new ConsoleButtonString(parent, cssArray); } return(ret); } int cssStartCharIndex = 0; int buttonEndCharIndex = 0; int cssIndex = 0; List <AConsoleDisplayPart> buttonCssList = new List <AConsoleDisplayPart>(); for (int i = 0; i < ret.Length; i++) { ButtonPrimitive bp = bpList[i]; buttonEndCharIndex += bp.Str.Length; while (true) { if (cssIndex >= cssList.Count) { break; } AConsoleDisplayPart css = cssList[cssIndex]; if (cssStartCharIndex + css.Str.Length >= buttonEndCharIndex) { //ボタンの終端を発見 int used = buttonEndCharIndex - cssStartCharIndex; if (used > 0 && css.CanDivide) { //cssの区切りの途中でボタンの区切りがある。 ConsoleStyledString newCss = ((ConsoleStyledString)css).DivideAt(used); if (newCss != null) { cssList.Insert(cssIndex + 1, newCss); newCss.PointX = css.PointX + css.Width; } } buttonCssList.Add(css); cssStartCharIndex += css.Str.Length; cssIndex++; break; } //ボタンの終端はまだ先。 buttonCssList.Add(css); cssStartCharIndex += css.Str.Length; cssIndex++; } cssArray = new AConsoleDisplayPart[buttonCssList.Count]; buttonCssList.CopyTo(cssArray); if (bp.CanSelect) { ret[i] = new ConsoleButtonString(parent, cssArray, bp.Input); } else { ret[i] = new ConsoleButtonString(parent, cssArray); } buttonCssList.Clear(); } return(ret); }
private static List<ButtonPrimitive> syn(string printBuffer) { string printString = printBuffer.ToString(); List<ButtonPrimitive> ret = new List<ButtonPrimitive>(); if (printString.Length == 0) goto nonButton; List<string> strs = null; if ((!printString.Contains("[")) || (!printString.Contains("]"))) goto nonButton; strs = lex(new StringStream(printString)); if (strs == null) goto nonButton; bool beforeButton = false;//最初のボタン("[1]"とか)より前にテキストがある bool afterButton = false;//最後のボタン("[1]"とか)より後にテキストがある int buttonCount = 0; Int64 inpL = 0; for (int i = 0; i < strs.Count; i++) { if (strs[i].Length == 0) continue; char c = strs[i][0]; if (LexicalAnalyzer.IsWhiteSpace(c)) {//ただの空白 } //数値以外はボタン化しない方向にした。 //else if ((c == '[') && (!isSymbols(strArray[i]))) else if (isButtonCore(strs[i], ref inpL)) {//[]で囲まれた文字列。選択肢の核となるかどうかはこの段階では判定しない。 buttonCount++; afterButton = false; } else {//選択肢の説明になるかもしれない文字列 afterButton = true; if (buttonCount == 0) beforeButton = true; } } if (buttonCount <= 1) { ButtonPrimitive button = new ButtonPrimitive(); button.Str = printBuffer.ToString(); button.CanSelect = (buttonCount >= 1); button.Input = inpL; ret.Add(button); return ret; } buttonCount = 0; bool alignmentRight = !beforeButton && afterButton;//説明はボタンの右固定 bool alignmentLeft = beforeButton && !afterButton;//説明はボタンの左固定 bool alignmentEtc = !alignmentRight && !alignmentLeft;//臨機応変に bool canSelect = false; Int64 input = 0; int state = 0; StringBuilder buffer = new StringBuilder(); VoidMethod reduce = delegate { if (buffer.Length == 0) return; ButtonPrimitive button = new ButtonPrimitive(); button.Str = buffer.ToString(); button.CanSelect = canSelect; button.Input = input; ret.Add(button); buffer.Remove(0, buffer.Length); canSelect = false; input = 0; }; for (int i = 0; i < strs.Count; i++) { if (strs[i].Length == 0) continue; char c = strs[i][0]; if (LexicalAnalyzer.IsWhiteSpace(c)) {//ただの空白 if (((state & 3) == 3) && (alignmentEtc) && (strs[i].Length >= 2)) {//核と説明を含んだものが完成していればボタン生成。 //一文字以下のスペースはキニシナイ。キャラ購入画面対策 reduce(); buffer.Append(strs[i]); state = 0; } else { buffer.Append(strs[i]); } continue; } if(isButtonCore(strs[i], ref inpL)) { buttonCount++; if (((state & 1) == 1) || alignmentRight) {//bufferが既に核を含んでいる、又は強制的に右配置 reduce(); buffer.Append(strs[i]); input = inpL; canSelect = true; state = 1; }//((state & 2) == 2) || else if (alignmentLeft) {//bufferが説明を含んでいる、又は強制的に左配置 buffer.Append(strs[i]); input = inpL; canSelect = true; reduce(); state = 0; } else {//bufferが空または空白文字列 buffer.Append(strs[i]); input = inpL; canSelect = true; state = 1; } continue; } //else //{//選択肢の説明になるかもしれない文字列 buffer.Append(strs[i]); state |= 2; //} }; reduce(); return ret; nonButton: ret = new List<ButtonPrimitive>(); ButtonPrimitive singleButton = new ButtonPrimitive(); singleButton.Str = printString; ret.Add(singleButton); return ret; }