cosmic/widget/icon/
mod.rs1mod bundle;
7mod named;
8use std::sync::Arc;
9
10pub use named::{IconFallback, Named};
11
12mod handle;
13pub use handle::{Data, Handle, from_path, from_raster_bytes, from_raster_pixels, from_svg_bytes};
14
15use crate::Element;
16use derive_setters::Setters;
17use iced::widget::{Image, Svg};
18use iced::{ContentFit, Length, Radians, Rectangle};
19use iced_core::Rotation;
20
21pub fn icon(handle: Handle) -> Icon {
23 Icon {
24 content_fit: ContentFit::Fill,
25 handle,
26 height: None,
27 size: 16,
28 class: crate::theme::Svg::default(),
29 rotation: None,
30 width: None,
31 }
32}
33
34pub fn from_name(name: impl Into<Arc<str>>) -> Named {
36 Named::new(name)
37}
38
39#[must_use]
41#[derive(Clone, Setters)]
42pub struct Icon {
43 #[setters(skip)]
44 handle: Handle,
45 class: crate::theme::Svg,
46 #[setters(skip)]
47 pub(super) size: u16,
48 content_fit: ContentFit,
49 #[setters(strip_option)]
50 width: Option<Length>,
51 #[setters(strip_option)]
52 height: Option<Length>,
53 #[setters(strip_option)]
54 rotation: Option<Rotation>,
55}
56
57impl Icon {
58 #[must_use]
59 pub fn into_svg_handle(self) -> Option<crate::widget::svg::Handle> {
60 match self.handle.data {
61 Data::Image(_) => (),
62 Data::Svg(handle) => return Some(handle),
63 }
64
65 None
66 }
67
68 #[must_use]
69 pub fn size(mut self, size: u16) -> Self {
70 self.size = size;
71 self
72 }
73
74 #[must_use]
75 fn view<'a, Message: 'a>(self) -> Element<'a, Message> {
76 let from_image = |handle| {
77 Image::new(handle)
78 .width(
79 self.width
80 .unwrap_or_else(|| Length::Fixed(f32::from(self.size))),
81 )
82 .height(
83 self.height
84 .unwrap_or_else(|| Length::Fixed(f32::from(self.size))),
85 )
86 .rotation(self.rotation.unwrap_or_default())
87 .content_fit(self.content_fit)
88 .into()
89 };
90
91 let from_svg = |handle| {
92 Svg::<crate::Theme>::new(handle)
93 .class(self.class.clone())
94 .width(
95 self.width
96 .unwrap_or_else(|| Length::Fixed(f32::from(self.size))),
97 )
98 .height(
99 self.height
100 .unwrap_or_else(|| Length::Fixed(f32::from(self.size))),
101 )
102 .rotation(self.rotation.unwrap_or_default())
103 .content_fit(self.content_fit)
104 .symbolic(self.handle.symbolic)
105 .into()
106 };
107
108 match self.handle.data {
109 Data::Image(handle) => from_image(handle),
110 Data::Svg(handle) => from_svg(handle),
111 }
112 }
113}
114
115impl<'a, Message: 'a> From<Icon> for Element<'a, Message> {
116 fn from(icon: Icon) -> Self {
117 icon.view::<Message>()
118 }
119}
120
121pub fn draw(renderer: &mut crate::Renderer, handle: &Handle, icon_bounds: Rectangle) {
123 match handle.clone().data {
124 Data::Svg(handle) => iced_core::svg::Renderer::draw_svg(
125 renderer,
126 iced_core::svg::Svg::new(handle),
127 icon_bounds,
128 icon_bounds,
129 ),
130
131 Data::Image(handle) => {
132 iced_core::image::Renderer::draw_image(
133 renderer,
134 iced_core::Image {
135 handle,
136 filter_method: iced_core::image::FilterMethod::Linear,
137 rotation: Radians(0.),
138 border_radius: [0.0; 4].into(),
139 opacity: 1.0,
140 snap: true,
141 },
142 icon_bounds,
143 icon_bounds,
144 );
145 }
146 }
147}