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