/// <summary> /// Recursively processes InlineCollection and builds text representation of the RichTextBlock selected content. /// InlineCollection can contain the following inlines: Hyperlink, Bold, Italic, Underline, Span, Run, LineBreak or InlineUIContainer. /// All types of inlines except InlineUIContainer are processed recursively for the full tree depth. /// InlineUIContainer processing is limited only to the children of type TextBlock and RichTextBlock since for practical purposes /// only these UIElements can be easily converted to text. /// E.g. React.js markup that results in creation of InlineUIContainer: /// <![CDATA[ /// <Text> /// Some text /// <Text>Red text</Text> /// <View> /// <Image /> /// <Text>Image description</Text> /// </View> /// </Text>]]> /// The image and the image description will be placed in an InlineUIContainer. /// To simplify processing entire content of Hyperlink and InlineUIContainer is considered selected if <paramref name="selectionEnd"/> is somewhere in the element content. /// </summary> /// <param name="inlines">InlineCollection to be processed.</param> /// <param name="selectedText">Will contain the text representation upon procedure completion.</param> /// <param name="accumulate">If 'true', includes inlines as part of the processed selection.</param> /// <param name="selectionStart">TextPointer to selection start.</param> /// <param name="selectionEnd">TextPointer to selection end.</param> /// <returns>'true' if recursion terminal condition is met.</returns> private static bool ProcessSelectedInlines( InlineCollection inlines, StringBuilder selectedText, bool accumulate, TextPointer selectionStart, TextPointer selectionEnd) { foreach (Inline inline in inlines) { // Begin building the string from selectionStart. if (!accumulate && (object.ReferenceEquals(inline, selectionStart.Parent) || selectionStart.Offset <= inline.ContentEnd.Offset)) { accumulate = true; } // Check for terminal condition. if (inline.ContentStart.Offset > selectionEnd.Offset) { return(true); } switch (inline) { case Hyperlink hyperlink: if (hyperlink.NavigateUri != null) { if (accumulate) { selectedText.Append(hyperlink.NavigateUri.ToString()); } } else { if (ProcessSelectedInlines(hyperlink.Inlines, selectedText, accumulate, selectionStart, selectionEnd)) { return(true); } } break; // Also covers Bold, Italic, Underline. case Span span: if (ProcessSelectedInlines(span.Inlines, selectedText, accumulate, selectionStart, selectionEnd)) { return(true); } break; case Run run: if (accumulate) { int rangeStart = 0; // Check for selection start in this run. if (object.ReferenceEquals(inline, selectionStart.Parent)) { rangeStart = selectionStart.Offset - inline.ContentStart.Offset; } // Check for selection end in this run. if (object.ReferenceEquals(inline, selectionEnd.Parent)) { int rangeEnd = selectionEnd.Offset - inline.ContentStart.Offset; selectedText.Append(run.Text.Substring(rangeStart, rangeEnd - rangeStart)); } else { selectedText.Append(run.Text.Substring(rangeStart)); } } break; case LineBreak lineBreak: if (accumulate) { selectedText.AppendLine(); } break; case InlineUIContainer inlineUIContainer: if (accumulate) { if (inlineUIContainer.Child is Panel panel) { foreach (UIElement uiElement in panel.Children) { ProcessInlineContainerUIElement(uiElement, selectedText); } } else { ProcessInlineContainerUIElement(inlineUIContainer.Child, selectedText); } } break; default: break; } // Check for terminal condition. if (object.ReferenceEquals(inline, selectionEnd.Parent)) { return(true); } } return(false); }
void WindowLoaded(Object sender, RoutedEventArgs args) { int x = GetOffsetRelativeToParagraph(fdsv.Document.ContentStart); TextPointer tp = FindFirstRunInTextContainer(fdsv.Document); }
/// <summary> /// Compute visible rectangle. /// </summary> private Rect CalculateVisibleRect(ITextView textView, TextElement textElement, TextPointer startPointer, TextPointer endPointer) { Geometry geometry = textView.GetTightBoundingGeometryFromTextPositions(startPointer, endPointer); Rect visibleRect = (geometry != null) ? geometry.Bounds : Rect.Empty; Visual visual = textView.RenderScope; while (visual != null && visibleRect != Rect.Empty) { if (VisualTreeHelper.GetClip(visual) != null) { GeneralTransform transform = textView.RenderScope.TransformToAncestor(visual).Inverse; // Safer version of transform to descendent (doing the inverse ourself), // we want the rect inside of our space. (Which is always rectangular and much nicer to work with) if (transform != null) { Rect rectBounds = VisualTreeHelper.GetClip(visual).Bounds; rectBounds = transform.TransformBounds(rectBounds); visibleRect.Intersect(rectBounds); } else { // No visibility if non-invertable transform exists. return(Rect.Empty); } } visual = VisualTreeHelper.GetParent(visual) as Visual; } return(visibleRect); }
internal void DoUpdates() { RichTextBoxHighlight tu; List <Run> newCheckRuns = new List <Run>(); //get indices of change changeIndices = TextBoxHighlightHandler.IdentifyChange(currentText, oldText); TextPointer[] editPoints = adapter.GetPointerAtIndex(changeIndices[0], changeIndices[1]); if (editPoints[0] != null && editPoints[1] != null) { newCheckRuns.AddRange(GetRuns(editPoints[0], editPoints[1])); } //go through underlines and adjust for change int changeMagnitude = currentText.Length - oldText.Length; //set old text to current oldText = currentText; //need highlights to be in sorted order for highlightIndexes to work highlights.Sort(highlightComparer); List <TextPointer> highlightPointers = new List <TextPointer>(highlights.Count); List <int[]> highlightIndexes = new List <int[]>(highlights.Count); List <RichTextBoxHighlight> highlightsToMove = new List <RichTextBoxHighlight>(highlights.Count); bool willMove = false; for (int i = 0; i < highlights.Count && i >= 0; i++) { willMove = false; tu = highlights[i] as RichTextBoxHighlight; //text preceding text in change text US after UE change // ^--------------------------^ // removal //move start and end by change magnitude, if this moves index past start of change //then set the index to the point of change. (true if index was in removal seciton) if (changeIndices[0] == tu.AbsoluteStart || changeIndices[0] == tu.AbsoluteEnd || changeIndices[1] == tu.AbsoluteStart || changeIndices[1] == tu.AbsoluteEnd) { tu.Hidden = false; } int newStart = tu.AbsoluteStart, newEnd = tu.AbsoluteEnd; //change was before underline, update to where underline will be NOW. if (changeIndices[0] <= tu.AbsoluteStart) { //if the change began before the underline start (doesnt matter where it ended) if (tu.AbsoluteStart + changeMagnitude >= changeIndices[0]) { newStart = tu.AbsoluteStart + changeMagnitude; } else { newStart = changeIndices[0]; } } if (changeIndices[0] < tu.AbsoluteEnd) { //if the change began before the underline end (doesnt matter where it ended) if (tu.AbsoluteEnd + changeMagnitude >= changeIndices[0]) { newEnd = tu.AbsoluteEnd + changeMagnitude; } else { newEnd = changeIndices[0]; } } if (newStart != tu.AbsoluteStart || newEnd != tu.AbsoluteEnd) { willMove = true; // highlightIndexes.Add(new int[2]{newStart, newEnd}); // highlightsToMove.Add(tu); /* TextPointer[] startPoints = adapter.GetPointerAtIndex(newStart, newEnd); * if(startPoints!=null) * MoveHighlight(tu, startPoints[0],newEnd-newStart); */ } //MoveHighlight(tu, newStart, newEnd, true); int c0 = changeIndices[0] , c1 = changeIndices[1] , us = tu.AbsoluteStart , ue = tu.AbsoluteEnd; //We must remove underlines that have been tampered with, because although in most cases it wont matter, if the tamper is an added or removed //space we must let the spell check add correct lines. One underline broken into two, will not happen without this. if ( (c0 >= us && c0 < ue) || //change start is inside underline (c1 > us && c1 <= ue) || //change end is inside underline (c0 <= us && c1 >= ue) || //change is around underline (us == ue) //underline shrunk to nothing ) { RemoveHighlight(tu); willMove = false; //newCheckRuns.Add(tu.Run); --i; // continue; } if (willMove && newStart != newEnd) { highlightIndexes.Add(new int[2] { newStart, newEnd }); highlightsToMove.Add(tu); } } if (highlightsToMove.Count > 0) { //highlightIndexes.Clear(); //highlightIndexes.Add(new int[] { 11382, 1 }); adapter.GetPointerAtIndexes(highlightIndexes, highlightPointers); for (int i = 0; i < highlightsToMove.Count; i++) { if (i >= highlightPointers.Count)//we have a highlight left over from an edit it seems { RemoveHighlight(highlightsToMove[i]); } else { TextPointer startPoints = highlightPointers[i]; //adapter.GetPointerAtIndex(newStart, newEnd); if (startPoints != null) { MoveHighlight(highlightsToMove[i], startPoints, highlightIndexes[i][1] - highlightIndexes[i][0]); } } } } OnNewSearchNeeded(newCheckRuns); AdornerLayer.Update(); }
private void Terminal_CursorPositionSet(object sender, EventArgs e) { if (Terminal == null) { return; } GenericTools.RunUI(() => { try { int ColumnNumber, LineNumber; GetCaretPosition(out ColumnNumber, out LineNumber); if (ColumnNumber == Terminal.CursorX && LineNumber == Terminal.CursorY) { Log.Verbose("Caret already where it should be"); return; } else { Log.Debug("Caret at " + ColumnNumber + "," + LineNumber + " but shold be at " + Terminal.CursorX + "," + Terminal.CursorY); } if (rtbConsole.Document.Blocks.Count < Terminal.CursorY) { Log.Output("Cannot move caret, UI not complete"); return; } //int diff = 0; //while(ColumnNumber != Terminal.CursorX || LineNumber != Terminal.CursorY) //{ // if (Terminal.CursorX <= 0 && Terminal.CursorY <= 0) return; // diff++; // var y = Terminal.CursorY - 1; // if (y < 0) y = 0; // var x = Terminal.CursorX + diff; // if (diff > 40) return; // // if (x > 80) x = 80; // var _p = rtbConsole.Document.Blocks.ElementAt(y); // if (_p == null) return; // TextPointer myTextPointer2 = _p.ContentStart.GetPositionAtOffset(x); // if (myTextPointer2 == null) return; // rtbConsole.CaretPosition = myTextPointer2; // GetCaretPosition(out ColumnNumber, out LineNumber); // if (ColumnNumber != Terminal.CursorX || LineNumber != Terminal.CursorY) // { // Console. Write Line("Caret at " + ColumnNumber + "," + LineNumber + " but shold be at " + Terminal.CursorX + "," + Terminal.CursorY); // } //} var y = Terminal.CursorY - 1; if (y < 0) { y = 0; } var x = Terminal.CursorX + 4; var _p = rtbConsole.Document.Blocks.ElementAt(y); if (_p == null) { return; } TextPointer myTextPointer2 = _p.ContentStart.GetPositionAtOffset(x); if (myTextPointer2 == null) { return; } rtbConsole.CaretPosition = myTextPointer2; Log.Debug("Set Carrat at " + Terminal.CursorX + "," + Terminal.CursorY); } catch (Exception ex) { Log.Error(ex.ToString()); return; } }); }
/// <summary> /// Returns the associated SpellingError at a specified position. /// </summary> /// <param name="position"> /// Position of text to query. /// </param> /// <remarks> /// The position and its LogicalDirection specify a character to query. /// If the specificed character is not part of a misspelled word then /// this method will return null. /// </remarks> public SpellingError GetSpellingError(TextPointer position) { ValidationHelper.VerifyPosition(this.TextContainer, position); return(this.TextEditor.GetSpellingErrorAtPosition(position, position.LogicalDirection)); }
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { try { RichTextBox richTextBox = d as RichTextBox; if (richTextBox == null) { return; } string content = (string)e.NewValue; if (string.IsNullOrEmpty(content)) { return; } var dd = richTextBox.Margin.Right + SystemInformation.HorizontalResizeBorderThickness + SystemInformation.HorizontalScrollBarThumbWidth + content.Length + 80; richTextBox.Width = dd; StringWriter myWriter = new StringWriter(); HttpUtility.HtmlDecode(content, myWriter); content = myWriter.ToString(); var Replacer = content.Replace("<br> <br>", "\r\n"); content = Replacer; richTextBox.Document.Blocks.Clear(); richTextBox.IsDocumentEnabled = true; Paragraph block = new Paragraph(); var para = new Paragraph { LineHeight = 1 }; var r = new Run(content); string emoticonText = GetEmoticonText(r.Text); para.Inlines.Add(r); if (!string.IsNullOrEmpty(emoticonText)) { while (!string.IsNullOrEmpty(emoticonText)) { TextPointer tp = r.ContentStart; while (!tp.GetTextInRun(LogicalDirection.Forward).StartsWith(emoticonText)) { tp = tp.GetNextInsertionPosition(LogicalDirection.Forward); } var tr = new TextRange(tp, tp.GetPositionAtOffset(emoticonText.Length)) { Text = string.Empty }; string path = _dict[emoticonText]; BitmapImage Emogi = new BitmapImage(new Uri(path, UriKind.RelativeOrAbsolute)); Image smiley = new Image(); smiley.Source = Emogi; smiley.Width = 19; smiley.Height = 19; new InlineUIContainer(smiley, tp); if (para != null) { var endRun = para.Inlines.LastInline as Run; if (endRun == null) { break; } else { emoticonText = GetEmoticonText(endRun.Text); } } } richTextBox.Document.Blocks.Add(para); } else { string sample = content; var f = sample.Split(new char[] { ' ' }); var para2 = new Paragraph(); Color Btn_Background_Color = (Color)ColorConverter.ConvertFromString("#3297ac"); foreach (var item in f) { if (item.StartsWith("http") || item.StartsWith("www.") || item.StartsWith("ftp:") || item.StartsWith("Smtp:")) { var link = new Hyperlink(); link.Inlines.Add(item); link.TargetName = "_blank"; link.TextDecorations = null; link.Foreground = new SolidColorBrush(Btn_Background_Color); link.NavigateUri = new Uri(item); para2.Inlines.Add(link); link.Click += OnUrlClick; } else if (item.StartsWith("#")) { var link = new Hyperlink(); item.TrimStart(new char[] { '#' }); link.Inlines.Add(item); link.TargetName = "_blank"; link.Foreground = new SolidColorBrush(Btn_Background_Color); link.TextDecorations = null;; string Hashtag = item.Replace("#", ""); link.NavigateUri = new Uri(WoWonderClient.Client.WebsiteUrl + "/hashtag/" + Hashtag); para2.Inlines.Add(link); link.Click += OnUrlClick; } else if (item.StartsWith("DownloadUrlFrom>>>")) { var link = new Hyperlink(); string Url = item.Replace("DownloadUrlFrom>>>", ""); link.Inlines.Add("Download"); link.TargetName = "_blank"; link.Foreground = new SolidColorBrush(Btn_Background_Color); link.TextDecorations = null; link.NavigateUri = new Uri(Url); para2.Inlines.Add(link); link.Click += OnUrlClick; } else { para2.Inlines.Add(item); } para2.Inlines.Add(" "); } richTextBox.Document.Blocks.Add(para2); } } catch { } }
public static int CountStyle(this Paragraph paragraph, ComplexStyle style, double defaultSize, ref TextPointer position, bool positionOnly) { if (position != null) { return(0); } var count = 0; foreach (Inline inline in paragraph.Inlines) { TextPointer pos = null; if (!inline.IsStyle(style, defaultSize, out pos)) { continue; } if (position == null) { position = pos; } count++; } return(count); }
public static bool IsStyle(this TextElement text, ComplexStyle style, double defaultSize, out TextPointer position) { position = null; var run = text as Run; if (run != null && string.IsNullOrEmpty(run.Text)) { return(false); } var range = new TextRange(text.ContentStart, text.ContentEnd); var sty = GetCurrentStyle(range, defaultSize); position = text.ContentStart; return(ComplexStyle.Equals(sty, style)); }
public static string GetWordAtPointer(TextPointer textPointer) { return(string.Join(string.Empty, GetWordCharactersBefore(textPointer), GetWordCharactersAfter(textPointer))); }
public static int CountStyle(this Block block, ComplexStyle style, double defaultSize, ref TextPointer position, bool positionOnly) { if (position != null) { return(0); } var section = block as Section; if (section != null) { return(section.CountStyle(style, defaultSize, ref position, positionOnly)); } var paragraph = block as Paragraph; if (paragraph != null) { return(paragraph.CountStyle(style, defaultSize, ref position, positionOnly)); } var list = block as List; if (list != null) { return(list.CountStyle(style, defaultSize, ref position, positionOnly)); } return(0); }
public static int CountStyle(this ListItem item, ComplexStyle style, double defaultSize, ref TextPointer position, bool positionOnly) { var counter = 0; if (position != null) { return(0); } foreach (var block in item.Blocks.ToList()) { counter += block.CountStyle(style, defaultSize, ref position, positionOnly); } return(counter); }
public static int CountStyle(this List list, ComplexStyle style, double defaultSize, ref TextPointer position, bool positionOnly) { if (position != null) { return(0); } var counter = 0; foreach (var listItem in list.ListItems.ToList()) { counter += listItem.CountStyle(style, defaultSize, ref position, positionOnly); } return(counter); }
/// <summary> /// Creates a new Underline instance covering existing content. /// </summary> /// <param name="start"> /// Start position of the new Underline. /// </param> /// <param name="end"> /// End position of the new Underline. /// </param> /// <remarks> /// start and end must both be parented by the same Paragraph, otherwise /// the method will raise an ArgumentException. /// </remarks> public Underline(TextPointer start, TextPointer end) : base(start, end) { }
/// <summary> /// Is manipulating a specific string inside of a TextPointer Range (TextBlock, TextBox...) /// </summary> /// <param name="startPointer">Starting point where to look</param> /// <param name="endPointer">Endpoint where to look</param> /// <param name="keyword">This is the string you want to manipulate</param> /// <param name="fontStyle">The new FontStyle</param> /// <param name="fontWeight">The new FontWeight</param> /// <param name="foreground">The new foreground</param> /// <param name="background">The new background</param> /// <param name="fontSize">The new FontSize</param> public static void FromTextPointer(TextPointer startPointer, TextPointer endPointer, string keyword, FontStyle fontStyle, FontWeight fontWeight, Brush foreground, Brush background, double fontSize) { FromTextPointer(startPointer, endPointer, keyword, fontStyle, fontWeight, foreground, background, fontSize, null); }
/// <summary> /// Creates a new Italic instance. /// </summary> /// <param name="childInline"> /// Optional child Inline for the new Italic. May be null. /// </param> /// <param name="insertionPosition"> /// Optional position at which to insert the new Italic. May be null. /// </param> public Italic(Inline childInline, TextPointer insertionPosition) : base(childInline, insertionPosition) { }
void advanceColor_Click(object sender, RoutedEventArgs e) { DialogWindowBrushColor dialoWindow = new DialogWindowBrushColor(); dialoWindow.Owner = Application.Current.MainWindow; Lovatts.ColorEditor.BrushEditor brushEditor = (Lovatts.ColorEditor.BrushEditor)dialoWindow.Content; brushEditor.ParentWindow = dialoWindow; if (dialoWindow.ShowDialog() == true) { Brush newBrush = brushEditor.BrushEditorViewModel.Brush; MainWindow mainWindow = (MainWindow)Application.Current.MainWindow; ColorButton colorButton = new ColorButton(CustomRichTextBox, Grid, newBrush, stackPanelRecentColor, DropButton, RectangleColor); if (mainWindow.RecentColorCollection.Count < 7) { stackPanelRecentColor.Children.Add(colorButton); mainWindow.RecentColorCollection.Add(colorButton); } else { mainWindow.RecentColorCollection.RemoveAt(0); mainWindow.RecentColorCollection.Add(colorButton); stackPanelRecentColor.Children.RemoveAt(0); stackPanelRecentColor.Children.Add(colorButton); } RectangleColor.Fill = newBrush; TextPointer textPoint = CustomRichTextBox.CaretPosition; CustomRichTextBox.startTextPointer = null; CustomRichTextBox.endTextPointer = null; if (CustomRichTextBox.Selection.IsEmpty) { TextElement textElement = null; if (CustomRichTextBox.CaretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.None) { CustomRichTextBox.IsCreateRunNull = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; e.Handled = true; return; } else if (CustomRichTextBox.CaretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementStart) { textElement = (TextElement)CustomRichTextBox.CaretPosition.GetAdjacentElement(LogicalDirection.Backward); if (textElement is Paragraph) { CustomRichTextBox.IsCreateRunNull = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; e.Handled = true; return; } else if (textElement is ListItem) { CustomRichTextBox.IsCreateRunNull = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; e.Handled = true; return; } } else if (CustomRichTextBox.CaretPosition.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.ElementEnd) { textElement = (TextElement)CustomRichTextBox.CaretPosition.GetAdjacentElement(LogicalDirection.Backward); if (textElement is LineBreak) { CustomRichTextBox.IsCreateRunNull = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; e.Handled = true; return; } } if (textPoint.GetTextRunLength(LogicalDirection.Backward) > 0) // Если позади каретки в текстовом элементе есть текст { TextPointer textPointer = textPoint.GetNextContextPosition(LogicalDirection.Backward); Run run = (Run)textPointer.GetAdjacentElement(LogicalDirection.Backward); TextElement nextBackTextElement = (TextElement)run.ElementStart.GetAdjacentElement(LogicalDirection.Backward); int i = CustomRichTextBox.CaretPosition.GetTextRunLength(LogicalDirection.Backward); TextRange textRange = new TextRange(textPointer, CustomRichTextBox.CaretPosition); int index = textRange.Text.LastIndexOfAny(new char[] { ' ', ',', '.', '?', '!', ':', ';' }); if (index != -1) { if (textRange.Text[i - 1] != ' ' && textRange.Text[i - 1] != ',' && textRange.Text[i - 1] != '.' && textRange.Text[i - 1] != '?' && textRange.Text[i - 1] != '!' && textRange.Text[i - 1] != ':' && textRange.Text[i - 1] != ';') { CustomRichTextBox.startTextPointer = CustomRichTextBox.CaretPosition.GetPositionAtOffset(index + 1 - i); } else { CustomRichTextBox.startTextPointer = null; } } else { CustomRichTextBox.IsText = true; CustomRichTextBox.StartTextPointer(nextBackTextElement); } } else { CustomRichTextBox.IsTextNull = true; TextElement nextBackTextElement = (TextElement)CustomRichTextBox.CaretPosition.GetAdjacentElement(LogicalDirection.Backward); if (nextBackTextElement is Run) { nextBackTextElement = (TextElement)nextBackTextElement.ElementStart.GetAdjacentElement(LogicalDirection.Backward); } CustomRichTextBox.StartTextPointer(nextBackTextElement); } CustomRichTextBox.IsTextNull = false; CustomRichTextBox.IsText = false; if (textPoint.GetTextRunLength(LogicalDirection.Forward) > 0) // Если в текстовом элементе впереди каретки есть текст { TextPointer textPointer = textPoint.GetNextContextPosition(LogicalDirection.Forward); Run run = (Run)textPointer.GetAdjacentElement(LogicalDirection.Forward); TextElement nextForwardTextElement = (TextElement)run.ElementEnd.GetAdjacentElement(LogicalDirection.Forward); int i = CustomRichTextBox.CaretPosition.GetTextRunLength(LogicalDirection.Forward); TextRange textRange = new TextRange(CustomRichTextBox.CaretPosition, textPointer); int index = textRange.Text.IndexOfAny(new char[] { ' ', ',', '.', '?', '!', ':', ';' }); if (index != -1) { if (textRange.Text[0] != ' ' && textRange.Text[0] != ',' && textRange.Text[0] != '.' && textRange.Text[0] != '?' && textRange.Text[0] != '!' && textRange.Text[0] != ':' && textRange.Text[0] != ';') { CustomRichTextBox.endTextPointer = CustomRichTextBox.CaretPosition.GetPositionAtOffset(index); } else { CustomRichTextBox.endTextPointer = null; } } else { CustomRichTextBox.IsText = true; CustomRichTextBox.EndTextPointer(nextForwardTextElement); } } else { CustomRichTextBox.IsTextNull = true; TextElement nextForwardTextElement = (TextElement)CustomRichTextBox.CaretPosition.GetAdjacentElement(LogicalDirection.Forward); if (nextForwardTextElement is Run) { nextForwardTextElement = (TextElement)nextForwardTextElement.ElementEnd.GetAdjacentElement(LogicalDirection.Forward); } CustomRichTextBox.EndTextPointer(nextForwardTextElement); } CustomRichTextBox.IsText = false; CustomRichTextBox.IsTextNull = false; if (CustomRichTextBox.startTextPointer != null && CustomRichTextBox.endTextPointer != null) { TextRange textRange = new TextRange(CustomRichTextBox.startTextPointer, CustomRichTextBox.endTextPointer); textRange.ApplyPropertyValue(TextElement.ForegroundProperty, newBrush); } else { if (CustomRichTextBox.Run.Foreground is SolidColorBrush && newBrush is SolidColorBrush) { SolidColorBrush runBrush = CustomRichTextBox.Run.Foreground as SolidColorBrush; SolidColorBrush newSolidColorBrush = newBrush as SolidColorBrush; if (runBrush.Color.A != newSolidColorBrush.Color.A || runBrush.Color.B != newSolidColorBrush.Color.B || runBrush.Color.G != newSolidColorBrush.Color.G || runBrush.Color.R != newSolidColorBrush.Color.R || runBrush.Color.ScA != newSolidColorBrush.Color.ScA || runBrush.Color.ScB != newSolidColorBrush.Color.ScB || runBrush.Color.ScG != newSolidColorBrush.Color.ScG || runBrush.Color.ScR != newSolidColorBrush.Color.ScR || runBrush.Opacity != newSolidColorBrush.Opacity) { CustomRichTextBox.IsCreateRunColor = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; } else { CustomRichTextBox.IsCreateRunColor = false; } } else if (CustomRichTextBox.Run.Foreground is LinearGradientBrush && newBrush is LinearGradientBrush) { LinearGradientBrush runBrush = CustomRichTextBox.Run.Foreground as LinearGradientBrush; LinearGradientBrush newLinearGradientBrush = newBrush as LinearGradientBrush; int count = 0; if (runBrush.ColorInterpolationMode != newLinearGradientBrush.ColorInterpolationMode || runBrush.EndPoint != newLinearGradientBrush.EndPoint || runBrush.Opacity != newLinearGradientBrush.Opacity || runBrush.MappingMode != newLinearGradientBrush.MappingMode || runBrush.SpreadMethod != newLinearGradientBrush.SpreadMethod || runBrush.StartPoint != newLinearGradientBrush.StartPoint || runBrush.GradientStops.Count != newLinearGradientBrush.GradientStops.Count) { CustomRichTextBox.IsCreateRunColor = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; } else { GradientStop newGradientStop; foreach (GradientStop runGradientStop in runBrush.GradientStops) { newGradientStop = newLinearGradientBrush.GradientStops[count]; if (runGradientStop.Color.A != newGradientStop.Color.A || runGradientStop.Color.B != newGradientStop.Color.B || runGradientStop.Color.G != newGradientStop.Color.G || runGradientStop.Color.R != newGradientStop.Color.R || runGradientStop.Color.ScA != newGradientStop.Color.ScA || runGradientStop.Color.ScB != newGradientStop.Color.ScB || runGradientStop.Color.ScG != newGradientStop.Color.ScG || runGradientStop.Color.ScR != newGradientStop.Color.ScR) { CustomRichTextBox.IsCreateRunColor = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; e.Handled = true; return; } else { CustomRichTextBox.IsCreateRunColor = false; } count++; } } } else if (CustomRichTextBox.Run.Foreground is RadialGradientBrush && newBrush is RadialGradientBrush) { RadialGradientBrush runBrush = CustomRichTextBox.Run.Foreground as RadialGradientBrush; RadialGradientBrush newRadialGradientBrush = newBrush as RadialGradientBrush; int count = 0; if (runBrush.Center != newRadialGradientBrush.Center || runBrush.ColorInterpolationMode != newRadialGradientBrush.ColorInterpolationMode || runBrush.GradientOrigin != newRadialGradientBrush.GradientOrigin || runBrush.MappingMode != newRadialGradientBrush.MappingMode || runBrush.Opacity != newRadialGradientBrush.Opacity || runBrush.RadiusX != newRadialGradientBrush.RadiusX || runBrush.RadiusY != newRadialGradientBrush.RadiusY || runBrush.SpreadMethod != newRadialGradientBrush.SpreadMethod || runBrush.GradientStops.Count != newRadialGradientBrush.GradientStops.Count) { CustomRichTextBox.IsCreateRunColor = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; } else { GradientStop newGradientStop; foreach (GradientStop runGradientStop in runBrush.GradientStops) { newGradientStop = newRadialGradientBrush.GradientStops[count]; if (runGradientStop.Color.A != newGradientStop.Color.A || runGradientStop.Color.B != newGradientStop.Color.B || runGradientStop.Color.G != newGradientStop.Color.G || runGradientStop.Color.R != newGradientStop.Color.R || runGradientStop.Color.ScA != newGradientStop.Color.ScA || runGradientStop.Color.ScB != newGradientStop.Color.ScB || runGradientStop.Color.ScG != newGradientStop.Color.ScG || runGradientStop.Color.ScR != newGradientStop.Color.ScR) { CustomRichTextBox.IsCreateRunColor = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; e.Handled = true; return; } else { CustomRichTextBox.IsCreateRunColor = false; } count++; } } } else { CustomRichTextBox.IsCreateRunColor = true; CustomRichTextBox.CreateRunTextPointer = CustomRichTextBox.CaretPosition; } } } else { CustomRichTextBox.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, newBrush); } } e.Handled = true; }
public string GetExpression(TextPointer start = null, TextPointer end = null) { return(this.Document.GetTextWithVariable(start, end)); }
internal static TextPointer GetOffsetTextPointer(this TextPointer start, int offset) { return(start.GetInsertionPosition(LogicalDirection.Forward).GetPositionAtOffset(offset)); }
public PhysicalCharInfo HitTest(Point point, bool snapToText, out Rect bounds) { PhysicalCharInfo result = null; bounds = Rect.Empty; double nearestDistance = double.PositiveInfinity; PhysicalCharInfo nearest = null; PhysicalCharInfo xResult = null; bool yResult = false; PhysicalCharInfo prevChar = null; foreach (var currChar in this.Characters) { Rect charBounds = currChar.GetBounds(); bounds.Union(charBounds); if (!yResult) { yResult = !bounds.IsEmpty && bounds.Top <= point.Y && point.Y < bounds.Bottom; // If true we have found a line that overlaps the hit-test point on the y-axis } if (xResult == null) { TextPointer candidate = currChar.HitTestHorizontal(point); if (candidate != null) { if (candidate.GetOffsetToPosition(currChar.NearPosition) == 0) { xResult = currChar; } else { Assert.IsNotNull(prevChar); Assert.AreEqual(0, candidate.GetOffsetToPosition(prevChar.NearPosition)); xResult = prevChar; } } } if (yResult && xResult != null) { // We have found a character that is in range of the hit-test point on the x-axis and y-axis result = xResult; break; } else { // Even if the the hit test point is outside this lines vertical range we will keep searching because // We may find a character further down the line that extends the lines vertical range and makes the // hit test result valid. } if (snapToText) { double distance = Math.Abs(charBounds.X - point.X); if (distance < nearestDistance) { nearestDistance = distance; nearest = currChar; } } prevChar = currChar; } if (result == null) { if (snapToText && yResult) { result = nearest; } } else { Assert.IsTrue(bounds.Contains(point)); } return(result); }
public static void InsertInlineAt(this FlowDocument doc, InlineUIContainer container, TextPointer p) { if (p.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementStart) { p = p.GetNextContextPosition(LogicalDirection.Backward); } if (p.Parent is FlowDocument) { Paragraph paragraph = (doc.Blocks.FirstBlock as Paragraph); paragraph.Inlines.InsertBefore(paragraph.Inlines.FirstInline, container); } else if (p.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd) { if (p.Parent is Inline) { Inline inline = p.Parent as Inline; (inline.Parent as Paragraph).Inlines.InsertAfter(inline, container); } else if (p.Parent is Paragraph) { (p.Parent as Paragraph).Inlines.Add(container); } else { throw new Exception("not handled"); } } else { if (p.Parent is Run) { Run run = p.Parent as Run; Paragraph paragraph = run.Parent as Paragraph; // break up Run int mid = -p.GetOffsetToPosition(run.ContentStart); Run run1 = new Run(run.Text.Substring(0, mid)); Run run2 = new Run(run.Text.Substring(mid)); paragraph.Inlines.InsertBefore(run, run1); paragraph.Inlines.InsertBefore(run, container); paragraph.Inlines.InsertBefore(run, run2); paragraph.Inlines.Remove(run); } else { throw new Exception("not handled"); } } }
/// <summary> /// Returns the position of the next character in a specificed direction /// that is the start of a misspelled word. /// </summary> /// <param name="position"> /// Position of text to query. /// </param> /// <param name="direction"> /// Direction to query. /// </param> /// <remarks> /// The position and its LogicalDirection specify a character to query. /// The search includes the spelling error containing the character /// specified by position/direction (if any). /// /// If no misspelled word is encountered, the method returns null. /// </remarks> public TextPointer GetNextSpellingErrorPosition(TextPointer position, LogicalDirection direction) { ValidationHelper.VerifyPosition(this.TextContainer, position); return((TextPointer)this.TextEditor.GetNextSpellingErrorPosition(position, direction)); }
public static void DeleteRunsAndInlinecontainers(this FlowDocument doc, TextPointer start = null, TextPointer end = null) { for (TextPointer position = start; position != null && position.CompareTo(end) <= 0; position = position.GetNextContextPosition(LogicalDirection.Forward)) { if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd) { // } else { TextPointer nextPosition = position.GetNextContextPosition(LogicalDirection.Forward); if (position.Parent is Run) { Run run = position.Parent as Run; TextPointer p1 = (position.CompareTo(run.ContentStart) >= 0) ? position : run.ContentStart; TextPointer p2 = (nextPosition.CompareTo(end) <= 0) ? nextPosition : end; int x2 = -p2.GetOffsetToPosition(p1); p1.DeleteTextInRun(x2); } else if (position.Parent is InlineUIContainer) { InlineUIContainer inline = position.Parent as InlineUIContainer; (inline.Parent as Paragraph).Inlines.Remove(inline); } } } }
// Helper that returns true when passed TextPointer is within the scope of a Hyperlink element. public static bool IsInHyperlinkScope(TextPointer position) { return(GetHyperlinkAncestor(position) != null); }
private static IEnumerable <string> GetRunsAndInlinecontainersString(FlowDocument doc, TextPointer start = null, TextPointer end = null) { for (TextPointer position = start; position != null && position.CompareTo(end) <= 0; position = position.GetNextContextPosition(LogicalDirection.Forward)) { if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.ElementEnd) { // } else { TextPointer nextPosition = position.GetNextContextPosition(LogicalDirection.Forward); if (position.Parent is Run) { Run run = position.Parent as Run; TextPointer p1 = (position.CompareTo(run.ContentStart) >= 0) ? position : run.ContentStart; TextPointer p2 = (nextPosition.CompareTo(end) <= 0) ? nextPosition : end; int x1 = -position.GetOffsetToPosition(run.ContentStart); int x2 = -p2.GetOffsetToPosition(p1); yield return(run.Text.Substring(x1, x2)); } else if (position.Parent is InlineUIContainer) { InlineUIContainer inline = position.Parent as InlineUIContainer; if (inline.Child is TextBox) { string variable = (inline.Child as TextBox).Tag as String; yield return("[" + variable + "]"); } } } } }
/// <summary> /// Returns a text representation of the elements between <paramref name="start"/> and <paramref name="end"/> in the RichTextBlock. /// </summary> /// <param name="view">The RichTextBlock.</param> /// <param name="start">Start TextPointer.</param> /// <param name="end">End TextPointer.</param> /// <returns></returns> public static string GetStringByStartAndEndPointers(RichTextBlock view, TextPointer start, TextPointer end) { if (start == null || end == null) { return(null); } else if (start == end) { return(string.Empty); } // Parse the RichTextBlock contents. StringBuilder selectedText = new StringBuilder(); Debug.Assert(view.Blocks.Count == 1, "RichTextBlock is expected to contain only one paragraph."); Paragraph paragraph = view?.Blocks?.First() as Paragraph; if (paragraph == null) { return(null); } ProcessSelectedInlines(paragraph.Inlines, selectedText, false, start, end); return(selectedText.ToString()); }
public static string GetTextWithVariable(this FlowDocument doc, TextPointer start = null, TextPointer end = null) { if (start == null) { start = doc.ContentStart; } if (end == null) { end = doc.ContentEnd; } StringBuilder sb = new StringBuilder(); foreach (string str in GetRunsAndInlinecontainersString(doc, start, end)) { sb.Append(str); } return(sb.ToString()); }
public SyntaxTag(TextPointer s, TextPointer e, SyntaxHighlighter.SyntaxType t) { start = s; end = e; type = t; }
/// <summary> /// Writes the container into the specified XmlWriter. /// </summary> private void WriteContainer(TextPointer start, TextPointer end, XmlWriter writer) { TextElement textElement; System.Diagnostics.Debug.Assert(start != null); System.Diagnostics.Debug.Assert(end != null); System.Diagnostics.Debug.Assert(writer != null); _writer = writer; WriteWordXmlHead(); _cursor = start; while (_cursor.CompareTo(end) < 0) { switch (_cursor.GetPointerContext(_dir)) { case TextPointerContext.None: System.Diagnostics.Debug.Assert(false, "Next symbol should never be None if cursor < End."); break; case TextPointerContext.Text: RequireOpenRange(); _writer.WriteStartElement(WordXmlSerializer.WordTextTag); _writer.WriteString(_cursor.GetTextInRun(_dir)); _writer.WriteEndElement(); break; case TextPointerContext.EmbeddedElement: DependencyObject obj = _cursor.GetAdjacentElement(LogicalDirection.Forward); if (obj is LineBreak) { RequireOpenRange(); _writer.WriteStartElement(WordXmlSerializer.WordBreakTag); _writer.WriteEndElement(); } // TODO: try to convert some known embedded objects. break; case TextPointerContext.ElementStart: TextPointer position; position = _cursor; position = position.GetNextContextPosition(LogicalDirection.Forward); textElement = position.Parent as TextElement; if (textElement is Paragraph) { RequireClosedRange(); RequireOpenParagraph(); } else if (textElement is Inline) { RequireClosedRange(); RequireOpenParagraph(); RequireOpenRange(); } break; case TextPointerContext.ElementEnd: textElement = _cursor.Parent as TextElement; if (textElement is Inline) { RequireClosedRange(); } else if (textElement is Paragraph) { RequireClosedParagraph(); } break; } _cursor = _cursor.GetNextContextPosition(_dir); } RequireClosedRange(); WriteWordXmlTail(); }
/// <summary> /// Creates a new Underline instance. /// </summary> /// <param name="childInline"> /// Optional child Inline for the new Underline. May be null. /// </param> /// <param name="insertionPosition"> /// Optional position at which to insert the new Underline. May be null. /// </param> public Underline(Inline childInline, TextPointer insertionPosition) : base(childInline, insertionPosition) { }
public bool CaretIsInLeftMostOfEditArea(TextPointer caretPostion) => this.CanEditing && this.Editor.ContentStart.IsInSameDocument(caretPostion) && this.Editor.ContentStart.GetOffsetToPosition(caretPostion) - 1 == this.Prompt.Length;
/// <summary> /// Creates a new Span instance covering existing content. /// </summary> /// <param name="start"> /// Start position of the new Span. /// </param> /// <param name="end"> /// End position of the new Span. /// </param> /// <remarks> /// start and end must both be parented by the same Paragraph, otherwise /// the method will raise an ArgumentException. /// </remarks> public Bold(TextPointer start, TextPointer end) : base(start, end) { }
private void InsertTextInRunAndMoveCaret(string text) { TextPointer newPosition = this.Document.InsertTextAt(text, this.CaretPosition); this.CaretPosition = newPosition; }
/// <summary> /// Creates a new Italic instance covering existing content. /// </summary> /// <param name="start"> /// Start position of the new Italic. /// </param> /// <param name="end"> /// End position of the new Italic. /// </param> /// <remarks> /// start and end must both be parented by the same Paragraph, otherwise /// the method will raise an ArgumentException. /// </remarks> public Italic(TextPointer start, TextPointer end) : base(start, end) { }
public static int CountStyle(this Section section, ComplexStyle style, double defaultSize, ref TextPointer position, bool positionOnly) { var counter = 0; foreach (var block in section.Blocks.ToList()) { counter += block.CountStyle(style, defaultSize, ref position, positionOnly); } return(counter); }