PowerShell/src/Microsoft.Management.UI.Internal/HelpWindow/HelpViewModel.cs

284 lines
8.4 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Management.Automation;
using System.Windows.Documents;
namespace Microsoft.Management.UI.Internal
{
/// <summary>
/// ViewModel for the Help Dialog used to:
/// build the help document
/// search the help document
/// offer text for labels.
/// </summary>
internal class HelpViewModel : INotifyPropertyChanged
{
/// <summary>
/// The builder for the help FlowDocument Paragraph used in a RichEditText control.
/// </summary>
private readonly HelpParagraphBuilder helpBuilder;
/// <summary>
/// Searcher for selecting current matches in paragraph text.
/// </summary>
private readonly ParagraphSearcher searcher;
/// <summary>
/// Title of the help window.
/// </summary>
private readonly string helpTitle;
/// <summary>
/// the zoom bound to the zoom slider value.
/// </summary>
private double zoom = 100;
/// <summary>
/// Text to be found. This is bound to the find TextBox.
/// </summary>
private string findText;
/// <summary>
/// text for the number of matches found.
/// </summary>
private string matchesLabel;
/// <summary>
/// Initializes a new instance of the HelpViewModel class.
/// </summary>
/// <param name="psObj">Object containing help.</param>
/// <param name="documentParagraph">Paragraph in which help text is built/searched.</param>
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
/// <summary>
/// Used to notify of property changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
#endregion
/// <summary>
/// Gets or sets the Zoom bound to the zoom slider value.
/// </summary>
public double Zoom
{
get
{
return this.zoom;
}
set
{
this.zoom = value;
this.OnNotifyPropertyChanged("Zoom");
this.OnNotifyPropertyChanged("ZoomLabel");
this.OnNotifyPropertyChanged("ZoomLevel");
}
}
/// <summary>
/// Gets the value bound to the RichTextEdit zoom, which is calculated based on the zoom.
/// </summary>
public double ZoomLevel
{
get
{
return this.zoom / 100.0;
}
}
/// <summary>
/// Gets the label to be displayed for the zoom.
/// </summary>
public string ZoomLabel
{
get
{
return string.Format(CultureInfo.CurrentCulture, HelpWindowResources.ZoomLabelTextFormat, this.zoom);
}
}
/// <summary>
/// Gets or sets the text to be found.
/// </summary>
public string FindText
{
get
{
return this.findText;
}
set
{
this.findText = value;
this.Search();
this.SetMatchesLabel();
}
}
/// <summary>
/// Gets the title of the window.
/// </summary>
public string HelpTitle
{
get
{
return this.helpTitle;
}
}
/// <summary>
/// Gets or sets the label for current matches.
/// </summary>
public string MatchesLabel
{
get
{
return this.matchesLabel;
}
set
{
this.matchesLabel = value;
this.OnNotifyPropertyChanged("MatchesLabel");
}
}
/// <summary>
/// Gets a value indicating whether there are matches to go to.
/// </summary>
public bool CanGoToNextOrPrevious
{
get
{
return this.HelpBuilder.HighlightCount != 0;
}
}
/// <summary>
/// Gets the searcher for selecting current matches in paragraph text.
/// </summary>
internal ParagraphSearcher Searcher
{
get { return this.searcher; }
}
/// <summary>
/// Gets the paragraph builder used to write help content.
/// </summary>
internal HelpParagraphBuilder HelpBuilder
{
get { return this.helpBuilder; }
}
/// <summary>
/// Highlights all matches to this.findText
/// Called when findText changes or whenever the search has to be refreshed
/// </summary>
internal void Search()
{
this.HelpBuilder.HighlightAllInstancesOf(this.findText, HelpWindowSettings.Default.HelpSearchMatchCase, HelpWindowSettings.Default.HelpSearchWholeWord);
this.searcher.ResetSearch();
}
/// <summary>
/// Increases Zoom if not above maximum.
/// </summary>
internal void ZoomIn()
{
if (this.Zoom + HelpWindow.ZoomInterval <= HelpWindow.MaximumZoom)
{
this.Zoom += HelpWindow.ZoomInterval;
}
}
/// <summary>
/// Decreases Zoom if not below minimum.
/// </summary>
internal void ZoomOut()
{
if (this.Zoom - HelpWindow.ZoomInterval >= HelpWindow.MinimumZoom)
{
this.Zoom -= HelpWindow.ZoomInterval;
}
}
/// <summary>
/// Called to update the matches label.
/// </summary>
/// <param name="sender">Event sender.</param>
/// <param name="e">Event arguments.</param>
private void HelpBuilder_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "HighlightCount")
{
this.SetMatchesLabel();
this.OnNotifyPropertyChanged("CanGoToNextOrPrevious");
}
}
/// <summary>
/// Sets the current matches label.
/// </summary>
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);
}
}
}
}
/// <summary>
/// Called internally to notify when a proiperty changed.
/// </summary>
/// <param name="propertyName">Property name.</param>
private void OnNotifyPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}