Skip to main content

winprint_ext/ticket/
feature_option_pack.rs

1use xml::name::OwnedName;
2
3use super::{
4    document::{
5        ParameterInit, PrintFeature, PrintFeatureOption, PrintTicketDocument, WithProperties,
6        NS_PSK,
7    },
8    PrintCapabilities, PrintTicket,
9};
10
11/// A trait for the predefined name.
12pub trait PredefinedName: Sized {
13    /// Get the predefined name from the given name.
14    /// If the name is not predefined, `None` is returned.
15    fn from_name(name: &OwnedName) -> Option<Self>;
16}
17
18/// A trait for the feature option pack.
19pub trait FeatureOptionPack: Sized {
20    /// Create a new instance.
21    fn new(option: PrintFeatureOption, parameters: Vec<ParameterInit>) -> Self;
22
23    /// Get the feature name of the option.
24    fn feature_name() -> OwnedName;
25
26    /// Get the DOM of the option.
27    fn option(&self) -> &PrintFeatureOption;
28    /// Get the mutable reference to the DOM of the option.
29    fn option_mut(&mut self) -> &mut PrintFeatureOption;
30
31    /// Get the parameters that is used by the option.
32    fn parameters(&self) -> &[ParameterInit];
33    /// Get the mutable reference to the parameters that is used by the option.
34    fn parameters_mut(&mut self) -> &mut Vec<ParameterInit>;
35
36    /// Convert the feature option pack into the option and the parameters.
37    fn into_option_with_parameters(self) -> (PrintFeatureOption, Vec<ParameterInit>);
38
39    /// Get display name of the page orientation.
40    fn display_name(&self) -> Option<&str> {
41        self.option()
42            .get_property("DisplayName", Some(NS_PSK))
43            .and_then(|x| x.value.as_ref())
44            .and_then(|x| x.string())
45    }
46
47    /// List all possible options defined in the capabilities.
48    fn list(capabilities: &PrintCapabilities) -> impl Iterator<Item = Self> + '_ {
49        capabilities
50            .options_for_feature(Self::feature_name())
51            .map(move |option| {
52                let default_parameters = capabilities
53                    .default_parameters_for(option.parameters_dependent().as_slice())
54                    .collect();
55                Self::new(option.clone(), default_parameters)
56            })
57    }
58}
59
60impl<T> From<T> for PrintTicket
61where
62    T: FeatureOptionPack,
63{
64    fn from(value: T) -> Self {
65        let (option, parameters) = value.into_option_with_parameters();
66        PrintTicketDocument {
67            properties: vec![],
68            parameter_inits: parameters,
69            features: vec![PrintFeature {
70                name: T::feature_name(),
71                properties: vec![],
72                options: vec![option],
73                features: vec![],
74            }],
75        }
76        .into()
77    }
78}
79
80/// A trait for the feature option pack with predefined name.
81pub trait FeatureOptionPackWithPredefined: FeatureOptionPack {
82    /// The type which represents the predefined name.
83    type PredefinedName: PredefinedName;
84
85    /// Get the predefined name of the option.
86    /// If the option is not predefined, `None` is returned.
87    fn as_predefined_name(&self) -> Option<Self::PredefinedName> {
88        self.option()
89            .name
90            .as_ref()
91            .and_then(Self::PredefinedName::from_name)
92    }
93}
94
95/// Implement the [`FeatureOptionPack`] for the given type.
96///
97/// # Parameters
98/// - `$feature_name:expr`: The feature name of the option.
99/// - `$name:ident`: The type to define.
100/// - `$predefined_name:ident`: The type of predefined name. If not specified, the type is not predefined.
101///
102/// # Example
103/// ```ignore
104/// define_feature_option_pack!(
105///     OwnedName::qualified("MyFeature", NS_PSK, Some("psk")),
106///     MyPack,
107///     MyPredefinedName
108/// );
109/// ```
110macro_rules! define_feature_option_pack {
111    ($feature_name:expr, $name:ident) => {
112        #[derive(Clone, Debug)]
113        #[doc = concat!("Represents a feature option pack as [`", stringify!($name), "`].")]
114        pub struct $name {
115            /// The option of the feature.
116            option: PrintFeatureOption,
117            /// The parameters that is used by the option.
118            parameters: Vec<ParameterInit>,
119        }
120
121        impl crate::ticket::FeatureOptionPack for $name {
122            fn new(option: PrintFeatureOption, parameters: Vec<ParameterInit>) -> Self {
123                Self { option, parameters }
124            }
125
126            fn feature_name() -> OwnedName {
127                $feature_name
128            }
129
130            fn option(&self) -> &PrintFeatureOption {
131                &self.option
132            }
133
134            fn option_mut(&mut self) -> &mut PrintFeatureOption {
135                &mut self.option
136            }
137
138            fn parameters(&self) -> &[ParameterInit] {
139                &self.parameters
140            }
141
142            fn parameters_mut(&mut self) -> &mut Vec<ParameterInit> {
143                &mut self.parameters
144            }
145
146            fn into_option_with_parameters(self) -> (PrintFeatureOption, Vec<ParameterInit>) {
147                (self.option, self.parameters)
148            }
149        }
150    };
151    ($feature_name:expr, $name:ident, $predefined_name:ident) => {
152        define_feature_option_pack!($feature_name, $name);
153
154        impl crate::ticket::FeatureOptionPackWithPredefined for $name {
155            type PredefinedName = $predefined_name;
156        }
157    };
158}
159pub(crate) use define_feature_option_pack;