use std::marker::PhantomData;
use std::num::NonZeroU8;
use image::DynamicImage;
use crate::{
error::PrintJobCreationError,
media::{LabelType, Media},
printjob::{CutBehavior, PrintJob},
raster_image::RasterImage,
};
pub struct HasImages {}
pub struct NoImages {}
pub struct PrintJobBuilder<State> {
images: Vec<DynamicImage>,
media: Media,
no_copies: NonZeroU8,
high_dpi: bool,
compressed: bool,
quality_priority: bool,
cut_behavior: CutBehavior,
_state: PhantomData<State>,
}
impl PrintJobBuilder<NoImages> {
#[must_use]
pub fn new(media: Media) -> Self {
Self {
images: Vec::new(),
media,
no_copies: NonZeroU8::MIN,
high_dpi: false,
compressed: false,
quality_priority: true,
cut_behavior: match media.label_type() {
LabelType::Continuous => CutBehavior::CutEach,
LabelType::DieCut => CutBehavior::CutAtEnd,
},
_state: PhantomData,
}
}
#[must_use]
pub fn add_label(mut self, img: DynamicImage) -> PrintJobBuilder<HasImages> {
self.images.push(img);
PrintJobBuilder {
images: self.images,
media: self.media,
no_copies: self.no_copies,
high_dpi: self.high_dpi,
compressed: self.compressed,
quality_priority: self.quality_priority,
cut_behavior: self.cut_behavior,
_state: PhantomData,
}
}
}
impl PrintJobBuilder<HasImages> {
#[must_use]
pub fn add_label(mut self, img: DynamicImage) -> Self {
self.images.push(img);
self
}
#[must_use]
pub fn add_labels<I: IntoIterator<Item = DynamicImage>>(mut self, imgs: I) -> Self {
self.images.extend(imgs);
self
}
pub fn build(self) -> Result<PrintJob, PrintJobCreationError> {
let raster_images = self
.images
.into_iter()
.map(|img| RasterImage::new(img, self.media))
.collect::<Result<Vec<_>, _>>()?;
Ok(PrintJob {
no_copies: self.no_copies,
raster_images,
media: self.media,
high_dpi: self.high_dpi,
compressed: self.compressed,
quality_priority: self.quality_priority,
cut_behavior: self.cut_behavior,
})
}
}
impl<State> PrintJobBuilder<State> {
#[must_use]
pub fn copies(mut self, no_copies: NonZeroU8) -> Self {
self.no_copies = no_copies;
self
}
#[must_use]
pub fn high_dpi(mut self, high_dpi: bool) -> Self {
self.high_dpi = high_dpi;
self
}
#[must_use]
pub fn compressed(mut self, compressed: bool) -> Self {
self.compressed = compressed;
self
}
#[must_use]
pub fn quality_priority(mut self, quality_priority: bool) -> Self {
self.quality_priority = quality_priority;
self
}
#[must_use]
pub fn cut_behavior(mut self, cut_behavior: CutBehavior) -> Self {
self.cut_behavior = cut_behavior;
self
}
}