PrtTicket_Public_Simple.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Print / Reach / PrintConfig / PrtTicket_Public_Simple.cs / 1 / PrtTicket_Public_Simple.cs

                            /*++ 

Copyright (C) 2003-2005 Microsoft Corporation
All rights reserved.
 
Module Name:
 
    PrtTicket_Public_Simple.cs 

Abstract: 

    Definition and implementation of simple public PT/PC classes.

Author: 

    [....] ([....]) 8/26/2005 
 
--*/
 
using System;
using System.Xml;
using System.IO;
using System.Collections; 
using System.Collections.ObjectModel;
using System.Collections.Generic; 
using System.Globalization; 

using System.Printing; 
using MS.Internal.Printing.Configuration;

namespace System.Printing
{ 
    /// 
    /// Represents page media size setting. 
    ///  
    public sealed class PageMediaSize
    { 
        #region Constructors

        /// 
        /// Constructs a new instance of  with the specified media size name. 
        /// 
        /// name of the media size 
        public PageMediaSize(PageMediaSizeName mediaSizeName) 
        {
            _mediaSizeName = mediaSizeName; 
            _width = _height = null;
        }

        ///  
        /// Constructs a new instance of  with the specified dimensions.
        ///  
        /// width of the physical media (in 1/96 inch unit) 
        /// height of the physical media (in 1/96 inch unit)
        public PageMediaSize(double width, double height) 
        {
            _mediaSizeName = null;
            _width = width;
            _height = height; 
        }
 
        ///  
        /// Constructs a new instance of  with the specified media size name
        /// and dimensions. 
        /// 
        /// name of the media size
        /// width of the physical media (in 1/96 inch unit)
        /// height of the physical media (in 1/96 inch unit) 
        public PageMediaSize(PageMediaSizeName mediaSizeName, double width, double height)
        { 
            _mediaSizeName = mediaSizeName; 
            _width = width;
            _height = height; 
        }

        #endregion Constructors
 
        #region Public Properties
 
        ///  
        /// Gets the media size name. Returns null if the media size name is not specified.
        ///  
        public Nullable PageMediaSizeName
        {
            get
            { 
                return _mediaSizeName;
            } 
        } 

        ///  
        /// Gets the physical media width dimension (in 1/96 inch unit). Returns null if the dimension is not specified.
        /// 
        public Nullable Width
        { 
            get
            { 
                return _width; 
            }
        } 

        /// 
        /// Gets the physical media height dimension (in 1/96 inch unit). Returns null if the dimension is not specified.
        ///  
        public Nullable Height
        { 
            get 
            {
                return _height; 
            }
        }

        #endregion Public Properties 

        #region Public Methods 
 
        /// 
        /// Converts the page media size setting to human-readable string. 
        /// 
        /// String that shows the page media size setting.
        public override string ToString()
        { 
            return ((PageMediaSizeName != null) ? String.Format(CultureInfo.CurrentCulture, "{0}", PageMediaSizeName) : "Null") + " (" +
                   ((Width != null) ? String.Format(CultureInfo.CurrentCulture, "{0}", Width) : "Null") + 
                   " x " + 
                   ((Height != null) ? String.Format(CultureInfo.CurrentCulture, "{0}", Height) : "Null") +
                   ")"; 
        }
        #endregion Public Methods

        #region Private Properties 

        private Nullable _mediaSizeName; 
        private Nullable _width; 
        private Nullable _height;
 
        #endregion Private Properties
    }

    ///  
    /// Represents page resolution setting.
    ///  
    public sealed class PageResolution 
    {
        #region Constructors 

        /// 
        /// Constructs a new instance of  with the specified resolution values.
        ///  
        /// x component of the resolution (in DPI unit)
        /// y component of the resolution (in DPI unit) 
        public PageResolution(int resolutionX, int resolutionY) 
        {
            _x = resolutionX; 
            _y = resolutionY;
            _qualitative = null;
        }
 
        /// 
        /// Constructs a new instance of  with the specified resolution quality label. 
        ///  
        /// quality label of the resolution
        public PageResolution(PageQualitativeResolution qualitative) 
        {
            _x = null;
            _y = null;
            _qualitative = qualitative; 
        }
 
        ///  
        /// Constructs a new instance of  with the specified resolution values
        /// and quality label. 
        /// 
        /// x component of the resolution (in DPI unit)
        /// y component of the resolution (in DPI unit)
        /// quality label of the resolution 
        public PageResolution(int resolutionX, int resolutionY, PageQualitativeResolution qualitative)
        { 
            _x = resolutionX; 
            _y = resolutionY;
            _qualitative = qualitative; 
        }

        #endregion Constructors
 
        #region Public Properties
 
        ///  
        /// Gets the x component of the resolution (in DPI unit). Returns null if the x component is not specified.
        ///  
        public Nullable X
        {
            get
            { 
                return _x;
            } 
        } 

        ///  
        /// Gets the y component of the resolution (in DPI unit). Returns null if the y component is not specified.
        /// 
        public Nullable Y
        { 
            get
            { 
                return _y; 
            }
        } 

        /// 
        /// Gets the quality label of the resolution. Returns null if the quality label is not specified.
        ///  
        public Nullable QualitativeResolution
        { 
            get 
            {
                return _qualitative; 
            }
        }

        #endregion Public Properties 

        #region Public Methods 
 
        /// 
        /// Converts the page resolution setting to human-readable string. 
        /// 
        /// String that shows the page resolution setting.
        public override string ToString()
        { 
            return ((X != null) ? String.Format(CultureInfo.CurrentCulture, "{0}", X) : "Null") +
                   " x " + 
                   ((Y != null) ? String.Format(CultureInfo.CurrentCulture, "{0}", Y) : "Null") + 
                   " (QualitativeResolution: " +
                   ((QualitativeResolution != null) ? QualitativeResolution.ToString() : "Null") + 
                   ")";
        }

        #endregion Public Methods 

        #region Private Fields 
 
        private Nullable _x;
        private Nullable _y; 
        private Nullable _qualitative;

        #endregion private Fields
    } 

    ///  
    /// Represents print settings. 
    /// 
    public sealed class PrintTicket : System.ComponentModel.INotifyPropertyChanged 
    {
        #region Constructors

        ///  
        /// Constructs a new instance of  with no print settings.
        ///  
        public PrintTicket() 
        {
            _printTicket = new InternalPrintTicket(); 
            _setterCache = new Dictionary();
        }

        ///  
        /// Constructs a new instance of  with settings based on the XML form of PrintTicket.
        ///  
        ///  object containing the XML form of PrintTicket. 
        /// 
        /// The  parameter is null. 
        /// 
        /// 
        /// The  object specified by  parameter doesn't contain a
        /// well-formed XML PrintTicket. The exception object's  property describes 
        /// why the XML content is not well-formed PrintTicket. If not null, the exception object's
        ///  property provides more details. 
        ///  
        /// 
        /// This constructor doesn't reset the current position of the stream back to the original position 
        /// before the constructor is called. It's the caller's responsibility to reset the stream current position
        /// if needed.
        /// 
        public PrintTicket(Stream xmlStream) 
        {
            _printTicket = new InternalPrintTicket(xmlStream); 
            _setterCache = new Dictionary(); 
        }
 
        #endregion Constructors

        #region Public Methods
 
        /// 
        /// Creates a duplicate of the current  object. 
        ///  
        /// The duplicated  object.
        public PrintTicket Clone() 
        {
            PrintTicket clonePT = new PrintTicket(this.GetXmlStream());

            return clonePT; 
        }
 
        ///  
        /// Gets a  object that contains the XML form of current  object.
        ///  
        /// The  object that contains the XML form of current  object.
        public MemoryStream GetXmlStream()
        {
            ExecuteCachedSetters(); 

            return _printTicket.XmlStream; 
        } 

        ///  
        /// Saves the XML form of current  object to the specified stream.
        /// 
        /// The  object to which you want to save.
        ///  
        /// The  parameter is null.
        ///  
        ///  
        /// This function doesn't reset the current position of the stream back to the original position
        /// before the function is called. It's the caller's responsibility to reset the stream current position 
        /// if needed.
        /// 
        public void SaveTo(Stream outStream)
        { 
            ExecuteCachedSetters();
 
            _printTicket.SaveTo(outStream); 
        }
 
        #endregion Public Methods

        #region Public Properties
 
        /// 
        /// Gets or sets the document collate setting. 
        ///  
        /// 
        /// If the document collate setting is not specified, this property will return null. 
        /// If caller sets this property to null, document collate setting will become unspecified and
        /// document collate setting content in the XML form of current  object
        /// will be removed.
        ///  
        /// 
        /// The value to set is not one of the standard  values. 
        ///  
        public Nullable Collation
        { 
            get
            {
                Collation valueGot = GetEnumValueFromCacheOrXml(
                                         CapabilityName.DocumentCollate, 
                                         _printTicket.DocumentCollate.Value);
 
                // handle Unspecified => null conversion 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null; 
                else
                    return valueGot;
            }
            set 
            {
                if ((value != null) && 
                    (value < PrintSchema.CollationEnumMin || 
                     value > PrintSchema.CollationEnumMax))
                { 
                    throw new ArgumentOutOfRangeException("value");
                }

                AddSetterEnumValueToCache( 
                    CapabilityName.DocumentCollate,
                    (value == null) ? (Collation)PrintSchema.EnumUnspecifiedValue : (Collation)value); 
 
                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("Collation"); 
            }
        }

        ///  
        /// Gets or sets the job copy count setting.
        ///  
        ///  
        /// If the job copy count setting is not specified, this property will return null.
        /// If caller sets this property to null, job copy count setting will become unspecified and 
        /// job copy count setting content in the XML form of current  object
        /// will be removed.
        /// 
        ///  
        /// The value to set is not a positive value.
        ///  
        public Nullable CopyCount 
        {
            get 
            {
                int copyValue = _printTicket.JobCopyCount.Value;

                if (copyValue > 0) 
                    return copyValue;
                else 
                    return null; 
            }
            set 
            {
                if (value == null)
                {
                    _printTicket.JobCopyCount.ClearSetting(); 
                }
                else 
                { 
                    if (value <= 0)
                    { 
                        throw new ArgumentOutOfRangeException("value",
                                      PTUtility.GetTextFromResource("ArgumentException.PositiveValue"));
                    }
 
                    // no need to cache set calls
                    _printTicket.JobCopyCount.Value = (int)value; 
                } 

                // Raise PropertyChanged event for IPropertyChange implementation 
                NotifyPropertyChanged("CopyCount");
            }
        }
 
        /// 
        /// Gets or sets the device font substitution setting. 
        ///  
        /// 
        /// If the device font substitution setting is not specified, this property will return null. 
        /// If caller sets this property to null, device font substitution setting will become unspecified and
        /// device font substitution setting content in the XML form of current  object
        /// will be removed.
        ///  
        /// 
        /// The value to set is not one of the standard  values. 
        ///  
        public Nullable DeviceFontSubstitution
        { 
            get
            {
                DeviceFontSubstitution valueGot = GetEnumValueFromCacheOrXml(
                                                      CapabilityName.PageDeviceFontSubstitution, 
                                                      _printTicket.PageDeviceFontSubstitution.Value);
 
                // handle Unspecified => null conversion 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null; 
                else
                    return valueGot;
            }
            set 
            {
                if ((value != null) && 
                    (value < PrintSchema.DeviceFontSubstitutionEnumMin || 
                     value > PrintSchema.DeviceFontSubstitutionEnumMax))
                { 
                    throw new ArgumentOutOfRangeException("value");
                }

                AddSetterEnumValueToCache( 
                    CapabilityName.PageDeviceFontSubstitution,
                    (value == null) ? (DeviceFontSubstitution)PrintSchema.EnumUnspecifiedValue : (DeviceFontSubstitution)value); 
 
                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("DeviceFontSubstitution"); 
            }
        }

        ///  
        /// Gets or sets the job duplex setting.
        ///  
        ///  
        /// If the job duplex setting is not specified, this property will return null.
        /// If caller sets this property to null, job duplex setting will become unspecified and 
        /// job duplex setting content in the XML form of current  object
        /// will be removed.
        /// 
        ///  
        /// The value to set is not one of the standard  values.
        ///  
        public Nullable Duplexing 
        {
            get 
            {
                Duplexing valueGot = GetEnumValueFromCacheOrXml(
                                         CapabilityName.JobDuplex,
                                         _printTicket.JobDuplex.Value); 

                // handle Unspecified => null conversion 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue) 
                    return null;
                else 
                    return valueGot;
            }
            set
            { 
                if ((value != null) &&
                    (value < PrintSchema.DuplexingEnumMin || 
                     value > PrintSchema.DuplexingEnumMax)) 
                {
                    throw new ArgumentOutOfRangeException("value"); 
                }

                AddSetterEnumValueToCache(
                    CapabilityName.JobDuplex, 
                    (value == null) ? (Duplexing)PrintSchema.EnumUnspecifiedValue : (Duplexing)value);
 
                // Raise PropertyChanged event for IPropertyChange implementation 
                NotifyPropertyChanged("Duplexing");
            } 
        }

        /// 
        /// Gets or sets the input bin setting. 
        /// 
        ///  
        /// Print Schema defines three input bin settings: JobInputBin, DocumentInputBin and PageInputBin. 
        ///
        /// If none of the JobInputBin, DocumentInputBin or PageInputBin setting is specified in the XML form of current 
        ///  object, then this property will return null. Otherwise, this property will return
        /// the input bin setting for JobInputBin if JobInputBin is specified, or for DocumentInputBin if DocumentInputBin
        /// is specified, or for PageInputBin.
        /// 
        /// If caller sets this property to null, input bin setting will become unspecified and any JobInputBin, DocumentInputBin,
        /// or PageInputBin setting content in the XML form of current  object will be removed. 
        /// 
        /// If caller sets this property to a standard  value, then in the XML form of current
        ///  object, JobInputBin setting will be set to the specified value, and any DocumentInputBin or 
        /// PageInputBin setting content will be removed.
        /// 
        /// 
        /// The value to set is not one of the standard  values. 
        /// 
        public Nullable InputBin 
        { 
            get
            { 
                // get the JobInputBin setting
                InputBin valueGot = GetEnumValueFromCacheOrXml(
                                        CapabilityName.JobInputBin,
                                        _printTicket.JobInputBin.Value); 

                // if no JobInputBin setting, then get the DocumentInputBin setting 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue) 
                {
                    valueGot = GetEnumValueFromCacheOrXml( 
                                   CapabilityName.DocumentInputBin,
                                   _printTicket.DocumentInputBin.Value);
                }
 
                // if neither JobInputBin nor DocumentInputBin setting exists, then get the PageInputBin setting
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue) 
                { 
                    valueGot = GetEnumValueFromCacheOrXml(
                                   CapabilityName.PageInputBin, 
                                   _printTicket.PageInputBin.Value);
                }

                // handle Unspecified => null conversion 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null; 
                else 
                    return valueGot;
            } 
            set
            {
                if ((value != null) &&
                    (value < PrintSchema.InputBinEnumMin || 
                    value > PrintSchema.InputBinEnumMax))
                { 
                    throw new ArgumentOutOfRangeException("value"); 
                }
 
                // always set the job-scope input bin setting to increase portability
                AddSetterEnumValueToCache(
                    CapabilityName.JobInputBin,
                    (value == null) ? (InputBin)PrintSchema.EnumUnspecifiedValue : (InputBin)value); 

                // need to remove document-scope and page-scope input bin setting so only job-scope 
                // input bin setting will be persisted 
                AddSetterEnumValueToCache(
                    CapabilityName.DocumentInputBin, (InputBin)PrintSchema.EnumUnspecifiedValue); 
                AddSetterEnumValueToCache(
                    CapabilityName.PageInputBin, (InputBin)PrintSchema.EnumUnspecifiedValue);

                // Raise PropertyChanged event for IPropertyChange implementation 
                NotifyPropertyChanged("InputBin");
            } 
        } 

        ///  
        /// Gets or sets the page output color setting.
        /// 
        /// 
        /// If the page output color setting is not specified, this property will return null. 
        /// If caller sets this property to null, page output color setting will become unspecified and
        /// page output color setting content in the XML form of current  object 
        /// will be removed. 
        /// 
        ///  
        /// The value to set is not one of the standard  values.
        /// 
        public Nullable OutputColor
        { 
            get
            { 
                OutputColor valueGot = GetEnumValueFromCacheOrXml( 
                                           CapabilityName.PageOutputColor,
                                           _printTicket.PageOutputColor.Value); 

                // handle Unspecified => null conversion
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null; 
                else
                    return valueGot; 
            } 
            set
            { 
                if ((value != null) &&
                    (value < PrintSchema.OutputColorEnumMin ||
                     value > PrintSchema.OutputColorEnumMax))
                { 
                    throw new ArgumentOutOfRangeException("value");
                } 
 
                AddSetterEnumValueToCache(
                    CapabilityName.PageOutputColor, 
                    (value == null) ? (OutputColor)PrintSchema.EnumUnspecifiedValue : (OutputColor)value);

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("OutputColor"); 
            }
        } 
 
        /// 
        /// Gets or sets the page output quality setting. 
        /// 
        /// 
        /// If the page output quality setting is not specified, this property will return null.
        /// If caller sets this property to null, page output quality setting will become unspecified and 
        /// page output quality setting content in the XML form of current  object
        /// will be removed. 
        ///  
        /// 
        /// The value to set is not one of the standard  values. 
        /// 
        public Nullable OutputQuality
        {
            get 
            {
                OutputQuality valueGot = GetEnumValueFromCacheOrXml( 
                                             CapabilityName.PageOutputQuality, 
                                             _printTicket.PageOutputQuality.Value);
 
                // handle Unspecified => null conversion
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null;
                else 
                    return valueGot;
            } 
            set 
            {
                if ((value != null) && 
                    (value < PrintSchema.OutputQualityEnumMin ||
                     value > PrintSchema.OutputQualityEnumMax))
                {
                    throw new ArgumentOutOfRangeException("value"); 
                }
 
                AddSetterEnumValueToCache( 
                    CapabilityName.PageOutputQuality,
                    (value == null) ? (OutputQuality)PrintSchema.EnumUnspecifiedValue : (OutputQuality)value); 

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("OutputQuality");
            } 
        }
 
        ///  
        /// Gets or sets the page borderless setting.
        ///  
        /// 
        /// If the page borderless setting is not specified, this property will return null.
        /// If caller sets this property to null, page borderless setting will become unspecified and
        /// page borderless setting content in the XML form of current  object 
        /// will be removed.
        ///  
        ///  
        /// The value to set is not one of the standard  values.
        ///  
        public Nullable PageBorderless
        {
            get
            { 
                PageBorderless valueGot = GetEnumValueFromCacheOrXml(
                                              CapabilityName.PageBorderless, 
                                              _printTicket.PageBorderless.Value); 

                // handle Unspecified => null conversion 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null;
                else
                    return valueGot; 
            }
            set 
            { 
                if ((value != null) &&
                    (value < PrintSchema.PageBorderlessEnumMin || 
                     value > PrintSchema.PageBorderlessEnumMax))
                {
                    throw new ArgumentOutOfRangeException("value");
                } 

                AddSetterEnumValueToCache( 
                    CapabilityName.PageBorderless, 
                    (value == null) ? (PageBorderless)PrintSchema.EnumUnspecifiedValue : (PageBorderless)value);
 
                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PageBorderless");
            }
        } 

        ///  
        /// Gets or sets the page media size setting. 
        /// 
        ///  
        /// If the page media size setting is not specified, this property will return null.
        /// If caller sets this property to null, page media size setting will become unspecified and
        /// page media size setting content in the XML form of current  object
        /// will be removed. 
        /// 
        ///  
        /// Set call doesn't set either  property or the pair 
        /// of  and  properties.
        ///  
        /// 
        /// The value to set  property is not one of the
        /// standard  values.
        ///  
        /// 
        /// The value to set  property or  
        /// property is not a positive value. 
        /// 
        public PageMediaSize PageMediaSize 
        {
            get
            {
                // return the most recent cached set operation if it exists 
                if ((_setterCache != null) &&
                    _setterCache.ContainsKey(CapabilityName.PageMediaSize)) 
                { 
                    object cacheObj;
 
                    _setterCache.TryGetValue(CapabilityName.PageMediaSize, out cacheObj);

                    return (PageMediaSize)cacheObj;
                } 

                // if we fail to get the cached set operation, then we return based on XML content 
                if ((_printTicket.PageMediaSize.MediaSizeWidth > 0) && 
                    (_printTicket.PageMediaSize.MediaSizeHeight > 0))
                { 
                    if ((int)_printTicket.PageMediaSize.Value != PrintSchema.EnumUnspecifiedValue)
                    {
                        // There are valid media size name and width/height values
                        return new PageMediaSize(_printTicket.PageMediaSize.Value, 
                                                 _printTicket.PageMediaSize.MediaSizeWidth,
                                                 _printTicket.PageMediaSize.MediaSizeHeight); 
                    } 
                    else
                    { 
                        // There are only valid width/height values
                        return new PageMediaSize(_printTicket.PageMediaSize.MediaSizeWidth,
                                                 _printTicket.PageMediaSize.MediaSizeHeight);
                    } 
                }
                else if ((int)_printTicket.PageMediaSize.Value != PrintSchema.EnumUnspecifiedValue) 
                { 
                    // No valid width/height values but we do have valid meida size name value
                    return new PageMediaSize(_printTicket.PageMediaSize.Value); 
                }
                else
                {
                    return null; 
                }
            } 
            set 
            {
                // first performing input parameter validation 
                if (value != null)
                {
                    // either media name or the width/height values need to be specified
                    if ((value.PageMediaSizeName == null) && 
                        (value.Width == null || value.Height == null))
                    { 
                        throw new ArgumentOutOfRangeException("value"); 
                    }
 
                    // if size name is specified, it needs to be valid name
                    if ((value.PageMediaSizeName != null) &&
                        (value.PageMediaSizeName < PrintSchema.PageMediaSizeNameEnumMin ||
                         value.PageMediaSizeName > PrintSchema.PageMediaSizeNameEnumMax)) 
                    {
                        throw new ArgumentOutOfRangeException("value.PageMediaSizeName"); 
                    } 

                    // if width or height value is specified, it needs to be positive 
                    if ((value.Width != null) && (value.Width <= 0))
                    {
                        throw new ArgumentOutOfRangeException("value.Width",
                                  PTUtility.GetTextFromResource("ArgumentException.PositiveValue")); 
                    }
 
                    if ((value.Height != null) && (value.Height <= 0)) 
                    {
                        throw new ArgumentOutOfRangeException("value.Height", 
                                  PTUtility.GetTextFromResource("ArgumentException.PositiveValue"));
                    }
                }
 
                // then adding the set operation to the cache (replacing older set operations)
                if (_setterCache.ContainsKey(CapabilityName.PageMediaSize)) 
                { 
                    _setterCache.Remove(CapabilityName.PageMediaSize);
                } 

                _setterCache.Add(CapabilityName.PageMediaSize, value);

                // Raise PropertyChanged event for IPropertyChange implementation 
                NotifyPropertyChanged("PageMediaSize");
            } 
        } 

        ///  
        /// Gets or sets the page media type setting.
        /// 
        /// 
        /// If the page media type setting is not specified, this property will return null. 
        /// If caller sets this property to null, page media type setting will become unspecified and
        /// page media type setting content in the XML form of current  object 
        /// will be removed. 
        /// 
        ///  
        /// The value to set is not one of the standard  values.
        /// 
        public Nullable PageMediaType
        { 
            get
            { 
                PageMediaType valueGot = GetEnumValueFromCacheOrXml( 
                                             CapabilityName.PageMediaType,
                                             _printTicket.PageMediaType.Value); 

                // handle Unspecified => null conversion
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null; 
                else
                    return valueGot; 
            } 
            set
            { 
                if ((value != null) &&
                    (value < PrintSchema.PageMediaTypeEnumMin ||
                     value > PrintSchema.PageMediaTypeEnumMax))
                { 
                    throw new ArgumentOutOfRangeException("value");
                } 
 
                AddSetterEnumValueToCache(
                    CapabilityName.PageMediaType, 
                    (value == null) ? (PageMediaType)PrintSchema.EnumUnspecifiedValue : (PageMediaType)value);

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PageMediaType"); 
            }
        } 
 
        /// 
        /// Gets or sets the job page order setting. 
        /// 
        /// 
        /// If the job page order setting is not specified, this property will return null.
        /// If caller sets this property to null, job page order setting will become unspecified and 
        /// job page order setting content in the XML form of current  object
        /// will be removed. 
        ///  
        /// 
        /// The value to set is not one of the standard  values. 
        /// 
        public Nullable PageOrder
        {
            get 
            {
                PageOrder valueGot = GetEnumValueFromCacheOrXml( 
                                         CapabilityName.JobPageOrder, 
                                         _printTicket.JobPageOrder.Value);
 
                // handle Unspecified => null conversion
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null;
                else 
                    return valueGot;
            } 
            set 
            {
                if ((value != null) && 
                    (value < PrintSchema.PageOrderEnumMin ||
                     value > PrintSchema.PageOrderEnumMax))
                {
                    throw new ArgumentOutOfRangeException("value"); 
                }
 
                AddSetterEnumValueToCache( 
                    CapabilityName.JobPageOrder,
                    (value == null) ? (PageOrder)PrintSchema.EnumUnspecifiedValue : (PageOrder)value); 

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PageOrder");
            } 
        }
 
        ///  
        /// Gets or sets the page orientation setting.
        ///  
        /// 
        /// If the page orientation setting is not specified, this property will return null.
        /// If caller sets this property to null, page orientation setting will become unspecified and
        /// page orientation setting content in the XML form of current  object 
        /// will be removed.
        ///  
        ///  
        /// The value to set is not one of the standard  values.
        ///  
        public Nullable PageOrientation
        {
            get
            { 
                PageOrientation valueGot = GetEnumValueFromCacheOrXml(
                                               CapabilityName.PageOrientation, 
                                               _printTicket.PageOrientation.Value); 

                // handle Unspecified => null conversion 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null;
                else
                    return valueGot; 
            }
            set 
            { 
                if ((value != null) &&
                    (value < PrintSchema.PageOrientationEnumMin || 
                     value > PrintSchema.PageOrientationEnumMax))
                {
                    throw new ArgumentOutOfRangeException("value");
                } 

                AddSetterEnumValueToCache( 
                    CapabilityName.PageOrientation, 
                    (value == null) ? (PageOrientation)PrintSchema.EnumUnspecifiedValue : (PageOrientation)value);
 
                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PageOrientation");
            }
        } 

        ///  
        /// Gets or sets the page resolution setting. 
        /// 
        ///  
        /// If the page resolution setting is not specified, this property will return null.
        /// If caller sets this property to null, page resolution setting will become unspecified and
        /// page resolution setting content in the XML form of current  object
        /// will be removed. 
        /// 
        ///  
        /// Set call doesn't set either  property or the pair 
        /// of  and  properties.
        ///  
        /// 
        /// The value to set  property is not one of the
        /// standard  values.
        ///  
        /// 
        /// The value to set  property or  
        /// property is not a positive value. 
        /// 
        public PageResolution PageResolution 
        {
            get
            {
                // return the most recent cached set operation if it exists 
                if ((_setterCache != null) &&
                    _setterCache.ContainsKey(CapabilityName.PageResolution)) 
                { 
                    object cacheObj;
 
                    _setterCache.TryGetValue(CapabilityName.PageResolution, out cacheObj);

                    return (PageResolution)cacheObj;
                } 

                // if we fail to get the cached set operation, then we return based on XML content 
                if ((_printTicket.PageResolution.ResolutionX > 0) && 
                    (_printTicket.PageResolution.ResolutionY > 0))
                { 
                    if ((int)_printTicket.PageResolution.QualitativeResolution != PrintSchema.EnumUnspecifiedValue)
                    {
                        // There are valid x/y and quality label values.
                        return new PageResolution(_printTicket.PageResolution.ResolutionX, 
                                                  _printTicket.PageResolution.ResolutionY,
                                                  _printTicket.PageResolution.QualitativeResolution); 
                    } 
                    else
                    { 
                        // There are only valid x/y values.
                        return new PageResolution(_printTicket.PageResolution.ResolutionX,
                                                  _printTicket.PageResolution.ResolutionY);
                    } 
                }
                else if ((int)_printTicket.PageResolution.QualitativeResolution != PrintSchema.EnumUnspecifiedValue) 
                { 
                    // No valid x/y values but we do have valid quality label value.
                    return new PageResolution(_printTicket.PageResolution.QualitativeResolution); 
                }
                else
                {
                    return null; 
                }
            } 
            set 
            {
                // first performing input parameter validation 
                if (value != null)
                {
                    if ((value.QualitativeResolution == null) &&
                        (value.X == null || value.Y == null)) 
                    {
                        throw new ArgumentOutOfRangeException("value"); 
                    } 

                    // If quality lable is specified, it needs to be valid value 
                    if ((value.QualitativeResolution != null) &&
                        (value.QualitativeResolution < PrintSchema.PageQualitativeResolutionEnumMin ||
                         value.QualitativeResolution > PrintSchema.PageQualitativeResolutionEnumMax))
                    { 
                        throw new ArgumentOutOfRangeException("value.QualitativeResolution");
                    } 
 
                    // If specified, resolution X and Y values must be positive
                    if ((value.X != null) && (value.X <= 0)) 
                    {
                        throw new ArgumentOutOfRangeException("value.X",
                                      PTUtility.GetTextFromResource("ArgumentException.PositiveValue"));
                    } 

                    if ((value.Y != null) && (value.Y <= 0)) 
                    { 
                        throw new ArgumentOutOfRangeException("value.Y",
                                      PTUtility.GetTextFromResource("ArgumentException.PositiveValue")); 
                    }
                }

                // then adding the set operation to the cache (replacing older set operations) 
                if (_setterCache.ContainsKey(CapabilityName.PageResolution))
                { 
                    _setterCache.Remove(CapabilityName.PageResolution); 
                }
 
                _setterCache.Add(CapabilityName.PageResolution, value);

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PageResolution"); 
            }
        } 
 
        /// 
        /// Gets or sets the page scaling factor (in percentage unit) setting. 
        /// 
        /// 
        /// If the page scaling factor setting is not specified, this property will return null.
        /// If caller sets this property to null, page scaling factor setting will become unspecified and 
        /// page scaling factor setting content in the XML form of current  object
        /// will be removed. 
        ///  
        /// 
        /// The value to set is not a positive value. 
        /// 
        public Nullable PageScalingFactor
        {
            get 
            {
                if ((_printTicket.PageScaling.Value == PageScaling.CustomSquare) && 
                    (_printTicket.PageScaling.CustomSquareScale > 0)) 
                {
                    return _printTicket.PageScaling.CustomSquareScale; 
                }
                else if ((_printTicket.PageScaling.Value == PageScaling.Custom) &&
                         (_printTicket.PageScaling.CustomScaleWidth > 0))
                { 
                    return _printTicket.PageScaling.CustomScaleWidth;
                } 
                else 
                    return null;
            } 
            set
            {
                if (value == null)
                { 
                    _printTicket.PageScaling.ClearSetting();
                } 
                else 
                {
                    if (value <= 0) 
                    {
                        throw new ArgumentOutOfRangeException("value",
                                      PTUtility.GetTextFromResource("ArgumentException.PositiveValue"));
                    } 

                    // no need to cache set calls 
                    _printTicket.PageScaling.SetCustomSquareScaling((int)value); 
                }
 
                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PageScalingFactor");
            }
        } 

        ///  
        /// Gets or sets the job pages-per-sheet setting. 
        /// 
        ///  
        /// If the job pages-per-sheet setting is not specified, this property will return null.
        /// If caller sets this property to null, job pages-per-sheet setting will become unspecified and
        /// job pages-per-sheet setting content in the XML form of current  object
        /// will be removed. 
        /// (Pages-per-sheet is to output multiple logical pages to a single physical sheet.)
        ///  
        ///  
        /// The value to set is not a positive value.
        ///  
        public Nullable PagesPerSheet
        {
            get
            { 
                int nupValue = _printTicket.JobNUp.PagesPerSheet;
 
                if (nupValue > 0) 
                    return nupValue;
                else 
                    return null;
            }
            set
            { 
                if (value == null)
                { 
                    _printTicket.JobNUp.ClearSetting(); 
                }
                else 
                {
                    if (value <= 0)
                    {
                        throw new ArgumentOutOfRangeException("value", 
                                      PTUtility.GetTextFromResource("ArgumentException.PositiveValue"));
                    } 
 
                    // no need to cache set calls
                    _printTicket.JobNUp.PagesPerSheet = (int)value; 
                }

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PagesPerSheet"); 
            }
        } 
 
        /// 
        /// Gets or sets the job pages-per-sheet direction setting. 
        /// 
        /// 
        /// If the job pages-per-sheet direction setting is not specified, this property will return null.
        /// If caller sets this property to null, job pages-per-sheet direction setting will become unspecified and 
        /// job pages-per-sheet direction setting content in the XML form of current  object
        /// will be removed. 
        /// (Pages-per-sheet is to output multiple logical pages to a single physical sheet.) 
        /// 
        ///  
        /// The value to set is not one of the standard  values.
        /// 
        public Nullable PagesPerSheetDirection
        { 
            get
            { 
                PagesPerSheetDirection valueGot = GetEnumValueFromCacheOrXml( 
                                         CapabilityName.JobNUp,
                                         _printTicket.JobNUp.PresentationDirection.Value); 

                // handle Unspecified => null conversion
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null; 
                else
                    return valueGot; 
            } 
            set
            { 
                if ((value != null) &&
                    (value < PrintSchema.PagesPerSheetDirectionEnumMin ||
                     value > PrintSchema.PagesPerSheetDirectionEnumMax))
                { 
                    throw new ArgumentOutOfRangeException("value");
                } 
 
                AddSetterEnumValueToCache(
                    CapabilityName.JobNUp, 
                    (value == null) ? (PagesPerSheetDirection)PrintSchema.EnumUnspecifiedValue : (PagesPerSheetDirection)value);

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PagesPerSheetDirection"); 
            }
        } 
 
        /// 
        /// Gets or sets the page photo printing intent setting. 
        /// 
        /// 
        /// If the page photo printing intent setting is not specified, this property will return null.
        /// If caller sets this property to null, page photo printing intent setting will become unspecified and 
        /// page photo printing intent setting content in the XML form of current  object
        /// will be removed. 
        ///  
        /// 
        /// The value to set is not one of the standard  values. 
        /// 
        public Nullable PhotoPrintingIntent
        {
            get 
            {
                PhotoPrintingIntent valueGot = GetEnumValueFromCacheOrXml( 
                                                   CapabilityName.PagePhotoPrintingIntent, 
                                                   _printTicket.PagePhotoPrintingIntent.Value);
 
                // handle Unspecified => null conversion
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null;
                else 
                    return valueGot;
            } 
            set 
            {
                if ((value != null) && 
                    (value < PrintSchema.PhotoPrintingIntentEnumMin ||
                     value > PrintSchema.PhotoPrintingIntentEnumMax))
                {
                    throw new ArgumentOutOfRangeException("value"); 
                }
 
                AddSetterEnumValueToCache( 
                    CapabilityName.PagePhotoPrintingIntent,
                    (value == null) ? (PhotoPrintingIntent)PrintSchema.EnumUnspecifiedValue : (PhotoPrintingIntent)value); 

                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("PhotoPrintingIntent");
            } 
        }
 
        ///  
        /// Gets or sets the job output stapling setting.
        ///  
        /// 
        /// If the job output stapling setting is not specified, this property will return null.
        /// If caller sets this property to null, job output stapling setting will become unspecified and
        /// job output stapling setting content in the XML form of current  object 
        /// will be removed.
        ///  
        ///  
        /// The value to set is not one of the standard  values.
        ///  
        public Nullable Stapling
        {
            get
            { 
                Stapling valueGot = GetEnumValueFromCacheOrXml(
                                         CapabilityName.JobStaple, 
                                         _printTicket.JobStaple.Value); 

                // handle Unspecified => null conversion 
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue)
                    return null;
                else
                    return valueGot; 
            }
            set 
            { 
                if ((value != null) &&
                    (value < PrintSchema.StaplingEnumMin || 
                     value > PrintSchema.StaplingEnumMax))
                {
                    throw new ArgumentOutOfRangeException("value");
                } 

                AddSetterEnumValueToCache( 
                    CapabilityName.JobStaple, 
                    (value == null) ? (Stapling)PrintSchema.EnumUnspecifiedValue : (Stapling)value);
 
                // Raise PropertyChanged event for IPropertyChange implementation
                NotifyPropertyChanged("Stapling");
            }
        } 

        ///  
        /// Gets or sets the TrueType font handling mode setting. 
        /// 
        ///  
        /// If the TrueType font handling mode setting is not specified, this property will return null.
        /// If caller sets this property to null, TrueType font handling mode setting will become unspecified and
        /// TrueType font handling mode setting content in the XML form of current  object
        /// will be removed. 
        /// 
        ///  
        /// The value to set is not one of the standard  values. 
        /// 
        public Nullable TrueTypeFontMode 
        {
            get
            {
                TrueTypeFontMode valueGot = GetEnumValueFromCacheOrXml( 
                                                CapabilityName.PageTrueTypeFontMode,
                                                _printTicket.PageTrueTypeFontMode.Value); 
 
                // handle Unspecified => null conversion
                if ((int)valueGot == PrintSchema.EnumUnspecifiedValue) 
                    return null;
                else
                    return valueGot;
            } 
            set
            { 
                if ((value != null) && 
                    (value < PrintSchema.TrueTypeFontModeEnumMin ||
                     value > PrintSchema.TrueTypeFontModeEnumMax)) 
                {
                    throw new ArgumentOutOfRangeException("value");
                }
 
                AddSetterEnumValueToCache(
                    CapabilityName.PageTrueTypeFontMode, 
                    (value == null) ? (TrueTypeFontMode)PrintSchema.EnumUnspecifiedValue : (TrueTypeFontMode)value); 

                // Raise PropertyChanged event for IPropertyChange implementation 
                NotifyPropertyChanged("TrueTypeFontMode");
            }
        }
 
        #endregion Public Properties
 
        #region IPropertyChange implementation 

        ///  
        ///
        /// 
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
 
        /// 
        /// This method is called for any public property as it is getting changed 
        /// to notify anyone registered for property change notifications that the 
        /// property has changed.
        ///  
        /// The name of the property that changed.
        private void NotifyPropertyChanged(string name)
        {
            if (null != PropertyChanged) 
            {
                PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(name)); 
            } 

            _isSettingChanged = true; 
        }

        #endregion IPropertyChange implementation
 
        #region Internal Properties
 
        ///  
        /// Gets a boolean to indicate whether or not public setting in the PrinTicket has been changed by the client.
        ///  
        [MS.Internal.ReachFramework.FriendAccessAllowed]
        internal bool IsSettingChanged
        {
            get 
            {
                return _isSettingChanged; 
            } 
        }
 
        #endregion Internal Properties

        #region Private Methods
 
        private EnumType GetEnumValueFromCacheOrXml(CapabilityName feature,
                                                              EnumType xmlValue) 
        { 
            EnumType valueGot;
 
            if ((_setterCache != null) &&
                _setterCache.ContainsKey(feature))
            {
                object cacheObj; 

                _setterCache.TryGetValue(feature, out cacheObj); 
 
                valueGot = (EnumType)cacheObj;
            } 
            else
            {
                valueGot = xmlValue;
            } 

            return valueGot; 
        } 

        private void AddSetterEnumValueToCache(CapabilityName feature, 
                                                         EnumType value)
        {
            // Newer value replaces old value in the cache.
            if (_setterCache.ContainsKey(feature)) 
            {
                _setterCache.Remove(feature); 
            } 

            _setterCache.Add(feature, value); 
        }

        private void ExecuteMediaSizeSetter(object cacheValue)
        { 
            if (cacheValue == null)
            { 
                _printTicket.PageMediaSize.ClearSetting(); 
            }
            else 
            {
                PageMediaSize mediaSize = (PageMediaSize)cacheValue;

                if (mediaSize.PageMediaSizeName != null) 
                {
                    // If we have non-null media name, the property setter validation code should have verified 
                    // it's not the special Unspecified value of 0. 
                    if ((int)mediaSize.PageMediaSizeName != PrintSchema.EnumUnknownValue)
                    { 
                        if ((mediaSize.Width != null) && (mediaSize.Height != null))
                        {
                            _printTicket.PageMediaSize.SetFixedMediaSize((PageMediaSizeName)mediaSize.PageMediaSizeName,
                                                                         (double)mediaSize.Width, (double)mediaSize.Height); 
                        }
                        else 
                        { 
                            _printTicket.PageMediaSize.SetFixedMediaSize((PageMediaSizeName)mediaSize.PageMediaSizeName);
                        } 
                    }
                    else
                    {
                        if ((mediaSize.Width != null) && (mediaSize.Height != null)) 
                        {
                            _printTicket.PageMediaSize.SetFixedMediaSize((double)mediaSize.Width, (double)mediaSize.Height); 
                        } 
                        else
                        { 
                            // no-op
                        }
                    }
                } 
                else
                { 
                    // If we have no valid media name, the property setter validation code should have already 
                    // guaranteed any cached set operation will have valid width/height values.
                    _printTicket.PageMediaSize.SetFixedMediaSize((double)mediaSize.Width, (double)mediaSize.Height); 
                }
            }
        }
 
        private void ExecuteResolutionSetter(object cacheValue)
        { 
            if (cacheValue == null) 
            {
                _printTicket.PageResolution.ClearSetting(); 
            }
            else
            {
                PageResolution resoluton = (PageResolution)cacheValue; 

                if ((resoluton.X != null) || (resoluton.Y != null) || 
                    ((resoluton.QualitativeResolution != null) && 
                     ((int)resoluton.QualitativeResolution != PrintSchema.EnumUnknownValue)))
                { 
                    // If any of the 3 properties are set by client, we need to do a ClearSetting before setting
                    // the correponding scored properties, since PageResolution scored property setters only affect
                    // their own XML fragment.
                    _printTicket.PageResolution.ClearSetting(); 
                }
 
                if (resoluton.X != null) 
                    _printTicket.PageResolution.ResolutionX = (int)resoluton.X;
 
                if (resoluton.Y != null)
                    _printTicket.PageResolution.ResolutionY = (int)resoluton.Y;

                if ((resoluton.QualitativeResolution != null) && 
                    ((int)resoluton.QualitativeResolution != PrintSchema.EnumUnknownValue))
                { 
                    // If we have non-null quality label, the property setter validation code should have verified 
                    // it's not the special Unspecified value of 0.
                    _printTicket.PageResolution.QualitativeResolution = 
                        (PageQualitativeResolution)resoluton.QualitativeResolution;
                }
            }
        } 

        private void ExecuteGeneralEnumSetters(CapabilityName feature, object cacheValue) 
        { 
            if ((int)cacheValue == PrintSchema.EnumUnspecifiedValue)
            { 
                _printTicket.GetBasePTFeatureObject(feature).ClearSetting();
            }
            else if ((int)cacheValue != PrintSchema.EnumUnknownValue)
            { 
                // If the value to set is EnumUnknownValue, then we treat the set call as no-op.
                switch (feature) 
                { 
                    case CapabilityName.DocumentCollate:
                        _printTicket.DocumentCollate.Value = (Collation)cacheValue; 
                        break;

                    case CapabilityName.PageDeviceFontSubstitution:
                        _printTicket.PageDeviceFontSubstitution.Value = 
                            (DeviceFontSubstitution)cacheValue;
                        break; 
 
                    case CapabilityName.JobDuplex:
                        _printTicket.JobDuplex.Value = (Duplexing)cacheValue; 
                        break;

                    case CapabilityName.JobInputBin:
                        _printTicket.JobInputBin.Value = (InputBin)cacheValue; 
                        break;
 
                    case CapabilityName.PageOutputColor: 
                        _printTicket.PageOutputColor.Value = (OutputColor)cacheValue;
                        break; 

                    case CapabilityName.PageOutputQuality:
                        _printTicket.PageOutputQuality.Value = (OutputQuality)cacheValue;
                        break; 

                    case CapabilityName.PageBorderless: 
                        _printTicket.PageBorderless.Value = (PageBorderless)cacheValue; 
                        break;
 
                    case CapabilityName.PageMediaType:
                        _printTicket.PageMediaType.Value = (PageMediaType)cacheValue;
                        break;
 
                    case CapabilityName.JobPageOrder:
                        _printTicket.JobPageOrder.Value = (PageOrder)cacheValue; 
                        break; 

                    case CapabilityName.PageOrientation: 
                        _printTicket.PageOrientation.Value = (PageOrientation)cacheValue;
                        break;

                    case CapabilityName.JobNUp: 
                        _printTicket.JobNUp.PresentationDirection.Value =
                            (PagesPerSheetDirection)cacheValue; 
                        break; 

                    case CapabilityName.PagePhotoPrintingIntent: 
                        _printTicket.PagePhotoPrintingIntent.Value = (PhotoPrintingIntent)cacheValue;
                        break;

                    case CapabilityName.JobStaple: 
                        _printTicket.JobStaple.Value = (Stapling)cacheValue;
                        break; 
 
                    case CapabilityName.PageTrueTypeFontMode:
                        _printTicket.PageTrueTypeFontMode.Value = (TrueTypeFontMode)cacheValue; 
                        break;

                    default:
                        break; 
                }
            } 
        } 

        private void ExecuteCachedSetters() 
        {
            object cacheValue;

            // Console.WriteLine("\n --- Executing Setters ---\n"); 
            foreach (CapabilityName feature in _setterCache.Keys)
            { 
                _setterCache.TryGetValue(feature, out cacheValue); 

                // Console.WriteLine("{0} - {1}", feature, cacheValue); 

                if (feature == CapabilityName.PageMediaSize)
                {
                    ExecuteMediaSizeSetter(cacheValue); 
                }
                else if (feature == CapabilityName.PageResolution) 
                { 
                    ExecuteResolutionSetter(cacheValue);
                } 
                else
                {
                    ExecuteGeneralEnumSetters(feature, cacheValue);
                } 
            }
 
            _setterCache.Clear(); 
        }
 
        #endregion Private Methods

        #region Private Fields
 
        // simple PT/PC API is based on internal object-hierarchy based PT/PC classes
        private InternalPrintTicket _printTicket; 
 
        // bool to indicate whether or not any public setting in the PrinTicket has been changed by the client
        private bool _isSettingChanged; 

        // dictionary to cache PrintTicket setter calls. The cache is needed to defer changing the content of the
        // underlying PrintTicket XML until client requests serialization of the XML content.
        private Dictionary _setterCache; 

        #endregion Private Fields 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK