xref: /StarryEngine/starry_applications/src/asset_manager/code/mod.rs (revision 8a41b76c5717dfb7ea5d2beaed20030c10ffce86)
1 use self::asset_item::AssetItem;
2 use crate::starry_toolkit::traits::focus::Focus;
3 use starry_client::base::color::Color;
4 use starry_server::base::image::Image as ImageResource;
5 use starry_server::core::{SCREEN_HEIGHT, SCREEN_WIDTH};
6 use starry_toolkit::{
7     base::{panel::Panel, rect::Rect},
8     layout::grid::{Grid, GridArrangeType},
9     traits::enter::Enter,
10     widgets::{image::Image, widget_add_child},
11 };
12 use std::{collections::BTreeMap, fs, sync::Arc};
13 
14 pub mod asset_item;
15 
16 const DESKTOP_BG_PATH: &[u8] = include_bytes!("../resource/desktop_bg.png");
17 
18 pub struct AssetManager {
19     cur_path: String,
20     asset_grid: Arc<Grid>,
21     items: BTreeMap<(usize, usize), Arc<AssetItem>>,
22     panel: Panel,
23 }
24 
25 impl AssetManager {
26     pub fn new() -> Self {
27         AssetManager {
28             cur_path: String::from("/"),
29             asset_grid: Grid::new(),
30             items: BTreeMap::new(),
31             panel: Panel::new(
32                 Rect::new(0, 0, SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32),
33                 "Title",
34                 Color::rgb(0, 0, 0),
35             ),
36         }
37     }
38 
39     pub fn init(&mut self) {
40         let grid = self.asset_grid.clone();
41         grid.set_upper_limit(5);
42         grid.set_space(20, 20);
43         grid.set_arrange_type(GridArrangeType::Horizontal);
44 
45         let self_ptr = self as *mut AssetManager;
46         grid.set_enter_callback(move |grid, char, redraw| {
47             if char == ' ' {
48                 let asset_manager: &mut AssetManager = unsafe { &mut *self_ptr };
49 
50                 if let Some(item) = asset_manager.items.get(&grid.focused_id.get().unwrap()) {
51                     asset_manager.cur_path.push_str(&item.file_path.borrow());
52                     asset_manager.cur_path.push_str(&"/");
53                     asset_manager.refresh();
54                 }
55 
56                 return;
57             }
58 
59             let row_offset: i32 = match char {
60                 'a' => 0,
61                 'A' => 0,
62                 'd' => 0,
63                 'D' => 0,
64                 'w' => -1,
65                 'W' => -1,
66                 's' => 1,
67                 'S' => 1,
68                 _ => 0,
69             };
70 
71             let col_offset: i32 = match char {
72                 'a' => -1,
73                 'A' => -1,
74                 'd' => 1,
75                 'D' => 1,
76                 'w' => 0,
77                 'W' => 0,
78                 's' => 0,
79                 'S' => 0,
80                 _ => 0,
81             };
82 
83             if row_offset == 0 && col_offset == 0 {
84                 return;
85             }
86             let mut nxt_row = grid.focused_id.get().unwrap().0 as i32 + row_offset;
87             let mut nxt_col = grid.focused_id.get().unwrap().1 as i32 + col_offset;
88             loop {
89                 if nxt_row < 0
90                     || nxt_row >= grid.max_row.get() as i32
91                     || nxt_col < 0
92                     || nxt_col >= grid.max_column.get() as i32
93                 {
94                     return;
95                 }
96 
97                 if grid
98                     .elements
99                     .borrow()
100                     .contains_key(&(nxt_row as usize, nxt_col as usize))
101                 {
102                     break;
103                 }
104 
105                 nxt_row += row_offset;
106                 nxt_col += col_offset;
107             }
108 
109             grid.focus(
110                 grid.elements
111                     .borrow()
112                     .get(&(nxt_row as usize, nxt_col as usize))
113                     .unwrap(),
114             );
115             grid.focused_id
116                 .set(Some((nxt_row as usize, nxt_col as usize)));
117 
118             *redraw = true;
119         });
120 
121         self.panel.add_child(&Image::from_image(
122             ImageResource::from_path(DESKTOP_BG_PATH).unwrap(),
123         ));
124 
125         self.panel.add_child(&(self.asset_grid));
126     }
127 
128     pub fn refresh(&mut self) {
129         self.items.clear();
130         self.asset_grid.clear();
131 
132         // 读取目录中的文件列表
133         if let Ok(entries) = fs::read_dir(&self.cur_path) {
134             for entry in entries {
135                 if let Ok(item) = entry {
136                     let asset_item = AssetItem::new(
137                         item.file_name().to_str().unwrap(),
138                         item.metadata().unwrap().is_dir(),
139                     );
140                     let (row, col) = self.asset_grid.add(&asset_item);
141                     self.items.insert((row, col), asset_item.clone());
142                     widget_add_child(self.asset_grid.clone(), asset_item);
143                 }
144             }
145         } else {
146             println!(
147                 "[Error] AssetManager failed to read dir {:?}",
148                 self.cur_path
149             );
150         }
151 
152         let grid = self.asset_grid.clone();
153         if let Some(widget) = grid.elements.borrow().get(&(0, 0)) {
154             grid.focused_id.set(Some((0, 0)));
155             grid.focus(widget);
156         }
157 
158         self.panel.draw();
159     }
160 
161     pub fn exec(&mut self) {
162         self.panel.exec();
163     }
164 }
165