/// <summary> /// Updates the size. /// </summary> private void UpdateSize() { if (!this.isInitialized) { return; } this.LinesInfo.Clear(); if (!string.IsNullOrEmpty(this.text) && this.SpriteFont != null) { this.FontHeight = this.SpriteFont.MeasureString("A").Y; if (!this.RichTextEnabled) { if (this.textWrapping) { // Filters this.text = this.text.Replace("\r\n", " /n "); this.text = this.text.Replace("\n", " /n "); this.text = this.text.Replace("/n", " /n "); string[] words = this.text.Split(' '); var stringBuilder = new StringBuilder(); int i = 0; while (i < words.Length) { do { if (words[i].Equals("/n")) { i++; break; } string nextString = string.Format("{0}{1} ", stringBuilder, words[i]); float lineSize = this.SpriteFont.MeasureString(nextString).X; if (stringBuilder.Length != 0 && lineSize > this.Width) { break; } stringBuilder.Append(words[i]); stringBuilder.Append(" "); i++; } while (i < words.Length); string text = stringBuilder.ToString(); Vector2 size = this.SpriteFont.MeasureString(text); float offsetX = this.CalculateAlignmentOffset(size); this.LinesInfo.Add(new LineInfo(text, this.Foreground, size, offsetX)); stringBuilder.Length = 0; } this.Height = this.LinesInfo.Count * (this.FontHeight + this.lineSpacing); } else { Vector2 size = this.SpriteFont.MeasureString(this.text); float offsetX = this.CalculateAlignmentOffset(size); this.LinesInfo.Add(new LineInfo(this.text, this.Foreground, size, offsetX)); if (this.lineWidth != -1) { base.Width = this.lineWidth; } else { base.Width = size.X; } this.Height = size.Y; } } else { if (this.textWrapping) { // Filters this.text = this.text.Replace("\r\n", " /n "); this.text = this.text.Replace("\n", " /n "); this.text = this.text.Replace("/n", " /n "); } else { base.Width = 0; } XDocument document = XDocument.Parse("<p>" + this.text + "</p>"); float acumulatedSize = 0; int lineInfoId = 0; this.LinesInfo.Add(new LineInfo(0)); XNode child = document.Root.FirstNode; while (child != null) { Vector2 size; Color color; string textValue; switch (child.NodeType) { case XmlNodeType.Element: XElement element = child as XElement; if (element.Name == "rtf" && element.Attribute("Foreground") != null) { // Sets foreground var colorAttribute = element.Attribute("Foreground"); color = new Color(colorAttribute.Value); } else { color = this.Foreground; } textValue = element.Value; break; case XmlNodeType.Text: color = this.Foreground; XText xText = child as XText; textValue = xText.Value; break; default: color = this.Foreground; textValue = string.Empty; break; } string[] textFragments; if (!this.textWrapping) { textFragments = textValue.Split('\n'); } else { textFragments = textValue.Split(' '); } var stringBuilder = new StringBuilder(); int i = 0; while (i < textFragments.Length) { if (this.textWrapping) { stringBuilder.Clear(); do { if (textFragments[i].Equals("/n")) { i++; break; } string currentFragment = textFragments[i].Trim(); if (currentFragment == string.Empty) { i++; continue; } string nextString = string.Format("{0}{1} ", stringBuilder, currentFragment); float lineSize = this.SpriteFont.MeasureString(nextString).X + acumulatedSize; if (stringBuilder.Length != 0 && lineSize > this.Width) { break; } stringBuilder.Append(currentFragment); i++; stringBuilder.Append(" "); } while (i < textFragments.Length); } else { stringBuilder.Clear(); stringBuilder.Append(textFragments[i]); i++; } size = this.SpriteFont.MeasureString(stringBuilder.ToString()); LineInfo lineInfo = this.LinesInfo[lineInfoId]; lineInfo.AddText(stringBuilder.ToString(), color, size); this.LinesInfo[lineInfoId] = lineInfo; acumulatedSize += size.X; if (!this.textWrapping) { base.Width = MathHelper.Max(acumulatedSize, this.Width); } if (textFragments.Length > 1 && i < textFragments.Length) { this.LinesInfo.Add(new LineInfo(0)); lineInfoId++; acumulatedSize = 0; } } child = child.NextNode; } ////Debug.WriteLine("{"); float height = 0; for (int i = 0; i < this.LinesInfo.Count; i++) { LineInfo info = this.LinesInfo[i]; info.AlignmentOffsetX = this.CalculateAlignmentOffset(info.Size); this.LinesInfo[i] = info; height += info.Size.Y; ////Debug.WriteLine(string.Format("\tLineInfo [Size: {0} Offset: {1}]", info.Size, info.AlignmentOffsetX)); ////foreach (var fragment in info.SubTextList) ////{ //// Debug.WriteLine(string.Format("\t\tFragment [Size: {0} Text: \"{1}\"]", fragment.Size, fragment.Text)); ////} } ////Debug.WriteLine("}"); this.Height = height + (this.LineSpacing * this.LinesInfo.Count); if (this.Owner != null && this.Owner.Parent != null) { this.Arrange(this.Owner.Parent.FindComponent<Transform2D>().Rectangle); } } // Event if (this.OnWidthChanged != null) { this.OnWidthChanged(this, this.Width); } } }
/// <summary> /// Handles the TouchPressed event of the Gestures control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="GestureEventArgs" /> instance containing the event data.</param> private void Gestures_TouchPressed(object sender, GestureEventArgs e) { this.IsFocus = true; if (this.isReadOnly) { return; } if (this.inputService.KeyboardState.IsConnected) { float clickX = e.GestureSample.Position.X - this.Transform.Rectangle.X; float clickY = e.GestureSample.Position.Y - this.Transform.Rectangle.Y; // Cursor position Y float posY = this.textControl.LineSpacing; int lineIndex = 0; while (lineIndex < this.textControl.LinesInfo.Count - 1 && posY + this.textControl.FontHeight < clickY) { posY += this.textControl.FontHeight + this.textControl.LineSpacing; lineIndex++; } // Cursor position X float posX = 0; if (this.textControl.LinesInfo.Count > 0) { LineInfo lineInfo = this.textControl.LinesInfo[lineIndex]; if (posY + this.textControl.FontHeight < clickY) { // Outside of textControl posX = lineInfo.AlignmentOffsetX + lineInfo.Size.X; this.textBeforeCursor = this.textControl.Text; this.textAfterCursor = string.Empty; } else { // Search X position posX = lineInfo.AlignmentOffsetX; float maxOffsetX = lineInfo.AlignmentOffsetX + lineInfo.Size.X; int characterIndex = 0; string currentLineText = lineInfo.SubTextList[0].Text; float characterOffset = this.textControl.SpriteFont.MeasureString(currentLineText[characterIndex].ToString()).X; while (posX <= maxOffsetX && posX + (characterOffset / 2) < clickX) { posX += characterOffset; if (characterIndex < currentLineText.Length - 1) { characterIndex++; characterOffset = this.textControl.SpriteFont.MeasureString(currentLineText[characterIndex].ToString()).X; } else { break; } } // Text before cursor List <LineInfo> linesInfo = this.textControl.LinesInfo; this.textBeforeCursor = string.Empty; for (int i = 0; i < lineIndex; i++) { this.textBeforeCursor += this.textControl.LinesInfo[i].SubTextList[0].Text; } this.textBeforeCursor += currentLineText.Substring(0, characterIndex); // Text After cursor this.textAfterCursor = currentLineText.Substring(characterIndex); for (int i = lineIndex + 1; i < this.textControl.LinesInfo.Count; i++) { this.textAfterCursor += this.textControl.LinesInfo[i].SubTextList[0].Text; } } } // Final positions this.cursorTransform.X = posX; this.cursorTransform.Y = posY; this.cursorAnimation.BeginAnimation(Transform2D.OpacityProperty, this.flicker); } else { this.ShowScreenKeyboard(); } }