Skip to main content

iris_cssom/
bridge.rs

1//! CSSOM 桥接层
2//!
3//! 提供 CSSOM 与 iris-layout 之间的集成桥接。
4
5use std::sync::{Arc, Mutex};
6use crate::stylesheet::CSSStyleSheet;
7
8/// CSSOM 管理器
9///
10/// 管理多个样式表,并提供与 iris-layout 的集成接口。
11///
12/// # 示例
13///
14/// ```rust
15/// use iris_cssom::bridge::CSSOMManager;
16///
17/// let mut manager = CSSOMManager::new();
18/// manager.add_stylesheet("sheet1");
19/// manager.insert_rule_to_sheet("sheet1", ".class { color: red; }", 0).unwrap();
20///
21/// let stylesheet = manager.get_stylesheet_for_layout("sheet1");
22/// assert!(stylesheet.is_some());
23/// ```
24#[derive(Debug)]
25pub struct CSSOMManager {
26    /// 样式表注册表
27    stylesheets: std::collections::HashMap<String, Arc<Mutex<CSSStyleSheet>>>,
28}
29
30impl CSSOMManager {
31    /// 创建新的 CSSOM 管理器
32    pub fn new() -> Self {
33        Self {
34            stylesheets: std::collections::HashMap::new(),
35        }
36    }
37
38    /// 添加样式表
39    ///
40    /// # 参数
41    ///
42    /// * `name` - 样式表名称(唯一标识)
43    pub fn add_stylesheet(&mut self, name: &str) {
44        let sheet = CSSStyleSheet::new();
45        self.stylesheets.insert(name.to_string(), Arc::new(Mutex::new(sheet)));
46    }
47
48    /// 从 CSS 文本添加样式表
49    ///
50    /// # 参数
51    ///
52    /// * `name` - 样式表名称
53    /// * `css_text` - CSS 文本内容
54    pub fn add_stylesheet_from_css(&mut self, name: &str, css_text: &str) {
55        let sheet = CSSStyleSheet::from_css(css_text);
56        self.stylesheets.insert(name.to_string(), Arc::new(Mutex::new(sheet)));
57    }
58
59    /// 获取样式表
60    pub fn get_stylesheet(&self, name: &str) -> Option<Arc<Mutex<CSSStyleSheet>>> {
61        self.stylesheets.get(name).map(Arc::clone)
62    }
63
64    /// 移除样式表
65    pub fn remove_stylesheet(&mut self, name: &str) {
66        self.stylesheets.remove(name);
67    }
68
69    /// 向指定样式表插入规则
70    ///
71    /// # 参数
72    ///
73    /// * `sheet_name` - 样式表名称
74    /// * `rule` - CSS 规则文本
75    /// * `index` - 插入位置
76    pub fn insert_rule_to_sheet(
77        &mut self,
78        sheet_name: &str,
79        rule: &str,
80        index: usize,
81    ) -> Result<u32, String> {
82        if let Some(sheet) = self.stylesheets.get(sheet_name) {
83            sheet.lock().unwrap().insert_rule(rule, index)
84        } else {
85            Err(format!("Stylesheet '{}' not found", sheet_name))
86        }
87    }
88
89    /// 从指定样式表删除规则
90    pub fn delete_rule_from_sheet(
91        &mut self,
92        sheet_name: &str,
93        index: usize,
94    ) -> Result<(), String> {
95        if let Some(sheet) = self.stylesheets.get(sheet_name) {
96            sheet.lock().unwrap().delete_rule(index)
97        } else {
98            Err(format!("Stylesheet '{}' not found", sheet_name))
99        }
100    }
101
102    /// 获取用于 iris-layout 的样式表
103    ///
104    /// 这将返回 iris-layout 可以使用的内部样式表格式
105    pub fn get_stylesheet_for_layout(&self, name: &str) -> Option<crate::css::Stylesheet> {
106        self.stylesheets
107            .get(name)
108            .map(|sheet| sheet.lock().unwrap().internal_stylesheet())
109    }
110
111    /// 获取所有样式表的名称列表
112    pub fn get_stylesheet_names(&self) -> Vec<String> {
113        self.stylesheets.keys().cloned().collect()
114    }
115
116    /// 获取样式表数量
117    pub fn stylesheet_count(&self) -> usize {
118        self.stylesheets.len()
119    }
120
121    /// 清空所有样式表
122    pub fn clear_all(&mut self) {
123        self.stylesheets.clear();
124    }
125}
126
127impl Default for CSSOMManager {
128    fn default() -> Self {
129        Self::new()
130    }
131}
132
133#[cfg(test)]
134mod tests {
135    use super::*;
136
137    #[test]
138    fn test_new_manager() {
139        let manager = CSSOMManager::new();
140        assert_eq!(manager.stylesheet_count(), 0);
141    }
142
143    #[test]
144    fn test_add_stylesheet() {
145        let mut manager = CSSOMManager::new();
146        manager.add_stylesheet("main");
147        assert_eq!(manager.stylesheet_count(), 1);
148        assert!(manager.get_stylesheet("main").is_some());
149    }
150
151    #[test]
152    fn test_add_stylesheet_from_css() {
153        let mut manager = CSSOMManager::new();
154        manager.add_stylesheet_from_css("main", ".class { color: red; }");
155        
156        let sheet = manager.get_stylesheet("main");
157        assert!(sheet.is_some());
158        assert_eq!(sheet.unwrap().lock().unwrap().rule_count(), 1);
159    }
160
161    #[test]
162    fn test_insert_rule_to_sheet() {
163        let mut manager = CSSOMManager::new();
164        manager.add_stylesheet("main");
165        
166        let result = manager.insert_rule_to_sheet("main", ".class { color: red; }", 0);
167        assert!(result.is_ok());
168    }
169
170    #[test]
171    fn test_delete_rule_from_sheet() {
172        let mut manager = CSSOMManager::new();
173        manager.add_stylesheet_from_css("main", ".class { color: red; }");
174        
175        let result = manager.delete_rule_from_sheet("main", 0);
176        assert!(result.is_ok());
177        assert_eq!(
178            manager.get_stylesheet("main").unwrap().lock().unwrap().rule_count(),
179            0
180        );
181    }
182
183    #[test]
184    fn test_get_stylesheet_for_layout() {
185        let mut manager = CSSOMManager::new();
186        manager.add_stylesheet_from_css("main", ".class { color: red; }");
187        
188        let layout_sheet = manager.get_stylesheet_for_layout("main");
189        assert!(layout_sheet.is_some());
190        assert_eq!(layout_sheet.unwrap().rules.len(), 1);
191    }
192
193    #[test]
194    fn test_remove_stylesheet() {
195        let mut manager = CSSOMManager::new();
196        manager.add_stylesheet("main");
197        manager.remove_stylesheet("main");
198        assert_eq!(manager.stylesheet_count(), 0);
199    }
200
201    #[test]
202    fn test_clear_all() {
203        let mut manager = CSSOMManager::new();
204        manager.add_stylesheet("sheet1");
205        manager.add_stylesheet("sheet2");
206        manager.clear_all();
207        assert_eq!(manager.stylesheet_count(), 0);
208    }
209}