using System; using System.Collections.Generic; using System.Text; namespace Netron.Diagramming.Core { /// /// (Describe usage of "L:300" format string.) /// public interface IShowable : IFormattable { //TODO: wonder if we should use TextWriters instead of StringBuilders? /// /// Format this using at most approximately rest chars and /// append the result, possibly truncated, to stringbuilder. /// Subtract the actual number of used chars from rest. /// /// /// /// /// True if the appended formatted string was complete (not truncated). bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider); } // ------------------------------------------------------------ // Static helper methods for Showing collections /// /// /// public static class Showing { /// /// Show Object obj by appending it to stringbuilder /// /// /// /// /// /// True if obj was shown completely. public static bool Show(Object obj, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider) { if (rest <= 0) return false; else if (obj is IShowable) return ((IShowable)obj).Show(stringbuilder, ref rest, formatProvider); int oldLength = stringbuilder.Length; stringbuilder.AppendFormat(formatProvider, "{0}", obj); rest -= (stringbuilder.Length - oldLength); return true; } /// /// /// /// /// /// /// public static String ShowString(IShowable showable, String format, IFormatProvider formatProvider) { int rest = maxLength(format); StringBuilder sb = new StringBuilder(); showable.Show(sb, ref rest, formatProvider); return sb.ToString(); } /// /// /// /// /// static int maxLength(String format) { //TODO: validate format string if (format == null) return 80; if (format.Length > 1 && format.StartsWith("L")) { return int.Parse(format.Substring(1)); } else return int.MaxValue; } /// /// /// /// /// /// /// /// /// True if collection was shown completely public static bool ShowCollectionValue(ICollectionBase items, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider) { string startdelim = "{ ", enddelim = " }"; bool showIndexes = false; //TODO: do not test here at run time, but select code at compile time // perhaps by delivering the print type to this metod if (items is IList) { startdelim = "[ "; enddelim = " ]"; } else if (items is ICollection) { startdelim = "{{ "; enddelim = " }}"; } stringbuilder.Append(startdelim); rest -= 2 * startdelim.Length; bool first = true; bool complete = true; int index = 0; { foreach (T x in items) { complete = false; if (rest <= 0) break; if (first) first = false; else { stringbuilder.Append(", "); rest -= 2; } if (showIndexes) { string indexString = string.Format("{0}:", index++); stringbuilder.Append(indexString); rest -= indexString.Length; } complete = Showing.Show(x, stringbuilder, ref rest, formatProvider); } } if (!complete) { stringbuilder.Append("..."); rest -= 3; } stringbuilder.Append(enddelim); return complete; } /// /// /// /// /// /// /// /// /// /// /// public static bool ShowDictionary(IDictionary dictionary, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider) { stringbuilder.Append("{ "); rest -= 4; // Account for "( " and " )" bool first = true; bool complete = true; foreach (KeyValuePair p in dictionary) { complete = false; if (rest <= 0) break; if (first) first = false; else { stringbuilder.Append(", "); rest -= 2; } complete = Showing.Show(p, stringbuilder, ref rest, formatProvider); } if (!complete) { stringbuilder.Append("..."); rest -= 3; } stringbuilder.Append(" }"); return complete; } } }