xref: /StarryEngine/starry_applications/src/asset_manager/code/asset_item_grid.rs (revision 731cae0674923fcc85c6e683a2eee596eb642796)
1 use std::{
2     any::Any,
3     cell::{Cell, RefCell},
4     str::FromStr,
5     sync::{Arc, Weak},
6 };
7 
8 use starry_client::base::{color::Color, renderer::Renderer};
9 use starry_toolkit::{
10     base::{panel::Panel, rect::Rect, vector2::Vector2},
11     traits::text::Text,
12     widgets::{
13         image::Image,
14         label::{Label, LabelOverflowType},
15         PivotType, Widget,
16     },
17 };
18 
19 use crate::starry_server::base::image::Image as ImageResource;
20 
21 const FILE_ICON_PATH: &[u8] = include_bytes!("../resource/file_icon.png");
22 const DIR_ICON_PATH: &[u8] = include_bytes!("../resource/dir_icon.png");
23 
24 pub struct AssetItemGrid {
25     self_ref: RefCell<Weak<AssetItemGrid>>,
26     pub rect: Cell<Rect>,
27     pivot: Cell<PivotType>,
28     pivot_offset: Cell<Vector2>,
29     parent: RefCell<Option<Arc<dyn Widget>>>,
30     children: RefCell<Vec<Arc<dyn Widget>>>,
31     panel: RefCell<Option<Arc<Panel>>>,
32     /// 缓存值
33     cache_focused: Cell<bool>,
34     pub file_path: RefCell<String>,
35     pub is_dir: Cell<bool>,
36 }
37 
38 impl AssetItemGrid {
39     pub const ITEM_WIDTH: u32 = 144;
40     pub const ITEM_HEIGHT: u32 = 144;
41 
new(file_name: &str, is_dir: bool) -> Arc<Self>42     pub fn new(file_name: &str, is_dir: bool) -> Arc<Self> {
43         let item = Arc::new(AssetItemGrid {
44             self_ref: RefCell::new(Weak::default()),
45             rect: Cell::new(Rect::new(0, 0, Self::ITEM_WIDTH, Self::ITEM_HEIGHT)),
46             pivot: Cell::new(PivotType::TopLeft),
47             pivot_offset: Cell::new(Vector2::new(0, 0)),
48             children: RefCell::new(Vec::new()),
49             parent: RefCell::new(None),
50             panel: RefCell::new(None),
51             cache_focused: Cell::new(false),
52             file_path: RefCell::new(String::from_str(file_name).unwrap()),
53             is_dir: Cell::new(is_dir),
54         });
55 
56         (*item.self_ref.borrow_mut()) = Arc::downgrade(&item);
57 
58         // 背景Image
59         let bg =
60             Image::new_from_color(Self::ITEM_WIDTH, Self::ITEM_HEIGHT, Color::rgba(0, 0, 0, 0));
61         bg.set_pivot_type(PivotType::Center);
62         item.add_child(bg);
63 
64         // 文件图标Image
65         if let Some(icon) = match is_dir {
66             true => ImageResource::from_path(DIR_ICON_PATH),
67             false => ImageResource::from_path(FILE_ICON_PATH),
68         } {
69             let icon = Image::new_from_image(icon);
70             icon.set_pivot_type(PivotType::Top);
71             item.add_child(icon);
72         }
73 
74         // 文件名Label
75         let name = Label::new();
76         name.set_adapt_type(LabelOverflowType::Omit);
77         name.resize(Self::ITEM_WIDTH, 16);
78         name.set_text(file_name);
79         name.set_pivot_type(PivotType::Bottom);
80         name.set_pivot_offset(Vector2::new(0, -4));
81         item.add_child(name);
82 
83         return item;
84     }
85 }
86 
87 impl Widget for AssetItemGrid {
self_ref(&self) -> Arc<dyn Widget>88     fn self_ref(&self) -> Arc<dyn Widget> {
89         self.self_ref.borrow().upgrade().unwrap()
90     }
91 
as_any_ref(&self) -> &dyn Any92     fn as_any_ref(&self) -> &dyn Any {
93         self
94     }
95 
name(&self) -> &str96     fn name(&self) -> &str {
97         "AssetItem_Grid"
98     }
99 
rect(&self) -> &Cell<Rect>100     fn rect(&self) -> &Cell<Rect> {
101         &self.rect
102     }
103 
pivot(&self) -> &Cell<PivotType>104     fn pivot(&self) -> &Cell<PivotType> {
105         &self.pivot
106     }
107 
pivot_offset(&self) -> &Cell<Vector2>108     fn pivot_offset(&self) -> &Cell<Vector2> {
109         &self.pivot_offset
110     }
111 
parent(&self) -> &RefCell<Option<Arc<dyn Widget>>>112     fn parent(&self) -> &RefCell<Option<Arc<dyn Widget>>> {
113         &self.parent
114     }
115 
children(&self) -> &RefCell<Vec<Arc<dyn Widget>>>116     fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>> {
117         &self.children
118     }
119 
panel(&self) -> &RefCell<Option<Arc<Panel>>>120     fn panel(&self) -> &RefCell<Option<Arc<Panel>>> {
121         &self.panel
122     }
123 
draw(&self, renderer: &mut dyn Renderer, focused: bool)124     fn draw(&self, renderer: &mut dyn Renderer, focused: bool) {
125         if focused != self.cache_focused.get() {
126             self.cache_focused.set(focused);
127 
128             // 如果当前被选中,则背景高亮
129             let children = self.children.borrow_mut();
130             let bg_image = children[0].self_ref();
131             let bg_image = bg_image
132                 .as_any_ref()
133                 .downcast_ref::<Image>()
134                 .expect("[Error] AssetItem failed to cast widget to image");
135             if focused {
136                 bg_image.set_from_color(Color::rgba(0, 255, 255, 64));
137             } else {
138                 bg_image.set_from_color(Color::rgba(0, 0, 0, 0));
139             }
140         }
141 
142         for child in self.children.borrow().iter() {
143             child.draw(renderer, focused);
144         }
145     }
146 }
147