internal int LinesRequiredMethod(PSHostRawUserInterface rawUi, int maxWidth) { ProgressNode.RenderStyle style = this.Style; switch (style) { case ProgressNode.RenderStyle.Invisible: { return 0; } case ProgressNode.RenderStyle.Minimal: { return 1; } case ProgressNode.RenderStyle.Compact: { return this.LinesRequiredInCompactStyle; } case ProgressNode.RenderStyle.Full: { return this.LinesRequiredInFullStyleMethod(rawUi, maxWidth, false); } case ProgressNode.RenderStyle.FullPlus: { return this.LinesRequiredInFullStyleMethod(rawUi, maxWidth, true); } } return 0; }
private int CompressToFit(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth) { int num = 0; if (!this.CompressToFitHelper(rawUi, maxHeight, maxWidth, out num, ProgressNode.RenderStyle.FullPlus, ProgressNode.RenderStyle.Full)) { if (!this.CompressToFitHelper(rawUi, maxHeight, maxWidth, out num, ProgressNode.RenderStyle.Full, ProgressNode.RenderStyle.Compact)) { if (!this.CompressToFitHelper(rawUi, maxHeight, maxWidth, out num, ProgressNode.RenderStyle.Compact, ProgressNode.RenderStyle.Minimal)) { if (!this.CompressToFitHelper(rawUi, maxHeight, maxWidth, out num, ProgressNode.RenderStyle.Minimal, ProgressNode.RenderStyle.Invisible)) { return 0; } else { return num; } } else { return 0; } } else { return 0; } } else { return 0; } }
TruncateToBufferCellWidth(PSHostRawUserInterface rawUI, string toTruncate, int maxWidthInBufferCells) { Dbg.Assert(rawUI != null, "need a reference"); Dbg.Assert(maxWidthInBufferCells >= 0, "maxWidthInBufferCells must be positive"); string result; int i = Math.Min(toTruncate.Length, maxWidthInBufferCells); do { result = toTruncate.Substring(0, i); int cellCount = rawUI.LengthInBufferCells(result); if (cellCount <= maxWidthInBufferCells) { // the segment from start..i fits break; } else { // The segment does not fit, back off a tad until it does // We need to back off 1 by 1 because there could theoretically // be characters taking more 2 buffer cells --i; } } while (true); return result; }
internal ServerRemoteHostUserInterface(System.Management.Automation.Remoting.ServerRemoteHost remoteHost) { this._remoteHost = remoteHost; this._serverMethodExecutor = remoteHost.ServerMethodExecutor; this._rawUI = remoteHost.HostInfo.IsHostRawUINull ? null : new ServerRemoteHostRawUserInterface(this); AddHostDefaultData(); }
public GoosePSHostUserInterface(IList<string> output, IList<string> warning, IList<string> error, IList<string> verbose, IList<string> debug) { this.Output = output; this.Warning = warning; this.Error = error; this.Verbose = verbose; this.Debug = debug; this.rawUi = new GoosePSHostRawUserInterface(); }
internal static string TruncateToBufferCellWidth(PSHostRawUserInterface rawUI, string toTruncate, int maxWidthInBufferCells) { int length = Math.Min(toTruncate.Length, maxWidthInBufferCells); while (true) { string source = toTruncate.Substring(0, length); if (rawUI.LengthInBufferCells(source) <= maxWidthInBufferCells) { return source; } length--; } }
internal ProgressPane(ConsoleHostUserInterface ui) { this.location = new Coordinates(0, 0); if (ui != null) { this.ui = ui; this.rawui = ui.RawUI; return; } else { throw new ArgumentNullException("ui"); } }
private bool CompressToFitHelper(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth, out int nodesCompressed, ProgressNode.RenderStyle priorStyle, ProgressNode.RenderStyle newStyle) { nodesCompressed = 0; int num = 0; do { ProgressNode progressNode = this.FindOldestNodeOfGivenStyle(this.topLevelNodes, num, priorStyle); if (progressNode == null) { return false; } else { progressNode.Style = newStyle; nodesCompressed = nodesCompressed + 1; } } while (this.TallyHeight(rawUi, maxHeight, maxWidth) > maxHeight); return true; }
internal static string TruncateToBufferCellWidth( PSHostRawUserInterface rawUI, string toTruncate, int maxWidthInBufferCells) { var length = Math.Min(toTruncate.Length, maxWidthInBufferCells); string source; while (true) { source = toTruncate.Substring(0, length); if (rawUI.LengthInBufferCells(source) > maxWidthInBufferCells) { --length; } else { break; } } return source; }
private int LinesRequiredInFullStyleMethod(PSHostRawUserInterface rawUi, int maxWidth, bool isFullPlus) { int count = 1; string str = new string(' ', 5); ArrayList arrayLists = new ArrayList(); if (!isFullPlus) { count++; } else { arrayLists.Clear(); ProgressNode.RenderFullDescription(base.StatusDescription, str, maxWidth, rawUi, arrayLists, true); count = count + arrayLists.Count; } if (base.PercentComplete >= 0) { count++; } if (base.SecondsRemaining >= 0) { count++; } if (!string.IsNullOrEmpty(base.CurrentOperation)) { if (!isFullPlus) { count = count + 2; } else { count++; arrayLists.Clear(); ProgressNode.RenderFullDescription(base.CurrentOperation, str, maxWidth, rawUi, arrayLists, true); count = count + arrayLists.Count; } } return count; }
private static void RenderFullDescription(string description, string indent, int maxWidth, PSHostRawUserInterface rawUi, ArrayList strCollection, bool isFullPlus) { string oldDescription = StringUtil.Format(" {0}{1} ", indent, description); string newDescription; do { newDescription = StringUtil.TruncateToBufferCellWidth(rawUi, oldDescription, maxWidth); strCollection.Add(newDescription); if (oldDescription.Length == newDescription.Length) { break; } else { oldDescription = StringUtil.Format(" {0}{1}", indent, oldDescription.Substring(newDescription.Length)); } } while (isFullPlus); }
Render(ArrayList strCollection, int indentation, int maxWidth, PSHostRawUserInterface rawUI) { Dbg.Assert(strCollection != null, "strCollection should not be null"); Dbg.Assert(indentation >= 0, "indentation is negative"); Dbg.Assert(this.RecordType != ProgressRecordType.Completed, "should never render completed records"); switch (Style) { case RenderStyle.FullPlus: RenderFull(strCollection, indentation, maxWidth, rawUI, isFullPlus: true); break; case RenderStyle.Full: RenderFull(strCollection, indentation, maxWidth, rawUI, isFullPlus: false); break; case RenderStyle.Compact: RenderCompact(strCollection, indentation, maxWidth, rawUI); break; case RenderStyle.Minimal: RenderMinimal(strCollection, indentation, maxWidth, rawUI); break; case RenderStyle.Invisible: // do nothing break; default: Dbg.Assert(false, "unrecognized RenderStyle value"); break; } }
RenderFull(ArrayList strCollection, int indentation, int maxWidth, PSHostRawUserInterface rawUI, bool isFullPlus) { string indent = new string(' ', indentation); // First line: the activity strCollection.Add( StringUtil.TruncateToBufferCellWidth( rawUI, StringUtil.Format(" {0}{1} ", indent, this.Activity), maxWidth)); indentation += 3; indent = new string(' ', indentation); // Second line: the status description RenderFullDescription(this.StatusDescription, indent, maxWidth, rawUI, strCollection, isFullPlus); // Third line: the percentage thermometer. The size of this is proportional to the width we're allowed // to consume. -2 for the whitespace, -2 again for the brackets around thermo, -5 to not be too big if (PercentComplete >= 0) { int thermoWidth = Math.Max(3, maxWidth - indentation - 2 - 2 - 5); int mercuryWidth = 0; mercuryWidth = PercentComplete * thermoWidth / 100; if (PercentComplete < 100 && mercuryWidth == thermoWidth) { // back off a tad unless we're totally complete to prevent the appearance of completion before // the fact. --mercuryWidth; } strCollection.Add( StringUtil.TruncateToBufferCellWidth( rawUI, StringUtil.Format( " {0}[{1}{2}] ", indent, new string('o', mercuryWidth), new string(' ', thermoWidth - mercuryWidth)), maxWidth)); } // Fourth line: the seconds remaining if (SecondsRemaining >= 0) { TimeSpan span = new TimeSpan(0, 0, this.SecondsRemaining); strCollection.Add( StringUtil.TruncateToBufferCellWidth( rawUI, " " + StringUtil.Format( ProgressNodeStrings.SecondsRemaining, indent, span) + " ", maxWidth)); } // Fifth and Sixth lines: The current operation if (!String.IsNullOrEmpty(CurrentOperation)) { strCollection.Add(" "); RenderFullDescription(this.CurrentOperation, indent, maxWidth, rawUI, strCollection, isFullPlus); } }
InternalHostRawUserInterface(PSHostRawUserInterface externalRawUI, InternalHost parentHost) { // externalRawUI may be null _externalRawUI = externalRawUI; _parentHost = parentHost; }
public HostUI(IConsole control, UISettings settings, PSHostRawUserInterface rawUi) { _control = control; _settings = settings; _rawUI = rawUi; }
private int TallyHeight(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth) { PendingProgress.HeightTallyer heightTallyer = new PendingProgress.HeightTallyer(rawUi, maxHeight, maxWidth); PendingProgress.NodeVisitor.VisitNodes(this.topLevelNodes, heightTallyer); return heightTallyer.Tally; }
CompressToFitHelper( PSHostRawUserInterface rawUi, int maxHeight, int maxWidth, out int nodesCompressed, ProgressNode.RenderStyle priorStyle, ProgressNode.RenderStyle newStyle) { nodesCompressed = 0; int age = 0; do { ProgressNode node = FindOldestNodeOfGivenStyle(_topLevelNodes, age, priorStyle); if (node == null) { // We've compressed every node of the prior style already. break; } node.Style = newStyle; ++nodesCompressed; if (TallyHeight(rawUi, maxHeight, maxWidth) <= maxHeight) { return true; } } while (true); // If we get all the way to here, then we've compressed all the nodes and we still don't fit. #if DEBUG || ASSERTIONS_TRACE Dbg.Assert( nodesCompressed == CountNodes(), "We should have compressed every node in the tree."); Dbg.Assert( AllNodesHaveGivenStyle(_topLevelNodes, newStyle), "We should have compressed every node in the tree."); #endif return false; }
RenderHelper(ArrayList strings, ArrayList nodes, int indentation, int maxWidth, PSHostRawUserInterface rawUI) { Dbg.Assert(strings != null, "strings should not be null"); Dbg.Assert(nodes != null, "nodes should not be null"); if (nodes == null) { return; } foreach (ProgressNode node in nodes) { int lines = strings.Count; node.Render(strings, indentation, maxWidth, rawUI); if (node.Children != null) { // indent only if the rendering of node actually added lines to the strings. int indentationIncrement = (strings.Count > lines) ? 2 : 0; RenderHelper(strings, node.Children, indentation + indentationIncrement, maxWidth, rawUI); } } }
internal HeightTallyer(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth) { _rawUi = rawUi; _maxHeight = maxHeight; _maxWidth = maxWidth; }
internal string[] Render(int maxWidth, int maxHeight, PSHostRawUserInterface rawUI) { if (this.topLevelNodes == null || this.topLevelNodes.Count <= 0) { return null; } else { int fit = 0; if (this.TallyHeight(rawUI, maxHeight, maxWidth) > maxHeight) { fit = this.CompressToFit(rawUI, maxHeight, maxWidth); } ArrayList arrayLists = new ArrayList(); string str = new string(' ', maxWidth); arrayLists.Add(str); this.RenderHelper(arrayLists, this.topLevelNodes, 0, maxWidth, rawUI); if (fit != 1) { if (fit > 1) { arrayLists.Add(string.Concat(" ", StringUtil.Format(ProgressNodeStrings.InvisibleNodesMessagePlural, fit))); } } else { arrayLists.Add(string.Concat(" ", StringUtil.Format(ProgressNodeStrings.InvisibleNodesMessageSingular, fit))); } arrayLists.Add(str); return (string[])arrayLists.ToArray(typeof(string)); } }
Render(int maxWidth, int maxHeight, PSHostRawUserInterface rawUI) { Dbg.Assert(_topLevelNodes != null, "Shouldn't need to render progress if no data exists"); Dbg.Assert(maxWidth > 0, "maxWidth is too small"); Dbg.Assert(maxHeight >= 3, "maxHeight is too small"); if (_topLevelNodes == null || _topLevelNodes.Count <= 0) { // we have nothing to render. return null; } int invisible = 0; if (TallyHeight(rawUI, maxHeight, maxWidth) > maxHeight) { // This will smash down nodes until the tree will fit into the alloted number of lines. If in the // process some nodes were made invisible, we will add a line to the display to say so. invisible = CompressToFit(rawUI, maxHeight, maxWidth); } ArrayList result = new ArrayList(); string border = new string(' ', maxWidth); result.Add(border); RenderHelper(result, _topLevelNodes, 0, maxWidth, rawUI); if (invisible == 1) { result.Add( " " + StringUtil.Format( ProgressNodeStrings.InvisibleNodesMessageSingular, invisible)); } else if (invisible > 1) { result.Add( " " + StringUtil.Format( ProgressNodeStrings.InvisibleNodesMessagePlural, invisible)); } result.Add(border); return (string[])result.ToArray(typeof(string)); }
/// <summary> /// /// The number of vertical BufferCells that are required to render the node in its current style. /// /// </summary> /// <value></value> internal int LinesRequiredMethod(PSHostRawUserInterface rawUi, int maxWidth) { Dbg.Assert(this.RecordType != ProgressRecordType.Completed, "should never render completed records"); switch (Style) { case RenderStyle.FullPlus: return LinesRequiredInFullStyleMethod(rawUi, maxWidth, isFullPlus: true); case RenderStyle.Full: return LinesRequiredInFullStyleMethod(rawUi, maxWidth, isFullPlus: false); case RenderStyle.Compact: return LinesRequiredInCompactStyle; case RenderStyle.Minimal: return 1; case RenderStyle.Invisible: return 0; default: Dbg.Assert(false, "Unknown RenderStyle value"); break; } return 0; }
internal InternalHostRawUserInterface(PSHostRawUserInterface externalRawUI, InternalHost parentHost) { this.externalRawUI = externalRawUI; this.parentHost = parentHost; }
private void RenderHelper(ArrayList strings, ArrayList nodes, int indentation, int maxWidth, PSHostRawUserInterface rawUI) { int num; if (nodes != null) { foreach (ProgressNode node in nodes) { int count = strings.Count; node.Render(strings, indentation, maxWidth, rawUI); if (node.Children == null) { continue; } if (strings.Count > count) { num = 2; } else { num = 0; } int num1 = num; this.RenderHelper(strings, node.Children, indentation + num1, maxWidth, rawUI); } return; } else { return; } }
RenderCompact(ArrayList strCollection, int indentation, int maxWidth, PSHostRawUserInterface rawUI) { string indent = new string(' ', indentation); // First line: the activity strCollection.Add( StringUtil.TruncateToBufferCellWidth( rawUI, StringUtil.Format(" {0}{1} ", indent, this.Activity), maxWidth)); indentation += 3; indent = new string(' ', indentation); // Second line: the status description with percentage and time remaining, if applicable. string percent = ""; if (PercentComplete >= 0) { percent = StringUtil.Format("{0}% ", PercentComplete); } string secRemain = ""; if (SecondsRemaining >= 0) { TimeSpan span = new TimeSpan(0, 0, SecondsRemaining); secRemain = span.ToString() + " "; } strCollection.Add( StringUtil.TruncateToBufferCellWidth( rawUI, StringUtil.Format( " {0}{1}{2}{3} ", indent, percent, secRemain, StatusDescription), maxWidth)); // Third line: The current operation if (!String.IsNullOrEmpty(CurrentOperation)) { strCollection.Add( StringUtil.TruncateToBufferCellWidth( rawUI, StringUtil.Format(" {0}{1} ", indent, this.CurrentOperation), maxWidth)); } }
/// <summary> /// /// Tallies up the number of BufferCells vertically that will be required to show all the ProgressNodes in the given /// list, and all of their children. /// /// </summary> /// <param name="maxHeight"> /// /// The maximum height (in BufferCells) that the rendering may consume. /// /// </param> /// <param name="rawUi"> /// /// The PSHostRawUserInterface used to gauge string widths in the rendering. /// /// </param> /// <returns> /// /// The vertical height (in BufferCells) that will be required to show all of the nodes in the given list. /// /// </returns> /// <param name="maxWidth"> /// /// /// /// </param> private int TallyHeight(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth) { HeightTallyer ht = new HeightTallyer(rawUi, maxHeight, maxWidth); NodeVisitor.VisitNodes(_topLevelNodes, ht); return ht.Tally; }
RenderMinimal(ArrayList strCollection, int indentation, int maxWidth, PSHostRawUserInterface rawUI) { string indent = new string(' ', indentation); // First line: Everything mushed into one line string percent = ""; if (PercentComplete >= 0) { percent = StringUtil.Format("{0}% ", PercentComplete); } string secRemain = ""; if (SecondsRemaining >= 0) { TimeSpan span = new TimeSpan(0, 0, SecondsRemaining); secRemain = span.ToString() + " "; } strCollection.Add( StringUtil.TruncateToBufferCellWidth( rawUI, StringUtil.Format( " {0}{1} {2}{3}{4} ", indent, Activity, percent, secRemain, StatusDescription), maxWidth)); }
internal HeightTallyer(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth) { this.rawUi = rawUi; this.maxHeight = maxHeight; this.maxWidth = maxWidth; }
/// <summary> /// /// The number of vertical BufferCells that are required to render the node in the Full style. /// /// </summary> /// <value></value> private int LinesRequiredInFullStyleMethod(PSHostRawUserInterface rawUi, int maxWidth, bool isFullPlus) { // Since the fields of this instance could have been changed, we compute this on-the-fly. // NTRAID#Windows OS Bugs-1062104-2004/12/15-sburns we assume 1 line for each field. If we ever need to // word-wrap text fields, then this calculation will need updating. // Start with 1 for the Activity int lines = 1; // Use 5 spaces as the heuristic indent. 5 spaces stand for the indent for the CurrentOperation of the first-level child node var indent = new string(' ', 5); var temp = new ArrayList(); if (isFullPlus) { temp.Clear(); RenderFullDescription(StatusDescription, indent, maxWidth, rawUi, temp, isFullPlus: true); lines += temp.Count; } else { // 1 for the Status lines++; } if (PercentComplete >= 0) { ++lines; } if (SecondsRemaining >= 0) { ++lines; } if (!String.IsNullOrEmpty(CurrentOperation)) { if (isFullPlus) { lines += 1; temp.Clear(); RenderFullDescription(CurrentOperation, indent, maxWidth, rawUi, temp, isFullPlus: true); lines += temp.Count; } else { lines += 2; } } return lines; }
CompressToFit(PSHostRawUserInterface rawUi, int maxHeight, int maxWidth) { Dbg.Assert(_topLevelNodes != null, "Shouldn't need to compress if no data exists"); int nodesCompressed = 0; // This algorithm potentially makes many, many passes over the tree. It might be possible to optimize // that some, but I'm not trying to be too clever just yet. if ( CompressToFitHelper( rawUi, maxHeight, maxWidth, out nodesCompressed, ProgressNode.RenderStyle.FullPlus, ProgressNode.RenderStyle.Full)) { return 0; } if ( CompressToFitHelper( rawUi, maxHeight, maxWidth, out nodesCompressed, ProgressNode.RenderStyle.Full, ProgressNode.RenderStyle.Compact)) { return 0; } if ( CompressToFitHelper( rawUi, maxHeight, maxWidth, out nodesCompressed, ProgressNode.RenderStyle.Compact, ProgressNode.RenderStyle.Minimal)) { return 0; } if ( CompressToFitHelper( rawUi, maxHeight, maxWidth, out nodesCompressed, ProgressNode.RenderStyle.Minimal, ProgressNode.RenderStyle.Invisible)) { // The nodes that we compressed here are now invisible. return nodesCompressed; } Dbg.Assert(false, "with all nodes invisible, we should never reach this point."); return 0; }