Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Controls / FlowDocumentReader.cs / 1305600 / FlowDocumentReader.cs
//----------------------------------------------------------------------------
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//---------------------------------------------------------------------------
using System; // Object
using System.Collections; // IEnumerator
using System.Collections.ObjectModel; // ReadOnlyCollection
using System.Security; // SecurityCritical
using System.Windows.Automation.Peers; // AutomationPeer
using System.Windows.Data; // BindingOperations
using System.Windows.Controls.Primitives; // PlacementMode
using System.Windows.Documents; // FlowDocument
using System.Windows.Input; // KeyEventArgs
using System.Windows.Media; // ScaleTransform, VisualTreeHelper
using System.Windows.Markup; // IAddChild
using System.Windows.Threading; // Dispatcher
using MS.Internal; // Invariant, DoubleUtil
using MS.Internal.Commands; // CommandHelpers
using MS.Internal.Controls; // EmptyEnumerator
using MS.Internal.Documents; // FindToolBar
using MS.Internal.KnownBoxes; // BooleanBoxes
using MS.Internal.AppModel; // IJournalState
namespace System.Windows.Controls
{
///
/// FlowDocumentReader provides a full user experience for consuming text content.
/// It will be used as the default viewer for loose XAML or containers that contain
/// text content, and can be styled and re-used by developers for use within their applications.
///
[TemplatePart(Name = "PART_ContentHost", Type = typeof(Decorator))]
[TemplatePart(Name = "PART_FindToolBarHost", Type = typeof(Decorator))]
[ContentProperty("Document")]
public class FlowDocumentReader : Control, IAddChild, IJournalState
{
//-------------------------------------------------------------------
//
// Constructors
//
//-------------------------------------------------------------------
#region Constructors
///
/// Static Constructor
///
static FlowDocumentReader()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIFlowDocumentReader")));
_dType = DependencyObjectType.FromSystemTypeInternal(typeof(FlowDocumentReader));
TextBoxBase.SelectionBrushProperty.OverrideMetadata(typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement)));
TextBoxBase.SelectionOpacityProperty.OverrideMetadata(typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(new PropertyChangedCallback(UpdateCaretElement)));
CreateCommandBindings();
EventManager.RegisterClassHandler(typeof(FlowDocumentReader), Keyboard.KeyDownEvent, new KeyEventHandler(KeyDownHandler), true);
}
///
/// Default Constructor
///
public FlowDocumentReader()
: base()
{
}
#endregion Constructors
//--------------------------------------------------------------------
//
// Public Methods
//
//-------------------------------------------------------------------
#region Public Methods
///
/// Build Visual tree
///
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Initialize ContentHost.
// If old ContentHost is enabled, disable it first to ensure appropriate cleanup.
if (CurrentViewer != null)
{
DetachViewer(CurrentViewer);
_contentHost.Child = null;
}
_contentHost = GetTemplateChild(_contentHostTemplateName) as Decorator;
if (_contentHost != null)
{
if (_contentHost.Child != null)
{
throw new NotSupportedException(SR.Get(SRID.FlowDocumentReaderDecoratorMarkedAsContentHostMustHaveNoContent));
}
SwitchViewingModeCore(ViewingMode);
}
// Initialize FindTooBar host.
// If old FindToolBar is enabled, disable it first to ensure appropriate cleanup.
if (FindToolBar != null)
{
ToggleFindToolBar(false);
}
_findToolBarHost = GetTemplateChild(_findToolBarHostTemplateName) as Decorator;
_findButton = GetTemplateChild(_findButtonTemplateName) as ToggleButton;
}
///
/// Whether the master page can be moved to the specified page.
///
/// Page number.
public bool CanGoToPage(int pageNumber)
{
bool canGoToPage = false;
if (CurrentViewer != null)
{
canGoToPage = CurrentViewer.CanGoToPage(pageNumber);
}
return canGoToPage;
}
///
/// Invokes the Find Toolbar. This is analogous to the ApplicationCommands.Find.
///
public void Find()
{
OnFindCommand();
}
///
/// Invokes the Print Dialog. This is analogous to the ApplicationCommands.Print.
///
public void Print()
{
OnPrintCommand();
}
///
/// Cancels current printing job. This is analogous to the ApplicationCommands.CancelPrint.
///
public void CancelPrint()
{
OnCancelPrintCommand();
}
///
/// Increases the current zoom.
///
public void IncreaseZoom()
{
OnIncreaseZoomCommand();
}
///
/// Decreases the current zoom.
///
public void DecreaseZoom()
{
OnDecreaseZoomCommand();
}
///
/// Switches the current viewing mode. This is analogous to the SwitchViewingModeCommand.
///
/// Viewing mode.
public void SwitchViewingMode(FlowDocumentReaderViewingMode viewingMode)
{
OnSwitchViewingModeCommand(viewingMode);
}
#endregion Public Methods
//--------------------------------------------------------------------
//
// Public Properties
//
//--------------------------------------------------------------------
#region Public Properties
///
/// ViewingMode of FlowDocumentReader.
///
public FlowDocumentReaderViewingMode ViewingMode
{
get { return (FlowDocumentReaderViewingMode)GetValue(ViewingModeProperty); }
set { SetValue(ViewingModeProperty, value); }
}
///
/// Text Selection (readonly)
///
public TextSelection Selection
{
get
{
TextSelection result = null;
IFlowDocumentViewer viewer;
if (_contentHost != null)
{
viewer = _contentHost.Child as IFlowDocumentViewer;
if(viewer != null)
{
result = viewer.TextSelection as TextSelection;
}
}
return result;
}
}
///
/// Whether Page view can be enabled or not.
///
public bool IsPageViewEnabled
{
get { return (bool)GetValue(IsPageViewEnabledProperty); }
set { SetValue(IsPageViewEnabledProperty, BooleanBoxes.Box(value)); }
}
///
/// Whether TwoPage view can be enabled or not.
///
public bool IsTwoPageViewEnabled
{
get { return (bool)GetValue(IsTwoPageViewEnabledProperty); }
set { SetValue(IsTwoPageViewEnabledProperty, BooleanBoxes.Box(value)); }
}
///
/// Whether Scroll view can be enabled or not.
///
public bool IsScrollViewEnabled
{
get { return (bool)GetValue(IsScrollViewEnabledProperty); }
set { SetValue(IsScrollViewEnabledProperty, BooleanBoxes.Box(value)); }
}
///
/// The number of pages currently available for viewing. This value
/// is updated as content is paginated, and will change dramatically
/// when the content is resized, or edited.
///
public int PageCount
{
get { return (int)GetValue(PageCountProperty); }
}
///
/// The one-based page number of the page being displayed. If there is no content,
/// this value will be 0.
///
public int PageNumber
{
get { return (int)GetValue(PageNumberProperty); }
}
///
/// Whether the viewer can move the master page to the previous page.
///
public bool CanGoToPreviousPage
{
get { return (bool)GetValue(CanGoToPreviousPageProperty); }
}
///
/// Whether the viewer can advance the master page to the next page.
///
public bool CanGoToNextPage
{
get { return (bool)GetValue(CanGoToNextPageProperty); }
}
///
/// Is find function enabled or not
///
public bool IsFindEnabled
{
get { return (bool)GetValue(IsFindEnabledProperty); }
set { SetValue(IsFindEnabledProperty, BooleanBoxes.Box(value)); }
}
///
/// Is print function enabled or not
///
public bool IsPrintEnabled
{
get { return (bool)GetValue(IsPrintEnabledProperty); }
set { SetValue(IsPrintEnabledProperty, BooleanBoxes.Box(value)); }
}
///
/// A Property representing a content of this FlowDocumentScrollViewer.
///
public FlowDocument Document
{
get { return (FlowDocument)GetValue(DocumentProperty); }
set { SetValue(DocumentProperty, value); }
}
///
/// The Zoom applied to all pages; this value is 100-based.
///
public double Zoom
{
get { return (double)GetValue(ZoomProperty); }
set { SetValue(ZoomProperty, value); }
}
///
/// The maximum allowed value of the Zoom property.
///
public double MaxZoom
{
get { return (double)GetValue(MaxZoomProperty); }
set { SetValue(MaxZoomProperty, value); }
}
///
/// The minimum allowed value of the Zoom property.
///
public double MinZoom
{
get { return (double)GetValue(MinZoomProperty); }
set { SetValue(MinZoomProperty, value); }
}
///
/// The amount the Zoom property is incremented or decremented when
/// the IncreaseZoom or DecreaseZoom command is executed.
///
public double ZoomIncrement
{
get { return (double)GetValue(ZoomIncrementProperty); }
set { SetValue(ZoomIncrementProperty, value); }
}
///
/// Whether the viewer can increase the current zoom.
///
public bool CanIncreaseZoom
{
get { return (bool)GetValue(CanIncreaseZoomProperty); }
}
///
/// Whether the viewer can decrease the current zoom.
///
public bool CanDecreaseZoom
{
get { return (bool)GetValue(CanDecreaseZoomProperty); }
}
///
///
///
public Brush SelectionBrush
{
get { return (Brush)GetValue(SelectionBrushProperty); }
set { SetValue(SelectionBrushProperty, value); }
}
///
///
///
public double SelectionOpacity
{
get { return (double)GetValue(SelectionOpacityProperty); }
set { SetValue(SelectionOpacityProperty, value); }
}
#region Public Dynamic Properties
///
///
///
public static readonly DependencyProperty ViewingModeProperty =
DependencyProperty.Register(
"ViewingMode",
typeof(FlowDocumentReaderViewingMode),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
FlowDocumentReaderViewingMode.Page,
FrameworkPropertyMetadataOptions.AffectsMeasure,
new PropertyChangedCallback(ViewingModeChanged)),
new ValidateValueCallback(IsValidViewingMode));
///
///
///
public static readonly DependencyProperty IsPageViewEnabledProperty =
DependencyProperty.Register(
"IsPageViewEnabled",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
BooleanBoxes.TrueBox,
new PropertyChangedCallback(ViewingModeEnabledChanged)));
///
///
///
public static readonly DependencyProperty IsTwoPageViewEnabledProperty =
DependencyProperty.Register(
"IsTwoPageViewEnabled",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
BooleanBoxes.TrueBox,
new PropertyChangedCallback(ViewingModeEnabledChanged)));
///
///
///
public static readonly DependencyProperty IsScrollViewEnabledProperty =
DependencyProperty.Register(
"IsScrollViewEnabled",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
BooleanBoxes.TrueBox,
new PropertyChangedCallback(ViewingModeEnabledChanged)));
///
///
///
private static readonly DependencyPropertyKey PageCountPropertyKey =
DependencyProperty.RegisterReadOnly(
"PageCount",
typeof(int),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(0));
///
///
///
public static readonly DependencyProperty PageCountProperty = PageCountPropertyKey.DependencyProperty;
///
///
///
private static readonly DependencyPropertyKey PageNumberPropertyKey =
DependencyProperty.RegisterReadOnly(
"PageNumber",
typeof(int),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(0));
///
///
///
public static readonly DependencyProperty PageNumberProperty = PageNumberPropertyKey.DependencyProperty;
///
///
///
private static readonly DependencyPropertyKey CanGoToPreviousPagePropertyKey =
DependencyProperty.RegisterReadOnly(
"CanGoToPreviousPage",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));
///
///
///
public static readonly DependencyProperty CanGoToPreviousPageProperty = CanGoToPreviousPagePropertyKey.DependencyProperty;
///
///
///
private static readonly DependencyPropertyKey CanGoToNextPagePropertyKey =
DependencyProperty.RegisterReadOnly(
"CanGoToNextPage",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(BooleanBoxes.FalseBox));
///
///
///
public static readonly DependencyProperty CanGoToNextPageProperty = CanGoToNextPagePropertyKey.DependencyProperty;
///
///
///
public static readonly DependencyProperty IsFindEnabledProperty =
DependencyProperty.Register(
"IsFindEnabled",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
BooleanBoxes.TrueBox,
new PropertyChangedCallback(IsFindEnabledChanged)));
///
///
///
public static readonly DependencyProperty IsPrintEnabledProperty =
DependencyProperty.Register(
"IsPrintEnabled",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
BooleanBoxes.TrueBox,
new PropertyChangedCallback(IsPrintEnabledChanged)));
///
///
///
public static readonly DependencyProperty DocumentProperty =
DependencyProperty.Register(
"Document",
typeof(FlowDocument),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
null,
new PropertyChangedCallback(DocumentChanged)));
///
///
///
public static readonly DependencyProperty ZoomProperty =
FlowDocumentPageViewer.ZoomProperty.AddOwner(
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
100d,
new PropertyChangedCallback(ZoomChanged),
new CoerceValueCallback(CoerceZoom)));
///
///
///
public static readonly DependencyProperty MaxZoomProperty =
FlowDocumentPageViewer.MaxZoomProperty.AddOwner(
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
200d,
new PropertyChangedCallback(MaxZoomChanged),
new CoerceValueCallback(CoerceMaxZoom)));
///
///
///
public static readonly DependencyProperty MinZoomProperty =
FlowDocumentPageViewer.MinZoomProperty.AddOwner(
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(
80d,
new PropertyChangedCallback(MinZoomChanged)));
///
///
///
public static readonly DependencyProperty ZoomIncrementProperty =
FlowDocumentPageViewer.ZoomIncrementProperty.AddOwner(
typeof(FlowDocumentReader));
///
///
///
private static readonly DependencyPropertyKey CanIncreaseZoomPropertyKey =
DependencyProperty.RegisterReadOnly(
"CanIncreaseZoom",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(BooleanBoxes.TrueBox));
///
///
///
public static readonly DependencyProperty CanIncreaseZoomProperty = CanIncreaseZoomPropertyKey.DependencyProperty;
///
///
///
private static readonly DependencyPropertyKey CanDecreaseZoomPropertyKey =
DependencyProperty.RegisterReadOnly(
"CanDecreaseZoom",
typeof(bool),
typeof(FlowDocumentReader),
new FrameworkPropertyMetadata(BooleanBoxes.TrueBox));
///
///
///
public static readonly DependencyProperty CanDecreaseZoomProperty = CanDecreaseZoomPropertyKey.DependencyProperty;
///
///
///
public static readonly DependencyProperty SelectionBrushProperty =
TextBoxBase.SelectionBrushProperty.AddOwner(typeof(FlowDocumentReader));
///
///
///
public static readonly DependencyProperty SelectionOpacityProperty =
TextBoxBase.SelectionOpacityProperty.AddOwner(typeof(FlowDocumentReader));
#endregion Public Dynamic Properties
#endregion Public Properties
//-------------------------------------------------------------------
//
// Public Commands
//
//--------------------------------------------------------------------
#region Public Commands
///
/// Switch ViewingMode command
///
public static readonly RoutedUICommand SwitchViewingModeCommand = new RoutedUICommand(SR.Get(SRID.SwitchViewingMode), "SwitchViewingMode", typeof(FlowDocumentReader), null);
#endregion
//-------------------------------------------------------------------
//
// Protected Methods
//
//-------------------------------------------------------------------
#region Protected Methods
///
/// Called when print has been completed.
///
protected virtual void OnPrintCompleted()
{
if (_printInProgress)
{
_printInProgress = false;
// Since _printInProgress value is used to determine CanExecute state, we must invalidate that state.
CommandManager.InvalidateRequerySuggested();
}
}
///
/// Handler for the Find command
///
protected virtual void OnFindCommand()
{
if (CanShowFindToolBar)
{
// Toggle on the FindToolBar between visible and hidden state.
ToggleFindToolBar(FindToolBar == null);
}
}
///
/// Handler for the Print command.
///
protected virtual void OnPrintCommand()
{
if (CurrentViewer != null)
{
CurrentViewer.Print();
}
}
///
/// Handler for the CancelPrint command.
///
protected virtual void OnCancelPrintCommand()
{
if (CurrentViewer != null)
{
CurrentViewer.CancelPrint();
}
}
///
/// Handler for the IncreaseZoom command.
///
protected virtual void OnIncreaseZoomCommand()
{
// If can zoom in, increase zoom by the zoom increment value.
if (CanIncreaseZoom)
{
SetCurrentValueInternal(ZoomProperty, Math.Min(Zoom + ZoomIncrement, MaxZoom));
}
}
///
/// Handler for the DecreaseZoom command.
///
protected virtual void OnDecreaseZoomCommand()
{
// If can zoom out, decrease zoom by the zoom increment value.
if (CanDecreaseZoom)
{
SetCurrentValueInternal(ZoomProperty, Math.Max(Zoom - ZoomIncrement, MinZoom));
}
}
///
/// Handler for the SwitchViewingMode command.
///
/// Viewing mode.
protected virtual void OnSwitchViewingModeCommand(FlowDocumentReaderViewingMode viewingMode)
{
SwitchViewingModeCore(viewingMode);
}
///
/// Called when IsInitialized is set to true.
///
/// Event arguments
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
// Defer the Is*ViewEnabled & ViewingMode conflict exception.
// Otherwise won't work.
if (IsInitialized && !CanSwitchToViewingMode(ViewingMode))
{
throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict));
}
}
///
/// Creates AutomationPeer ( )
///
protected override AutomationPeer OnCreateAutomationPeer()
{
return new FlowDocumentReaderAutomationPeer(this);
}
///
/// An event reporting that the IsKeyboardFocusWithin property changed.
///
protected override void OnIsKeyboardFocusWithinChanged(DependencyPropertyChangedEventArgs e)
{
base.OnIsKeyboardFocusWithinChanged(e);
// In order to enable selection rendering and other similar services, the embedded viewer
// needs to get focus, when any part of the control gets focused.
// But if the focus is within the Document, do not change it. Otherwise it
// will interfere with input handling inside the Document.
if (IsKeyboardFocusWithin && CurrentViewer != null)
{
bool isFocusWithinDocument = IsFocusWithinDocument();
if (!isFocusWithinDocument)
{
((FrameworkElement)CurrentViewer).Focus();
}
}
}
///
/// This is the method that responds to the KeyDown event.
///
/// Event arguments
///
/// Critical: get_SearchUp is defined in a non-APTCA assembly.
/// TreatAsSafe: call to get_SearchUp does not entail any risk.
///
[SecurityCritical, SecurityTreatAsSafe]
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Handled) { return; }
switch (e.Key)
{
// Esc -- Close FindToolBar
case Key.Escape:
if (FindToolBar != null)
{
ToggleFindToolBar(false);
e.Handled = true;
}
break;
// F3 -- Invoke Find
case Key.F3:
if (CanShowFindToolBar)
{
if (FindToolBar != null)
{
// If the Shift key is also pressed, then search up.
FindToolBar.SearchUp = ((e.KeyboardDevice.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift);
OnFindInvoked(this, EventArgs.Empty);
}
else
{
// Make the FindToolBar visible
ToggleFindToolBar(true);
}
e.Handled = true;
}
break;
}
// If not handled, do default handling.
if (!e.Handled)
{
base.OnKeyDown(e);
}
}
#endregion Protected Methods
//-------------------------------------------------------------------
//
// Protected Properties
//
//--------------------------------------------------------------------
#region Protected Properties
///
/// Returns enumerator to logical children.
///
protected internal override IEnumerator LogicalChildren
{
get
{
if (HasLogicalChildren && Document != null)
{
return new SingleChildEnumerator(Document);
}
return EmptyEnumerator.Instance;
}
}
#endregion Protected Properties
//-------------------------------------------------------------------
//
// Internal Methods
//
//--------------------------------------------------------------------
#region Internal Methods
///
/// Allows FrameworkElement to augment the EventRoute.
///
internal override bool BuildRouteCore(EventRoute route, RoutedEventArgs args)
{
// Do not add intermediate ContentElements to the route,
// because they were added by embedded viewer.
return BuildRouteCoreHelper(route, args, false);
}
#endregion Internal Methods
//--------------------------------------------------------------------
//
// Private Methods
//
//-------------------------------------------------------------------
#region Private Methods
///
/// Handler for the SwitchViewingMode command.
///
/// Viewing mode.
protected virtual void SwitchViewingModeCore(FlowDocumentReaderViewingMode viewingMode)
{
ITextSelection textSelection = null;
ContentPosition contentPosition = null;
IFlowDocumentViewer viewer;
FrameworkElement feViewer;
bool isKeyboardFocusWithin;
DependencyObject focusedElement = null;
if (_contentHost != null)
{
// Remember the current keyboard focus state.
isKeyboardFocusWithin = IsKeyboardFocusWithin;
// Detach old viewer
viewer = _contentHost.Child as IFlowDocumentViewer;
if (viewer != null)
{
// Remember focused element, if the focus is within the Document.
// After switching to a different viewer, this focus needs to be restored.
if (isKeyboardFocusWithin)
{
bool isFocusWithinDocument = IsFocusWithinDocument();
if (isFocusWithinDocument)
{
focusedElement = Keyboard.FocusedElement as DependencyObject;
}
}
// Retrieve the current viewing state from the old viewer.
textSelection = viewer.TextSelection;
contentPosition = viewer.ContentPosition;
// Detach old viewer
DetachViewer(viewer);
}
viewer = GetViewerFromMode(viewingMode);
feViewer = (FrameworkElement)viewer;
if (viewer != null)
{
// Attach new viewer
_contentHost.Child = feViewer;
AttachViewer(viewer);
// Restore viewing state.
viewer.TextSelection = textSelection;
viewer.ContentPosition = contentPosition;
// Bring the focus to previously focused element within the document
// or to the current viewer.
if (isKeyboardFocusWithin)
{
if (focusedElement is UIElement)
{
((UIElement)focusedElement).Focus();
}
else if (focusedElement is ContentElement)
{
((ContentElement)focusedElement).Focus();
}
else
{
feViewer.Focus();
}
}
}
// Viewer changes invalidates following properties:
// - PageCount
// - PageNumber
// - CanGoToPreviousPage
// - CanGoToNextPage
UpdateReadOnlyProperties(true, true);
}
}
///
/// Determines whether focus is within Document.
///
private bool IsFocusWithinDocument()
{
DependencyObject focusedElement = Keyboard.FocusedElement as DependencyObject;
while (focusedElement != null && focusedElement != Document)
{
// Skip elements in the control's template (if such exists) and
// walk up logical tree to find if the focused element is within
// the document.
FrameworkElement fe = focusedElement as FrameworkElement;
if (fe != null && fe.TemplatedParent != null)
{
focusedElement = fe.TemplatedParent;
}
else
{
focusedElement = LogicalTreeHelper.GetParent(focusedElement);
}
}
return (focusedElement != null);
}
///
/// The Document has changed and needs to be updated.
///
private void DocumentChanged(FlowDocument oldDocument, FlowDocument newDocument)
{
// Cleanup state associated with the old document.
if (oldDocument != null)
{
// If Document was added to logical tree before, remove it.
if (_documentAsLogicalChild)
{
RemoveLogicalChild(oldDocument);
}
}
// If FlowDocumentReader was created through style, then do not modify
// the logical tree. Instead, set "core parent" for the Document.
if (TemplatedParent != null && newDocument != null && LogicalTreeHelper.GetParent(newDocument) != null)
{
// Set the "core parent" back to us.
ContentOperations.SetParent(newDocument, this);
_documentAsLogicalChild = false;
}
else
{
_documentAsLogicalChild = true;
}
// Initialize state associated with the new document.
if (newDocument != null)
{
// If Document should be part of DocumentViewer's logical tree, add it.
if (_documentAsLogicalChild)
{
AddLogicalChild(newDocument);
}
}
// Attach document to the current viewer.
if (CurrentViewer != null)
{
CurrentViewer.SetDocument(newDocument);
}
// Document invalidation invalidates following properties:
// - PageCount
// - PageNumber
// - CanGoToPreviousPage
// - CanGoToNextPage
UpdateReadOnlyProperties(true, true);
// Update the toolbar with our current document state.
if (!CanShowFindToolBar)
{
// Disable FindToolBar, if the content does not support it.
if (FindToolBar != null)
{
ToggleFindToolBar(false);
}
}
// Document is also represented as Automation child. Need to invalidate peer to force update.
FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(this) as FlowDocumentReaderAutomationPeer;
if (peer != null)
{
peer.InvalidatePeer();
}
}
///
/// Detach embedded viewer form the reader control.
///
private void DetachViewer(IFlowDocumentViewer viewer)
{
Invariant.Assert(viewer != null && viewer is FrameworkElement);
FrameworkElement feViewer = (FrameworkElement)viewer;
// Clear property bindings.
BindingOperations.ClearBinding(feViewer, ZoomProperty);
BindingOperations.ClearBinding(feViewer, MaxZoomProperty);
BindingOperations.ClearBinding(feViewer, MinZoomProperty);
BindingOperations.ClearBinding(feViewer, ZoomIncrementProperty);
// Unregister event handlers.
viewer.PageCountChanged -= new EventHandler(OnPageCountChanged);
viewer.PageNumberChanged -= new EventHandler(OnPageNumberChanged);
viewer.PrintStarted -= new EventHandler(OnViewerPrintStarted);
viewer.PrintCompleted -= new EventHandler(OnViewerPrintCompleted);
// Clear TemplatedParent
//feViewer._templatedParent = null;
// Detach document
viewer.SetDocument(null);
}
///
/// Attach embedded viewer to the reader control.
///
private void AttachViewer(IFlowDocumentViewer viewer)
{
Invariant.Assert(viewer != null && viewer is FrameworkElement);
FrameworkElement feViewer = (FrameworkElement)viewer;
// Set document
viewer.SetDocument(Document);
// Set TemplatedParent
//feViewer._templatedParent = TemplatedParent;
// Register event handlers.
viewer.PageCountChanged += new EventHandler(OnPageCountChanged);
viewer.PageNumberChanged += new EventHandler(OnPageNumberChanged);
viewer.PrintStarted += new EventHandler(OnViewerPrintStarted);
viewer.PrintCompleted += new EventHandler(OnViewerPrintCompleted);
// Create property bindings.
CreateTwoWayBinding(feViewer, ZoomProperty, "Zoom");
CreateTwoWayBinding(feViewer, MaxZoomProperty, "MaxZoom");
CreateTwoWayBinding(feViewer, MinZoomProperty, "MinZoom");
CreateTwoWayBinding(feViewer, ZoomIncrementProperty, "ZoomIncrement");
}
///
/// Create two way property binding.
///
private void CreateTwoWayBinding(FrameworkElement fe, DependencyProperty dp, string propertyPath)
{
Binding binding = new Binding(propertyPath);
binding.Mode = BindingMode.TwoWay;
binding.Source = this;
fe.SetBinding(dp, binding);
}
///
/// Determines whether can switch to specified ViewingMode or not.
///
private bool CanSwitchToViewingMode(FlowDocumentReaderViewingMode mode)
{
bool canSwitch = false;
switch (mode)
{
case FlowDocumentReaderViewingMode.Page:
canSwitch = IsPageViewEnabled;
break;
case FlowDocumentReaderViewingMode.TwoPage:
canSwitch = IsTwoPageViewEnabled;
break;
case FlowDocumentReaderViewingMode.Scroll:
canSwitch = IsScrollViewEnabled;
break;
}
return canSwitch;
}
///
/// Retrieves viewer form specified ViewingMode.
///
private IFlowDocumentViewer GetViewerFromMode(FlowDocumentReaderViewingMode mode)
{
IFlowDocumentViewer viewer = null;
switch (mode)
{
case FlowDocumentReaderViewingMode.Page:
if (_pageViewer == null)
{
_pageViewer = new ReaderPageViewer();
_pageViewer.SetResourceReference(StyleProperty, PageViewStyleKey);
_pageViewer.Name = "PageViewer";
CommandManager.AddPreviewCanExecuteHandler(_pageViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
}
viewer = _pageViewer;
break;
case FlowDocumentReaderViewingMode.TwoPage:
if (_twoPageViewer == null)
{
_twoPageViewer = new ReaderTwoPageViewer();
_twoPageViewer.SetResourceReference(StyleProperty, TwoPageViewStyleKey);
_twoPageViewer.Name = "TwoPageViewer";
CommandManager.AddPreviewCanExecuteHandler(_twoPageViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
}
viewer = _twoPageViewer;
break;
case FlowDocumentReaderViewingMode.Scroll:
if (_scrollViewer == null)
{
_scrollViewer = new ReaderScrollViewer();
_scrollViewer.SetResourceReference(StyleProperty, ScrollViewStyleKey);
_scrollViewer.Name = "ScrollViewer";
CommandManager.AddPreviewCanExecuteHandler(_scrollViewer, new CanExecuteRoutedEventHandler(PreviewCanExecuteRoutedEventHandler));
}
viewer = _scrollViewer;
break;
}
return viewer;
}
///
/// Update values for readonly properties.
///
/// Whether PageCount has been changed.
/// Whether PageNumber has been changed.
private void UpdateReadOnlyProperties(bool pageCountChanged, bool pageNumberChanged)
{
if (pageCountChanged)
{
SetValue(PageCountPropertyKey, (CurrentViewer != null) ? CurrentViewer.PageCount : 0);
}
if (pageNumberChanged)
{
SetValue(PageNumberPropertyKey, (CurrentViewer != null) ? CurrentViewer.PageNumber : 0);
SetValue(CanGoToPreviousPagePropertyKey, (CurrentViewer != null) ? CurrentViewer.CanGoToPreviousPage : false);
}
if (pageCountChanged || pageNumberChanged)
{
SetValue(CanGoToNextPagePropertyKey, (CurrentViewer != null) ? CurrentViewer.CanGoToNextPage : false);
}
}
///
/// Event handler for IFlowDocumentViewer.PageCountChanged.
///
private void OnPageCountChanged(object sender, EventArgs e)
{
Invariant.Assert(CurrentViewer != null && sender == CurrentViewer);
UpdateReadOnlyProperties(true, false);
}
///
/// Event handler for IFlowDocumentViewer.PageNumberChanged.
///
private void OnPageNumberChanged(object sender, EventArgs e)
{
Invariant.Assert(CurrentViewer != null && sender == CurrentViewer);
UpdateReadOnlyProperties(false, true);
}
///
/// Event handler for IFlowDocumentViewer.PrintStarted.
///
private void OnViewerPrintStarted(object sender, EventArgs e)
{
Invariant.Assert(CurrentViewer != null && sender == CurrentViewer);
_printInProgress = true;
// Since _printInProgress value is used to determine CanExecute state, we must invalidate that state.
CommandManager.InvalidateRequerySuggested();
}
///
/// Event handler for IFlowDocumentViewer.PrintCompleted.
///
private void OnViewerPrintCompleted(object sender, EventArgs e)
{
Invariant.Assert(CurrentViewer != null && sender == CurrentViewer);
OnPrintCompleted();
}
///
/// Convert object value to FlowDocumentReaderViewingMode.
///
private bool ConvertToViewingMode(object value, out FlowDocumentReaderViewingMode mode)
{
bool success;
if (value is FlowDocumentReaderViewingMode)
{
mode = (FlowDocumentReaderViewingMode)value;
success = true;
}
else if (value is String)
{
String str = (String)value;
if (str == FlowDocumentReaderViewingMode.Page.ToString())
{
mode = FlowDocumentReaderViewingMode.Page;
success = true;
}
else if (str == FlowDocumentReaderViewingMode.TwoPage.ToString())
{
mode = FlowDocumentReaderViewingMode.TwoPage;
success = true;
}
else if (str == FlowDocumentReaderViewingMode.Scroll.ToString())
{
mode = FlowDocumentReaderViewingMode.Scroll;
success = true;
}
else
{
mode = FlowDocumentReaderViewingMode.Page;
success = false;
}
}
else
{
mode = FlowDocumentReaderViewingMode.Page;
success = false;
}
return success;
}
///
/// Enables/disables the FindToolBar.
///
/// Whether to enable/disable FindToolBar.
private void ToggleFindToolBar(bool enable)
{
Invariant.Assert(enable == (FindToolBar == null));
// Command event for toggle button is only fired in OnClick - Therefore we just need to change the state
if(_findButton != null && _findButton.IsChecked.HasValue && _findButton.IsChecked.Value != enable)
{
_findButton.IsChecked = enable;
}
DocumentViewerHelper.ToggleFindToolBar(_findToolBarHost, new EventHandler(OnFindInvoked), enable);
}
#region Commands
///
/// Set up Command and RoutedCommand bindings.
///
private static void CreateCommandBindings()
{
ExecutedRoutedEventHandler executedHandler;
CanExecuteRoutedEventHandler canExecuteHandler;
// Create our generic ExecutedRoutedEventHandler.
executedHandler = new ExecutedRoutedEventHandler(ExecutedRoutedEventHandler);
// Create our generic CanExecuteRoutedEventHandler
canExecuteHandler = new CanExecuteRoutedEventHandler(CanExecuteRoutedEventHandler);
// Command: SwitchViewingMode
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), FlowDocumentReader.SwitchViewingModeCommand,
executedHandler, canExecuteHandler, SRID.KeySwitchViewingMode, SRID.KeySwitchViewingModeDisplayString);
// Command: ApplicationCommands.Find
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.Find,
executedHandler, canExecuteHandler);
// Command: ApplicationCommands.Print
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.Print,
executedHandler, canExecuteHandler);
// Command: ApplicationCommands.CancelPrint
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), ApplicationCommands.CancelPrint,
executedHandler, canExecuteHandler);
// Command: NavigationCommands.PreviousPage
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.PreviousPage,
executedHandler, canExecuteHandler);
// Command: NavigationCommands.NextPage
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.NextPage,
executedHandler, canExecuteHandler);
// Command: NavigationCommands.FirstPage
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.FirstPage,
executedHandler, canExecuteHandler);
// Command: NavigationCommands.LastPage
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.LastPage,
executedHandler, canExecuteHandler);
// Command: NavigationCommands.IncreaseZoom
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.IncreaseZoom,
executedHandler, canExecuteHandler, new KeyGesture(Key.OemPlus, ModifierKeys.Control));
// Command: NavigationCommands.DecreaseZoom
CommandHelpers.RegisterCommandHandler(typeof(FlowDocumentReader), NavigationCommands.DecreaseZoom,
executedHandler, canExecuteHandler, new KeyGesture(Key.OemMinus, ModifierKeys.Control));
}
///
/// Central handler for CanExecute events fired by Commands directed at FlowDocumentReader.
///
/// The target of this Command, expected to be FlowDocumentReader
/// The event arguments for this event.
private static void CanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args)
{
FlowDocumentReader viewer = target as FlowDocumentReader;
Invariant.Assert(viewer != null, "Target of CanExecuteRoutedEventHandler must be FlowDocumentReader.");
Invariant.Assert(args != null, "args cannot be null.");
// FlowDocumentReader is capable of execution of the majority of its commands.
// Special rules:
// a) during printing only CancelPrint is enabled.
// b) Find command is enabled only when FindToolBar is enabled.
// c) Print command is enabled when Document is attached and printing is enabled.
// d) CancelPrint command is enabled only during printing.
// e) SwitchViewingMode command is enabled if the viewing mode is enabled, or
// the command has no parameters (will switch to the next available view).
if (!viewer._printInProgress)
{
if (args.Command == FlowDocumentReader.SwitchViewingModeCommand)
{
// This command is enabled if the viewing mode is enabled, or the command
// has no parameters (will switch to the next available view).
FlowDocumentReaderViewingMode mode;
if (viewer.ConvertToViewingMode(args.Parameter, out mode))
{
args.CanExecute = viewer.CanSwitchToViewingMode(mode);
}
else
{
args.CanExecute = (args.Parameter == null);
}
}
else if (args.Command == ApplicationCommands.Find)
{
args.CanExecute = viewer.CanShowFindToolBar;
}
else if (args.Command == ApplicationCommands.Print)
{
args.CanExecute = (viewer.Document != null) && viewer.IsPrintEnabled;
}
else if (args.Command == ApplicationCommands.CancelPrint)
{
args.CanExecute = false;
}
else
{
args.CanExecute = true;
}
}
else
{
args.CanExecute = (args.Command == ApplicationCommands.CancelPrint);
}
}
///
/// Central handler for all ExecuteEvents fired by Commands directed at FlowDocumentReader.
///
/// The target of this Command, expected to be FlowDocumentReader.
/// The event arguments associated with this event.
private static void ExecutedRoutedEventHandler(object target, ExecutedRoutedEventArgs args)
{
FlowDocumentReader viewer = target as FlowDocumentReader;
Invariant.Assert(viewer != null, "Target of ExecutedRoutedEventHandler must be FlowDocumentReader.");
Invariant.Assert(args != null, "args cannot be null.");
if (args.Command == FlowDocumentReader.SwitchViewingModeCommand)
{
viewer.TrySwitchViewingMode(args.Parameter);
}
else if (args.Command == ApplicationCommands.Find)
{
viewer.OnFindCommand();
}
else if (args.Command == ApplicationCommands.Print)
{
viewer.OnPrintCommand();
}
else if (args.Command == ApplicationCommands.CancelPrint)
{
viewer.OnCancelPrintCommand();
}
else if (args.Command == NavigationCommands.IncreaseZoom)
{
viewer.OnIncreaseZoomCommand();
}
else if (args.Command == NavigationCommands.DecreaseZoom)
{
viewer.OnDecreaseZoomCommand();
}
else if (args.Command == NavigationCommands.PreviousPage)
{
viewer.OnPreviousPageCommand();
}
else if (args.Command == NavigationCommands.NextPage)
{
viewer.OnNextPageCommand();
}
else if (args.Command == NavigationCommands.FirstPage)
{
viewer.OnFirstPageCommand();
}
else if (args.Command == NavigationCommands.LastPage)
{
viewer.OnLastPageCommand();
}
else
{
Invariant.Assert(false, "Command not handled in ExecutedRoutedEventHandler.");
}
}
///
/// Changes the current viewing mode.
///
private void TrySwitchViewingMode(object parameter)
{
FlowDocumentReaderViewingMode mode;
// Convert command parameter to viewing mode value.
// If parameter is not provided, the viewing mode is the next one available.
// If parameter cannot be converted, the command is ignored.
if (!ConvertToViewingMode(parameter, out mode))
{
if (parameter == null)
{
mode = (FlowDocumentReaderViewingMode)((((int)ViewingMode) + 1) % 3);
}
else
{
return;
}
}
// If the current ViewingMode is disabled, go to next one.
while (!CanSwitchToViewingMode(mode))
{
mode = (FlowDocumentReaderViewingMode)((((int)mode) + 1) % 3);
}
// Set new ViewingMode value.
SetCurrentValueInternal(ViewingModeProperty, mode);
}
///
/// Handler for the PreviousPage command.
///
private void OnPreviousPageCommand()
{
if (CurrentViewer != null)
{
CurrentViewer.PreviousPage();
}
}
///
/// Handler for the NextPage command.
///
private void OnNextPageCommand()
{
if (CurrentViewer != null)
{
CurrentViewer.NextPage();
}
}
///
/// Handler for the FirstPage command.
///
private void OnFirstPageCommand()
{
if (CurrentViewer != null)
{
CurrentViewer.FirstPage();
}
}
///
/// Handler for the LastPage command.
///
private void OnLastPageCommand()
{
if (CurrentViewer != null)
{
CurrentViewer.LastPage();
}
}
///
/// Invoked when the "Find" button in the Find Toolbar is clicked.
/// This method invokes the actual Find process.
///
/// The object that sent this event
/// The Click Events associated with this event
private void OnFindInvoked(object sender, EventArgs e)
{
ITextRange findResult;
TextEditor textEditor = TextEditor;
FindToolBar findToolBar = FindToolBar;
if (findToolBar != null && textEditor != null)
{
// In order to show current text selection TextEditor requires Focus to be set on the UIScope.
// If there embedded controls, it may happen that embedded control currently has focus and find
// was invoked through hotkeys. To support this case we manually move focus to the appropriate element.
if (CurrentViewer != null && CurrentViewer is UIElement)
{
((UIElement)CurrentViewer).Focus();
}
findResult = DocumentViewerHelper.Find(findToolBar, textEditor, textEditor.TextView, textEditor.TextView);
// If we found something, bring it into the view. Otherwise alert the user.
if ((findResult != null) && (!findResult.IsEmpty))
{
// Bring find result into view.
if (CurrentViewer != null)
{
CurrentViewer.ShowFindResult(findResult);
}
}
else
{
DocumentViewerHelper.ShowFindUnsuccessfulMessage(findToolBar);
}
}
}
///
/// Disable commands on IFlowDocumentViewer when this funcionality is explicitly
/// disabled on the reader control.
///
private void PreviewCanExecuteRoutedEventHandler(object target, CanExecuteRoutedEventArgs args)
{
if (args.Command == ApplicationCommands.Find)
{
// Find is handled by FlowDocumentReader.
args.CanExecute = false;
args.Handled = true;
}
else if (args.Command == ApplicationCommands.Print)
{
args.CanExecute = IsPrintEnabled;
args.Handled = !IsPrintEnabled;
}
}
///
/// Called when a key event occurs.
///
private static void KeyDownHandler(object sender, KeyEventArgs e)
{
DocumentViewerHelper.KeyDownHelper(e, ((FlowDocumentReader)sender)._findToolBarHost);
}
#endregion Commands
#region Static Methods
///
/// ViewingMode has been changed.
///
private static void ViewingModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
if (viewer.CanSwitchToViewingMode((FlowDocumentReaderViewingMode)e.NewValue))
{
viewer.SwitchViewingModeCore((FlowDocumentReaderViewingMode)e.NewValue);
}
else if (viewer.IsInitialized)
{
throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict));
}
// Fire automation events if automation is active.
FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(viewer) as FlowDocumentReaderAutomationPeer;
if (peer != null)
{
peer.RaiseCurrentViewChangedEvent((FlowDocumentReaderViewingMode)e.NewValue, (FlowDocumentReaderViewingMode)e.OldValue);
}
}
///
/// Validate value of ViewingMode property.
///
private static bool IsValidViewingMode(object o)
{
FlowDocumentReaderViewingMode value = (FlowDocumentReaderViewingMode)o;
return (value == FlowDocumentReaderViewingMode.Page ||
value == FlowDocumentReaderViewingMode.TwoPage ||
value == FlowDocumentReaderViewingMode.Scroll);
}
///
/// One of viewing modes has been enabled/disabled.
///
private static void ViewingModeEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
// Cannot disable all viewing modes.
if (!viewer.IsPageViewEnabled &&
!viewer.IsTwoPageViewEnabled &&
!viewer.IsScrollViewEnabled)
{
throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderCannotDisableAllViewingModes));
}
// Cannot disable the current viewing mode.
if (viewer.IsInitialized && !viewer.CanSwitchToViewingMode(viewer.ViewingMode))
{
throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderViewingModeEnabledConflict));
}
// Fire automation events if automation is active.
FlowDocumentReaderAutomationPeer peer = UIElementAutomationPeer.FromElement(viewer) as FlowDocumentReaderAutomationPeer;
if (peer != null)
{
peer.RaiseSupportedViewsChangedEvent(e);
}
}
///
/// IsFindEnabled value has changed.
///
private static void IsFindEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
// Update the toolbar with our current state.
if (!viewer.CanShowFindToolBar)
{
if (viewer.FindToolBar != null)
{
viewer.ToggleFindToolBar(false);
}
}
// Since IsFindEnabled state is used to determine CanExecute state, we must invalidate that state.
CommandManager.InvalidateRequerySuggested();
}
///
/// IsPrintEnabled value has changed.
///
private static void IsPrintEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
// Since IsPrintEnabled state is used to determine CanExecute state, we must invalidate that state.
CommandManager.InvalidateRequerySuggested();
}
///
/// The Document has changed and needs to be updated.
///
private static void DocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
viewer.DocumentChanged((FlowDocument)e.OldValue, (FlowDocument)e.NewValue);
// Since Document state is used to determine CanExecute state, we must invalidate that state.
CommandManager.InvalidateRequerySuggested();
}
///
/// The Zoom has changed and needs to be updated.
///
private static void ZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
if (!DoubleUtil.AreClose((double)e.OldValue, (double)e.NewValue))
{
// If zoom has been changed, CanIncrease/DecreaseZoom property need to be updated.
viewer.SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(viewer.MaxZoom, viewer.Zoom)));
viewer.SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(viewer.MinZoom, viewer.Zoom)));
}
}
///
/// Coerce Zoom with Max/MinZoom, MinZoom works as the baseline.
///
private static object CoerceZoom(DependencyObject d, object value)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
double zoom = (double)value;
double maxZoom = viewer.MaxZoom;
if (DoubleUtil.LessThan(maxZoom, zoom))
{
return maxZoom;
}
double minZoom = viewer.MinZoom;
if (DoubleUtil.GreaterThan(minZoom, zoom))
{
return minZoom;
}
return value;
}
///
/// The MaxZoom has changed and needs to be updated.
///
private static void MaxZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
viewer.CoerceValue(ZoomProperty);
viewer.SetValue(CanIncreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.GreaterThan(viewer.MaxZoom, viewer.Zoom)));
}
///
/// MaxZoom need to be coerced if MinZoom > MaxZoom
///
private static object CoerceMaxZoom(DependencyObject d, object value)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
double min = viewer.MinZoom;
return ((double)value < min) ? min : value;
}
///
/// The MinZoom has changed and needs to be updated.
///
private static void MinZoomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Invariant.Assert(d != null && d is FlowDocumentReader);
FlowDocumentReader viewer = (FlowDocumentReader)d;
viewer.CoerceValue(MaxZoomProperty);
viewer.CoerceValue(ZoomProperty);
viewer.SetValue(CanDecreaseZoomPropertyKey, BooleanBoxes.Box(DoubleUtil.LessThan(viewer.MinZoom, viewer.Zoom)));
}
///
/// Validate Zoom, MaxZoom, MinZoom and ZoomIncrement value.
///
/// Value to validate.
/// True if the value is valid, false otherwise.
private static bool ZoomValidateValue(object o)
{
double value = (double)o;
return (!Double.IsNaN(value) && !Double.IsInfinity(value) && DoubleUtil.GreaterThan(value, 0d));
}
///
/// PropertyChanged callback for a property that affects the selection or caret rendering.
///
private static void UpdateCaretElement(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FlowDocumentReader reader = (FlowDocumentReader)d;
if (reader.Selection != null)
{
CaretElement caretElement = reader.Selection.CaretElement;
if (caretElement != null)
{
caretElement.InvalidateVisual();
}
}
}
#endregion Static Methods
#endregion Private Methods
//--------------------------------------------------------------------
//
// Private Properties
//
//-------------------------------------------------------------------
#region Private Properties
///
/// Whether FindToolBar can be enabled.
///
private bool CanShowFindToolBar
{
get { return ((_findToolBarHost != null) && IsFindEnabled && (Document != null)); }
}
///
/// Returns TextEditor, if availabe.
///
private TextEditor TextEditor
{
get
{
TextEditor textEditor = null;
IFlowDocumentViewer currentViewer = CurrentViewer;
if (currentViewer != null && currentViewer.TextSelection != null)
{
textEditor = currentViewer.TextSelection.TextEditor;
}
return textEditor;
}
}
///
/// Returns FindToolBar, if enabled.
///
private FindToolBar FindToolBar
{
get { return (_findToolBarHost != null) ? _findToolBarHost.Child as FindToolBar : null; }
}
///
/// Returns the current content viewer.
///
private IFlowDocumentViewer CurrentViewer
{
get
{
if (_contentHost != null)
{
return (IFlowDocumentViewer)_contentHost.Child;
}
return null;
}
}
#endregion Private Properties
//-------------------------------------------------------------------
//
// Private Fields
//
//-------------------------------------------------------------------
#region Private Fields
private Decorator _contentHost; // Host for content viewer
private Decorator _findToolBarHost; // Host for FindToolBar
private ToggleButton _findButton; // Find toggle button
private ReaderPageViewer _pageViewer; // Viewer for Page viewing mode
private ReaderTwoPageViewer _twoPageViewer; // Viewer for TwoPage viewing mode
private ReaderScrollViewer _scrollViewer; // Viewer for Scroll viewing mode
private bool _documentAsLogicalChild; // Is Document part of logical tree
private bool _printInProgress; // Whether print is currently in progress.
private const string _contentHostTemplateName = "PART_ContentHost"; // Name for ContentHost
private const string _findToolBarHostTemplateName = "PART_FindToolBarHost"; // Name for the Find ToolBar host
private const string _findButtonTemplateName = "FindButton"; // Name for the Find Button
#endregion Private Fields
//--------------------------------------------------------------------
//
// IAddChild Members
//
//-------------------------------------------------------------------
#region IAddChild Members
///
/// Called to add the object as a Child.
///
/// Object to add as a child.
/// FlowDocumentScrollViewer only supports a single child of type IDocumentPaginator.
void IAddChild.AddChild(Object value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
// Check if Content has already been set.
if (this.Document != null)
{
throw new ArgumentException(SR.Get(SRID.FlowDocumentReaderCanHaveOnlyOneChild));
}
if (!(value is FlowDocument))
{
throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, value.GetType(), typeof(FlowDocument)), "value");
}
Document = value as FlowDocument;
}
///
/// Called when text appears under the tag in markup
///
/// Text to add to the Object.
/// FlowDocumentScrollViewer does not support Text children.
void IAddChild.AddText(string text)
{
XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);
}
#endregion IAddChild Members
//--------------------------------------------------------------------
//
// IJournalState Members
//
//--------------------------------------------------------------------
#region IJournalState Members
[Serializable]
private class JournalState : CustomJournalStateInternal
{
public JournalState(int contentPosition, LogicalDirection contentPositionDirection, double zoom, FlowDocumentReaderViewingMode viewingMode)
{
ContentPosition = contentPosition;
ContentPositionDirection = contentPositionDirection;
Zoom = zoom;
ViewingMode = viewingMode;
}
public int ContentPosition;
public LogicalDirection ContentPositionDirection;
public double Zoom;
public FlowDocumentReaderViewingMode ViewingMode;
}
///
///
///
CustomJournalStateInternal IJournalState.GetJournalState(JournalReason journalReason)
{
int cp = -1;
LogicalDirection cpDirection = LogicalDirection.Forward;
IFlowDocumentViewer viewer = CurrentViewer;
if (viewer != null)
{
TextPointer contentPosition = viewer.ContentPosition as TextPointer;
if (contentPosition != null)
{
cp = contentPosition.Offset;
cpDirection = contentPosition.LogicalDirection;
}
}
return new JournalState(cp, cpDirection, Zoom, ViewingMode);
}
///
///
///
void IJournalState.RestoreJournalState(CustomJournalStateInternal state)
{
JournalState viewerState = state as JournalState;
if (state != null)
{
SetCurrentValueInternal(ZoomProperty, viewerState.Zoom);
SetCurrentValueInternal(ViewingModeProperty, viewerState.ViewingMode);
if (viewerState.ContentPosition != -1)
{
IFlowDocumentViewer viewer = CurrentViewer;
FlowDocument document = Document;
if (viewer != null && document != null)
{
TextContainer textContainer = document.StructuralCache.TextContainer;
if (viewerState.ContentPosition <= textContainer.SymbolCount)
{
TextPointer contentPosition = textContainer.CreatePointerAtOffset(viewerState.ContentPosition, viewerState.ContentPositionDirection);
viewer.ContentPosition = contentPosition;
}
}
}
}
}
#endregion IJournalState Members
//-------------------------------------------------------------------
//
// DTypeThemeStyleKey
//
//--------------------------------------------------------------------
#region DTypeThemeStyleKey
///
/// Returns the DependencyObjectType for the registered ThemeStyleKey's default
/// value. Controls will override this method to return approriate types
///
internal override DependencyObjectType DTypeThemeStyleKey
{
get { return _dType; }
}
private static DependencyObjectType _dType;
#endregion DTypeThemeStyleKey
//-------------------------------------------------------------------
//
// Style Keys
//
//-------------------------------------------------------------------
#region Style Keys
///
/// Key used to mark the style for use by the PageView
///
private static ResourceKey PageViewStyleKey
{
get
{
if (_pageViewStyleKey == null)
{
_pageViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIPageViewStyleKey");
}
return _pageViewStyleKey;
}
}
///
/// Key used to mark the style for use by the TwoPageView
///
private static ResourceKey TwoPageViewStyleKey
{
get
{
if (_twoPageViewStyleKey == null)
{
_twoPageViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUITwoPageViewStyleKey");
}
return _twoPageViewStyleKey;
}
}
///
/// Key used to mark the style for use by the ScrollView
///
private static ResourceKey ScrollViewStyleKey
{
get
{
if (_scrollViewStyleKey == null)
{
_scrollViewStyleKey = new ComponentResourceKey(typeof(PresentationUIStyleResources), "PUIScrollViewStyleKey");
}
return _scrollViewStyleKey;
}
}
private static ComponentResourceKey _pageViewStyleKey;
private static ComponentResourceKey _twoPageViewStyleKey;
private static ComponentResourceKey _scrollViewStyleKey;
#endregion
}
///
///
public enum FlowDocumentReaderViewingMode
{
///
///
Page,
///
///
TwoPage,
///
///
Scroll
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DataTableMappingCollection.cs
- DictionaryEntry.cs
- EventItfInfo.cs
- AssemblyNameProxy.cs
- DependencyPropertyAttribute.cs
- ListBoxItem.cs
- AnonymousIdentificationSection.cs
- XmlSchemaValidator.cs
- FrameworkTextComposition.cs
- Soap.cs
- RectangleGeometry.cs
- GradientStopCollection.cs
- ProfileProvider.cs
- DocumentSequence.cs
- BufferModeSettings.cs
- BindingSource.cs
- SerializableReadOnlyDictionary.cs
- SqlErrorCollection.cs
- CodeCompileUnit.cs
- ApplicationProxyInternal.cs
- SnapLine.cs
- TransportSecurityBindingElement.cs
- DeferredElementTreeState.cs
- StringArrayEditor.cs
- Visual.cs
- KoreanLunisolarCalendar.cs
- PerformanceCountersElement.cs
- TimeSpanValidator.cs
- LayoutInformation.cs
- LZCodec.cs
- RenderTargetBitmap.cs
- RemotingConfiguration.cs
- EndpointDiscoveryElement.cs
- ListViewItemSelectionChangedEvent.cs
- CompiledQuery.cs
- PocoPropertyAccessorStrategy.cs
- ZipIOLocalFileHeader.cs
- ReferentialConstraint.cs
- odbcmetadatacollectionnames.cs
- CacheMode.cs
- DataStreams.cs
- DefaultSection.cs
- Frame.cs
- ExtendedTransformFactory.cs
- FlowchartDesigner.Helpers.cs
- AdRotatorDesigner.cs
- HScrollBar.cs
- GridViewRow.cs
- CodeTypeReferenceCollection.cs
- QilLoop.cs
- ParameterCollectionEditorForm.cs
- WCFServiceClientProxyGenerator.cs
- ZoneIdentityPermission.cs
- NumericUpDownAcceleration.cs
- FederatedMessageSecurityOverHttpElement.cs
- AddInServer.cs
- SafeLibraryHandle.cs
- DataGridItemEventArgs.cs
- NonDualMessageSecurityOverHttp.cs
- NameObjectCollectionBase.cs
- Axis.cs
- RepeatBehaviorConverter.cs
- StylusEditingBehavior.cs
- BitmapCodecInfoInternal.cs
- HtmlInputControl.cs
- HandlerFactoryWrapper.cs
- ClientFormsAuthenticationCredentials.cs
- ProfileServiceManager.cs
- MatrixStack.cs
- WindowsListView.cs
- SingleTagSectionHandler.cs
- NegotiateStream.cs
- COM2PropertyDescriptor.cs
- _AutoWebProxyScriptEngine.cs
- Profiler.cs
- OlePropertyStructs.cs
- TransactionManager.cs
- ListBox.cs
- ActivityPropertyReference.cs
- SrgsNameValueTag.cs
- Point3DCollection.cs
- VariantWrapper.cs
- LayoutDump.cs
- ActivationServices.cs
- TextViewSelectionProcessor.cs
- MessageSecurityOverTcpElement.cs
- EmbeddedObject.cs
- OleDbMetaDataFactory.cs
- SmiEventStream.cs
- WebUtil.cs
- WorkItem.cs
- SqlTypeConverter.cs
- SocketManager.cs
- DetailsViewModeEventArgs.cs
- MenuItem.cs
- ConfigurationElement.cs
- EditorAttribute.cs
- ResourceExpressionBuilder.cs
- StringAttributeCollection.cs
- ToolboxItemCollection.cs