diff --git a/src/Microsoft.PowerShell.GraphicalHost/CommonHelper.cs b/src/Microsoft.PowerShell.GraphicalHost/CommonHelper.cs
new file mode 100644
index 000000000..37066d70b
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/CommonHelper.cs
@@ -0,0 +1,74 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements HelpWindow.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI
+{
+ using System.Windows;
+
+ ///
+ /// Utilities in common in this assembly
+ ///
+ internal static class CommonHelper
+ {
+ ///
+ /// Restore the values from the settings to the actual window position, size and state.
+ ///
+ /// the window we are setting position and size of
+ /// the value for top from the user settings
+ /// the value for left from the user settings
+ /// the value for width from the user settings
+ /// the value for height from the user settings
+ /// the with used if is not valid
+ /// the height used if is not valid
+ /// true if the window is maximized in the user setting
+ internal static void SetStartingPositionAndSize(Window target, double userSettingTop, double userSettingLeft, double userSettingWidth, double userSettingHeight, double defaultWidth, double defaultHeight, bool userSettingMaximized)
+ {
+ bool leftInvalid = userSettingLeft < System.Windows.SystemParameters.VirtualScreenLeft ||
+ userSettingWidth > System.Windows.SystemParameters.VirtualScreenLeft +
+ System.Windows.SystemParameters.VirtualScreenWidth;
+
+ bool topInvalid = userSettingTop < System.Windows.SystemParameters.VirtualScreenTop ||
+ userSettingTop > System.Windows.SystemParameters.VirtualScreenTop +
+ System.Windows.SystemParameters.VirtualScreenHeight;
+
+ bool widthInvalid = userSettingWidth < 0 ||
+ userSettingWidth > System.Windows.SystemParameters.VirtualScreenWidth;
+
+ bool heightInvalid = userSettingHeight < 0 ||
+ userSettingHeight > System.Windows.SystemParameters.VirtualScreenHeight;
+
+ if (leftInvalid || topInvalid)
+ {
+ target.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
+ }
+ else
+ {
+ target.Left = userSettingLeft;
+ target.Top = userSettingTop;
+ }
+
+ // If any saved coordinate is invalid, we set the window to the default position
+ if (widthInvalid || heightInvalid)
+ {
+ target.Width = defaultWidth;
+ target.Height = defaultHeight;
+ }
+ else
+ {
+ target.Width = userSettingWidth;
+ target.Height = userSettingHeight;
+ }
+
+ if (userSettingMaximized)
+ {
+ target.WindowState = WindowState.Maximized;
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpParagraphBuilder.cs b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpParagraphBuilder.cs
new file mode 100644
index 000000000..49c2b87c5
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpParagraphBuilder.cs
@@ -0,0 +1,983 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements HelpParagraphBuilder.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.Management.Automation;
+ using System.Text;
+ using System.Windows.Documents;
+
+ ///
+ /// Builds a help paragraph for a cmdlet
+ ///
+ internal class HelpParagraphBuilder : ParagraphBuilder
+ {
+ ///
+ /// Indentation size
+ ///
+ internal const int IndentSize = 4;
+
+ ///
+ /// new line separators
+ ///
+ private static readonly string[] Separators = new string[] { "\r\n", "\n" };
+
+ ///
+ /// Object with the cmdelt
+ ///
+ private PSObject psObj;
+
+ ///
+ /// Initializes a new instance of the HelpParagraphBuilder class
+ ///
+ /// paragraph being built
+ /// object with help information
+ internal HelpParagraphBuilder(Paragraph paragraph, PSObject psObj)
+ : base(paragraph)
+ {
+ this.psObj = psObj;
+ this.AddTextToParagraphBuilder();
+ }
+
+ ///
+ /// Enum for category of Help.
+ ///
+ private enum HelpCategory { Default, DscResource, Class };
+
+ ///
+ /// Gets the string value of a property or null if it could not be retrieved
+ ///
+ /// object with the property
+ /// property name
+ /// the string value of a property or null if it could not be retrieved
+ internal static string GetPropertyString(PSObject psObj, string propertyName)
+ {
+ Debug.Assert(psObj != null, "ensured by caller");
+ object value = GetPropertyObject(psObj, propertyName);
+
+ if (value == null)
+ {
+ return null;
+ }
+
+ return value.ToString();
+ }
+
+ ///
+ /// Adds the help text to the paragraph
+ ///
+ internal void AddTextToParagraphBuilder()
+ {
+ this.ResetAllText();
+
+ string strCategory = (HelpParagraphBuilder.GetProperty(this.psObj, "Category")).Value.ToString();
+
+ HelpCategory category = HelpCategory.Default;
+
+ if (String.Compare(strCategory, "DscResource", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ category = HelpCategory.DscResource;
+ }
+ else if (String.Compare(strCategory, "Class", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ category = HelpCategory.Class;
+ }
+
+ if (HelpParagraphBuilder.GetProperty(this.psObj, "Syntax") == null)
+ {
+ if(category == HelpCategory.Default)
+ {
+ // if there is no syntax, this is not the standard help
+ // it might be an about page
+ this.AddText(this.psObj.ToString(), false);
+ return;
+ }
+ }
+
+ switch (category)
+ {
+ case HelpCategory.Class:
+ this.AddDescription(HelpWindowSettings.Default.HelpSynopsysDisplayed, HelpWindowResources.SynopsisTitle, "Introduction");
+ this.AddMembers(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.PropertiesTitle);
+ this.AddMembers(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.MethodsTitle);
+ break;
+ case HelpCategory.DscResource:
+ this.AddStringSection(HelpWindowSettings.Default.HelpSynopsysDisplayed, "Synopsis", HelpWindowResources.SynopsisTitle);
+ this.AddDescription(HelpWindowSettings.Default.HelpDescriptionDisplayed, HelpWindowResources.DescriptionTitle, "Description");
+ this.AddParameters(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.PropertiesTitle, "Properties", HelpCategory.DscResource);
+ break;
+ default:
+ this.AddStringSection(HelpWindowSettings.Default.HelpSynopsysDisplayed, "Synopsis", HelpWindowResources.SynopsisTitle);
+ this.AddDescription(HelpWindowSettings.Default.HelpDescriptionDisplayed, HelpWindowResources.DescriptionTitle, "Description");
+ this.AddParameters(HelpWindowSettings.Default.HelpParametersDisplayed, HelpWindowResources.ParametersTitle, "Parameters", HelpCategory.Default);
+ this.AddSyntax(HelpWindowSettings.Default.HelpSyntaxDisplayed, HelpWindowResources.SyntaxTitle);
+ break;
+ }
+
+ this.AddInputOrOutputEntries(HelpWindowSettings.Default.HelpInputsDisplayed, HelpWindowResources.InputsTitle, "inputTypes", "inputType");
+ this.AddInputOrOutputEntries(HelpWindowSettings.Default.HelpOutputsDisplayed, HelpWindowResources.OutputsTitle, "returnValues", "returnValue");
+ this.AddNotes(HelpWindowSettings.Default.HelpNotesDisplayed, HelpWindowResources.NotesTitle);
+ this.AddExamples(HelpWindowSettings.Default.HelpExamplesDisplayed, HelpWindowResources.ExamplesTitle);
+ this.AddNavigationLink(HelpWindowSettings.Default.HelpRelatedLinksDisplayed, HelpWindowResources.RelatedLinksTitle);
+ this.AddStringSection(HelpWindowSettings.Default.HelpRemarksDisplayed, "Remarks", HelpWindowResources.RemarksTitle);
+ }
+
+ ///
+ /// Gets the object property or null if it could not be retrieved
+ ///
+ /// object with the property
+ /// property name
+ /// the object property or null if it could not be retrieved
+ private static PSPropertyInfo GetProperty(PSObject psObj, string propertyName)
+ {
+ Debug.Assert(psObj != null, "ensured by caller");
+ return psObj.Properties[propertyName];
+ }
+
+ ///
+ /// Gets a PSObject and then a value from it or null if the value could not be retrieved
+ ///
+ /// PSObject that contains another PSObject as a property
+ /// property name that contains the PSObject
+ /// property name in thye inner PSObject
+ /// the string from the inner psObject property or null if it could not be retrieved
+ private static string GetInnerPSObjectPropertyString(PSObject psObj, string psObjectName, string propertyName)
+ {
+ Debug.Assert(psObj != null, "ensured by caller");
+ PSObject innerPsObj = GetPropertyObject(psObj, psObjectName) as PSObject;
+
+ if (innerPsObj == null)
+ {
+ return null;
+ }
+
+ object value = GetPropertyObject(innerPsObj, propertyName);
+
+ if (value == null)
+ {
+ return null;
+ }
+
+ return value.ToString();
+ }
+
+ ///
+ /// Gets the value of a property or null if the value could not be retrieved
+ ///
+ /// object with the property
+ /// property name
+ /// the value of a property or null if the value could not be retrieved
+ private static object GetPropertyObject(PSObject psObj, string propertyName)
+ {
+ Debug.Assert(psObj != null, "ensured by caller");
+ PSPropertyInfo property = HelpParagraphBuilder.GetProperty(psObj, propertyName);
+ if (property == null)
+ {
+ return null;
+ }
+
+ object value = null;
+ try
+ {
+ value = property.Value;
+ }
+ catch (ExtendedTypeSystemException)
+ {
+ }
+
+ return value;
+ }
+
+ ///
+ /// Gets the text from a property of type PSObject[] where the first object has a text property
+ ///
+ /// objhect to get text from
+ /// property with PSObject[] containing text
+ /// the text from a property of type PSObject[] where the first object has a text property
+ private static string GetTextFromArray(PSObject psObj, string propertyText)
+ {
+ PSObject[] introductionObjects = HelpParagraphBuilder.GetPropertyObject(psObj, propertyText) as PSObject[];
+ if (introductionObjects != null && introductionObjects.Length > 0)
+ {
+ return GetPropertyString(introductionObjects[0], "text");
+ }
+
+ return null;
+ }
+
+ ///
+ /// Returns the largest size of a group of strings
+ ///
+ /// strings to evaluate the largest size from
+ /// the largest size of a group of strings
+ private static int LargestSize(params string[] strs)
+ {
+ int returnValue = 0;
+
+ foreach (string str in strs)
+ {
+ if (str != null && str.Length > returnValue)
+ {
+ returnValue = str.Length;
+ }
+ }
+
+ return returnValue;
+ }
+
+ ///
+ /// Splits the string adding indentation before each line
+ ///
+ /// string to add indentation to
+ /// the string indented
+ private static string AddIndent(string str)
+ {
+ return HelpParagraphBuilder.AddIndent(str, 1);
+ }
+
+ ///
+ /// Splits the string adding indentation before each line
+ ///
+ /// string to add indentation to
+ /// number of indentations
+ /// the string indented
+ private static string AddIndent(string str, int numberOfIdents)
+ {
+ StringBuilder indent = new StringBuilder();
+ indent.Append(' ', numberOfIdents * HelpParagraphBuilder.IndentSize);
+ return HelpParagraphBuilder.AddIndent(str, indent.ToString());
+ }
+
+ ///
+ /// Splits the string adding indentation before each line
+ ///
+ /// string to add indentation to
+ /// indentation string
+ /// the string indented
+ private static string AddIndent(string str, string indentString)
+ {
+ if (str == null)
+ {
+ return String.Empty;
+ }
+
+ string[] lines = str.Split(Separators, StringSplitOptions.None);
+
+ StringBuilder returnValue = new StringBuilder();
+ foreach (string line in lines)
+ {
+ // Indentation is not localized
+ returnValue.AppendFormat("{0}{1}\r\n", indentString, line);
+ }
+
+ if (returnValue.Length > 2)
+ {
+ // remove the last \r\n
+ returnValue.Remove(returnValue.Length - 2, 2);
+ }
+
+ return returnValue.ToString();
+ }
+
+ ///
+ /// Get the object array value of a property
+ ///
+ /// object containing the property
+ /// property with the array value
+ /// the object array value of a property
+ private static object[] GetPropertyObjectArray(PSObject obj, string propertyName)
+ {
+ object innerObject;
+ if ((innerObject = HelpParagraphBuilder.GetPropertyObject(obj, propertyName)) == null)
+ {
+ return null;
+ }
+
+ if (innerObject is PSObject)
+ {
+ return new object[] { innerObject };
+ }
+
+ object[] innerObjectArray = innerObject as object[];
+ if (innerObject == null)
+ {
+ return null;
+ }
+
+ return innerObjectArray;
+ }
+
+
+ ///
+ /// Adds a section that contains only a string
+ ///
+ /// true if it should add the segment
+ /// name of the section to add
+ /// title of the section
+ private void AddStringSection(bool setting, string sectionName, string sectionTitle)
+ {
+ string propertyValue;
+ if (!setting || (propertyValue = HelpParagraphBuilder.GetPropertyString(this.psObj, sectionName)) == null)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+ this.AddText(HelpParagraphBuilder.AddIndent(propertyValue), false);
+ this.AddText("\r\n\r\n", false);
+ }
+
+ ///
+ /// Adds the help syntax segment
+ ///
+ /// true if it should add the segment
+ /// title of the section
+ private void AddSyntax(bool setting, string sectionTitle)
+ {
+ PSObject syntaxObject;
+ if (!setting || (syntaxObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "Syntax") as PSObject) == null)
+ {
+ return;
+ }
+
+ object[] syntaxItemsObj = HelpParagraphBuilder.GetPropertyObjectArray(syntaxObject, "syntaxItem");
+ if (syntaxItemsObj == null || syntaxItemsObj.Length == 0)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+
+ foreach (object syntaxItemObj in syntaxItemsObj)
+ {
+ PSObject syntaxItem = syntaxItemObj as PSObject;
+ if (syntaxItem == null)
+ {
+ continue;
+ }
+
+ string commandName = GetPropertyString(syntaxItem, "name");
+
+ object[] parameterObjs = HelpParagraphBuilder.GetPropertyObjectArray(syntaxItem, "parameter");
+ if (commandName == null || parameterObjs == null || parameterObjs.Length == 0)
+ {
+ continue;
+ }
+
+ string commandStart = String.Format(CultureInfo.CurrentCulture, "{0} ", commandName);
+ this.AddText(HelpParagraphBuilder.AddIndent(commandStart), false);
+
+ foreach (object parameterObj in parameterObjs)
+ {
+ PSObject parameter = parameterObj as PSObject;
+ if (parameter == null)
+ {
+ continue;
+ }
+
+ string parameterValue = GetPropertyString(parameter, "parameterValue");
+ string position = GetPropertyString(parameter, "position");
+ string required = GetPropertyString(parameter, "required");
+ string parameterName = GetPropertyString(parameter, "name");
+ if (position == null || required == null || parameterName == null)
+ {
+ continue;
+ }
+
+ string parameterType = parameterValue == null ? String.Empty : String.Format(CultureInfo.CurrentCulture, "<{0}>", parameterValue);
+
+ string parameterOptionalOpenBrace, parameterOptionalCloseBrace;
+
+ if (String.Equals(required, "true", StringComparison.OrdinalIgnoreCase))
+ {
+ parameterOptionalOpenBrace = parameterOptionalCloseBrace = String.Empty;
+ }
+ else
+ {
+ parameterOptionalOpenBrace = "[";
+ parameterOptionalCloseBrace = "]";
+ }
+
+ string parameterNameOptionalOpenBrace, parameterNameOptionalCloseBrace;
+
+ if (String.Equals(position, "named", StringComparison.OrdinalIgnoreCase))
+ {
+ parameterNameOptionalOpenBrace = parameterNameOptionalCloseBrace = String.Empty;
+ }
+ else
+ {
+ parameterNameOptionalOpenBrace = "[";
+ parameterNameOptionalCloseBrace = "]";
+ }
+
+ string paramterPrefix = String.Format(
+ CultureInfo.CurrentCulture,
+ "{0}{1}-",
+ parameterOptionalOpenBrace,
+ parameterNameOptionalOpenBrace);
+
+ this.AddText(paramterPrefix, false);
+ this.AddText(parameterName, true);
+
+ string paramterSuffix = String.Format(
+ CultureInfo.CurrentCulture,
+ "{0} {1}{2} ",
+ parameterNameOptionalCloseBrace,
+ parameterType,
+ parameterOptionalCloseBrace);
+ this.AddText(paramterSuffix, false);
+ }
+
+ string commonParametersText = String.Format(
+ CultureInfo.CurrentCulture,
+ "[<{0}>]\r\n\r\n",
+ HelpWindowResources.CommonParameters);
+
+ this.AddText(commonParametersText, false);
+ }
+
+ this.AddText("\r\n", false);
+ }
+
+ ///
+ /// Adds the help description segment
+ ///
+ /// true if it should add the segment
+ /// title of the section
+ /// propertyName that has description
+ private void AddDescription(bool setting, string sectionTitle, string propertyName)
+ {
+ PSObject[] descriptionObjects;
+ if (!setting ||
+ (descriptionObjects = HelpParagraphBuilder.GetPropertyObject(this.psObj, propertyName) as PSObject[]) == null ||
+ descriptionObjects.Length == 0)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+
+ foreach (PSObject description in descriptionObjects)
+ {
+ string descriptionText = GetPropertyString(description, "text");
+ this.AddText(HelpParagraphBuilder.AddIndent(descriptionText), false);
+ this.AddText("\r\n", false);
+ }
+
+ this.AddText("\r\n\r\n", false);
+ }
+
+ ///
+ /// Adds the help examples segment
+ ///
+ /// true if it should add the segment
+ /// title of the section
+ private void AddExamples(bool setting, string sectionTitle)
+ {
+ if (!setting)
+ {
+ return;
+ }
+
+ PSObject exampleRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "Examples") as PSObject;
+ if (exampleRootObject == null)
+ {
+ return;
+ }
+
+ object[] exampleObjects = HelpParagraphBuilder.GetPropertyObjectArray(exampleRootObject, "example");
+ if (exampleObjects == null || exampleObjects.Length == 0)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+
+ foreach (object exampleObj in exampleObjects)
+ {
+ PSObject example = exampleObj as PSObject;
+ if (example == null)
+ {
+ continue;
+ }
+
+ string introductionText = null;
+ introductionText = GetTextFromArray(example, "introduction");
+
+ string codeText = GetPropertyString(example, "code");
+ string title = GetPropertyString(example, "title");
+
+ if (codeText == null)
+ {
+ continue;
+ }
+
+ if (title != null)
+ {
+ this.AddText(HelpParagraphBuilder.AddIndent(title), false);
+ this.AddText("\r\n", false);
+ }
+
+ string codeLine = String.Format(
+ CultureInfo.CurrentCulture,
+ "{0}{1}\r\n\r\n",
+ introductionText,
+ codeText);
+
+ this.AddText(HelpParagraphBuilder.AddIndent(codeLine), false);
+
+ PSObject[] remarks = HelpParagraphBuilder.GetPropertyObject(example, "remarks") as PSObject[];
+ if (remarks == null)
+ {
+ continue;
+ }
+
+ foreach (PSObject remark in remarks)
+ {
+ string remarkText = GetPropertyString(remark, "text");
+ if (remarkText == null)
+ {
+ continue;
+ }
+
+ this.AddText(remarkText, false);
+ this.AddText("\r\n", false);
+ }
+ }
+
+ this.AddText("\r\n\r\n", false);
+ }
+
+ private void AddMembers(bool setting, string sectionTitle)
+ {
+ if(!setting || String.IsNullOrEmpty(sectionTitle))
+ return;
+
+ PSObject memberRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "Members") as PSObject;
+ if (memberRootObject == null)
+ return;
+
+ object[] memberObjects = HelpParagraphBuilder.GetPropertyObjectArray(memberRootObject, "member");
+
+ if (memberObjects == null)
+ return;
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+
+ foreach (object memberObj in memberObjects)
+ {
+ string description = null;
+ string memberText = null;
+
+ PSObject member = memberObj as PSObject;
+ if (member == null)
+ continue;
+
+ string name = GetPropertyString(member, "title");
+ string type = GetPropertyString(member, "type");
+ string propertyType = null;
+
+ if (String.Compare("field", type, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ PSObject fieldData = HelpParagraphBuilder.GetPropertyObject(member, "fieldData") as PSObject;
+
+ if (fieldData != null)
+ {
+ PSObject propertyTypeObject = HelpParagraphBuilder.GetPropertyObject(fieldData, "type") as PSObject;
+ if (propertyTypeObject != null)
+ {
+ propertyType = GetPropertyString(propertyTypeObject, "name");
+ description = GetPropertyString(propertyTypeObject, "description");
+ }
+
+ memberText = String.Format(CultureInfo.CurrentCulture, " [{0}] {1}\r\n", propertyType, name);
+ }
+ }
+ else if (String.Compare("method", type, StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ FormatMethodData(member, name, out memberText, out description);
+ }
+
+ if (!String.IsNullOrEmpty(memberText))
+ {
+ this.AddText(HelpParagraphBuilder.AddIndent(""), false);
+ this.AddText(memberText, true);
+
+ if (description != null)
+ {
+ this.AddText(HelpParagraphBuilder.AddIndent(description, 2), false);
+ this.AddText("\r\n", false);
+ }
+
+ this.AddText("\r\n", false);
+ }
+ }
+ }
+
+ private void FormatMethodData(PSObject member, string name, out string memberText, out string description)
+ {
+ memberText = null;
+ description = null;
+
+ if (member == null || String.IsNullOrEmpty(name))
+ {
+ return;
+ }
+
+ string returnType = null;
+ StringBuilder parameterText = new StringBuilder();
+
+ //Get method return type
+ PSObject returnTypeObject = HelpParagraphBuilder.GetPropertyObject(member, "returnValue") as PSObject;
+ if (returnTypeObject != null)
+ {
+ PSObject returnTypeData = HelpParagraphBuilder.GetPropertyObject(returnTypeObject, "type") as PSObject;
+ if (returnTypeData != null)
+ returnType = GetPropertyString(returnTypeData, "name");
+ }
+
+ //Get method description.
+ PSObject[] methodDescriptions = HelpParagraphBuilder.GetPropertyObject(member, "introduction") as PSObject[];
+ if (methodDescriptions != null)
+ {
+ foreach (var methodDescription in methodDescriptions)
+ {
+ description = GetPropertyString(methodDescription, "Text");
+
+ //If we get an text we do not need to iterate more.
+ if (!String.IsNullOrEmpty(description))
+ break;
+ }
+ }
+
+ //Get method parameters.
+ PSObject parametersObject = HelpParagraphBuilder.GetPropertyObject(member, "parameters") as PSObject;
+ if (parametersObject != null)
+ {
+ PSObject[] paramObject = HelpParagraphBuilder.GetPropertyObject(parametersObject, "parameter") as PSObject[];
+
+ if (paramObject != null)
+ {
+ foreach (var param in paramObject)
+ {
+ string parameterName = GetPropertyString(param, "name");
+ string parameterType = null;
+
+ PSObject parameterTypeData = HelpParagraphBuilder.GetPropertyObject(param, "type") as PSObject;
+
+ if (parameterTypeData != null)
+ {
+ parameterType = GetPropertyString(parameterTypeData, "name");
+
+ //If there is no type for the paramter, we expect it is System.Object
+ if (String.IsNullOrEmpty(parameterType))
+ parameterType = "object";
+ }
+
+ string paramString = String.Format(CultureInfo.CurrentCulture, "[{0}] ${1},", parameterType, parameterName);
+
+ parameterText.Append(paramString);
+ }
+
+ if (String.Compare(parameterText[parameterText.Length - 1].ToString(), ",", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ parameterText = parameterText.Remove(parameterText.Length - 1, 1);
+ }
+ }
+ }
+
+ memberText = String.Format(CultureInfo.CurrentCulture, " [{0}] {1}({2})\r\n", returnType, name, parameterText.ToString());
+ }
+
+ ///
+ /// Adds the help parameters segment
+ ///
+ /// true if it should add the segment
+ /// title of the section
+ /// name of the property which has properties
+ /// category of help
+ private void AddParameters(bool setting, string sectionTitle, string paramPropertyName, HelpCategory helpCategory)
+ {
+ if (!setting)
+ {
+ return;
+ }
+
+ PSObject parameterRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, paramPropertyName) as PSObject;
+ if (parameterRootObject == null)
+ {
+ return;
+ }
+
+ object[] parameterObjects = null;
+
+ //Root object for Class has members not parameters.
+ if (helpCategory != HelpCategory.Class)
+ {
+ parameterObjects = HelpParagraphBuilder.GetPropertyObjectArray(parameterRootObject, "parameter");
+ }
+
+ if (parameterObjects == null || parameterObjects.Length == 0)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+
+ foreach (object parameterObj in parameterObjects)
+ {
+ PSObject parameter = parameterObj as PSObject;
+ if (parameter == null)
+ {
+ continue;
+ }
+
+ string parameterValue = GetPropertyString(parameter, "parameterValue");
+ string name = GetPropertyString(parameter, "name");
+ string description = GetTextFromArray(parameter, "description");
+ string required = GetPropertyString(parameter, "required");
+ string position = GetPropertyString(parameter, "position");
+ string pipelineinput = GetPropertyString(parameter, "pipelineInput");
+ string defaultValue = GetPropertyString(parameter, "defaultValue");
+ string acceptWildcard = GetPropertyString(parameter, "globbing");
+
+ if (String.IsNullOrEmpty(name))
+ {
+ continue;
+ }
+
+ // This syntax string is not localized
+
+ if (helpCategory == HelpCategory.DscResource)
+ this.AddText(HelpParagraphBuilder.AddIndent(""), false);
+ else
+ this.AddText(HelpParagraphBuilder.AddIndent("-"), false);
+
+ this.AddText(name, true);
+ string parameterText = String.Format(
+ CultureInfo.CurrentCulture,
+ " <{0}>\r\n",
+ parameterValue);
+
+ this.AddText(parameterText, false);
+
+ if (description != null)
+ {
+ this.AddText(HelpParagraphBuilder.AddIndent(description, 2), false);
+ this.AddText("\r\n", false);
+ }
+
+ this.AddText("\r\n", false);
+
+ int largestSize = HelpParagraphBuilder.LargestSize(
+ HelpWindowResources.ParameterRequired,
+ HelpWindowResources.ParameterPosition,
+ HelpWindowResources.ParameterDefautValue,
+ HelpWindowResources.ParameterPipelineInput,
+ HelpWindowResources.ParameterAcceptWildcard);
+
+ // justification of parameter values is not localized
+ string formatString = String.Format(
+ CultureInfo.CurrentCulture,
+ "{{0,-{0}}}{{1}}",
+ largestSize + 2);
+
+ string tableLine;
+
+ tableLine = String.Format(
+ CultureInfo.CurrentCulture,
+ formatString,
+ HelpWindowResources.ParameterRequired,
+ required);
+ this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
+ this.AddText("\r\n", false);
+
+ //these are not applicable for Dsc Resource help
+ if (helpCategory != HelpCategory.DscResource)
+ {
+ tableLine = String.Format(
+ CultureInfo.CurrentCulture,
+ formatString,
+ HelpWindowResources.ParameterPosition,
+ position);
+ this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
+ this.AddText("\r\n", false);
+
+ tableLine = String.Format(
+ CultureInfo.CurrentCulture,
+ formatString,
+ HelpWindowResources.ParameterDefautValue,
+ defaultValue);
+ this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
+ this.AddText("\r\n", false);
+
+ tableLine = String.Format(
+ CultureInfo.CurrentCulture,
+ formatString,
+ HelpWindowResources.ParameterPipelineInput,
+ pipelineinput);
+ this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
+ this.AddText("\r\n", false);
+
+ tableLine = String.Format(
+ CultureInfo.CurrentCulture,
+ formatString,
+ HelpWindowResources.ParameterAcceptWildcard,
+ acceptWildcard);
+ this.AddText(HelpParagraphBuilder.AddIndent(tableLine, 2), false);
+ }
+
+ this.AddText("\r\n\r\n", false);
+ }
+
+ this.AddText("\r\n\r\n", false);
+ }
+
+ ///
+ /// Adds the help navigation links segment
+ ///
+ /// true if it should add the segment
+ /// title of the section
+ private void AddNavigationLink(bool setting, string sectionTitle)
+ {
+ if (!setting)
+ {
+ return;
+ }
+
+ PSObject linkRootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "RelatedLinks") as PSObject;
+ if (linkRootObject == null)
+ {
+ return;
+ }
+
+ PSObject[] linkObjects;
+
+ if ((linkObjects = HelpParagraphBuilder.GetPropertyObject(linkRootObject, "navigationLink") as PSObject[]) == null ||
+ linkObjects.Length == 0)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+
+ foreach (PSObject linkObject in linkObjects)
+ {
+ string text = GetPropertyString(linkObject, "linkText");
+ string uri = GetPropertyString(linkObject, "uri");
+
+ string linkLine = String.IsNullOrEmpty(uri) ? text : String.Format(
+ CultureInfo.CurrentCulture,
+ HelpWindowResources.LinkTextFormat,
+ text,
+ uri);
+
+ this.AddText(HelpParagraphBuilder.AddIndent(linkLine), false);
+ this.AddText("\r\n", false);
+ }
+
+ this.AddText("\r\n\r\n", false);
+ }
+
+ ///
+ /// Adds the help input or output segment
+ ///
+ /// true if it should add the segment
+ /// title of the section
+ /// property with the outter object
+ /// property with the inner object
+ private void AddInputOrOutputEntries(bool setting, string sectionTitle, string inputOrOutputProperty, string inputOrOutputInnerProperty)
+ {
+ if (!setting)
+ {
+ return;
+ }
+
+ PSObject rootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, inputOrOutputProperty) as PSObject;
+ if (rootObject == null)
+ {
+ return;
+ }
+
+ object[] inputOrOutputObjs;
+ inputOrOutputObjs = HelpParagraphBuilder.GetPropertyObjectArray(rootObject, inputOrOutputInnerProperty);
+
+ if (inputOrOutputObjs == null || inputOrOutputObjs.Length == 0)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+
+ foreach (object inputOrOutputObj in inputOrOutputObjs)
+ {
+ PSObject inputOrOutput = inputOrOutputObj as PSObject;
+ if (inputOrOutput == null)
+ {
+ continue;
+ }
+
+ string type = HelpParagraphBuilder.GetInnerPSObjectPropertyString(inputOrOutput, "type", "name");
+ string description = GetTextFromArray(inputOrOutput, "description");
+
+ this.AddText(HelpParagraphBuilder.AddIndent(type), false);
+ this.AddText("\r\n", false);
+ if (description != null)
+ {
+ this.AddText(HelpParagraphBuilder.AddIndent(description), false);
+ this.AddText("\r\n", false);
+ }
+ }
+
+ this.AddText("\r\n", false);
+ }
+
+ ///
+ /// Adds the help notes segment
+ ///
+ /// true if it should add the segment
+ /// title of the section
+ private void AddNotes(bool setting, string sectionTitle)
+ {
+ if (!setting)
+ {
+ return;
+ }
+
+ PSObject rootObject = HelpParagraphBuilder.GetPropertyObject(this.psObj, "alertSet") as PSObject;
+ if (rootObject == null)
+ {
+ return;
+ }
+
+ string note = GetTextFromArray(rootObject, "alert");
+
+ if (note == null)
+ {
+ return;
+ }
+
+ this.AddText(sectionTitle, true);
+ this.AddText("\r\n", false);
+ this.AddText(HelpParagraphBuilder.AddIndent(note), false);
+ this.AddText("\r\n\r\n", false);
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpViewModel.cs b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpViewModel.cs
new file mode 100644
index 000000000..91f44fc4e
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpViewModel.cs
@@ -0,0 +1,289 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements HelpViewModel.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.ComponentModel;
+ using System.Diagnostics;
+ using System.Globalization;
+ using System.Management.Automation;
+ using System.Windows.Documents;
+
+ ///
+ /// ViewModel for the Help Dialog used to:
+ /// build the help document
+ /// search the help document
+ /// offer text for labels
+ ///
+ internal class HelpViewModel : INotifyPropertyChanged
+ {
+ ///
+ /// The builder for the help FlowDocument Paragraph used in a RichEditText control
+ ///
+ private HelpParagraphBuilder helpBuilder;
+
+ ///
+ /// Searcher for selecting current matches in paragraph text
+ ///
+ private ParagraphSearcher searcher;
+
+ ///
+ /// Title of the help window
+ ///
+ private string helpTitle;
+
+ ///
+ /// the zoom bound to the zoom slider value
+ ///
+ private double zoom = 100;
+
+ ///
+ /// Text to be found. This is bound to the find TextBox
+ ///
+ private string findText;
+
+ ///
+ /// text for the number of matches found
+ ///
+ private string matchesLabel;
+
+ ///
+ /// Initializes a new instance of the HelpViewModel class
+ ///
+ /// object containing help
+ /// paragraph in which help text is built/searched
+ internal HelpViewModel(PSObject psObj, Paragraph documentParagraph)
+ {
+ Debug.Assert(psObj != null, "ensured by caller");
+ Debug.Assert(documentParagraph != null, "ensured by caller");
+
+ this.helpBuilder = new HelpParagraphBuilder(documentParagraph, psObj);
+ this.helpBuilder.BuildParagraph();
+ this.searcher = new ParagraphSearcher();
+ this.helpBuilder.PropertyChanged += new PropertyChangedEventHandler(this.HelpBuilder_PropertyChanged);
+ this.helpTitle = String.Format(
+ CultureInfo.CurrentCulture,
+ HelpWindowResources.HelpTitleFormat,
+ HelpParagraphBuilder.GetPropertyString(psObj, "name"));
+ }
+
+ #region INotifyPropertyChanged Members
+ ///
+ /// Used to notify of property changes
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+ #endregion
+
+ ///
+ /// Gets or sets the Zoom bound to the zoom slider value
+ ///
+ public double Zoom
+ {
+ get
+ {
+ return this.zoom;
+ }
+
+ set
+ {
+ this.zoom = value;
+ this.OnNotifyPropertyChanged("Zoom");
+ this.OnNotifyPropertyChanged("ZoomLabel");
+ this.OnNotifyPropertyChanged("ZoomLevel");
+ }
+ }
+
+ ///
+ /// Gets the value bound to the RichTextEdit zoom, which is calculated based on the zoom
+ ///
+ public double ZoomLevel
+ {
+ get
+ {
+ return this.zoom / 100.0;
+ }
+ }
+
+ ///
+ /// Gets the label to be displayed for the zoom
+ ///
+ public string ZoomLabel
+ {
+ get
+ {
+ return String.Format(CultureInfo.CurrentCulture, HelpWindowResources.ZoomLabelTextFormat, this.zoom);
+ }
+ }
+
+ ///
+ /// Gets or sets the text to be found
+ ///
+ public string FindText
+ {
+ get
+ {
+ return this.findText;
+ }
+
+ set
+ {
+ this.findText = value;
+ this.Search();
+ this.SetMatchesLabel();
+ }
+ }
+
+ ///
+ /// Gets the title of the window
+ ///
+ public string HelpTitle
+ {
+ get
+ {
+ return this.helpTitle;
+ }
+ }
+
+ ///
+ /// Gets or sets the label for current matches
+ ///
+ public string MatchesLabel
+ {
+ get
+ {
+ return this.matchesLabel;
+ }
+
+ set
+ {
+ this.matchesLabel = value;
+ this.OnNotifyPropertyChanged("MatchesLabel");
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether there are matches to go to
+ ///
+ public bool CanGoToNextOrPrevious
+ {
+ get
+ {
+ return this.HelpBuilder.HighlightCount != 0;
+ }
+ }
+
+ ///
+ /// Gets the searcher for selecting current matches in paragraph text
+ ///
+ internal ParagraphSearcher Searcher
+ {
+ get { return this.searcher; }
+ }
+
+ ///
+ /// Gets the paragraph builder used to write help content
+ ///
+ internal HelpParagraphBuilder HelpBuilder
+ {
+ get { return this.helpBuilder; }
+ }
+
+ ///
+ /// Highlights all matches to this.findText
+ /// Called when findText changes or whenever the search has to be refreshed
+ ///
+ internal void Search()
+ {
+ this.HelpBuilder.HighlightAllInstancesOf(this.findText, HelpWindowSettings.Default.HelpSearchMatchCase, HelpWindowSettings.Default.HelpSearchWholeWord);
+ this.searcher.ResetSearch();
+ }
+
+ ///
+ /// Increases Zoom if not above maximum
+ ///
+ internal void ZoomIn()
+ {
+ if (this.Zoom + HelpWindow.ZoomInterval <= HelpWindow.MaximumZoom)
+ {
+ this.Zoom += HelpWindow.ZoomInterval;
+ }
+ }
+
+ ///
+ /// Decreases Zoom if not below minimum
+ ///
+ internal void ZoomOut()
+ {
+ if (this.Zoom - HelpWindow.ZoomInterval >= HelpWindow.MinimumZoom)
+ {
+ this.Zoom -= HelpWindow.ZoomInterval;
+ }
+ }
+
+ ///
+ /// Called to update the matches label
+ ///
+ /// event sender
+ /// event arguments
+ private void HelpBuilder_PropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "HighlightCount")
+ {
+ this.SetMatchesLabel();
+ this.OnNotifyPropertyChanged("CanGoToNextOrPrevious");
+ }
+ }
+
+ ///
+ /// Sets the current matches label
+ ///
+ private void SetMatchesLabel()
+ {
+ if (this.findText == null || this.findText.Trim().Length == 0)
+ {
+ this.MatchesLabel = String.Empty;
+ }
+ else
+ {
+ if (this.HelpBuilder.HighlightCount == 0)
+ {
+ this.MatchesLabel = HelpWindowResources.NoMatches;
+ }
+ else
+ {
+ if (this.HelpBuilder.HighlightCount == 1)
+ {
+ this.MatchesLabel = HelpWindowResources.OneMatch;
+ }
+ else
+ {
+ this.MatchesLabel = String.Format(
+ CultureInfo.CurrentCulture,
+ HelpWindowResources.SomeMatchesFormat,
+ this.HelpBuilder.HighlightCount);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Called internally to notify when a proiperty changed
+ ///
+ /// property name
+ private void OnNotifyPropertyChanged(string propertyName)
+ {
+ PropertyChangedEventHandler handler = this.PropertyChanged;
+ if (handler != null)
+ {
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpWindow.xaml.cs b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpWindow.xaml.cs
new file mode 100644
index 000000000..a858d26c8
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpWindow.xaml.cs
@@ -0,0 +1,309 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements HelpWindow.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI
+{
+ using System.Globalization;
+ using System.Management.Automation;
+ using System.Windows;
+ using System.Windows.Documents;
+ using System.Windows.Input;
+ using Microsoft.Management.UI.Internal;
+
+ ///
+ /// A window displaying help content and allowing search
+ ///
+ public partial class HelpWindow : Window
+ {
+ ///
+ /// Minimum zoom in the slider
+ ///
+ public const double MinimumZoom = 20;
+
+ ///
+ /// Maximum zoom in the slider
+ ///
+ public const double MaximumZoom = 300;
+
+ ///
+ /// Zoom interval
+ ///
+ public const double ZoomInterval = 10;
+
+ ///
+ /// The ViewModel for the dialog
+ ///
+ private HelpViewModel viewModel;
+
+ ///
+ /// Initializes a new instance of the HelpWindow class
+ ///
+ /// the object with help information
+ public HelpWindow(PSObject helpObject)
+ {
+ InitializeComponent();
+ this.viewModel = new HelpViewModel(helpObject, this.DocumentParagraph);
+ CommonHelper.SetStartingPositionAndSize(
+ this,
+ HelpWindowSettings.Default.HelpWindowTop,
+ HelpWindowSettings.Default.HelpWindowLeft,
+ HelpWindowSettings.Default.HelpWindowWidth,
+ HelpWindowSettings.Default.HelpWindowHeight,
+ double.Parse((string)HelpWindowSettings.Default.Properties["HelpWindowWidth"].DefaultValue, CultureInfo.InvariantCulture.NumberFormat),
+ double.Parse((string)HelpWindowSettings.Default.Properties["HelpWindowHeight"].DefaultValue, CultureInfo.InvariantCulture.NumberFormat),
+ HelpWindowSettings.Default.HelpWindowMaximized);
+
+ this.ReadZoomUserSetting();
+
+ this.viewModel.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(this.ViewModel_PropertyChanged);
+ this.DataContext = this.viewModel;
+
+ this.Loaded += new RoutedEventHandler(this.HelpDialog_Loaded);
+ this.Closed += new System.EventHandler(this.HelpDialog_Closed);
+ }
+
+ ///
+ /// Handles the mouse wheel to zoom in/out
+ ///
+ /// event arguments
+ protected override void OnPreviewMouseWheel(MouseWheelEventArgs e)
+ {
+ if (Keyboard.Modifiers != ModifierKeys.Control)
+ {
+ return;
+ }
+
+ if (e.Delta > 0)
+ {
+ this.viewModel.ZoomIn();
+ e.Handled = true;
+ }
+ else
+ {
+ this.viewModel.ZoomOut();
+ e.Handled = true;
+ }
+ }
+
+ ///
+ /// Handles key down to fix the Page/Douwn going to end of help issue
+ /// And to implement some additional shortcuts like Ctrl+F and ZoomIn/ZoomOut
+ ///
+ /// event arguments
+ protected override void OnPreviewKeyDown(KeyEventArgs e)
+ {
+ if (Keyboard.Modifiers == ModifierKeys.None)
+ {
+ if (e.Key == Key.PageUp)
+ {
+ this.Scroll.PageUp();
+ e.Handled = true;
+ return;
+ }
+
+ if (e.Key == Key.PageDown)
+ {
+ this.Scroll.PageDown();
+ e.Handled = true;
+ return;
+ }
+ }
+
+ if (Keyboard.Modifiers == ModifierKeys.Control)
+ {
+ this.HandleZoomInAndZoomOut(e);
+ if (e.Handled)
+ {
+ return;
+ }
+
+ if (e.Key == Key.F)
+ {
+ this.Find.Focus();
+ e.Handled = true;
+ return;
+ }
+ }
+
+ if (Keyboard.Modifiers == (ModifierKeys.Control | ModifierKeys.Shift))
+ {
+ this.HandleZoomInAndZoomOut(e);
+ if (e.Handled)
+ {
+ return;
+ }
+ }
+ }
+
+ ///
+ /// Reads the zoom part of the user settings
+ ///
+ private void ReadZoomUserSetting()
+ {
+ if (HelpWindowSettings.Default.HelpZoom < HelpWindow.MinimumZoom || HelpWindowSettings.Default.HelpZoom > HelpWindow.MaximumZoom)
+ {
+ HelpWindowSettings.Default.HelpZoom = 100;
+ }
+
+ this.viewModel.Zoom = HelpWindowSettings.Default.HelpZoom;
+ }
+
+ ///
+ /// Handles Zoom in and Zoom out keys
+ ///
+ /// event arguments
+ private void HandleZoomInAndZoomOut(KeyEventArgs e)
+ {
+ if (e.Key == Key.OemPlus || e.Key == Key.Add)
+ {
+ this.viewModel.ZoomIn();
+ e.Handled = true;
+ }
+
+ if (e.Key == Key.OemMinus || e.Key == Key.Subtract)
+ {
+ this.viewModel.ZoomOut();
+ e.Handled = true;
+ }
+ }
+
+ ///
+ /// Listens to changes in the zoom in order to update the user settings
+ ///
+ /// event sender
+ /// event arguments
+ private void ViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "Zoom")
+ {
+ HelpWindowSettings.Default.HelpZoom = this.viewModel.Zoom;
+ }
+ }
+
+ ///
+ /// Saves the user settings
+ ///
+ /// event sender
+ /// event arguments
+ private void HelpDialog_Closed(object sender, System.EventArgs e)
+ {
+ HelpWindowSettings.Default.Save();
+ }
+
+ ///
+ /// Updates the user setting with window state
+ ///
+ /// event sender
+ /// event arguments
+ private void HelpDialog_StateChanged(object sender, System.EventArgs e)
+ {
+ HelpWindowSettings.Default.HelpWindowMaximized = this.WindowState == WindowState.Maximized;
+ }
+
+ ///
+ /// Sets the positions from user settings and start monitoring position changes
+ ///
+ /// event sender
+ /// event arguments
+ private void HelpDialog_Loaded(object sender, RoutedEventArgs e)
+ {
+ this.StateChanged += new System.EventHandler(this.HelpDialog_StateChanged);
+ this.LocationChanged += new System.EventHandler(this.HelpDialog_LocationChanged);
+ this.SizeChanged += new SizeChangedEventHandler(this.HelpDialog_SizeChanged);
+ }
+
+ ///
+ /// Saves size changes in user settings
+ ///
+ /// event sender
+ /// event arguments
+ private void HelpDialog_SizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ HelpWindowSettings.Default.HelpWindowWidth = this.Width;
+ HelpWindowSettings.Default.HelpWindowHeight = this.Height;
+ }
+
+ ///
+ /// Saves position changes in user settings
+ ///
+ /// event sender
+ /// event arguments
+ private void HelpDialog_LocationChanged(object sender, System.EventArgs e)
+ {
+ HelpWindowSettings.Default.HelpWindowTop = this.Top;
+ HelpWindowSettings.Default.HelpWindowLeft = this.Left;
+ }
+
+ ///
+ /// Called when the settings button is clicked
+ ///
+ /// event sender
+ /// event arguments
+ private void Settings_Click(object sender, RoutedEventArgs e)
+ {
+ SettingsDialog settings = new SettingsDialog();
+ settings.Owner = this;
+
+ settings.ShowDialog();
+
+ if (settings.DialogResult == true)
+ {
+ this.viewModel.HelpBuilder.AddTextToParagraphBuilder();
+ this.viewModel.Search();
+ }
+ }
+
+ ///
+ /// Called when the Previous button is clicked
+ ///
+ /// event sender
+ /// event arguments
+ private void PreviousMatch_Click(object sender, RoutedEventArgs e)
+ {
+ this.MoveToNextMatch(false);
+ }
+
+ ///
+ /// Called when the Next button is clicked
+ ///
+ /// event sender
+ /// event arguments
+ private void NextMatch_Click(object sender, RoutedEventArgs e)
+ {
+ this.MoveToNextMatch(true);
+ }
+
+ ///
+ /// Moves to the previous or next match
+ ///
+ /// true for forward false for backwards
+ private void MoveToNextMatch(bool forward)
+ {
+ TextPointer caretPosition = this.HelpText.CaretPosition;
+ Run nextRun = this.viewModel.Searcher.MoveAndHighlightNextNextMatch(forward, caretPosition);
+ this.MoveToRun(nextRun);
+ }
+
+ ///
+ /// Moves to the caret and brings the view to the
+ ///
+ /// run to move to
+ private void MoveToRun(Run run)
+ {
+ if (run == null)
+ {
+ return;
+ }
+
+ run.BringIntoView();
+ this.HelpText.CaretPosition = run.ElementEnd;
+ this.HelpText.Focus();
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpWindowSettings.Designer.cs b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpWindowSettings.Designer.cs
new file mode 100644
index 000000000..6306c28bf
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/HelpWindowSettings.Designer.cs
@@ -0,0 +1,248 @@
+//
+// Copyright (C) Microsoft. All rights reserved.
+//
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.16598
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class HelpWindowSettings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static HelpWindowSettings defaultInstance = ((HelpWindowSettings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new HelpWindowSettings())));
+
+ public static HelpWindowSettings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpRemarksDisplayed
+ {
+ get
+ {
+ return ((bool)(this["HelpRemarksDisplayed"]));
+ }
+ set
+ {
+ this["HelpRemarksDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpSyntaxDisplayed {
+ get {
+ return ((bool)(this["HelpSyntaxDisplayed"]));
+ }
+ set {
+ this["HelpSyntaxDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpExamplesDisplayed {
+ get {
+ return ((bool)(this["HelpExamplesDisplayed"]));
+ }
+ set {
+ this["HelpExamplesDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpSynopsysDisplayed {
+ get {
+ return ((bool)(this["HelpSynopsysDisplayed"]));
+ }
+ set {
+ this["HelpSynopsysDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpDescriptionDisplayed {
+ get {
+ return ((bool)(this["HelpDescriptionDisplayed"]));
+ }
+ set {
+ this["HelpDescriptionDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpParametersDisplayed {
+ get {
+ return ((bool)(this["HelpParametersDisplayed"]));
+ }
+ set {
+ this["HelpParametersDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpInputsDisplayed {
+ get {
+ return ((bool)(this["HelpInputsDisplayed"]));
+ }
+ set {
+ this["HelpInputsDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpOutputsDisplayed {
+ get {
+ return ((bool)(this["HelpOutputsDisplayed"]));
+ }
+ set {
+ this["HelpOutputsDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpNotesDisplayed {
+ get {
+ return ((bool)(this["HelpNotesDisplayed"]));
+ }
+ set {
+ this["HelpNotesDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool HelpRelatedLinksDisplayed {
+ get {
+ return ((bool)(this["HelpRelatedLinksDisplayed"]));
+ }
+ set {
+ this["HelpRelatedLinksDisplayed"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool HelpSearchMatchCase {
+ get {
+ return ((bool)(this["HelpSearchMatchCase"]));
+ }
+ set {
+ this["HelpSearchMatchCase"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool HelpSearchWholeWord {
+ get {
+ return ((bool)(this["HelpSearchWholeWord"]));
+ }
+ set {
+ this["HelpSearchWholeWord"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("400")]
+ public double HelpWindowHeight {
+ get {
+ return ((double)(this["HelpWindowHeight"]));
+ }
+ set {
+ this["HelpWindowHeight"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("600")]
+ public double HelpWindowWidth {
+ get {
+ return ((double)(this["HelpWindowWidth"]));
+ }
+ set {
+ this["HelpWindowWidth"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("-1")]
+ public double HelpWindowTop {
+ get {
+ return ((double)(this["HelpWindowTop"]));
+ }
+ set {
+ this["HelpWindowTop"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("-1")]
+ public double HelpWindowLeft {
+ get {
+ return ((double)(this["HelpWindowLeft"]));
+ }
+ set {
+ this["HelpWindowLeft"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool HelpWindowMaximized {
+ get {
+ return ((bool)(this["HelpWindowMaximized"]));
+ }
+ set {
+ this["HelpWindowMaximized"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("100")]
+ public double HelpZoom {
+ get {
+ return ((double)(this["HelpZoom"]));
+ }
+ set {
+ this["HelpZoom"] = value;
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/ParagraphBuilder.cs b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/ParagraphBuilder.cs
new file mode 100644
index 000000000..3704b2eb9
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/ParagraphBuilder.cs
@@ -0,0 +1,383 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements ParagraphBuilder.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+ using System.ComponentModel;
+ using System.Text;
+ using System.Windows.Documents;
+ using System.Windows.Media;
+
+ ///
+ /// Builds a paragraph based on Text + Bold + Highlight information.
+ /// Bold are the segments of thexct that should be bold, and Highlight are
+ /// the segments of thext that should be highlighted (like search results).
+ ///
+ internal class ParagraphBuilder : INotifyPropertyChanged
+ {
+ ///
+ /// The text spans that should be bold
+ ///
+ private List boldSpans;
+
+ ///
+ /// The text spans that should be highlighted
+ ///
+ private List highlighedSpans;
+
+ ///
+ /// The text displayed
+ ///
+ private StringBuilder textBuilder;
+
+ ///
+ /// Paragraph built in BuildParagraph
+ ///
+ private Paragraph paragraph;
+
+ ///
+ /// Initializes a new instance of the ParagraphBuilder class
+ ///
+ /// paragraph we will be adding lines to in BuildParagraph
+ internal ParagraphBuilder(Paragraph paragraph)
+ {
+ if (paragraph == null)
+ {
+ throw new ArgumentNullException("paragraph");
+ }
+
+ this.paragraph = paragraph;
+ this.boldSpans = new List();
+ this.highlighedSpans = new List();
+ this.textBuilder = new StringBuilder();
+ }
+
+ #region INotifyPropertyChanged Members
+ ///
+ /// Used to notify of property changes
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+ #endregion
+
+ ///
+ /// Gets the number of highlights.
+ ///
+ internal int HighlightCount
+ {
+ get { return this.highlighedSpans.Count; }
+ }
+
+ ///
+ /// Gets the paragraph built in BuildParagraph
+ ///
+ internal Paragraph Paragraph
+ {
+ get { return this.paragraph; }
+ }
+
+ ///
+ /// Called after all the AddText calls have been made to build the paragraph
+ /// based on the current text.
+ /// This method goes over 3 collections simultaneouslly:
+ /// 1) characters in this.textBuilder
+ /// 2) spans in this.boldSpans
+ /// 3) spans in this.highlightedSpans
+ /// And adds the minimal number of Inlines to the paragraph so that all
+ /// characters that should be bold and/or highlighed are.
+ ///
+ internal void BuildParagraph()
+ {
+ this.paragraph.Inlines.Clear();
+
+ int currentBoldIndex = 0;
+ TextSpan? currentBoldSpan = this.boldSpans.Count == 0 ? (TextSpan?)null : this.boldSpans[0];
+ int currentHighlightedIndex = 0;
+ TextSpan? currentHighlightedSpan = this.highlighedSpans.Count == 0 ? (TextSpan?)null : this.highlighedSpans[0];
+
+ bool currentBold = false;
+ bool currentHighlighted = false;
+
+ StringBuilder sequence = new StringBuilder();
+ int i = 0;
+ foreach (char c in this.textBuilder.ToString())
+ {
+ bool newBold = false;
+ bool newHighlighted = false;
+
+ ParagraphBuilder.MoveSpanToPosition(ref currentBoldIndex, ref currentBoldSpan, i, this.boldSpans);
+ newBold = currentBoldSpan == null ? false : currentBoldSpan.Value.Contains(i);
+
+ ParagraphBuilder.MoveSpanToPosition(ref currentHighlightedIndex, ref currentHighlightedSpan, i, this.highlighedSpans);
+ newHighlighted = currentHighlightedSpan == null ? false : currentHighlightedSpan.Value.Contains(i);
+
+ if (newBold != currentBold || newHighlighted != currentHighlighted)
+ {
+ ParagraphBuilder.AddInline(this.paragraph, currentBold, currentHighlighted, sequence);
+ }
+
+ sequence.Append(c);
+
+ currentHighlighted = newHighlighted;
+ currentBold = newBold;
+ i++;
+ }
+
+ ParagraphBuilder.AddInline(this.paragraph, currentBold, currentHighlighted, sequence);
+ }
+
+ ///
+ /// Highlights all ocurrences of .
+ /// This is called after all calls to AddText have been made
+ ///
+ /// search string
+ /// true if search should be case sensitive
+ /// true if we should search whole word only
+ internal void HighlightAllInstancesOf(string search, bool caseSensitive, bool wholeWord)
+ {
+ this.highlighedSpans.Clear();
+
+ if (search == null || search.Trim().Length == 0)
+ {
+ this.BuildParagraph();
+ this.OnNotifyPropertyChanged("HighlightCount");
+ return;
+ }
+
+ string text = this.textBuilder.ToString();
+ StringComparison comparison = caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
+ int start = 0;
+ int match;
+ while ((match = text.IndexOf(search, start, comparison)) != -1)
+ {
+ // false loop
+ do
+ {
+ if (wholeWord)
+ {
+ if (match > 0 && Char.IsLetterOrDigit(text[match - 1]))
+ {
+ break;
+ }
+
+ if ((match + search.Length <= text.Length - 1) && Char.IsLetterOrDigit(text[match + search.Length]))
+ {
+ break;
+ }
+ }
+
+ this.AddHighlight(match, search.Length);
+ }
+ while (false);
+
+ start = match + search.Length;
+ }
+
+ this.BuildParagraph();
+ this.OnNotifyPropertyChanged("HighlightCount");
+ }
+
+ ///
+ /// Adds text to the paragraph later build with BuildParagraph
+ ///
+ /// text to be added
+ /// true if the text should be bold
+ internal void AddText(string str, bool bold)
+ {
+ if (str == null)
+ {
+ throw new ArgumentNullException("str");
+ }
+
+ if (str.Length == 0)
+ {
+ return;
+ }
+
+ if (bold)
+ {
+ this.boldSpans.Add(new TextSpan(this.textBuilder.Length, str.Length));
+ }
+
+ this.textBuilder.Append(str);
+ }
+
+ ///
+ /// Called before a derived class starts adding text
+ /// to reset the current content
+ ///
+ internal void ResetAllText()
+ {
+ this.boldSpans.Clear();
+ this.highlighedSpans.Clear();
+ this.textBuilder.Clear();
+ }
+
+ ///
+ /// Adds an inline to based on the remaining parameters.
+ ///
+ /// paragraph to add Inline to
+ /// true if text should be added in bold
+ /// true if the text should be added with highlight
+ /// the text to add and clear
+ private static void AddInline(Paragraph currentParagraph, bool currentBold, bool currentHighlighted, StringBuilder sequence)
+ {
+ if (sequence.Length == 0)
+ {
+ return;
+ }
+
+ Run run = new Run(sequence.ToString());
+ if (currentHighlighted)
+ {
+ run.Background = ParagraphSearcher.HighlightBrush;
+ }
+
+ Inline inline = currentBold ? (Inline)new Bold(run) : run;
+ currentParagraph.Inlines.Add(inline);
+ sequence.Clear();
+ }
+
+ ///
+ /// This is an auxiliar method in BuildParagraph to move the current bold or highlighed spans
+ /// according to the
+ /// The current bold and higlighed span should be ending ahead of the current position.
+ /// Moves and to the
+ /// propper span in according to the
+ /// This is an auxiliar method in BuildParagraph.
+ ///
+ /// current index within
+ /// current span within
+ /// caracter position. This comes from a position within this.textBuilder
+ /// the collection of spans. This is either this.boldSpans or this.highlightedSpans
+ private static void MoveSpanToPosition(ref int currentSpanIndex, ref TextSpan? currentSpan, int caracterPosition, List allSpans)
+ {
+ if (currentSpan == null || caracterPosition <= currentSpan.Value.End)
+ {
+ return;
+ }
+
+ for (int newBoldIndex = currentSpanIndex + 1; newBoldIndex < allSpans.Count; newBoldIndex++)
+ {
+ TextSpan newBoldSpan = allSpans[newBoldIndex];
+ if (caracterPosition <= newBoldSpan.End)
+ {
+ currentSpanIndex = newBoldIndex;
+ currentSpan = newBoldSpan;
+ return;
+ }
+ }
+
+ // there is no span ending ahead of current position, so
+ // we set the current span to null to prevent unecessary comparisons against the currentSpan
+ currentSpan = null;
+ }
+
+ ///
+ /// Adds one individual text highlight
+ /// This is called after all calls to AddText have been made
+ ///
+ /// highlight start
+ /// highlight length
+ private void AddHighlight(int start, int length)
+ {
+ if (start < 0)
+ {
+ throw new ArgumentOutOfRangeException("start");
+ }
+
+ if (start + length > this.textBuilder.Length)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ this.highlighedSpans.Add(new TextSpan(start, length));
+ }
+
+ ///
+ /// Called internally to notify when a proiperty changed
+ ///
+ /// property name
+ private void OnNotifyPropertyChanged(string propertyName)
+ {
+ PropertyChangedEventHandler handler = this.PropertyChanged;
+ if (handler != null)
+ {
+ handler(this, new PropertyChangedEventArgs(propertyName));
+ }
+ }
+
+ ///
+ /// A text span used to mark bold and highlighed segments
+ ///
+ internal struct TextSpan
+ {
+ ///
+ /// Index of the first character in the span
+ ///
+ private int start;
+
+ ///
+ /// Index of the last character in the span
+ ///
+ private int end;
+
+ ///
+ /// Initializes a new instance of the TextSpan struct
+ ///
+ /// Index of the first character in the span
+ /// Index of the last character in the span
+ internal TextSpan(int start, int length)
+ {
+ if (start < 0)
+ {
+ throw new ArgumentOutOfRangeException("start");
+ }
+
+ if (length < 1)
+ {
+ throw new ArgumentOutOfRangeException("length");
+ }
+
+ this.start = start;
+ this.end = start + length - 1;
+ }
+
+ ///
+ /// Gets the index of the first character in the span
+ ///
+ internal int Start
+ {
+ get { return this.start; }
+ }
+
+ ///
+ /// Gets the index of the first character in the span
+ ///
+ internal int End
+ {
+ get
+ {
+ return this.end;
+ }
+ }
+
+ ///
+ /// Returns true if the is between start and end (inclusive)
+ ///
+ /// position to verify if is in the span
+ /// true if the is between start and end (inclusive)
+ internal bool Contains(int position)
+ {
+ return (position >= this.start) && (position <= this.end);
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/ParagraphSearcher.cs b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/ParagraphSearcher.cs
new file mode 100644
index 000000000..c6337f7fb
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/ParagraphSearcher.cs
@@ -0,0 +1,247 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements ParagraphSearcher.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System.Diagnostics;
+ using System.Windows.Documents;
+ using System.Windows.Media;
+
+ ///
+ /// Moves through search highlights built in a ParagraphBuilder
+ /// changing the color of the current highlight
+ ///
+ internal class ParagraphSearcher
+ {
+ ///
+ /// Highlight for all matches except the current
+ ///
+ internal static readonly Brush HighlightBrush = Brushes.Yellow;
+
+ ///
+ /// Highlight for the current match
+ ///
+ private static readonly Brush CurrentHighlightBrush = Brushes.Cyan;
+
+ ///
+ /// Current match being highlighted in search
+ ///
+ private Run currentHighlightedMatch;
+
+ ///
+ /// Initializes a new instance of the ParagraphSearcher class
+ ///
+ internal ParagraphSearcher()
+ {
+ }
+
+ ///
+ /// Move to the next highlight starting at the
+ ///
+ /// true for next false for previous
+ /// caret position
+ /// the next highlight starting at the
+ internal Run MoveAndHighlightNextNextMatch(bool forward, TextPointer caretPosition)
+ {
+ Debug.Assert(caretPosition != null, "a caret position is allways valid");
+ Debug.Assert(caretPosition.Parent != null && caretPosition.Parent is Run, "a caret PArent is allways a valid Run");
+ Run caretRun = (Run)caretPosition.Parent;
+
+ Run currentRun;
+
+ if (this.currentHighlightedMatch != null)
+ {
+ // restore the curent highlighted background to plain highlighted
+ this.currentHighlightedMatch.Background = ParagraphSearcher.HighlightBrush;
+ }
+
+ // If the caret is in the end of a highlight we move to the adjacent run
+ // It has to be in the end because if there is a match at the begining of the file
+ // and the caret has not been touched (so it is in the beginning of the file too)
+ // we want to highlight this first match.
+ // Considering the caller allways set the caret to the end of the highlight
+ // The condition below works well for successive searchs
+ // We also need to move to the adjacent run if the caret is at the first run and we
+ // are moving backwards so that a search backwards when the first run is highlighted
+ // and the caret is at the beginning will wrap to the end
+ if ((!forward && IsFirstRun(caretRun)) ||
+ ((caretPosition.GetOffsetToPosition(caretRun.ContentEnd) == 0) && ParagraphSearcher.Ishighlighted(caretRun)))
+ {
+ currentRun = ParagraphSearcher.GetNextRun(caretRun, forward);
+ }
+ else
+ {
+ currentRun = caretRun;
+ }
+
+ currentRun = ParagraphSearcher.GetNextMatch(currentRun, forward);
+
+ if (currentRun == null)
+ {
+ // if we could not find a next highlight wrap arround
+ currentRun = ParagraphSearcher.GetFirstOrLastRun(caretRun, forward);
+ currentRun = ParagraphSearcher.GetNextMatch(currentRun, forward);
+ }
+
+ this.currentHighlightedMatch = currentRun;
+ if (this.currentHighlightedMatch != null)
+ {
+ // restore the curent highligthed background to current highlighted
+ this.currentHighlightedMatch.Background = ParagraphSearcher.CurrentHighlightBrush;
+ }
+
+ return currentRun;
+ }
+
+ ///
+ /// Resets the search for fresh calls to MoveAndHighlightNextNextMatch
+ ///
+ internal void ResetSearch()
+ {
+ this.currentHighlightedMatch = null;
+ }
+
+ ///
+ /// Returns true if is highlighted
+ ///
+ /// run to check if is highlighted
+ /// true if is highlighted
+ private static bool Ishighlighted(Run run)
+ {
+ if (run == null)
+ {
+ return false;
+ }
+
+ SolidColorBrush background = run.Background as SolidColorBrush;
+ if (background != null && background == ParagraphSearcher.HighlightBrush)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Get the next or previous run according to
+ ///
+ /// the current run
+ /// true for next false for previous
+ /// the next or previous run according to
+ private static Run GetNextRun(Run currentRun, bool forward)
+ {
+ Bold parentBold = currentRun.Parent as Bold;
+
+ Inline nextInline;
+
+ if (forward)
+ {
+ nextInline = parentBold != null ? ((Inline)parentBold).NextInline : currentRun.NextInline;
+ }
+ else
+ {
+ nextInline = parentBold != null ? ((Inline)parentBold).PreviousInline : currentRun.PreviousInline;
+ }
+
+ return GetRun(nextInline);
+ }
+
+ ///
+ /// Gets the run of an inline. Inlines in a ParagrahBuilder are either a Run or a Bold
+ /// which contains a Run
+ ///
+ /// inline to get the run from
+ /// the run of the inline
+ private static Run GetRun(Inline inline)
+ {
+ Bold inlineBold = inline as Bold;
+ if (inlineBold != null)
+ {
+ return (Run)inlineBold.Inlines.FirstInline;
+ }
+
+ return (Run)inline;
+ }
+
+ ///
+ /// Gets the next highlighted run starting and including
+ /// according to the direction specified in
+ ///
+ /// the current run
+ /// true for next false for previous
+ ///
+ /// the next highlighted run starting and including
+ /// according to the direction specified in
+ ///
+ private static Run GetNextMatch(Run currentRun, bool forward)
+ {
+ while (currentRun != null)
+ {
+ if (ParagraphSearcher.Ishighlighted(currentRun))
+ {
+ return currentRun;
+ }
+
+ currentRun = ParagraphSearcher.GetNextRun(currentRun, forward);
+ }
+
+ return currentRun;
+ }
+
+ ///
+ /// Gets the run's paragraph
+ ///
+ /// run to get the paragraph from
+ /// the run's paragraph
+ private static Paragraph GetParagraph(Run run)
+ {
+ Bold parentBold = run.Parent as Bold;
+ Paragraph parentParagraph = (parentBold != null ? parentBold.Parent : run.Parent) as Paragraph;
+ Debug.Assert(parentParagraph != null, "the documents we are saerching are built with ParagraphBuilder, which builds the document like this");
+ return parentParagraph;
+ }
+
+ ///
+ /// Returns true if the run is the fiorst run of the paragraph
+ ///
+ /// run to check
+ /// true if the run is the fiorst run of the paragraph
+ private static bool IsFirstRun(Run run)
+ {
+ Paragraph paragraph = GetParagraph(run);
+ Run firstRun = ParagraphSearcher.GetRun(paragraph.Inlines.FirstInline);
+ return run == firstRun;
+ }
+
+ ///
+ /// Gets the first or lasr run in the paragraph containing
+ ///
+ /// run containing the caret
+ /// true for first false for last
+ /// the first or last run in the paragraph containing
+ private static Run GetFirstOrLastRun(Run caretRun, bool forward)
+ {
+ Debug.Assert(caretRun != null, "a caret run is allways valid");
+
+ Paragraph paragraph = GetParagraph(caretRun);
+
+ Inline firstOrLastInline;
+ if (forward)
+ {
+ firstOrLastInline = paragraph.Inlines.FirstInline;
+ }
+ else
+ {
+ firstOrLastInline = paragraph.Inlines.LastInline;
+ }
+
+ return GetRun(firstOrLastInline);
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/SettingsDialog.xaml.cs b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/SettingsDialog.xaml.cs
new file mode 100644
index 000000000..538540bd5
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/HelpWindow/SettingsDialog.xaml.cs
@@ -0,0 +1,64 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Implements SettingsDialog.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI
+{
+ using System.Windows;
+ using Microsoft.Management.UI.Internal;
+
+ ///
+ /// Dialog with settings for the help dialog
+ ///
+ public partial class SettingsDialog : Window
+ {
+ ///
+ /// Initializes a new instance of the SettingsDialog class
+ ///
+ public SettingsDialog()
+ {
+ InitializeComponent();
+ this.Description.IsChecked = HelpWindowSettings.Default.HelpDescriptionDisplayed;
+ this.Examples.IsChecked = HelpWindowSettings.Default.HelpExamplesDisplayed;
+ this.Inputs.IsChecked = HelpWindowSettings.Default.HelpInputsDisplayed;
+ this.Notes.IsChecked = HelpWindowSettings.Default.HelpNotesDisplayed;
+ this.Outputs.IsChecked = HelpWindowSettings.Default.HelpOutputsDisplayed;
+ this.Parameters.IsChecked = HelpWindowSettings.Default.HelpParametersDisplayed;
+ this.RelatedLinks.IsChecked = HelpWindowSettings.Default.HelpRelatedLinksDisplayed;
+ this.Remarks.IsChecked = HelpWindowSettings.Default.HelpRemarksDisplayed;
+ this.Synopsys.IsChecked = HelpWindowSettings.Default.HelpSynopsysDisplayed;
+ this.Syntax.IsChecked = HelpWindowSettings.Default.HelpSyntaxDisplayed;
+ this.CaseSensitive.IsChecked = HelpWindowSettings.Default.HelpSearchMatchCase;
+ this.WholeWord.IsChecked = HelpWindowSettings.Default.HelpSearchWholeWord;
+ }
+
+ ///
+ /// Called when the OK button has been clicked
+ ///
+ /// event sender
+ /// event arguments
+ private void OK_Click(object sender, RoutedEventArgs e)
+ {
+ HelpWindowSettings.Default.HelpDescriptionDisplayed = this.Description.IsChecked == true;
+ HelpWindowSettings.Default.HelpExamplesDisplayed = this.Examples.IsChecked == true;
+ HelpWindowSettings.Default.HelpInputsDisplayed = this.Inputs.IsChecked == true;
+ HelpWindowSettings.Default.HelpOutputsDisplayed = this.Outputs.IsChecked == true;
+ HelpWindowSettings.Default.HelpNotesDisplayed = this.Notes.IsChecked == true;
+ HelpWindowSettings.Default.HelpParametersDisplayed = this.Parameters.IsChecked == true;
+ HelpWindowSettings.Default.HelpRelatedLinksDisplayed = this.RelatedLinks.IsChecked == true;
+ HelpWindowSettings.Default.HelpRemarksDisplayed = this.Remarks.IsChecked == true;
+ HelpWindowSettings.Default.HelpSynopsysDisplayed = this.Synopsys.IsChecked == true;
+ HelpWindowSettings.Default.HelpSyntaxDisplayed = this.Syntax.IsChecked == true;
+ HelpWindowSettings.Default.HelpSearchMatchCase = this.CaseSensitive.IsChecked == true;
+ HelpWindowSettings.Default.HelpSearchWholeWord = this.WholeWord.IsChecked == true;
+ HelpWindowSettings.Default.Save();
+ this.DialogResult = true;
+ this.Close();
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/AutomationTextBlock.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/AutomationTextBlock.cs
new file mode 100644
index 000000000..ccbdff12d
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/AutomationTextBlock.cs
@@ -0,0 +1,50 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ #region Using Directives
+
+ using System.ComponentModel;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Windows.Automation.Peers;
+ using System.Windows.Controls;
+
+ #endregion
+
+ ///
+ /// Provides a control that is always visible in the automation tree.
+ ///
+ [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ [Description("Provides a System.Windows.Controls.TextBlock control that is always visible in the automation tree.")]
+ public class AutomationTextBlock : TextBlock
+ {
+ #region Structors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public AutomationTextBlock()
+ {
+ // This constructor intentionally left blank
+ }
+
+ #endregion
+
+ #region Overides
+
+ ///
+ /// Returns the implementations for this control.
+ ///
+ /// The implementations for this control.
+ protected override AutomationPeer OnCreateAutomationPeer()
+ {
+ return new AutomationTextBlockAutomationPeer(this);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/AutomationTextBlockAutomationPeer.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/AutomationTextBlockAutomationPeer.cs
new file mode 100644
index 000000000..ac171da6e
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/AutomationTextBlockAutomationPeer.cs
@@ -0,0 +1,62 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Provides an automation peer for AutomationTextBlock.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ #region Using Directives
+
+ using System.Diagnostics.CodeAnalysis;
+ using System.Windows.Automation.Peers;
+ using System.Windows.Controls;
+
+ #endregion
+
+ ///
+ /// Provides an automation peer for AutomationTextBlock.
+ ///
+ [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ internal class AutomationTextBlockAutomationPeer : TextBlockAutomationPeer
+ {
+ #region Structors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The owner of the automation peer.
+ public AutomationTextBlockAutomationPeer(TextBlock owner)
+ : base(owner)
+ {
+ // This constructor intentionally left blank
+ }
+
+ #endregion
+
+ #region Overrides
+
+ ///
+ /// Gets a value that indicates whether the element is understood by the user as interactive or as contributing to the logical structure of the control in the GUI. Called by IsControlElement().
+ ///
+ /// This method always returns true.
+ protected override bool IsControlElementCore()
+ {
+ return true;
+ }
+
+ ///
+ /// Gets the class name.
+ ///
+ /// The class name.
+ protected override string GetClassNameCore()
+ {
+ return this.Owner.GetType().Name;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/BooleanBoxes.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/BooleanBoxes.cs
new file mode 100644
index 000000000..28dbe8e7d
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/BooleanBoxes.cs
@@ -0,0 +1,47 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+
+ ///
+ /// A class which returns the same boxed bool values.
+ ///
+ internal static class BooleanBoxes
+ {
+ private static object trueBox = true;
+ private static object falseBox = false;
+
+ internal static object TrueBox
+ {
+ get
+ {
+ return trueBox;
+ }
+ }
+
+ internal static object FalseBox
+ {
+ get
+ {
+ return falseBox;
+ }
+ }
+
+ internal static object Box(bool value)
+ {
+ if (value)
+ {
+ return TrueBox;
+ }
+ else
+ {
+ return FalseBox;
+ }
+ }
+ }
+
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/CommandHelper.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/CommandHelper.cs
new file mode 100644
index 000000000..04737d141
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/CommandHelper.cs
@@ -0,0 +1,57 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Helper routines for executing commands.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Windows;
+ using System.Windows.Input;
+ using System.Security;
+
+ internal static class CommandHelper
+ {
+ internal static void ExecuteCommand(ICommand command, object parameter, IInputElement target)
+ {
+ RoutedCommand command2 = command as RoutedCommand;
+ if (command2 != null)
+ {
+ if (command2.CanExecute(parameter, target))
+ {
+ command2.Execute(parameter, target);
+ }
+ }
+ else if (command.CanExecute(parameter))
+ {
+ command.Execute(parameter);
+ }
+ }
+
+ internal static bool CanExecuteCommand(ICommand command, object parameter, IInputElement target)
+ {
+ if (command == null)
+ {
+ return false;
+ }
+
+ RoutedCommand command2 = command as RoutedCommand;
+
+ if (command2 != null)
+ {
+ return command2.CanExecute(parameter, target);
+ }
+ else
+ {
+ return command.CanExecute(parameter);
+ }
+ }
+ }
+}
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/CustomTypeComparer.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/CustomTypeComparer.cs
new file mode 100644
index 000000000..3efb3af14
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/CustomTypeComparer.cs
@@ -0,0 +1,77 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Diagnostics;
+
+ ///
+ /// The CustomTypeComparer is responsible for holding custom comparers
+ /// for different types, which are in turn used to perform comparison
+ /// operations instead of the default IComparable comparison.
+ /// with a custom comparer
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public static class CustomTypeComparer
+ {
+ private static Dictionary comparers = new Dictionary();
+
+ ///
+ /// The static constructor.
+ ///
+ static CustomTypeComparer()
+ {
+ comparers.Add(typeof(DateTime), new DateTimeApproximationComparer());
+ }
+
+ ///
+ /// Compares two objects and returns a value indicating
+ /// whether one is less than, equal to, or greater than the other.
+ ///
+ ///
+ /// The first object to compare.
+ ///
+ ///
+ /// The second object to compare.
+ ///
+ ///
+ /// A type implementing IComparable.
+ ///
+ ///
+ /// If value1 is less than value2, then a value less than zero is returned.
+ /// If value1 equals value2, than zero is returned.
+ /// If value1 is greater than value2, then a value greater than zero is returned.
+ ///
+ public static int Compare(T value1, T value2) where T : IComparable
+ {
+ IComparer comparer;
+ if (false == TryGetCustomComparer(out comparer))
+ {
+ return value1.CompareTo(value2);
+ }
+
+ return comparer.Compare(value1, value2);
+ }
+
+ private static bool TryGetCustomComparer(out IComparer comparer) where T : IComparable
+ {
+ comparer = null;
+
+ object uncastComparer = null;
+ if (false == comparers.TryGetValue(typeof(T), out uncastComparer))
+ {
+ return false;
+ }
+
+ Debug.Assert(uncastComparer is IComparer);
+ comparer = (IComparer)uncastComparer;
+
+ return true;
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DataRoutedEventArgs.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DataRoutedEventArgs.cs
new file mode 100644
index 000000000..3594dba22
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DataRoutedEventArgs.cs
@@ -0,0 +1,44 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Windows;
+ using System.Diagnostics.CodeAnalysis;
+
+ ///
+ /// Routed event args which provide the ability to attach an
+ /// arbitrary peice of data.
+ ///
+ /// There are no restrictions on type T.
+ [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public class DataRoutedEventArgs : RoutedEventArgs
+ {
+ private T data;
+
+ ///
+ /// Constructs a new instance of the DataRoutedEventArgs class.
+ ///
+ /// The data payload to be stored.
+ /// The routed event.
+ public DataRoutedEventArgs(T data, RoutedEvent routedEvent)
+ {
+ this.data = data;
+ this.RoutedEvent = routedEvent;
+ }
+
+ ///
+ /// Gets a value containing the data being stored.
+ ///
+ public T Data
+ {
+ get { return this.data; }
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DateTimeApproximationComparer.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DateTimeApproximationComparer.cs
new file mode 100644
index 000000000..e49ab1dcb
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DateTimeApproximationComparer.cs
@@ -0,0 +1,71 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// The DateTimeApproximationComparer is responsible for comparing two
+ /// DateTime objects at a level of precision determined by
+ /// the first object. The comparison either compares at the
+ /// date level or the date and time (down to Seconds precision).
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public class DateTimeApproximationComparer : IComparer
+ {
+ ///
+ /// Compares two objects and returns a value indicating
+ /// whether one is less than, equal to, or greater than the other.
+ ///
+ ///
+ /// The first object to compare.
+ ///
+ ///
+ /// The second object to compare.
+ ///
+ ///
+ /// If value1 is less than value2, then a value less than zero is returned.
+ /// If value1 equals value2, than zero is returned.
+ /// If value1 is greater than value2, then a value greater than zero is returned.
+ ///
+ public int Compare(DateTime value1, DateTime value2)
+ {
+ DateTime roundedX;
+ DateTime roundedY;
+ GetRoundedValues(value1, value2, out roundedX, out roundedY);
+
+ return roundedX.CompareTo(roundedY);
+ }
+
+ private static void GetRoundedValues(DateTime value1, DateTime value2, out DateTime roundedValue1, out DateTime roundedValue2)
+ {
+ roundedValue1 = value1;
+ roundedValue2 = value2;
+
+ bool hasTimeComponent = HasTimeComponent(value1);
+
+ int hour = hasTimeComponent ? value1.Hour : value2.Hour;
+ int minute = hasTimeComponent ? value1.Minute : value2.Minute;
+ int second = hasTimeComponent ? value1.Second : value2.Second;
+
+ roundedValue1 = new DateTime(value1.Year, value1.Month, value1.Day, hour, minute, second);
+ roundedValue2 = new DateTime(value2.Year, value2.Month, value2.Day, value2.Hour, value2.Minute, value2.Second);
+ }
+
+ private static bool HasTimeComponent(DateTime value)
+ {
+ bool hasNoTimeComponent = true
+ && 0 == value.Hour
+ && 0 == value.Minute
+ && 0 == value.Second
+ && 0 == value.Millisecond;
+
+ return (!hasNoTimeComponent);
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DismissiblePopup.Generated.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DismissiblePopup.Generated.cs
new file mode 100644
index 000000000..d680283f4
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DismissiblePopup.Generated.cs
@@ -0,0 +1,283 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+//
+// This code was generated by a tool. DO NOT EDIT
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// -----------------------------------------------------------------------
+
+#region StyleCop Suppression - generated code
+using System;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Input;
+
+namespace Microsoft.Management.UI.Internal
+{
+
+ ///
+ /// A popup which child controls can signal to be dimissed.
+ ///
+ ///
+ /// If a control wants to dismiss the popup then they should execute the DismissPopupCommand on a target in the popup window.
+ ///
+ [Localizability(LocalizationCategory.None)]
+ partial class DismissiblePopup
+ {
+ //
+ // DismissPopup routed command
+ //
+ ///
+ /// A command which child controls can use to tell the popup to close.
+ ///
+ public static readonly RoutedCommand DismissPopupCommand = new RoutedCommand("DismissPopup",typeof(DismissiblePopup));
+
+ static private void DismissPopupCommand_CommandExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ DismissiblePopup obj = (DismissiblePopup) sender;
+ obj.OnDismissPopupExecuted( e );
+ }
+
+ ///
+ /// Called when DismissPopup executes.
+ ///
+ ///
+ /// A command which child controls can use to tell the popup to close.
+ ///
+ protected virtual void OnDismissPopupExecuted(ExecutedRoutedEventArgs e)
+ {
+ OnDismissPopupExecutedImplementation(e);
+ }
+
+ partial void OnDismissPopupExecutedImplementation(ExecutedRoutedEventArgs e);
+
+ //
+ // CloseOnEscape dependency property
+ //
+ ///
+ /// Identifies the CloseOnEscape dependency property.
+ ///
+ public static readonly DependencyProperty CloseOnEscapeProperty = DependencyProperty.Register( "CloseOnEscape", typeof(bool), typeof(DismissiblePopup), new PropertyMetadata( BooleanBoxes.TrueBox, CloseOnEscapeProperty_PropertyChanged) );
+
+ ///
+ /// Gets or sets a value indicating whether the popup closes when ESC is pressed.
+ ///
+ [Bindable(true)]
+ [Category("Common Properties")]
+ [Description("Gets or sets a value indicating whether the popup closes when ESC is pressed.")]
+ [Localizability(LocalizationCategory.None)]
+ public bool CloseOnEscape
+ {
+ get
+ {
+ return (bool) GetValue(CloseOnEscapeProperty);
+ }
+ set
+ {
+ SetValue(CloseOnEscapeProperty,BooleanBoxes.Box(value));
+ }
+ }
+
+ static private void CloseOnEscapeProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ DismissiblePopup obj = (DismissiblePopup) o;
+ obj.OnCloseOnEscapeChanged( new PropertyChangedEventArgs((bool)e.OldValue, (bool)e.NewValue) );
+ }
+
+ ///
+ /// Occurs when CloseOnEscape property changes.
+ ///
+ public event EventHandler> CloseOnEscapeChanged;
+
+ ///
+ /// Called when CloseOnEscape property changes.
+ ///
+ protected virtual void OnCloseOnEscapeChanged(PropertyChangedEventArgs e)
+ {
+ OnCloseOnEscapeChangedImplementation(e);
+ RaisePropertyChangedEvent(CloseOnEscapeChanged, e);
+ }
+
+ partial void OnCloseOnEscapeChangedImplementation(PropertyChangedEventArgs e);
+
+ //
+ // FocusChildOnOpen dependency property
+ //
+ ///
+ /// Identifies the FocusChildOnOpen dependency property.
+ ///
+ public static readonly DependencyProperty FocusChildOnOpenProperty = DependencyProperty.Register( "FocusChildOnOpen", typeof(bool), typeof(DismissiblePopup), new PropertyMetadata( BooleanBoxes.TrueBox, FocusChildOnOpenProperty_PropertyChanged) );
+
+ ///
+ /// Gets or sets a value indicating whether focus should be set on the child when the popup opens.
+ ///
+ [Bindable(true)]
+ [Category("Common Properties")]
+ [Description("Gets or sets a value indicating whether focus should be set on the child when the popup opens.")]
+ [Localizability(LocalizationCategory.None)]
+ public bool FocusChildOnOpen
+ {
+ get
+ {
+ return (bool) GetValue(FocusChildOnOpenProperty);
+ }
+ set
+ {
+ SetValue(FocusChildOnOpenProperty,BooleanBoxes.Box(value));
+ }
+ }
+
+ static private void FocusChildOnOpenProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ DismissiblePopup obj = (DismissiblePopup) o;
+ obj.OnFocusChildOnOpenChanged( new PropertyChangedEventArgs((bool)e.OldValue, (bool)e.NewValue) );
+ }
+
+ ///
+ /// Occurs when FocusChildOnOpen property changes.
+ ///
+ public event EventHandler> FocusChildOnOpenChanged;
+
+ ///
+ /// Called when FocusChildOnOpen property changes.
+ ///
+ protected virtual void OnFocusChildOnOpenChanged(PropertyChangedEventArgs e)
+ {
+ OnFocusChildOnOpenChangedImplementation(e);
+ RaisePropertyChangedEvent(FocusChildOnOpenChanged, e);
+ }
+
+ partial void OnFocusChildOnOpenChangedImplementation(PropertyChangedEventArgs e);
+
+ //
+ // SetFocusOnClose dependency property
+ //
+ ///
+ /// Identifies the SetFocusOnClose dependency property.
+ ///
+ public static readonly DependencyProperty SetFocusOnCloseProperty = DependencyProperty.Register( "SetFocusOnClose", typeof(bool), typeof(DismissiblePopup), new PropertyMetadata( BooleanBoxes.FalseBox, SetFocusOnCloseProperty_PropertyChanged) );
+
+ ///
+ /// Indicates whether the focus returns to either a defined by the FocusOnCloseTarget dependency property UIElement or PlacementTarget or not.
+ ///
+ [Bindable(true)]
+ [Category("Common Properties")]
+ [Description("Indicates whether the focus returns to either a defined by the FocusOnCloseTarget dependency property UIElement or PlacementTarget or not.")]
+ [Localizability(LocalizationCategory.None)]
+ public bool SetFocusOnClose
+ {
+ get
+ {
+ return (bool) GetValue(SetFocusOnCloseProperty);
+ }
+ set
+ {
+ SetValue(SetFocusOnCloseProperty,BooleanBoxes.Box(value));
+ }
+ }
+
+ static private void SetFocusOnCloseProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ DismissiblePopup obj = (DismissiblePopup) o;
+ obj.OnSetFocusOnCloseChanged( new PropertyChangedEventArgs((bool)e.OldValue, (bool)e.NewValue) );
+ }
+
+ ///
+ /// Occurs when SetFocusOnClose property changes.
+ ///
+ public event EventHandler> SetFocusOnCloseChanged;
+
+ ///
+ /// Called when SetFocusOnClose property changes.
+ ///
+ protected virtual void OnSetFocusOnCloseChanged(PropertyChangedEventArgs e)
+ {
+ OnSetFocusOnCloseChangedImplementation(e);
+ RaisePropertyChangedEvent(SetFocusOnCloseChanged, e);
+ }
+
+ partial void OnSetFocusOnCloseChangedImplementation(PropertyChangedEventArgs e);
+
+ //
+ // SetFocusOnCloseElement dependency property
+ //
+ ///
+ /// Identifies the SetFocusOnCloseElement dependency property.
+ ///
+ public static readonly DependencyProperty SetFocusOnCloseElementProperty = DependencyProperty.Register( "SetFocusOnCloseElement", typeof(UIElement), typeof(DismissiblePopup), new PropertyMetadata( null, SetFocusOnCloseElementProperty_PropertyChanged) );
+
+ ///
+ /// If the SetFocusOnClose property is set True and this property is set to a valid UIElement, focus returns to this UIElement after the DismissiblePopup is closed.
+ ///
+ [Bindable(true)]
+ [Category("Common Properties")]
+ [Description("If the SetFocusOnClose property is set True and this property is set to a valid UIElement, focus returns to this UIElement after the DismissiblePopup is closed.")]
+ [Localizability(LocalizationCategory.None)]
+ public UIElement SetFocusOnCloseElement
+ {
+ get
+ {
+ return (UIElement) GetValue(SetFocusOnCloseElementProperty);
+ }
+ set
+ {
+ SetValue(SetFocusOnCloseElementProperty,value);
+ }
+ }
+
+ static private void SetFocusOnCloseElementProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ DismissiblePopup obj = (DismissiblePopup) o;
+ obj.OnSetFocusOnCloseElementChanged( new PropertyChangedEventArgs((UIElement)e.OldValue, (UIElement)e.NewValue) );
+ }
+
+ ///
+ /// Occurs when SetFocusOnCloseElement property changes.
+ ///
+ public event EventHandler> SetFocusOnCloseElementChanged;
+
+ ///
+ /// Called when SetFocusOnCloseElement property changes.
+ ///
+ protected virtual void OnSetFocusOnCloseElementChanged(PropertyChangedEventArgs e)
+ {
+ OnSetFocusOnCloseElementChangedImplementation(e);
+ RaisePropertyChangedEvent(SetFocusOnCloseElementChanged, e);
+ }
+
+ partial void OnSetFocusOnCloseElementChangedImplementation(PropertyChangedEventArgs e);
+
+ ///
+ /// Called when a property changes.
+ ///
+ private void RaisePropertyChangedEvent(EventHandler> eh, PropertyChangedEventArgs e)
+ {
+ if(eh != null)
+ {
+ eh(this,e);
+ }
+ }
+
+ //
+ // Static constructor
+ //
+
+ ///
+ /// Called when the type is initialized.
+ ///
+ static DismissiblePopup()
+ {
+ CommandManager.RegisterClassCommandBinding( typeof(DismissiblePopup), new CommandBinding( DismissiblePopup.DismissPopupCommand, DismissPopupCommand_CommandExecuted ));
+ StaticConstructorImplementation();
+ }
+
+ static partial void StaticConstructorImplementation();
+
+ }
+}
+#endregion
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DismissiblePopup.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DismissiblePopup.cs
new file mode 100644
index 000000000..f67079529
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/DismissiblePopup.cs
@@ -0,0 +1,154 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+// -----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Diagnostics;
+ using System.Windows;
+ using System.Windows.Automation;
+ using System.Windows.Controls.Primitives;
+ using System.Windows.Input;
+ using System.Windows.Media;
+ using System.Windows.Data;
+
+ ///
+ /// Partial class implementation for DismissiblePopup control.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public partial class DismissiblePopup : Popup
+ {
+ ///
+ /// Constructs an instance of DismissablePopup.
+ ///
+ public DismissiblePopup() : base()
+ {
+ // nothing
+ }
+
+ private delegate void FocusChildDelegate();
+
+ ///
+ /// Responds to the condition in which the value of the IsOpen property changes from false to true.
+ ///
+ /// The event arguments.
+ protected override void OnOpened(EventArgs e)
+ {
+ base.OnOpened(e);
+
+ if (this.FocusChildOnOpen)
+ {
+ this.Dispatcher.BeginInvoke(
+ System.Windows.Threading.DispatcherPriority.Loaded,
+ new FocusChildDelegate(this.FocusChild));
+ }
+
+ this.SetupAutomationIdBinding();
+ }
+
+
+ ///
+ /// Responds when the value of the IsOpen property changes from to true to false.
+ ///
+ /// The event arguments.
+ protected override void OnClosed(EventArgs e)
+ {
+ base.OnClosed(e);
+
+ if (this.SetFocusOnClose)
+ {
+ // Find a control to set focus on.
+ if (this.SetFocusOnCloseElement != null)
+ {
+ // The focus target is set explicitly.
+ this.SetFocus(this.SetFocusOnCloseElement);
+ }
+ else if (this.PlacementTarget != null)
+ {
+ // Use PlacementTarget as a first chance option.
+ this.SetFocus(this.PlacementTarget);
+ }
+ else
+ {
+ // Use parent UIObject when neither FocusOnCloseTarget nor PlacementTarget is set.
+ UIElement parent = this.Parent as UIElement;
+ if (parent != null)
+ {
+ this.SetFocus(parent);
+ }
+ }
+ }
+ }
+
+ private void SetFocus(UIElement element)
+ {
+ if (element.Focusable)
+ {
+ element.Focus();
+ }
+ else
+ {
+ element.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
+ }
+ }
+
+ private void SetupAutomationIdBinding()
+ {
+ var popupRoot = this.FindPopupRoot();
+
+ var binding = new Binding();
+ binding.Source = this;
+ binding.Path = new PropertyPath(AutomationProperties.AutomationIdProperty);
+ popupRoot.SetBinding(AutomationProperties.AutomationIdProperty, binding);
+ }
+
+ private FrameworkElement FindPopupRoot()
+ {
+ DependencyObject element = this.Child;
+
+ while (false == element.GetType().Name.Equals("PopupRoot", StringComparison.Ordinal))
+ {
+ element = VisualTreeHelper.GetParent( element );
+ }
+
+ Debug.Assert(element != null );
+
+ return (FrameworkElement) element;
+ }
+
+ ///
+ /// Provides class handling for the KeyDown routed event that occurs when the user presses a key while this control has focus.
+ ///
+ /// The event data.
+ protected override void OnKeyDown(System.Windows.Input.KeyEventArgs e)
+ {
+ ////
+ // Close the popup if ESC is pressed
+ ////
+ if (e.Key == System.Windows.Input.Key.Escape && this.CloseOnEscape)
+ {
+ this.IsOpen = false;
+ }
+ else
+ {
+ base.OnKeyDown(e);
+ }
+ }
+
+ partial void OnDismissPopupExecutedImplementation(ExecutedRoutedEventArgs e)
+ {
+ this.IsOpen = false;
+ }
+
+ private void FocusChild()
+ {
+ if (this.Child != null)
+ {
+ this.Child.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
+ }
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/ExtendedFrameworkElementAutomationPeer.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/ExtendedFrameworkElementAutomationPeer.cs
new file mode 100644
index 000000000..10ac0f006
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/ExtendedFrameworkElementAutomationPeer.cs
@@ -0,0 +1,109 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Provides a base automation peer for FrameworkElement controls.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ #region Using Directives
+
+ using System.Diagnostics.CodeAnalysis;
+ using System.Windows;
+ using System.Windows.Automation.Peers;
+ using System.Windows.Controls;
+
+ #endregion
+
+ ///
+ /// Provides a base automation peer for FrameworkElement controls.
+ ///
+ [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public class ExtendedFrameworkElementAutomationPeer : FrameworkElementAutomationPeer
+ {
+ #region Fields
+
+ ///
+ /// Gets or sets the control type of the element that is associated with this automation peer.
+ ///
+ private AutomationControlType controlType = AutomationControlType.Custom;
+
+ ///
+ /// Gets or sets a value that indicates whether the control should show in the logical tree.
+ ///
+ private bool isControlElement = true;
+
+ #endregion
+
+ #region Structors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The owner of the automation peer.
+ public ExtendedFrameworkElementAutomationPeer(FrameworkElement owner)
+ : base(owner)
+ {
+ // This constructor intentionally left blank
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The owner of the automation peer.
+ /// The control type of the element that is associated with the automation peer.
+ public ExtendedFrameworkElementAutomationPeer(FrameworkElement owner, AutomationControlType controlType)
+ : this(owner)
+ {
+ this.controlType = controlType;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The owner of the automation peer.
+ /// The control type of the element that is associated with the automation peer.
+ /// Whether the element should show in the logical tree.
+ public ExtendedFrameworkElementAutomationPeer(FrameworkElement owner, AutomationControlType controlType, bool isControlElement)
+ : this(owner, controlType)
+ {
+ this.isControlElement = isControlElement;
+ }
+
+ #endregion
+
+ #region Overrides
+
+ ///
+ /// Gets the class name.
+ ///
+ /// The class name.
+ protected override string GetClassNameCore()
+ {
+ return this.Owner.GetType().Name;
+ }
+
+ ///
+ /// Gets the control type of the element that is associated with the automation peer.
+ ///
+ /// Returns the control type of the element that is associated with the automation peer.
+ protected override AutomationControlType GetAutomationControlTypeCore()
+ {
+ return this.controlType;
+ }
+
+ ///
+ /// Gets a value that indicates whether the element is understood by the user as interactive or as contributing to the logical structure of the control in the GUI. Called by IsControlElement().
+ ///
+ /// This method always returns true.
+ protected override bool IsControlElementCore()
+ {
+ return this.isControlElement;
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IAsyncProgress.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IAsyncProgress.cs
new file mode 100644
index 000000000..a776dd43c
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IAsyncProgress.cs
@@ -0,0 +1,45 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ #region Using Directives
+
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Windows;
+
+ #endregion
+
+ ///
+ /// An interface designed to provide updates about an asynchronous operation.
+ /// If the UI is data bound to the properties in this interface then INotifyPropertyChanged should
+ /// be implemented by the type implementing IAsyncProgress so the UI can get notification of the properties
+ /// being changed.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public interface IAsyncProgress
+ {
+ ///
+ /// Gets a value indicating whether the async operation is currently running.
+ ///
+ bool OperationInProgress
+ {
+ get;
+ }
+
+ ///
+ /// Gets a the error for the async operation. This field is only valid if
+ /// OperationInProgress is false. null indicates there was no error.
+ ///
+ Exception OperationError
+ {
+ get;
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IStateDescriptorFactory.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IStateDescriptorFactory.cs
new file mode 100644
index 000000000..24ed5f442
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IStateDescriptorFactory.cs
@@ -0,0 +1,27 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Diagnostics.CodeAnalysis;
+
+ ///
+ /// Defines an interface for a factory that creates
+ /// StateDescriptors.
+ ///
+ /// The type T used by the StateDescriptor.
+ [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public interface IStateDescriptorFactory
+ {
+ ///
+ /// Creates a new StateDescriptor based upon custom
+ /// logic.
+ ///
+ /// A new StateDescriptor.
+ StateDescriptor Create();
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IntegralConverter.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IntegralConverter.cs
new file mode 100644
index 000000000..7c01b5a0f
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IntegralConverter.cs
@@ -0,0 +1,90 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Windows.Data;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Windows;
+ using System.Globalization;
+
+ ///
+ /// Takes a value and returns the largest value which is a integral amount of the second value.
+ ///
+ [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public class IntegralConverter : IMultiValueConverter
+ {
+ ///
+ /// Takes a value and returns the largest value which is a integral amount of the second value.
+ ///
+ ///
+ /// The first value is the source. The second is the factor.
+ ///
+ /// The parameter is not used.
+ /// The padding to subtract from the first value.
+ /// The parameter is not used.
+ ///
+ /// The integral value.
+ ///
+ public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+
+ if (2 != values.Length)
+ {
+ throw new ArgumentException("Two values expected", "values");
+ }
+
+ if (values[0] == DependencyProperty.UnsetValue ||
+ values[1] == DependencyProperty.UnsetValue)
+ {
+ return DependencyProperty.UnsetValue;
+ }
+
+ var source = (double) values[0];
+ var factor = (double)values[1];
+
+ double padding = 0;
+
+ if (parameter != null)
+ {
+ padding = Double.Parse((string)parameter, CultureInfo.InvariantCulture);
+ }
+
+ var newSource = source - padding;
+
+ if (newSource < factor)
+ {
+ return source;
+ }
+
+ var remainder = newSource % factor;
+ var result = newSource - remainder;
+
+ return result;
+
+ }
+
+ ///
+ /// This method is not used.
+ ///
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/InverseBooleanConverter.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/InverseBooleanConverter.cs
new file mode 100644
index 000000000..33cfb8b3c
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/InverseBooleanConverter.cs
@@ -0,0 +1,51 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Windows.Data;
+
+ ///
+ /// Takes a bool value and returns the inverse.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public class InverseBooleanConverter : IValueConverter
+ {
+ ///
+ /// Converts a boolean value to be it's inverse.
+ ///
+ /// The source value.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The inverted boolean value.
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (value == null)
+ {
+ throw new ArgumentNullException("value");
+ }
+
+ var boolValue = (bool)value;
+
+ return !boolValue;
+ }
+
+ ///
+ /// This method is not used.
+ ///
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IsEqualConverter.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IsEqualConverter.cs
new file mode 100644
index 000000000..6fb0d52e1
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IsEqualConverter.cs
@@ -0,0 +1,80 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Used to determine whether two objects are equal.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Windows.Data;
+ using System.Diagnostics.CodeAnalysis;
+ using System.Windows;
+
+ ///
+ /// Takes two objects and determines whether they are equal.
+ ///
+ [SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public class IsEqualConverter : IMultiValueConverter
+ {
+ ///
+ /// Takes two items and determines whether they are equal.
+ ///
+ ///
+ /// Two objects of any type.
+ ///
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ ///
+ /// True if-and-only-if the two objects are equal per Object.Equals().
+ /// Null is equal only to null.
+ ///
+ public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ if (values == null)
+ {
+ throw new ArgumentNullException("values");
+ }
+
+ if (2 != values.Length)
+ {
+ throw new ArgumentException("Two values expected", "values");
+ }
+
+ object item1 = values[0];
+ object item2 = values[1];
+
+ if (null == item1)
+ {
+ return (null == item2);
+ }
+
+ if (null == item2)
+ {
+ return false;
+ }
+
+ bool equal = item1.Equals(item2);
+ return equal;
+ }
+
+ ///
+ /// This method is not used.
+ ///
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IsNotNullConverter.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IsNotNullConverter.cs
new file mode 100644
index 000000000..ba8825426
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/IsNotNullConverter.cs
@@ -0,0 +1,48 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Windows.Data;
+
+ ///
+ /// The IsNotNullConverter is responsible for converting a value into
+ /// a boolean indicting whether the value is not null.
+ ///
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.MSInternal", "CA903:InternalNamespaceShouldNotContainPublicTypes")]
+ public class IsNotNullConverter : IValueConverter
+ {
+ #region IValueConverter Members
+
+ ///
+ /// Determines if value is not null.
+ ///
+ /// The object to check.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// Returns true if value is not null, false otherwise.
+ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ return (null != value);
+ }
+
+ ///
+ /// This method is not used.
+ ///
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ /// The parameter is not used.
+ public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ {
+ throw new NotSupportedException();
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/KeyboardHelp.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/KeyboardHelp.cs
new file mode 100644
index 000000000..dded7361d
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/KeyboardHelp.cs
@@ -0,0 +1,152 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//-----------------------------------------------------------------------
+
+namespace Microsoft.Management.UI.Internal
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Text;
+ using System.Windows.Input;
+ using System.Diagnostics;
+ using System.Windows;
+
+ internal enum LogicalDirection
+ {
+ None,
+ Left,
+ Right
+ }
+
+ internal static class KeyboardHelp
+ {
+ ///
+ /// Gets the logical direction for a key, taking into account RTL settings.
+ ///
+ /// The element to get FlowDirection from.
+ /// The key pressed.
+ /// The logical direction.
+ public static LogicalDirection GetLogicalDirection(DependencyObject element, Key key)
+ {
+ Debug.Assert(element != null);
+
+ bool rightToLeft = IsElementRightToLeft(element);
+
+ switch (key)
+ {
+ case Key.Right:
+ if (rightToLeft)
+ {
+ return LogicalDirection.Left;
+ }
+ else
+ {
+ return LogicalDirection.Right;
+ }
+
+ case Key.Left:
+ if (rightToLeft)
+ {
+ return LogicalDirection.Right;
+ }
+ else
+ {
+ return LogicalDirection.Left;
+ }
+
+ default:
+ return LogicalDirection.None;
+ }
+ }
+
+ ///
+ /// Gets the focus direction for a key, taking into account RTL settings.
+ ///
+ /// The element to get FlowDirection from.
+ /// The key pressed.
+ /// The focus direction.
+ public static FocusNavigationDirection GetNavigationDirection(DependencyObject element, Key key)
+ {
+ Debug.Assert(element != null);
+ Debug.Assert(IsFlowDirectionKey(key));
+
+ bool rightToLeft = IsElementRightToLeft(element);
+
+ switch (key)
+ {
+ case Key.Right:
+ if (rightToLeft)
+ {
+ return FocusNavigationDirection.Left;
+ }
+ else
+ {
+ return FocusNavigationDirection.Right;
+ }
+
+ case Key.Left:
+ if (rightToLeft)
+ {
+ return FocusNavigationDirection.Right;
+ }
+ else
+ {
+ return FocusNavigationDirection.Left;
+ }
+
+ case Key.Down:
+ return FocusNavigationDirection.Down;
+ case Key.Up:
+ return FocusNavigationDirection.Up;
+ default:
+ Debug.Fail("Non-direction key specified");
+ return FocusNavigationDirection.First;
+ }
+ }
+
+ ///
+ /// Determines if the control key is pressed.
+ ///
+ /// True if a control is is pressed.
+ public static bool IsControlPressed()
+ {
+ if (ModifierKeys.Control == (Keyboard.Modifiers & ModifierKeys.Control))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// Determines if the key is a navigation key.
+ ///
+ /// The key pressed.
+ /// True if the key is a navigation key.
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ private static bool IsFlowDirectionKey(Key key)
+ {
+ switch (key)
+ {
+ case Key.Right:
+ case Key.Left:
+ case Key.Down:
+ case Key.Up:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static bool IsElementRightToLeft(DependencyObject element)
+ {
+ FlowDirection flowDirection = FrameworkElement.GetFlowDirection(element);
+ bool rightToLeft = (flowDirection == FlowDirection.RightToLeft);
+ return rightToLeft;
+ }
+ }
+}
diff --git a/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/ListOrganizer.Generated.cs b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/ListOrganizer.Generated.cs
new file mode 100644
index 000000000..7dc0cbc24
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/ManagementList/Common/ListOrganizer.Generated.cs
@@ -0,0 +1,490 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+//
+// This code was generated by a tool. DO NOT EDIT
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+// -----------------------------------------------------------------------
+
+#region StyleCop Suppression - generated code
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Data;
+using System.Windows.Input;
+
+namespace Microsoft.Management.UI.Internal
+{
+
+ ///
+ /// This control presents a dropdown listbox with associated organizing actions that can be performed on it.
+ ///
+ ///
+ ///
+ ///
+ /// If a custom template is provided for this control, then the template MUST provide the following template parts:
+ ///
+ /// PART_Picker - A required template part which must be of type PickerBase. This control provides basic functionality for Picker-like controls.
+ ///
+ ///
+ [TemplatePart(Name="PART_Picker", Type=typeof(PickerBase))]
+ [Localizability(LocalizationCategory.None)]
+ partial class ListOrganizer
+ {
+ //
+ // Fields
+ //
+ private PickerBase picker;
+
+ //
+ // ItemDeleted RoutedEvent
+ //
+ ///
+ /// Identifies the ItemDeleted RoutedEvent.
+ ///
+ public static readonly RoutedEvent ItemDeletedEvent = EventManager.RegisterRoutedEvent("ItemDeleted",RoutingStrategy.Bubble,typeof(EventHandler>),typeof(ListOrganizer));
+
+ ///
+ /// Occurs when an item is deleted from the list.
+ ///
+ public event EventHandler> ItemDeleted
+ {
+ add
+ {
+ AddHandler(ItemDeletedEvent,value);
+ }
+ remove
+ {
+ RemoveHandler(ItemDeletedEvent,value);
+ }
+ }
+
+ //
+ // ItemSelected RoutedEvent
+ //
+ ///
+ /// Identifies the ItemSelected RoutedEvent.
+ ///
+ public static readonly RoutedEvent ItemSelectedEvent = EventManager.RegisterRoutedEvent("ItemSelected",RoutingStrategy.Bubble,typeof(EventHandler>),typeof(ListOrganizer));
+
+ ///
+ /// Occurs when an item is selected in the list.
+ ///
+ public event EventHandler> ItemSelected
+ {
+ add
+ {
+ AddHandler(ItemSelectedEvent,value);
+ }
+ remove
+ {
+ RemoveHandler(ItemSelectedEvent,value);
+ }
+ }
+
+ //
+ // DeleteItem routed command
+ //
+ ///
+ /// Informs the ListOrganizer that it should delete the item passed.
+ ///
+ public static readonly RoutedCommand DeleteItemCommand = new RoutedCommand("DeleteItem",typeof(ListOrganizer));
+
+ static private void DeleteItemCommand_CommandExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ ListOrganizer obj = (ListOrganizer) sender;
+ obj.OnDeleteItemExecuted( e );
+ }
+
+ ///
+ /// Called when DeleteItem executes.
+ ///
+ ///
+ /// Informs the ListOrganizer that it should delete the item passed.
+ ///
+ protected virtual void OnDeleteItemExecuted(ExecutedRoutedEventArgs e)
+ {
+ OnDeleteItemExecutedImplementation(e);
+ }
+
+ partial void OnDeleteItemExecutedImplementation(ExecutedRoutedEventArgs e);
+
+ //
+ // SelectItem routed command
+ //
+ ///
+ /// Informs the ListOrganizer that it should select the item passed.
+ ///
+ public static readonly RoutedCommand SelectItemCommand = new RoutedCommand("SelectItem",typeof(ListOrganizer));
+
+ static private void SelectItemCommand_CommandExecuted(object sender, ExecutedRoutedEventArgs e)
+ {
+ ListOrganizer obj = (ListOrganizer) sender;
+ obj.OnSelectItemExecuted( e );
+ }
+
+ ///
+ /// Called when SelectItem executes.
+ ///
+ ///
+ /// Informs the ListOrganizer that it should select the item passed.
+ ///
+ protected virtual void OnSelectItemExecuted(ExecutedRoutedEventArgs e)
+ {
+ OnSelectItemExecutedImplementation(e);
+ }
+
+ partial void OnSelectItemExecutedImplementation(ExecutedRoutedEventArgs e);
+
+ //
+ // DropDownButtonTemplate dependency property
+ //
+ ///
+ /// Identifies the DropDownButtonTemplate dependency property.
+ ///
+ public static readonly DependencyProperty DropDownButtonTemplateProperty = DependencyProperty.Register( "DropDownButtonTemplate", typeof(ControlTemplate), typeof(ListOrganizer), new PropertyMetadata( null, DropDownButtonTemplateProperty_PropertyChanged) );
+
+ ///
+ /// Gets or sets a value that controls the visual tree of the DropDown button.
+ ///
+ [Bindable(true)]
+ [Category("Common Properties")]
+ [Description("Gets or sets a value that controls the visual tree of the DropDown button.")]
+ [Localizability(LocalizationCategory.None)]
+ public ControlTemplate DropDownButtonTemplate
+ {
+ get
+ {
+ return (ControlTemplate) GetValue(DropDownButtonTemplateProperty);
+ }
+ set
+ {
+ SetValue(DropDownButtonTemplateProperty,value);
+ }
+ }
+
+ static private void DropDownButtonTemplateProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ ListOrganizer obj = (ListOrganizer) o;
+ obj.OnDropDownButtonTemplateChanged( new PropertyChangedEventArgs((ControlTemplate)e.OldValue, (ControlTemplate)e.NewValue) );
+ }
+
+ ///
+ /// Occurs when DropDownButtonTemplate property changes.
+ ///
+ public event EventHandler> DropDownButtonTemplateChanged;
+
+ ///
+ /// Called when DropDownButtonTemplate property changes.
+ ///
+ protected virtual void OnDropDownButtonTemplateChanged(PropertyChangedEventArgs e)
+ {
+ OnDropDownButtonTemplateChangedImplementation(e);
+ RaisePropertyChangedEvent(DropDownButtonTemplateChanged, e);
+ }
+
+ partial void OnDropDownButtonTemplateChangedImplementation(PropertyChangedEventArgs e);
+
+ //
+ // DropDownStyle dependency property
+ //
+ ///
+ /// Identifies the DropDownStyle dependency property.
+ ///
+ public static readonly DependencyProperty DropDownStyleProperty = DependencyProperty.Register( "DropDownStyle", typeof(Style), typeof(ListOrganizer), new PropertyMetadata( null, DropDownStyleProperty_PropertyChanged) );
+
+ ///
+ /// Gets or sets the style of the drop-down.
+ ///
+ [Bindable(true)]
+ [Category("Common Properties")]
+ [Description("Gets or sets the style of the drop-down.")]
+ [Localizability(LocalizationCategory.None)]
+ public Style DropDownStyle
+ {
+ get
+ {
+ return (Style) GetValue(DropDownStyleProperty);
+ }
+ set
+ {
+ SetValue(DropDownStyleProperty,value);
+ }
+ }
+
+ static private void DropDownStyleProperty_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
+ {
+ ListOrganizer obj = (ListOrganizer) o;
+ obj.OnDropDownStyleChanged( new PropertyChangedEventArgs
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/CmdletControl.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/CmdletControl.xaml
new file mode 100644
index 000000000..240e697d3
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/CmdletControl.xaml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ColumnPicker.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ColumnPicker.xaml
new file mode 100644
index 000000000..2a4934e90
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ColumnPicker.xaml
@@ -0,0 +1,204 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/HelpWindow.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/HelpWindow.xaml
new file mode 100644
index 000000000..a002684f9
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/HelpWindow.xaml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageButton.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageButton.xaml
new file mode 100644
index 000000000..a31f9b2e4
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageButton.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageButtonCommon.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageButtonCommon.xaml
new file mode 100644
index 000000000..8c3c1d08b
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageButtonCommon.xaml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageToggleButton.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageToggleButton.xaml
new file mode 100644
index 000000000..034f534ee
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ImageToggleButton.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/MultipleSelectionControl.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/MultipleSelectionControl.xaml
new file mode 100644
index 000000000..73b5656e8
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/MultipleSelectionControl.xaml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/MultipleSelectionDialog.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/MultipleSelectionDialog.xaml
new file mode 100644
index 000000000..e757a0d1e
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/MultipleSelectionDialog.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/NotImportedCmdletControl.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/NotImportedCmdletControl.xaml
new file mode 100644
index 000000000..d0d627a9d
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/NotImportedCmdletControl.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ParameterSetControl.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ParameterSetControl.xaml
new file mode 100644
index 000000000..a1f714e45
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ParameterSetControl.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/SettingsDialog.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/SettingsDialog.xaml
new file mode 100644
index 000000000..34e40a6f1
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/SettingsDialog.xaml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowAllModulesWindow.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowAllModulesWindow.xaml
new file mode 100644
index 000000000..c8713ba5c
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowAllModulesWindow.xaml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowCommandWindow.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowCommandWindow.xaml
new file mode 100644
index 000000000..dfc2a8e1e
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowCommandWindow.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowModuleControl.xaml b/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowModuleControl.xaml
new file mode 100644
index 000000000..edc43d926
--- /dev/null
+++ b/src/Microsoft.PowerShell.GraphicalHost/xamls/ShowModuleControl.xaml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+