1 use std::{ 2 cell::{Cell, RefCell}, 3 sync::Arc, 4 }; 5 6 use starry_client::base::{color::Color, renderer::Renderer}; 7 8 use crate::{ 9 base::{point::Point, rect::Rect}, 10 traits::{place::Place, text::Text}, 11 }; 12 13 use super::{HorizontalPlacement, VerticalPlacement, Widget}; 14 15 pub struct Label { 16 pub rect: Cell<Rect>, 17 local_position: Cell<Point>, 18 vertical_placement: Cell<VerticalPlacement>, 19 horizontal_placement: Cell<HorizontalPlacement>, 20 children: RefCell<Vec<Arc<dyn Widget>>>, 21 pub text: RefCell<String>, 22 pub text_offset: Cell<Point>, 23 } 24 25 impl Label { 26 pub fn new() -> Arc<Self> { 27 Arc::new(Label { 28 rect: Cell::new(Rect::default()), 29 local_position: Cell::new(Point::new(0, 0)), 30 vertical_placement: Cell::new(VerticalPlacement::Absolute), 31 horizontal_placement: Cell::new(HorizontalPlacement::Absolute), 32 children: RefCell::new(vec![]), 33 text: RefCell::new(String::new()), 34 text_offset: Cell::new(Point::default()), 35 }) 36 } 37 38 fn adjust_size(&self) { 39 let text = self.text.borrow(); 40 self.size( 41 text.len() as u32 * 8 + 2 * self.text_offset.get().x as u32, 42 16 + 2 * self.text_offset.get().y as u32, 43 ); 44 } 45 } 46 47 impl Place for Label {} 48 49 impl Widget for Label { 50 fn name(&self) -> &str { 51 "Label" 52 } 53 54 fn rect(&self) -> &Cell<Rect> { 55 &self.rect 56 } 57 58 fn local_position(&self) -> &Cell<Point> { 59 &self.local_position 60 } 61 62 fn vertical_placement(&self) -> &Cell<VerticalPlacement> { 63 &self.vertical_placement 64 } 65 66 fn horizontal_placement(&self) -> &Cell<HorizontalPlacement> { 67 &self.horizontal_placement 68 } 69 70 fn children(&self) -> &RefCell<Vec<Arc<dyn Widget>>> { 71 &self.children 72 } 73 74 fn draw(&self, renderer: &mut dyn Renderer) { 75 let origin_rect = self.rect().get(); 76 let mut current_rect = self.rect().get(); // 当前字符渲染矩形 77 let origin_x = origin_rect.x; 78 let text = self.text.borrow().clone(); 79 80 for char in text.chars() { 81 if char == '\n' { 82 // 换行 退格到起始位置 83 current_rect.x = origin_x; 84 current_rect.y += 16; 85 } else { 86 // 避免超出矩形范围 87 if current_rect.x + 8 <= origin_rect.x + origin_rect.width as i32 88 && current_rect.y + 16 <= origin_rect.y + origin_rect.height as i32 89 { 90 // 默认渲染白色字体 91 // TODO 应用主题(Theme)颜色 92 renderer.char( 93 current_rect.x, 94 current_rect.y, 95 char, 96 Color::rgb(255, 255, 255), 97 ); 98 } 99 current_rect.x += 8; 100 } 101 } 102 } 103 } 104 105 impl Text for Label { 106 fn text<S: Into<String>>(&self, target_text: S) -> &Self { 107 { 108 let mut text = self.text.borrow_mut(); 109 *text = target_text.into(); 110 } 111 self.adjust_size(); 112 self 113 } 114 115 fn text_offset(&self, x: i32, y: i32) -> &Self { 116 self.text_offset.set(Point::new(x, y)); 117 self.adjust_size(); 118 self 119 } 120 } 121