File: PrintConfig\PageScaling.cs
Web Access
Project: src\src\Microsoft.DotNet.Wpf\src\ReachFramework\ReachFramework.csproj (ReachFramework)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
/*++
 
 
Abstract:
 
    Definition and implementation of this public feature/parameter related types.
 
 
 
--*/
 
using System;
using System.IO;
using System.Xml;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Text;
 
using System.Printing;
using MS.Internal.Printing.Configuration;
 
#pragma warning disable 1634, 1691 // Allows suppression of certain PreSharp messages
 
namespace MS.Internal.Printing.Configuration
{
    /// <summary>
    /// Represents a scaling option.
    /// </summary>
    internal class ScalingOption: PrintCapabilityOption
    {
        #region Constructors
 
        internal ScalingOption(PrintCapabilityFeature ownerFeature) : base(ownerFeature)
        {
            _value = PageScaling.Unspecified;
 
            // We use negative index value to indicate that the custom option's
            // ParameterRef element hasn't been parsed and accepted yet.
 
            _scaleWIndex = _scaleHIndex = _squareScaleIndex = -1;
        }
 
        #endregion Constructors
 
        #region Public Properties
 
        /// <summary>
        /// Gets the page scaling option's value.
        /// </summary>
        public PageScaling Value
        {
            get
            {
                return _value;
            }
        }
 
        /// <summary>
        /// Gets the <see cref="ScalingScaleWidthCapability"/> object that specifies the custom scaling option's scaling percentage capability in the width direction.
        /// </summary>
        /// <remarks>
        /// For non-custom scaling options, this property's value is always null.
        /// </remarks>
        public ScalingScaleWidthCapability CustomScaleWidth
        {
            get
            {
                if (_scaleWIndex < 0)
                    return null;
 
                #if _DEBUG
                Trace.Assert(Value == PageScaling.Custom, "THIS SHOULD NOT HAPPEN: non-Custom scaling option has ScaleWidth");
                #endif
 
                return (ScalingScaleWidthCapability)(this.OwnerFeature.OwnerPrintCap._pcLocalParamDefs[_scaleWIndex]);
            }
        }
 
        /// <summary>
        /// Gets the <see cref="ScalingScaleHeightCapability"/> object that specifies the custom scaling option's scaling percentage capability in the height direction.
        /// </summary>
        /// <remarks>
        /// For non-custom scaling options, this property's value is always null.
        /// </remarks>
        public ScalingScaleHeightCapability CustomScaleHeight
        {
            get
            {
                if (_scaleHIndex < 0)
                    return null;
 
                #if _DEBUG
                Trace.Assert(Value == PageScaling.Custom, "THIS SHOULD NOT HAPPEN: non-Custom scaling option has ScaleHeight");
                #endif
 
                return (ScalingScaleHeightCapability)(this.OwnerFeature.OwnerPrintCap._pcLocalParamDefs[_scaleHIndex]);
            }
        }
 
        public ScalingSquareScaleCapability CustomSquareScale
        {
            get
            {
                if (_squareScaleIndex < 0)
                    return null;
 
                return (ScalingSquareScaleCapability)(this.OwnerFeature.OwnerPrintCap._pcLocalParamDefs[_squareScaleIndex]);
            }
        }
 
        #endregion Public Properties
 
        #region Public Methods
 
        /// <summary>
        /// Converts the scaling option to human-readable string.
        /// </summary>
        /// <returns>A string that represents this scaling option.</returns>
        public override string ToString()
        {
            return Value.ToString() + ": " +
                   ((CustomScaleWidth != null) ? CustomScaleWidth.ToString() : "null") + " x " +
                   ((CustomScaleHeight != null) ? CustomScaleHeight.ToString() : "null") + " x " +
                   ((CustomSquareScale != null) ? CustomSquareScale.ToString() : "null");
        }
 
        #endregion Public Methods
 
        #region Internal Fields
 
        internal PageScaling _value;
 
        internal int _scaleWIndex, _scaleHIndex, _squareScaleIndex;
 
        #endregion Internal Fields
    }
 
    /// <summary>
    /// Represents page scaling capability.
    /// </summary>
    internal class PageScalingCapability : PrintCapabilityFeature
    {
        #region Constructors
 
        internal PageScalingCapability(InternalPrintCapabilities ownerPrintCap) : base(ownerPrintCap)
        {
        }
 
        #endregion Constructors
 
        #region Public Properties
 
        /// <summary>
        /// Gets the collection object that represents page scaling options supported by the device.
        /// </summary>
        public Collection<ScalingOption> ScalingOptions
        {
            get
            {
                return _scalingOptions;
            }
        }
 
        #endregion Public Properties
 
        #region Internal Methods
 
        internal static PrintCapabilityFeature NewFeatureCallback(InternalPrintCapabilities printCap)
        {
            PageScalingCapability cap = new PageScalingCapability(printCap);
            cap._scalingOptions = new Collection<ScalingOption>();
 
            return cap;
        }
 
        internal override sealed bool AddOptionCallback(PrintCapabilityOption baseOption)
        {
            bool complete = false;
 
            ScalingOption option = baseOption as ScalingOption;
 
            if (option._optionName != null)
            {
                int enumValue = PrintSchemaMapper.SchemaNameToEnumValueWithArray(
                                    PrintSchemaTags.Keywords.PageScalingKeys.ScalingNames,
                                    PrintSchemaTags.Keywords.PageScalingKeys.ScalingEnums,
                                    option._optionName);
 
                if (enumValue > 0)
                {
                    option._value = (PageScaling)enumValue;
                }
            }
 
            if (option.Value != PageScaling.Unspecified)
            {
                if (option.Value == PageScaling.None)
                {
                    // Non-custom scaling option doesn't need any ParameterRefs
                    complete = true;
                }
                else if (option.Value == PageScaling.Custom)
                {
                    // Custom scaling option must have the 2 scale ParameterRefs
                    if ((option._scaleWIndex >= 0) &&
                        (option._scaleHIndex >= 0))
                    {
                        complete = true;
                    }
                    else
                    {
                        // Need to reset the local parameter required flag since we are
                        // ignoring the custom scaling option
                        if (option._scaleWIndex >= 0)
                        {
                            option.OwnerFeature.OwnerPrintCap.SetLocalParameterDefAsRequired(option._scaleWIndex, false);
                        }
 
                        if (option._scaleHIndex >= 0)
                        {
                            option.OwnerFeature.OwnerPrintCap.SetLocalParameterDefAsRequired(option._scaleHIndex, false);
                        }
                    }
                }
                else if (option.Value == PageScaling.CustomSquare)
                {
                    // Custom square scaling option must have the scale ParameterRef
                    if (option._squareScaleIndex >= 0)
                    {
                        complete = true;
                    }
                    else
                    {
                        // Need to reset the local parameter required flag since we are
                        // ignoring the custom scaling option
                        if (option._squareScaleIndex >= 0)
                        {
                            option.OwnerFeature.OwnerPrintCap.SetLocalParameterDefAsRequired(option._squareScaleIndex, false);
                        }
                    }
                }
            }
 
            if (complete)
            {
                this.ScalingOptions.Add(option);
            }
 
            return complete;
        }
 
        internal override sealed void AddSubFeatureCallback(PrintCapabilityFeature subFeature)
        {
            // PageScaling has no sub features.
            return;
        }
 
        internal override sealed bool FeaturePropCallback(PrintCapabilityFeature feature, XmlPrintCapReader reader)
        {
            // no feature property to handle
            return false;
        }
 
        internal override sealed PrintCapabilityOption NewOptionCallback(PrintCapabilityFeature baseFeature)
        {
            ScalingOption newOption = new ScalingOption(baseFeature);
 
            return newOption;
        }
 
        internal override sealed void OptionAttrCallback(PrintCapabilityOption baseOption, XmlPrintCapReader reader)
        {
            // no option attribute to handle
            return;
        }
 
        /// <exception cref="XmlException">XML is not well-formed.</exception>
        internal override sealed bool OptionPropCallback(PrintCapabilityOption baseOption, XmlPrintCapReader reader)
        {
            bool handled = false;
 
            ScalingOption option = baseOption as ScalingOption;
 
            if (reader.CurrentElementNodeType == PrintSchemaNodeTypes.ScoredProperty)
            {
                handled = true;
 
                string sPropertyName = reader.CurrentElementNameAttrValue;
 
                if ( (sPropertyName == PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleWidth) ||
                     (sPropertyName == PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleHeight) ||
                     (sPropertyName == PrintSchemaTags.Keywords.PageScalingKeys.CustomSquareScale) )
                {
                    // custom or custom square scaling properties
                    try
                    {
                        string paramRefName = reader.GetCurrentPropertyParamRefNameWithException();
 
                        if ( (sPropertyName == PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleWidth) &&
                             (paramRefName == PrintSchemaTags.Keywords.ParameterDefs.PageScalingScaleWidth) )
                        {
                            option._scaleWIndex = (int)PrintSchemaLocalParameterDefs.PageScalingScaleWidth;
 
                            // Mark the local parameter-def as required
                            option.OwnerFeature.OwnerPrintCap.SetLocalParameterDefAsRequired(option._scaleWIndex, true);
                        }
                        else if ( (sPropertyName == PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleHeight) &&
                                  (paramRefName == PrintSchemaTags.Keywords.ParameterDefs.PageScalingScaleHeight) )
                        {
                            option._scaleHIndex = (int)PrintSchemaLocalParameterDefs.PageScalingScaleHeight;
 
                            // Mark the local parameter-def as required
                            option.OwnerFeature.OwnerPrintCap.SetLocalParameterDefAsRequired(option._scaleHIndex, true);
                        }
                        else if ( (sPropertyName == PrintSchemaTags.Keywords.PageScalingKeys.CustomSquareScale) &&
                                  (paramRefName == PrintSchemaTags.Keywords.ParameterDefs.PageSquareScalingScale) )
                        {
                            option._squareScaleIndex = (int)PrintSchemaLocalParameterDefs.PageSquareScalingScale;
 
                            // Mark the local parameter-def as required
                            option.OwnerFeature.OwnerPrintCap.SetLocalParameterDefAsRequired(option._squareScaleIndex, true);
                        }
                        else
                        {
                            #if _DEBUG
                            Trace.WriteLine("-Warning- skip unknown ParameterRef " + paramRefName +
                                            "' at line number " + reader._xmlReader.LineNumber +
                                            ", line position " + reader._xmlReader.LinePosition);
                            #endif
                        }
                    }
                    // We want to catch internal FormatException to skip recoverable XML content syntax error
                    #pragma warning suppress 56502
                    #if _DEBUG
                    catch (FormatException e)
                    #else
                    catch (FormatException)
                    #endif
                    {
                        #if _DEBUG
                        Trace.WriteLine("-Error- " + e.Message);
                        #endif
                    }
                }
                else
                {
                    handled = false;
 
                    #if _DEBUG
                    Trace.WriteLine("-Warning- skip unknown ScoredProperty '" +
                                    reader.CurrentElementNameAttrValue + "' at line " +
                                    reader._xmlReader.LineNumber + ", position " +
                                    reader._xmlReader.LinePosition);
                    #endif
                }
            }
 
            return handled;
        }
 
        #endregion Internal Methods
 
        #region Internal Properties
 
        internal override sealed bool IsValid
        {
            get
            {
                return (this.ScalingOptions.Count > 0);
            }
        }
 
        internal override sealed string FeatureName
        {
            get
            {
                return PrintSchemaTags.Keywords.PageScalingKeys.Self;
            }
        }
 
        internal override sealed bool HasSubFeature
        {
            get
            {
                return false;
            }
        }
 
        #endregion Internal Properties
 
        #region Internal Fields
 
        internal Collection<ScalingOption> _scalingOptions;
 
        #endregion Internal Fields
    }
 
    /// <summary>
    /// Represents page scaling setting.
    /// </summary>
    internal class PageScalingSetting : PrintTicketFeature
    {
        #region Constructors
 
        /// <summary>
        /// Constructs a new page scaling setting object.
        /// </summary>
        internal PageScalingSetting(InternalPrintTicket ownerPrintTicket) : base(ownerPrintTicket)
        {
            this._featureName = PrintSchemaTags.Keywords.PageScalingKeys.Self;
 
            this._propertyMaps = new PTPropertyMapEntry[] {
                new PTPropertyMapEntry(this,
                                       PrintSchemaTags.Framework.OptionNameProperty,
                                       PTPropValueTypes.EnumStringValue,
                                       PrintSchemaTags.Keywords.PageScalingKeys.ScalingNames,
                                       PrintSchemaTags.Keywords.PageScalingKeys.ScalingEnums),
                new PTPropertyMapEntry(this,
                                       PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleWidth,
                                       PTPropValueTypes.IntParamRefValue,
                                       PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleWidth,
                                       PrintSchemaTags.Keywords.ParameterDefs.PageScalingScaleWidth),
                new PTPropertyMapEntry(this,
                                       PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleHeight,
                                       PTPropValueTypes.IntParamRefValue,
                                       PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleHeight,
                                       PrintSchemaTags.Keywords.ParameterDefs.PageScalingScaleHeight),
                new PTPropertyMapEntry(this,
                                       PrintSchemaTags.Keywords.PageScalingKeys.CustomSquareScale,
                                       PTPropValueTypes.IntParamRefValue,
                                       PrintSchemaTags.Keywords.PageScalingKeys.CustomSquareScale,
                                       PrintSchemaTags.Keywords.ParameterDefs.PageSquareScalingScale),
                };
        }
 
        #endregion Constructors
 
        #region Public Properties
 
        /// <summary>
        /// Gets the value of the page scaling setting.
        /// </summary>
        /// <remarks>
        /// If the setting is not specified yet, the return value will be
        /// <see cref="PageScaling.Unspecified"/>.
        /// </remarks>
        public PageScaling Value
        {
            get
            {
                return (PageScaling)this[PrintSchemaTags.Framework.OptionNameProperty];
            }
        }
 
        /// <summary>
        /// Gets the custom page scaling setting's scaling percentage in the width direction.
        /// </summary>
        /// <remarks>
        /// If current page scaling setting is not <see cref="PageScaling.Custom"/>,
        /// the return value will be <see cref="PrintSchema.UnspecifiedIntValue"/>.
        /// </remarks>
        public int CustomScaleWidth
        {
            get
            {
                if (this.Value != PageScaling.Custom)
                    return PrintSchema.UnspecifiedIntValue;
 
                return this[PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleWidth];
            }
        }
 
        /// <summary>
        /// Gets the custom page scaling setting's scaling percentage in the height direction.
        /// </summary>
        /// <remarks>
        /// If current page scaling setting is not <see cref="PageScaling.Custom"/>,
        /// the return value will be <see cref="PrintSchema.UnspecifiedIntValue"/>.
        /// </remarks>
        public int CustomScaleHeight
        {
            get
            {
                if (this.Value != PageScaling.Custom)
                    return PrintSchema.UnspecifiedIntValue;
 
                return this[PrintSchemaTags.Keywords.PageScalingKeys.CustomScaleHeight];
            }
        }
 
        /// <summary>
        /// Gets the custom square page scaling setting's scaling percentage.
        /// </summary>
        /// <remarks>
        /// If current page scaling setting is not <see cref="PageScaling.CustomSquare"/>,
        /// the return value will be <see cref="PrintSchema.UnspecifiedIntValue"/>.
        /// </remarks>
        public int CustomSquareScale
        {
            get
            {
                if (this.Value != PageScaling.CustomSquare)
                    return PrintSchema.UnspecifiedIntValue;
 
                return this[PrintSchemaTags.Keywords.PageScalingKeys.CustomSquareScale];
            }
        }
 
        #endregion Public Properties
 
        #region Public Methods
 
        /// <summary>
        /// Sets page scaling setting to custom square scaling.
        /// </summary>
        /// <param name="squareScale">custom square scaling percentage</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// "squareScale" is not non-negative value.
        /// </exception>
        public void SetCustomSquareScaling(int squareScale)
        {
            // Scaling percentage value must be non-negative. We do allow negative scaling offset values.
            if (squareScale < 0)
            {
                throw new ArgumentOutOfRangeException("squareScale",
                                                      PTUtility.GetTextFromResource("ArgumentException.NonNegativeValue"));
            }
 
            // Remove all XML content related to PageScaling feature
            // any way to avoid redundant NotifyPropertyChanged calls?
            ClearSetting();
 
            this[PrintSchemaTags.Framework.OptionNameProperty] = (int)PageScaling.CustomSquare;
 
            this[PrintSchemaTags.Keywords.PageScalingKeys.CustomSquareScale] = squareScale;
        }
 
        /// <summary>
        /// Converts the page scaling setting to human-readable string.
        /// </summary>
        /// <returns>A string that represents this page scaling setting.</returns>
        public override string ToString()
        {
            if ((Value != PageScaling.Custom) || (Value != PageScaling.CustomSquare))
            {
                return Value.ToString();
            }
            else
            {
                return Value.ToString() +
                       ", ScaleWidth=" + CustomScaleWidth.ToString(CultureInfo.CurrentCulture) +
                       ", ScaleHeight=" + CustomScaleHeight.ToString(CultureInfo.CurrentCulture) +
                       ", SquareScale=" + CustomSquareScale.ToString(CultureInfo.CurrentCulture);
            }
        }
 
        #endregion Public Methods
    }
}