lazybar_core/
image.rs

1use std::{fs::File, path::PathBuf};
2
3use anyhow::{Context, Result};
4use cairo::ImageSurface;
5use derive_builder::Builder;
6
7use crate::{
8    get_table_from_config, parser, remove_float_from_config,
9    remove_string_from_config,
10};
11
12/// An image to be rendered on the bar
13#[derive(Debug, Builder, Clone)]
14#[builder_struct_attr(allow(missing_docs))]
15#[builder_impl_attr(allow(missing_docs))]
16pub struct Image {
17    surface: ImageSurface,
18    #[builder(default)]
19    x: f64,
20    #[builder(default)]
21    y: f64,
22}
23
24impl Image {
25    /// Creates a new instance
26    pub fn new(path: PathBuf, x: f64, y: f64) -> Result<Self> {
27        let mut file = File::open(path)?;
28        Ok(Self {
29            surface: ImageSurface::create_from_png(&mut file)?,
30            x,
31            y,
32        })
33    }
34
35    /// Attempts to parse a new instance from the global config
36    ///
37    /// Configuration options:
38    /// - `path`: the file path of the image (PNG only)
39    /// - `x`: the x coordinate of the image, relative to the panel
40    /// - `y`: the y coordinate of the image, relative to the panel
41    pub fn parse(name: &str) -> Result<Self> {
42        let images_table = parser::IMAGES.get().unwrap();
43
44        let mut table = get_table_from_config(name, images_table)
45            .with_context(|| format!("No subtable found with name {name}"))?;
46
47        let mut builder = ImageBuilder::default();
48
49        let path = remove_string_from_config("path", &mut table)
50            .context("No path specified")?;
51        let mut file = File::open(path)?;
52
53        builder.surface(ImageSurface::create_from_png(&mut file)?);
54
55        if let Some(x) = remove_float_from_config("x", &mut table) {
56            builder.x(x);
57        }
58
59        if let Some(y) = remove_float_from_config("y", &mut table) {
60            builder.y(y);
61        }
62
63        Ok(builder.build()?)
64    }
65
66    /// Draws the image on the bar. `cr`'s (0, 0) should be at the top left
67    /// corner of the panel.
68    pub fn draw(&self, cr: &cairo::Context) -> Result<()> {
69        cr.save()?;
70
71        cr.set_source_surface(self.surface.as_ref(), 0.0, 0.0)?;
72        cr.rectangle(
73            self.x,
74            self.y,
75            self.surface.width() as f64,
76            self.surface.height() as f64,
77        );
78
79        cr.fill()?;
80        cr.restore()?;
81
82        Ok(())
83    }
84}