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