cosmic/widget/icon/
handle.rs

1// Copyright 2023 System76 <info@system76.com>
2// SPDX-License-Identifier: MPL-2.0
3
4use super::{Icon, Named};
5use crate::widget::{image, svg};
6use std::borrow::Cow;
7use std::ffi::OsStr;
8use std::hash::Hash;
9use std::path::PathBuf;
10
11#[must_use]
12#[derive(Clone, Debug, Hash, derive_setters::Setters)]
13pub struct Handle {
14    pub symbolic: bool,
15    #[setters(skip)]
16    pub data: Data,
17}
18
19impl Handle {
20    #[inline]
21    pub fn icon(self) -> Icon {
22        super::icon(self)
23    }
24}
25
26#[must_use]
27#[derive(Clone, Debug, Hash)]
28pub enum Data {
29    Name(Named),
30    Image(image::Handle),
31    Svg(svg::Handle),
32}
33
34/// Create an icon handle from its path.
35pub fn from_path(path: PathBuf) -> Handle {
36    Handle {
37        symbolic: path
38            .file_stem()
39            .and_then(OsStr::to_str)
40            .is_some_and(|name| name.ends_with("-symbolic")),
41        data: if path.extension().is_some_and(|ext| ext == OsStr::new("svg")) {
42            Data::Svg(svg::Handle::from_path(path))
43        } else {
44            Data::Image(image::Handle::from_path(path))
45        },
46    }
47}
48
49/// Create an image handle from memory.
50pub fn from_raster_bytes(
51    bytes: impl Into<Cow<'static, [u8]>>
52    + std::convert::AsRef<[u8]>
53    + std::marker::Send
54    + std::marker::Sync
55    + 'static,
56) -> Handle {
57    fn inner(bytes: Cow<'static, [u8]>) -> Handle {
58        Handle {
59            symbolic: false,
60            data: match bytes {
61                Cow::Owned(b) => Data::Image(image::Handle::from_bytes(b)),
62                Cow::Borrowed(b) => Data::Image(image::Handle::from_bytes(b)),
63            },
64        }
65    }
66
67    inner(bytes.into())
68}
69
70/// Create an image handle from RGBA data, where you must define the width and height.
71pub fn from_raster_pixels(
72    width: u32,
73    height: u32,
74    pixels: impl Into<Cow<'static, [u8]>>
75    + std::convert::AsRef<[u8]>
76    + std::marker::Send
77    + std::marker::Sync,
78) -> Handle {
79    fn inner(width: u32, height: u32, pixels: Cow<'static, [u8]>) -> Handle {
80        Handle {
81            symbolic: false,
82            data: match pixels {
83                Cow::Owned(pixels) => Data::Image(image::Handle::from_rgba(width, height, pixels)),
84                Cow::Borrowed(pixels) => {
85                    Data::Image(image::Handle::from_rgba(width, height, pixels))
86                }
87            },
88        }
89    }
90
91    inner(width, height, pixels.into())
92}
93
94/// Create a SVG handle from memory.
95pub fn from_svg_bytes(bytes: impl Into<Cow<'static, [u8]>>) -> Handle {
96    Handle {
97        symbolic: false,
98        data: Data::Svg(svg::Handle::from_memory(bytes)),
99    }
100}