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