4 using System.Collections.Generic;
5 using System.Globalization;
8 using System.Text.RegularExpressions;
10 using System.Windows.Controls;
11 using System.Windows.Media;
13 using SiliconStudio.Presentation.Controls;
15 namespace SiliconStudio.Presentation.Behaviors
27 private FrameworkElement parent;
28 private string originalText;
30 public int Offset {
get; set; }
32 private string wordSeparators;
33 private string processedWordSeparators;
34 public string WordSeparators
36 get {
return wordSeparators; }
39 wordSeparators = value;
40 ProcessWordSeparators();
44 private void ProcessWordSeparators()
46 processedWordSeparators = Regex.Unescape(wordSeparators);
50 public TextTrimming TextTrimming {
get; set; }
52 public double ContentMargin {
get; set; }
54 private double trimmedTextWidth = double.MinValue;
63 parent = VisualTreeHelper.GetParent(AssociatedObject) as FrameworkElement;
66 parent = LogicalTreeHelper.GetParent(AssociatedObject) as FrameworkElement;
71 originalText = AssociatedObject.Text;
72 parent.SizeChanged += OnLogicalParentSizeChanged;
80 parent.SizeChanged -= OnLogicalParentSizeChanged;
83 private void OnLogicalParentSizeChanged(
object sender, SizeChangedEventArgs e)
88 private void ProcessText()
90 if (TextTrimming == TextTrimming.None)
95 var textWidth = GetTextWidth(AssociatedObject, originalText, out sizes);
96 var availableWidth = parent.ActualWidth - ContentMargin;
99 double epsilon = GetTextWidth(AssociatedObject,
".");
100 if (Math.Abs(availableWidth - trimmedTextWidth) < epsilon)
103 if (availableWidth >= textWidth)
104 AssociatedObject.Text = originalText;
107 if (TextTrimming == TextTrimming.CharacterEllipsis)
108 PerformEllipsis(sizes, originalText.ToCharArray().Select(c => c.ToString(CultureInfo.InvariantCulture)).ToArray(), availableWidth);
109 else if (TextTrimming == TextTrimming.WordEllipsis)
110 PerformEllipsis(sizes, Split(originalText), availableWidth);
112 throw new ArgumentException(
"Invalid 'TextTrimming' argument.");
116 private void PerformEllipsis(
double[] sizes,
string[] text,
double availableWidth)
120 var n = text.Length - 1;
121 var sb =
new StringBuilder();
123 for (var i = 0; i < Offset; i++)
127 var starting = sb.ToString();
129 var currentWidth = GetTextWidth(AssociatedObject, starting);
133 var test = currentWidth + sizes[n];
135 if (test > availableWidth)
138 sb.Insert(0, text[n--]);
142 trimmedTextWidth = currentWidth;
143 AssociatedObject.Text = string.Format(
"{0}{1}", starting, sb);
147 var currentWidth = GetTextWidth(AssociatedObject,
"...");
149 var n2 = text.Length - 1;
151 var begin =
new StringBuilder();
152 var end =
new StringBuilder();
156 var test = currentWidth + sizes[n1] + sizes[n2];
158 if (test > availableWidth)
161 begin.Append(text[n1++]);
162 end.Insert(0, text[n2--]);
167 AssociatedObject.Text = string.Format(
"{0}...{1}", begin, end);
172 var sb =
new StringBuilder();
173 for (var i = 0; i < Offset; i++)
174 sb.Insert(0, text[text.Length - i - 1]);
177 var ending = sb.ToString();
179 var currentWidth = GetTextWidth(AssociatedObject, ending);
183 var test = currentWidth + sizes[n];
185 if (test > availableWidth)
188 sb.Append(text[n++]);
192 AssociatedObject.Text = string.Format(
"{0}{1}", sb, ending);
196 private double GetTextWidth(TextBlock textBlock,
string text)
199 return GetTextWidth(textBlock, text, out dummy);
202 private double GetTextWidth(TextBlock textBlock,
string text, out
double[] sizes)
204 var typeface =
new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch);
206 var totalWidth = 0.0;
208 if (TextTrimming == TextTrimming.CharacterEllipsis)
210 sizes =
new double[text.Length];
212 for (var i = 0; i < text.Length; i++)
214 string token = text[i].ToString(CultureInfo.CurrentUICulture);
215 var formattedText =
new FormattedText(token, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeface, textBlock.FontSize, Brushes.Black);
216 double width = formattedText.Width;
222 else if (TextTrimming == TextTrimming.WordEllipsis)
224 var words = Split(text);
225 sizes =
new double[words.Length];
227 for (var i = 0; i < words.Length; i++)
229 string token = words[i];
230 var formattedText =
new FormattedText(token, CultureInfo.CurrentUICulture, FlowDirection.LeftToRight, typeface, textBlock.FontSize, Brushes.Black);
231 double width = formattedText.Width;
237 throw new ArgumentException(
"Invalid 'TextTrimming' argument.");
242 private string[] Split(
string text)
244 var words =
new List<string>();
246 var sb =
new StringBuilder();
247 foreach (var c
in text)
249 if (processedWordSeparators.Contains(c))
252 words.Add(sb.ToString());
256 words.Add(c.ToString(CultureInfo.InvariantCulture));
264 words.Add(sb.ToString());
266 return words.ToArray();
override void OnAttachedOverride()
override void OnDetachingOverride()