public static string ProcessTrimming(Control control, string text, double availableWidth) { TextTrimming trimming = GetTextTrimming(control); TrimmingSource source = GetTrimmingSource(control); string wordSeparators = GetWordSeparators(control); return(ProcessTrimming(control, text, availableWidth, trimming, source, wordSeparators)); }
/// <summary> /// Sets the value of the <see cref="TrimmingSource"/> dependency property attached to the given <see cref="DependencyObject"/>. /// </summary> /// <param name="target">The target <see cref="DependencyObject"/>.</param> /// <param name="value">The value to set.</param> public static void SetTrimmingSource([NotNull] DependencyObject target, TrimmingSource value) { target.SetValue(TrimmingSourceProperty, value); }
private static string ProcessTrimming(string text, [NotNull] Typeface typeface, double fontSize, TextTrimming trimming, TrimmingSource source, string wordSeparators, double availableWidth) { if (trimming == TextTrimming.None) { return(text); } var textWidth = GetTextWidth(text, trimming, typeface, fontSize, wordSeparators, out double[] sizes); if (availableWidth >= textWidth) { return(text); } if (sizes.Length == 0) { return(text); } List <string> words; switch (trimming) { case TextTrimming.CharacterEllipsis: words = text.ToCharArray().Select(c => c.ToString(CultureInfo.InvariantCulture)).ToList(); break; case TextTrimming.WordEllipsis: words = SplitWords(text, wordSeparators); break; default: throw new ArgumentException("Invalid 'TextTrimming' argument."); } var firstWord = true; switch (source) { case TrimmingSource.Begin: { var currentWidth = GetTextWidth(Ellipsis, trimming, typeface, fontSize, wordSeparators, out _); var ending = new StringBuilder(); for (var i = words.Count - 1; i >= 0; --i) { var test = currentWidth + sizes[i]; if (test > availableWidth) { // If there's not enough room for a single word, fall back on character trimming from the beginning if (trimming == TextTrimming.WordEllipsis && firstWord) { return(ProcessTrimming(words[i], typeface, fontSize, TextTrimming.CharacterEllipsis, TrimmingSource.Begin, wordSeparators, availableWidth)); } break; } ending.Insert(0, words[i]); currentWidth = test; firstWord = false; } return($"{Ellipsis}{ending}"); } case TrimmingSource.Middle: { var currentWidth = GetTextWidth(Ellipsis, trimming, typeface, fontSize, wordSeparators, out _); var begin = new StringBuilder(); var ending = new StringBuilder(); for (int i = 0, j = words.Count - 1; i <= j; ++i, --j) { var test = currentWidth + sizes[i] + (i != j ? sizes[j] : 0); if (test > availableWidth) { // If there's not enough room for a single word, fall back on character trimming from the end if (trimming == TextTrimming.WordEllipsis && firstWord) { return(ProcessTrimming(words[j], typeface, fontSize, TextTrimming.CharacterEllipsis, TrimmingSource.End, wordSeparators, availableWidth)); } break; } begin.Append(words[i]); if (i != j) { ending.Insert(0, words[j]); } currentWidth = test; firstWord = false; } return(string.Format("{0}{2}{1}", begin, ending, Ellipsis)); } case TrimmingSource.End: { var currentWidth = GetTextWidth(Ellipsis, trimming, typeface, fontSize, wordSeparators, out _); var begin = new StringBuilder(); for (var i = 0; i < words.Count; ++i) { var test = currentWidth + sizes[i]; if (test > availableWidth) { // If there's not enough room for a single word, fall back on character trimming from the end if (trimming == TextTrimming.WordEllipsis && firstWord) { return(ProcessTrimming(words[i], typeface, fontSize, TextTrimming.CharacterEllipsis, TrimmingSource.Begin, wordSeparators, availableWidth)); } break; } begin.Append(words[i]); currentWidth = test; firstWord = false; } return($"{begin}{Ellipsis}"); } default: throw new ArgumentOutOfRangeException(); } }
public static string ProcessTrimming([NotNull] TextBlock textBlock, string text, TextTrimming trimming, TrimmingSource source, string wordSeparators, double availableWidth) { var typeface = new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch); return(ProcessTrimming(text, typeface, textBlock.FontSize, trimming, source, wordSeparators, availableWidth)); }
/// <summary> /// Sets the value of the <see cref="TrimmingSource"/> dependency property attached to the given <see cref="DependencyObject"/>. /// </summary> /// <param name="target">The target <see cref="DependencyObject"/>.</param> /// <param name="value">The value to set.</param> public static void SetTrimmingSource(DependencyObject target, TrimmingSource value) { target.SetValue(TrimmingSourceProperty, value); }
private static string ProcessTrimming(Control control, string text, double availableWidth, TextTrimming trimming, TrimmingSource source, string wordSeparators) { if (trimming == TextTrimming.None) { return text; } double[] sizes; var textWidth = GetTextWidth(control, text, trimming, out sizes); if (availableWidth >= textWidth) { return text; } if (sizes.Length == 0) { return text; } List<string> words; switch (trimming) { case TextTrimming.CharacterEllipsis: words = text.ToCharArray().Select(c => c.ToString(CultureInfo.InvariantCulture)).ToList(); break; case TextTrimming.WordEllipsis: words = SplitWords(text, wordSeparators); break; default: throw new ArgumentException("Invalid 'TextTrimming' argument."); } bool firstWord = true; switch (source) { case TrimmingSource.Begin: { var currentWidth = GetTextWidth(control, Ellipsis, trimming); var ending = new StringBuilder(); for (int i = words.Count - 1; i >= 0; --i) { var test = currentWidth + sizes[i]; if (test > availableWidth) { // If there's not enough room for a single word, fall back on character trimming from the beginning if (trimming == TextTrimming.WordEllipsis && firstWord) { return ProcessTrimming(control, words[i], availableWidth, TextTrimming.CharacterEllipsis, TrimmingSource.Begin, wordSeparators); } break; } ending.Insert(0, words[i]); currentWidth = test; firstWord = false; } return string.Format("{0}{1}", Ellipsis, ending); } case TrimmingSource.Middle: { var currentWidth = GetTextWidth(control, Ellipsis, trimming); var begin = new StringBuilder(); var ending = new StringBuilder(); for (int i = 0, j = words.Count - 1; i <= j; ++i, --j) { var test = currentWidth + sizes[i] + (i != j ? sizes[j] : 0); if (test > availableWidth) { // If there's not enough room for a single word, fall back on character trimming from the end if (trimming == TextTrimming.WordEllipsis && firstWord) { return ProcessTrimming(control, words[j], availableWidth, TextTrimming.CharacterEllipsis, TrimmingSource.End, wordSeparators); } break; } begin.Append(words[i]); if (i != j) ending.Insert(0, words[j]); currentWidth = test; firstWord = false; } return string.Format("{0}{2}{1}", begin, ending, Ellipsis); } case TrimmingSource.End: { var currentWidth = GetTextWidth(control, Ellipsis, trimming); var begin = new StringBuilder(); for (int i = 0; i < words.Count; ++i) { var test = currentWidth + sizes[i]; if (test > availableWidth) { // If there's not enough room for a single word, fall back on character trimming from the end if (trimming == TextTrimming.WordEllipsis && firstWord) { return ProcessTrimming(control, words[i], availableWidth, TextTrimming.CharacterEllipsis, TrimmingSource.Begin, wordSeparators); } break; } begin.Append(words[i]); currentWidth = test; firstWord = false; } return string.Format("{0}{1}", begin, Ellipsis); } default: throw new ArgumentOutOfRangeException(); } }