xref: /StarryEngine/starry_applications/src/asset_manager/code/mod.rs (revision 1bee64b64bc410ee78964a11a40a0fff69945480)
18a41b76cSR0ronoa use self::asset_item::AssetItem;
249182ea7SR0ronoa use crate::starry_toolkit::traits::focus::Focus;
3b0262857SR0ronoa use starry_client::base::color::Color;
48a41b76cSR0ronoa use starry_server::base::image::Image as ImageResource;
549182ea7SR0ronoa use starry_server::core::{SCREEN_HEIGHT, SCREEN_WIDTH};
649182ea7SR0ronoa use starry_toolkit::{
749182ea7SR0ronoa     base::{panel::Panel, rect::Rect},
8b0262857SR0ronoa     layout::grid::{Grid, GridArrangeType},
98a41b76cSR0ronoa     traits::enter::Enter,
102b942a51SR0ronoa     widgets::image::Image,
1149182ea7SR0ronoa };
128a41b76cSR0ronoa use std::{collections::BTreeMap, fs, sync::Arc};
1349182ea7SR0ronoa pub mod asset_item;
1449182ea7SR0ronoa 
1549182ea7SR0ronoa const DESKTOP_BG_PATH: &[u8] = include_bytes!("../resource/desktop_bg.png");
16*1bee64b6SR0ronoa const LOADING_IMG_PATH: &[u8] = include_bytes!("../resource/loading.png");
1749182ea7SR0ronoa 
188a41b76cSR0ronoa pub struct AssetManager {
1949182ea7SR0ronoa     cur_path: String,
208a41b76cSR0ronoa     asset_grid: Arc<Grid>,
218a41b76cSR0ronoa     items: BTreeMap<(usize, usize), Arc<AssetItem>>,
22*1bee64b6SR0ronoa     panel: Arc<Panel>,
23*1bee64b6SR0ronoa     // 原则上一个应用程序对应一个Panel和Window
24*1bee64b6SR0ronoa     // 这里额外创建一个Panel用于Loading图标优先显示
25*1bee64b6SR0ronoa     // 后续通过Server来显示Loading或不显示Loading
26*1bee64b6SR0ronoa     loading_panel: Arc<Panel>,
27*1bee64b6SR0ronoa     init_show: bool,
2849182ea7SR0ronoa }
2949182ea7SR0ronoa 
308a41b76cSR0ronoa impl AssetManager {
3149182ea7SR0ronoa     pub fn new() -> Self {
328a41b76cSR0ronoa         AssetManager {
3349182ea7SR0ronoa             cur_path: String::from("/"),
348a41b76cSR0ronoa             asset_grid: Grid::new(),
358a41b76cSR0ronoa             items: BTreeMap::new(),
368a41b76cSR0ronoa             panel: Panel::new(
378a41b76cSR0ronoa                 Rect::new(0, 0, SCREEN_WIDTH as u32, SCREEN_HEIGHT as u32),
388a41b76cSR0ronoa                 "Title",
398a41b76cSR0ronoa                 Color::rgb(0, 0, 0),
408a41b76cSR0ronoa             ),
41*1bee64b6SR0ronoa             loading_panel: Panel::new(
42*1bee64b6SR0ronoa                 Rect::new(SCREEN_WIDTH as i32 - 64, SCREEN_HEIGHT as i32 - 64, 64, 64),
43*1bee64b6SR0ronoa                 "Loading",
44*1bee64b6SR0ronoa                 Color::rgb(255, 255, 255),
45*1bee64b6SR0ronoa             ),
46*1bee64b6SR0ronoa             init_show: true,
4749182ea7SR0ronoa         }
4849182ea7SR0ronoa     }
4949182ea7SR0ronoa 
508a41b76cSR0ronoa     pub fn init(&mut self) {
51*1bee64b6SR0ronoa         self.init_loading_panel();
52*1bee64b6SR0ronoa 
538a41b76cSR0ronoa         let grid = self.asset_grid.clone();
54*1bee64b6SR0ronoa         grid.set_upper_limit(8);
5549182ea7SR0ronoa         grid.set_space(20, 20);
56b0262857SR0ronoa         grid.set_arrange_type(GridArrangeType::Horizontal);
578a41b76cSR0ronoa 
582b942a51SR0ronoa         // 处理输入回调
598a41b76cSR0ronoa         let self_ptr = self as *mut AssetManager;
608a41b76cSR0ronoa         grid.set_enter_callback(move |grid, char, redraw| {
618a41b76cSR0ronoa             let asset_manager: &mut AssetManager = unsafe { &mut *self_ptr };
628a41b76cSR0ronoa 
63*1bee64b6SR0ronoa             if char == '\n' {
648a41b76cSR0ronoa                 if let Some(item) = asset_manager.items.get(&grid.focused_id.get().unwrap()) {
65*1bee64b6SR0ronoa                     // 判断是否是文件夹
66*1bee64b6SR0ronoa                     if item.is_dir.get() == false {
67*1bee64b6SR0ronoa                         return;
68*1bee64b6SR0ronoa                     }
69*1bee64b6SR0ronoa 
70*1bee64b6SR0ronoa                     // 返回上级目录
712b942a51SR0ronoa                     if item.file_path.borrow().eq(&"..".to_string()) {
722b942a51SR0ronoa                         if asset_manager.cur_path.len() == 1 {
732b942a51SR0ronoa                             return;
742b942a51SR0ronoa                         } else {
752b942a51SR0ronoa                             let split_path =
762b942a51SR0ronoa                                 &asset_manager.cur_path[..asset_manager.cur_path.len() - 1];
772b942a51SR0ronoa                             let slash_pos = split_path.rfind('/').unwrap();
782b942a51SR0ronoa                             let _ = asset_manager.cur_path.split_off(slash_pos + 1);
792b942a51SR0ronoa                         }
802b942a51SR0ronoa                     } else {
81*1bee64b6SR0ronoa                         // 打开文件夹
828a41b76cSR0ronoa                         asset_manager.cur_path.push_str(&item.file_path.borrow());
838a41b76cSR0ronoa                         asset_manager.cur_path.push_str(&"/");
842b942a51SR0ronoa                     }
858a41b76cSR0ronoa                     asset_manager.refresh();
8649182ea7SR0ronoa                 }
8749182ea7SR0ronoa 
888a41b76cSR0ronoa                 return;
898a41b76cSR0ronoa             }
908a41b76cSR0ronoa 
918a41b76cSR0ronoa             let row_offset: i32 = match char {
928a41b76cSR0ronoa                 'a' => 0,
938a41b76cSR0ronoa                 'A' => 0,
948a41b76cSR0ronoa                 'd' => 0,
958a41b76cSR0ronoa                 'D' => 0,
968a41b76cSR0ronoa                 'w' => -1,
978a41b76cSR0ronoa                 'W' => -1,
988a41b76cSR0ronoa                 's' => 1,
998a41b76cSR0ronoa                 'S' => 1,
1008a41b76cSR0ronoa                 _ => 0,
1018a41b76cSR0ronoa             };
1028a41b76cSR0ronoa 
1038a41b76cSR0ronoa             let col_offset: i32 = match char {
1048a41b76cSR0ronoa                 'a' => -1,
1058a41b76cSR0ronoa                 'A' => -1,
1068a41b76cSR0ronoa                 'd' => 1,
1078a41b76cSR0ronoa                 'D' => 1,
1088a41b76cSR0ronoa                 'w' => 0,
1098a41b76cSR0ronoa                 'W' => 0,
1108a41b76cSR0ronoa                 's' => 0,
1118a41b76cSR0ronoa                 'S' => 0,
1128a41b76cSR0ronoa                 _ => 0,
1138a41b76cSR0ronoa             };
1148a41b76cSR0ronoa 
1158a41b76cSR0ronoa             if row_offset == 0 && col_offset == 0 {
1168a41b76cSR0ronoa                 return;
1178a41b76cSR0ronoa             }
1188a41b76cSR0ronoa             let mut nxt_row = grid.focused_id.get().unwrap().0 as i32 + row_offset;
1198a41b76cSR0ronoa             let mut nxt_col = grid.focused_id.get().unwrap().1 as i32 + col_offset;
1208a41b76cSR0ronoa             loop {
1218a41b76cSR0ronoa                 if nxt_row < 0
1228a41b76cSR0ronoa                     || nxt_row >= grid.max_row.get() as i32
1238a41b76cSR0ronoa                     || nxt_col < 0
1248a41b76cSR0ronoa                     || nxt_col >= grid.max_column.get() as i32
1258a41b76cSR0ronoa                 {
1268a41b76cSR0ronoa                     return;
1278a41b76cSR0ronoa                 }
1288a41b76cSR0ronoa 
1298a41b76cSR0ronoa                 if grid
1308a41b76cSR0ronoa                     .elements
1318a41b76cSR0ronoa                     .borrow()
1328a41b76cSR0ronoa                     .contains_key(&(nxt_row as usize, nxt_col as usize))
1338a41b76cSR0ronoa                 {
1348a41b76cSR0ronoa                     break;
1358a41b76cSR0ronoa                 }
1368a41b76cSR0ronoa 
1378a41b76cSR0ronoa                 nxt_row += row_offset;
1388a41b76cSR0ronoa                 nxt_col += col_offset;
1398a41b76cSR0ronoa             }
1408a41b76cSR0ronoa 
1418a41b76cSR0ronoa             grid.focus(
1428a41b76cSR0ronoa                 grid.elements
1438a41b76cSR0ronoa                     .borrow()
1448a41b76cSR0ronoa                     .get(&(nxt_row as usize, nxt_col as usize))
1458a41b76cSR0ronoa                     .unwrap(),
1468a41b76cSR0ronoa             );
1478a41b76cSR0ronoa 
148*1bee64b6SR0ronoa             asset_manager.loading_panel.draw();
149*1bee64b6SR0ronoa             redraw.set(true);
1508a41b76cSR0ronoa         });
1518a41b76cSR0ronoa 
152*1bee64b6SR0ronoa         self.panel.add_child(&Image::new_from_image(
1538a41b76cSR0ronoa             ImageResource::from_path(DESKTOP_BG_PATH).unwrap(),
1548a41b76cSR0ronoa         ));
1558a41b76cSR0ronoa 
1568a41b76cSR0ronoa         self.panel.add_child(&(self.asset_grid));
1578a41b76cSR0ronoa     }
1588a41b76cSR0ronoa 
159*1bee64b6SR0ronoa     fn init_loading_panel(&mut self) {
160*1bee64b6SR0ronoa         self.loading_panel.add_child(&Image::new_from_image(
161*1bee64b6SR0ronoa             ImageResource::from_path(LOADING_IMG_PATH).unwrap(),
162*1bee64b6SR0ronoa         ));
163*1bee64b6SR0ronoa     }
164*1bee64b6SR0ronoa 
1658a41b76cSR0ronoa     pub fn refresh(&mut self) {
1668a41b76cSR0ronoa         self.items.clear();
1678a41b76cSR0ronoa         self.asset_grid.clear();
1688a41b76cSR0ronoa 
1692b942a51SR0ronoa         // 父目录
1702b942a51SR0ronoa         let parent_asset_item = AssetItem::new("..", true);
171*1bee64b6SR0ronoa         let (row, col) = self.asset_grid.add_element(&parent_asset_item);
1722b942a51SR0ronoa         self.items.insert((row, col), parent_asset_item.clone());
1732b942a51SR0ronoa 
17449182ea7SR0ronoa         // 读取目录中的文件列表
17549182ea7SR0ronoa         if let Ok(entries) = fs::read_dir(&self.cur_path) {
17649182ea7SR0ronoa             for entry in entries {
17749182ea7SR0ronoa                 if let Ok(item) = entry {
1782b942a51SR0ronoa                     let is_dir = if let Ok(metadata) = item.metadata() {
1792b942a51SR0ronoa                         metadata.is_dir()
1802b942a51SR0ronoa                     } else {
1812b942a51SR0ronoa                         false
1822b942a51SR0ronoa                     };
1832b942a51SR0ronoa 
1842b942a51SR0ronoa                     let asset_item = AssetItem::new(item.file_name().to_str().unwrap(), is_dir);
185*1bee64b6SR0ronoa                     let (row, col) = self.asset_grid.add_element(&asset_item);
1868a41b76cSR0ronoa                     self.items.insert((row, col), asset_item.clone());
18749182ea7SR0ronoa                 }
18849182ea7SR0ronoa             }
1898a41b76cSR0ronoa         } else {
1908a41b76cSR0ronoa             println!(
1918a41b76cSR0ronoa                 "[Error] AssetManager failed to read dir {:?}",
1928a41b76cSR0ronoa                 self.cur_path
1938a41b76cSR0ronoa             );
19449182ea7SR0ronoa         }
19549182ea7SR0ronoa 
1968a41b76cSR0ronoa         let grid = self.asset_grid.clone();
1978a41b76cSR0ronoa         if let Some(widget) = grid.elements.borrow().get(&(0, 0)) {
19849182ea7SR0ronoa             grid.focused_id.set(Some((0, 0)));
19949182ea7SR0ronoa             grid.focus(widget);
20049182ea7SR0ronoa         }
2018a41b76cSR0ronoa 
202*1bee64b6SR0ronoa         if self.init_show == true {
203*1bee64b6SR0ronoa             self.init_show = false
204*1bee64b6SR0ronoa         } else {
205*1bee64b6SR0ronoa             self.loading_panel.draw();
206*1bee64b6SR0ronoa         }
2078a41b76cSR0ronoa         self.panel.draw();
20849182ea7SR0ronoa     }
20949182ea7SR0ronoa 
2108a41b76cSR0ronoa     pub fn exec(&mut self) {
2118a41b76cSR0ronoa         self.panel.exec();
21249182ea7SR0ronoa     }
21349182ea7SR0ronoa }
214