/// <summary> /// When the text / scroll / highlight changes we need to /// re-compute how we are going to draw this text field /// </summary> public void ComputeDrawingCommands() { m_DrawCmds.Clear(); m_DrawDirty = false; /** * Split the text into lines using manual lines * breaks and word wrap */ string txt = null; if (m_Password) { /** Use * instead **/ txt = ""; for (int i = 0; i < m_SBuilder.Length; i++) { txt += "*"; } } else { txt = CurrentTextParsed; } var lineWidth = m_Width - (TextMargin.Left + TextMargin.Height); m_LineHeight = TextStyle.MeasureString("W").Y + TextStyle.LineHeightModifier; var bbCommands = BBCodeEnabled ? CodeParser.Commands : new List <BBCodeCommand>(); var bbIndex = 0; m_Lines.Clear(); //txt = txt.Replace("\r", ""); var words = txt.Split(' ').ToList(); var spaceWidth = TextStyle.MeasureString(" ").X; /** * Modify the array to make manual line breaks their own segment * in the array */ var newWordsArray = TextRenderer.ExtractLineBreaks(words); TextRenderer.CalculateLines(m_Lines, newWordsArray, TextStyle, lineWidth, spaceWidth, new Vector2(), m_LineHeight); var topLeft = new Vector2(TextMargin.Left, TextMargin.Top); var position = topLeft; var txtScale = TextStyle.Scale * _Scale; m_NumVisibleLines = Math.Max(1, (int)Math.Floor(m_Height / m_LineHeight)); /** Make sure the current vscroll is valid **/ VerticalScrollPosition = m_VScroll; if (m_Slider != null) { m_Slider.MaxValue = Math.Max(0, m_Lines.Count - m_NumVisibleLines); m_Slider.Value = VerticalScrollPosition; } var bbColorStack = new Stack <Color>(); var lastColor = TextStyle.Color; var yPosition = topLeft.Y; var numLinesAdded = 0; var shadowApplied = false; for (var i = 0; i < m_Lines.Count - m_VScroll; i++) { var line = m_Lines[m_VScroll + i]; var segments = CalculateSegments(line, bbCommands, ref bbIndex); var xPosition = topLeft.X; segments.ForEach(x => x.Size = TextStyle.MeasureString(x.Text)); var thisLineWidth = segments.Sum(x => x.Size.X); /** Alignment **/ if (Alignment == TextAlignment.Center) { xPosition += (int)Math.Round((lineWidth - thisLineWidth) / 2); } line.LineStartX = (int)xPosition; foreach (var segment in segments) { var segmentSize = segment.Size; var segmentPosition = LocalPoint(new Vector2(xPosition, yPosition)); if (segment.Selected) { m_DrawCmds.Add(new TextDrawCmd_SelectionBox { BlendColor = TextStyle.SelectionBoxColor, Texture = TextureGenerator.GetPxWhite(GameFacade.GraphicsDevice), Position = segmentPosition, Scale = new Vector2(segmentSize.X, m_LineHeight) * _Scale }); } if (segment.Text.Length > 0) { m_DrawCmds.Add(new TextDrawCmd_Text { Selected = segment.Selected, Text = segment.Text, Style = TextStyle, Position = segmentPosition, Scale = txtScale }); xPosition += segmentSize.X; } if (segment.StartCommand != null) { var cmd = segment.StartCommand; switch (cmd.Type) { case BBCodeCommandType.color: if (cmd.Close) { //pop a color off our stack if (bbColorStack.Count > 0) { lastColor = bbColorStack.Pop(); m_DrawCmds.Add(new TextDrawCmd_Color(TextStyle, lastColor)); } } else { bbColorStack.Push(lastColor); lastColor = cmd.ParseColor(); m_DrawCmds.Add(new TextDrawCmd_Color(TextStyle, lastColor)); } break; case BBCodeCommandType.s: if (cmd.Close) { m_DrawCmds.Add(new TextDrawCmd_Shadow(TextStyle, false)); shadowApplied = false; } else { m_DrawCmds.Add(new TextDrawCmd_Shadow(TextStyle, true)); shadowApplied = true; } break; case BBCodeCommandType.emoji: if (segment.BBCatchup) { break; } m_DrawCmds.Add(new TextDrawCmd_Emoji(TextStyle, cmd.Parameter, LocalPoint(new Vector2(xPosition, yPosition)), _Scale)); break; } } } yPosition += m_LineHeight; position.Y += m_LineHeight; numLinesAdded++; if (numLinesAdded >= m_NumVisibleLines) { break; } } if (shadowApplied) { m_DrawCmds.Add(new TextDrawCmd_Shadow(TextStyle, false)); } while (bbColorStack.Count > 0) { lastColor = bbColorStack.Pop(); m_DrawCmds.Add(new TextDrawCmd_Color(TextStyle, lastColor)); } /** No cursor in read only mode **/ if (m_IsReadOnly) { m_DrawCmds.ForEach(x => x.Init()); return; } var start = Control_GetSelectionStart(); var cursorLine = GetLineForIndex(start); if (cursorLine != null && cursorLine.LineNumber >= m_VScroll && cursorLine.LineNumber < m_VScroll + m_NumVisibleLines) { var prefix = start - cursorLine.StartIndex; var cursorPosition = new Vector2(cursorLine.LineStartX, topLeft.Y + ((cursorLine.LineNumber - m_VScroll) * m_LineHeight)); if (prefix > 0) { if (prefix > cursorLine.Text.Length - 1) { cursorPosition.X += cursorLine.LineWidth; } else { cursorPosition.X += TextStyle.MeasureString(cursorLine.Text.Substring(0, prefix)).X; } } m_DrawCmds.Add(new TextDrawCmd_Cursor { Scale = new Vector2(_Scale.X, m_LineHeight * _Scale.Y), Position = LocalPoint(cursorPosition), Texture = TextureGenerator.GetPxWhite(GameFacade.GraphicsDevice), Color = TextStyle.CursorColor }); } m_DrawCmds.ForEach(x => x.Init()); }
/// <summary> /// When the text / scroll / highlight changes we need to /// re-compute how we are going to draw this text field /// </summary> public void ComputeDrawingCommands() { m_DrawCmds.Clear(); m_DrawDirty = false; /** * Split the text into lines using manual lines * breaks and word wrap */ var txt = m_SBuilder.ToString(); var lineWidth = m_Width - (TextMargin.Left + TextMargin.Height); m_LineHeight = TextStyle.MeasureString("W").Y; m_Lines.Clear(); var words = txt.Split(' ').ToList(); var spaceWidth = TextStyle.MeasureString(" ").X; /** * Modify the array to make manual line breaks their own segment * in the array */ var newWordsArray = TextRenderer.ExtractLineBreaks(words); TextRenderer.CalculateLines(m_Lines, newWordsArray, TextStyle, lineWidth, spaceWidth, new Vector2(), m_LineHeight); var topLeft = new Vector2(TextMargin.Left, TextMargin.Top); var position = topLeft; var txtScale = TextStyle.Scale * _Scale; m_NumVisibleLines = (int)Math.Floor(m_Height / m_LineHeight); /** Make sure the current vscroll is valid **/ VerticalScrollPosition = m_VScroll; if (m_Slider != null) { m_Slider.MaxValue = Math.Max(0, m_Lines.Count - m_NumVisibleLines); m_Slider.Value = VerticalScrollPosition; } var yPosition = topLeft.Y; var numLinesAdded = 0; for (var i = 0; i < m_Lines.Count - m_VScroll; i++) { var line = m_Lines[m_VScroll + i]; var segments = CalculateSegments(line); var xPosition = topLeft.X; segments.ForEach(x => x.Size = TextStyle.MeasureString(x.Text)); var thisLineWidth = segments.Sum(x => x.Size.X); /** Alignment **/ if (Alignment == TextAlignment.Center) { xPosition += (int)Math.Round((lineWidth - thisLineWidth) / 2); } line.LineStartX = (int)xPosition; foreach (var segment in segments) { var segmentSize = segment.Size; var segmentPosition = LocalPoint(new Vector2(xPosition, yPosition)); if (segment.Selected) { m_DrawCmds.Add(new TextDrawCmd_SelectionBox { BlendColor = new Color(0xFF, 0xFF, 0xFF, 200), Texture = TextureUtils.TextureFromColor(GameFacade.GraphicsDevice, TextStyle.SelectionBoxColor), Position = segmentPosition, Scale = new Vector2(segmentSize.X, m_LineHeight) * _Scale }); } m_DrawCmds.Add(new TextDrawCmd_Text { Selected = segment.Selected, Text = segment.Text, Style = TextStyle, Position = segmentPosition, Scale = txtScale }); xPosition += segmentSize.X; } yPosition += m_LineHeight; position.Y += m_LineHeight; numLinesAdded++; if (numLinesAdded >= m_NumVisibleLines) { break; } } /** No cursor in read only mode **/ if (m_IsReadOnly) { m_DrawCmds.ForEach(x => x.Init()); return; } var start = Control_GetSelectionStart(); var cursorLine = GetLineForIndex(start); if (cursorLine != null && cursorLine.LineNumber >= m_VScroll && cursorLine.LineNumber < m_VScroll + m_NumVisibleLines) { var prefix = start - cursorLine.StartIndex; var cursorPosition = new Vector2(cursorLine.LineStartX, topLeft.Y + ((cursorLine.LineNumber - m_VScroll) * m_LineHeight)); if (prefix > 0) { if (prefix > cursorLine.Text.Length - 1) { cursorPosition.X += cursorLine.LineWidth; } else { cursorPosition.X += TextStyle.MeasureString(cursorLine.Text.Substring(0, prefix)).X; } } m_DrawCmds.Add(new TextDrawCmd_Cursor { Scale = new Vector2(_Scale.X, m_LineHeight * _Scale.Y), Position = LocalPoint(cursorPosition), Texture = TextureUtils.TextureFromColor(GameFacade.GraphicsDevice, TextStyle.CursorColor) }); } m_DrawCmds.ForEach(x => x.Init()); }