/// <summary> /// Extend the string constructor with a string.Format like syntax. /// </summary> /// <param name="args"></param> /// <param name="placing"></param> /// <returns></returns> private static string FormatWith(EllipsisPlacement placing, params object[] args) { string formatString; switch (placing) { case EllipsisPlacement.None: formatString = "{0}{1}"; break; case EllipsisPlacement.Left: formatString = "...{0}{1}"; break; case EllipsisPlacement.Center: formatString = "{0}...{1}"; break; case EllipsisPlacement.Right: formatString = "{0}{1}..."; break; default: throw new ArgumentOutOfRangeException(placing.ToString()); } return(string.Format(CultureInfo.InvariantCulture, formatString, args)); }
// Sets Text to a substring of LongText based on _placement and _curLen. private void CalcText() { if (LongText == null) { switch (EllipsisPlacement) { case EllipsisPlacement.Left: case EllipsisPlacement.Center: case EllipsisPlacement.Right: case EllipsisPlacement.Path: SetText(LongText); break; } return; } switch (EllipsisPlacement) { case EllipsisPlacement.Right: SetText(LongText.Substring(0, _curLen) + "\u2026"); break; case EllipsisPlacement.Center: int firstLen = _curLen / 2; int secondLen = _curLen - firstLen; SetText(LongText.Substring(0, firstLen) + "\u2026" + LongText.Substring(LongText.Length - secondLen)); break; case EllipsisPlacement.Left: int start = LongText.Length - _curLen; SetText("\u2026" + LongText.Substring(start)); break; case EllipsisPlacement.Path: var sb = new StringBuilder(_curLen + 1); PathCompactPathEx(sb, LongText, _curLen, 0); SetText(sb.ToString()); break; default: throw new Exception("Unexpected switch value: " + EllipsisPlacement.ToString()); } }
/// <summary> /// Compute the text to display (with ellipsis) that fits the ActualWidth of the container /// </summary> /// <param name="inputString">Input string to measure whether it fits into container width or not.</param> /// <param name="constraint">ActualWidth restriction by container element (eg.: Grid)</param> /// <param name="placement"></param> /// <param name="ctrl"></param> /// <returns></returns> private static Tuple <string, Size> GetTrimmedPath(string inputString, Size constraint, EllipsisPlacement placement, Control ctrl) { Size size = new Size(); string filename = string.Empty; string directory = string.Empty; if (constraint.Width != double.PositiveInfinity) { size.Width = constraint.Width; } if (constraint.Height != double.PositiveInfinity) { size.Height = constraint.Height; } switch (placement) { // We don't want no ellipses to be shown for a string shortener case EllipsisPlacement.None: size = MeasureString(inputString, ctrl); return(new Tuple <string, Size>(inputString, size)); // Try to show a nice ellipses somewhere in the middle of the string case EllipsisPlacement.Center: try { if (string.IsNullOrEmpty(inputString) == false) { if (inputString.Contains(string.Empty + System.IO.Path.DirectorySeparatorChar)) { // Lets try to display the file name with priority filename = System.IO.Path.GetFileName(inputString); directory = System.IO.Path.GetDirectoryName(inputString); } else { // Cut this right in the middle since it does not seem to hold path info int len = inputString.Length; int firstLen = inputString.Length / 2; filename = inputString.Substring(0, firstLen); if (inputString.Length >= (firstLen + 1)) { directory = inputString.Substring(firstLen); } } } else { size = MeasureString(string.Empty, ctrl); return(new Tuple <string, Size>(inputString, size)); } } catch (Exception) { directory = inputString; filename = string.Empty; } break; case EllipsisPlacement.Left: directory = inputString; filename = string.Empty; break; case EllipsisPlacement.Right: directory = string.Empty; filename = inputString; break; default: throw new ArgumentOutOfRangeException(placement.ToString()); } double fudgeValue = 3.0; bool widthOK = false; int indexString = 0; string path = inputString; bool changedWidth = false; if (placement == EllipsisPlacement.Left) { indexString = 1; } do { path = FormatWith(placement, directory, filename); size = MeasureString(path, ctrl); widthOK = (size.Width + fudgeValue) < constraint.Width; if (widthOK == false) { if (directory.Length == 0) { if (filename.Length > 0) { changedWidth = true; filename = filename.Substring(indexString, filename.Length - 1); } else { size = MeasureString(string.Empty, ctrl); return(new Tuple <string, Size>(inputString, size)); } } else { changedWidth = true; directory = directory.Substring(indexString, directory.Length - 1); } } }while (widthOK == false); size.Width += fudgeValue; if (changedWidth == false) { return(new Tuple <string, Size>(inputString, size)); } return(new Tuple <string, Size>(path, size)); }
/// <summary>Initializes a new instance of the <see cref="TextBoxWithEllipsis"/> class.</summary> public TextBoxWithEllipsis() { // Initialize inherited stuff as desired. this.IsReadOnlyCaretVisible = true; // Initialize stuff added by this class this.IsEllipsisEnabled = true; this.UseLongTextForToolTip = true; this.FudgePix = 3.0; this.placement = EllipsisPlacement.Right; this.internalEnabled = true; this.LayoutUpdated += this.TextBoxWithEllipsisLayoutUpdated; this.SizeChanged += this.TextBoxWithEllipsisSizeChanged; }