xref: /StarryEngine/starry_toolkit/src/widgets/image.rs (revision 282ef85ca13266353a8fb594bdc60918a2715518)
1 use std::{
2     any::Any,
3     cell::{Cell, RefCell},
4     sync::{Arc, Weak},
5 };
6 
7 use starry_client::base::{color::Color, renderer::Renderer};
8 
9 use crate::{
10     base::{panel::Panel, rect::Rect, vector2::Vector2},
11     util::get_local_rect,
12 };
13 
14 use super::{PivotType, Widget};
15 
16 use crate::starry_server::base::image::Image as ImageResource;
17 
18 pub struct Image {
19     self_ref: RefCell<Weak<Image>>,
20     rect: Cell<Rect>,
21     pivot: Cell<PivotType>,
22     pivot_offset: Cell<Vector2>,
23     children: RefCell<Vec<Arc<dyn Widget>>>,
24     parent: RefCell<Option<Arc<dyn Widget>>>,
25     panel: RefCell<Option<Arc<Panel>>>,
26     /// 图像源数据
27     image: RefCell<ImageResource>,
28 }
29 
30 impl Image {
31     pub fn new(width: u32, height: u32) -> Arc<Self> {
32         Self::new_from_image(ImageResource::new(width as i32, height as i32))
33     }
34 
35     pub fn new_from_color(width: u32, height: u32, color: Color) -> Arc<Self> {
36         Self::new_from_image(ImageResource::from_color(
37             width as i32,
38             height as i32,
39             color,
40         ))
41     }
42 
43     pub fn new_from_image(image: ImageResource) -> Arc<Self> {
44         let image = Arc::new(Image {
45             self_ref: RefCell::new(Weak::default()),
46             rect: Cell::new(Rect::new(0, 0, image.width() as u32, image.height() as u32)),
47             pivot: Cell::new(PivotType::TopLeft),
48             pivot_offset: Cell::new(Vector2::new(0, 0)),
49             children: RefCell::new(vec![]),
50             parent: RefCell::new(None),
51             panel: RefCell::new(None),
52             image: RefCell::new(image),
53         });
54 
55         (*image.self_ref.borrow_mut()) = Arc::downgrade(&image);
56 
57         return image;
58     }
59 
60     pub fn new_from_path(path: &[u8]) -> Option<Arc<Self>> {
61         if let Some(image) = ImageResource::from_path(path) {
62             Some(Self::new_from_image(image))
63         } else {
64             None
65         }
66     }
67 
68     pub fn set_from_path(&self, path: &[u8]) {
69         if let Some(image) = ImageResource::from_path(path) {
70             (*self.image.borrow_mut()) = image;
71         } else {
72             println!("[Error] Image failed to set image");
73         }
74     }
75 
76     pub fn set_from_color(&self, color: Color) {
77         (*self.image.borrow_mut()) = ImageResource::from_color(
78             self.rect.get().width as i32,
79             self.rect.get().height as i32,
80             color,
81         );
82     }
83 }
84 
85 impl Widget for Image {
86     fn self_ref(&self) -> Arc<dyn Widget> {
87         self.self_ref.borrow().upgrade().unwrap()
88     }
89 
90     fn as_any_ref(&self) -> &dyn Any {
91         self
92     }
93 
94     fn name(&self) -> &str {
95         "Image"
96     }
97 
98     fn rect(&self) -> &Cell<Rect> {
99         &self.rect
100     }
101 
102     fn pivot(&self) -> &Cell<PivotType> {
103         &self.pivot
104     }
105 
106     fn pivot_offset(&self) -> &Cell<Vector2> {
107         &self.pivot_offset
108     }
109 
110     fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>> {
111         &self.children
112     }
113 
114     fn parent(&self) -> &RefCell<Option<Arc<dyn Widget>>> {
115         &self.parent
116     }
117 
118     fn panel(&self) -> &RefCell<Option<Arc<Panel>>> {
119         &self.panel
120     }
121 
122     fn draw(&self, renderer: &mut dyn Renderer, _focused: bool) {
123         let image = self.image.borrow();
124         if self.panel().borrow().is_some() {
125             let panel_rect = self.panel.borrow().clone().unwrap().rect();
126             let local_rect = get_local_rect(self.rect.get(), panel_rect);
127             renderer.image(
128                 local_rect.x,
129                 local_rect.y,
130                 local_rect.width,
131                 local_rect.height,
132                 image.data(),
133             );
134         } else {
135             println!("[Error] Image do not belong to any panel!");
136         }
137     }
138 }
139