Skip to main content

easyofd_core/page_obj/
ct_template_page.rs

1//! CT_TemplatePage 模板页。
2
3/// 对应 Java: org.ofdrw.core.basicStructure.pageObj.CT_TemplatePage
4///
5/// 模板页描述,定义可复用的页面模板。
6/// 对应 GB/T 33190-2016 图 14。
7#[allow(non_camel_case_types)]
8#[derive(Debug, Clone, PartialEq)]
9pub struct CT_TemplatePage {
10    /// 模板页 ID。
11    pub id: u32,
12    /// 模板页名称。
13    pub name: Option<String>,
14    /// Z 序(绘制顺序)。
15    pub z_order: Option<TemplateZOrder>,
16    /// 模板页文件路径。
17    pub base_loc: Option<String>,
18}
19
20/// 模板页 Z 序枚举。
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum TemplateZOrder {
23    /// 背景。
24    Back,
25    /// 前景。
26    Front,
27}
28
29impl TemplateZOrder {
30    /// 转为 OFD XML 属性值。
31    #[must_use]
32    pub fn as_str(&self) -> &'static str {
33        match self {
34            Self::Back => "Back",
35            Self::Front => "Front",
36        }
37    }
38}
39
40impl std::fmt::Display for TemplateZOrder {
41    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42        f.write_str(self.as_str())
43    }
44}
45
46impl CT_TemplatePage {
47    /// 创建新的模板页。
48    #[must_use]
49    pub fn new(id: u32) -> Self {
50        Self {
51            id,
52            name: None,
53            z_order: None,
54            base_loc: None,
55        }
56    }
57
58    /// 设置模板页名称。
59    #[must_use]
60    pub fn name(mut self, name: impl Into<String>) -> Self {
61        self.name = Some(name.into());
62        self
63    }
64
65    /// 设置 Z 序。
66    #[must_use]
67    pub fn z_order(mut self, z_order: TemplateZOrder) -> Self {
68        self.z_order = Some(z_order);
69        self
70    }
71
72    /// 设置模板页文件路径。
73    #[must_use]
74    pub fn base_loc(mut self, loc: impl Into<String>) -> Self {
75        self.base_loc = Some(loc.into());
76        self
77    }
78
79    /// 获取模板页 ID。
80    #[must_use]
81    pub fn get_id(&self) -> u32 {
82        self.id
83    }
84
85    /// 获取模板页名称。
86    #[must_use]
87    pub fn get_name(&self) -> Option<&str> {
88        self.name.as_deref()
89    }
90
91    /// 获取 Z 序。
92    #[must_use]
93    pub fn get_z_order(&self) -> Option<TemplateZOrder> {
94        self.z_order
95    }
96
97    /// 获取模板页文件路径。
98    #[must_use]
99    pub fn get_base_loc(&self) -> Option<&str> {
100        self.base_loc.as_deref()
101    }
102
103    /// 序列化为 OFD XML 字符串。
104    #[must_use]
105    pub fn to_xml_string(&self) -> String {
106        use std::fmt::Write;
107        let mut xml = format!("<ofd:TemplatePage ID=\"{}\"", self.id);
108        if let Some(ref name) = self.name {
109            write!(xml, " TemplatePageName=\"{name}\"").expect("写入内存缓冲区不会失败");
110        }
111        if let Some(zo) = self.z_order {
112            write!(xml, " ZOrder=\"{}\"", zo.as_str()).expect("写入内存缓冲区不会失败");
113        }
114        if let Some(ref loc) = self.base_loc {
115            write!(xml, " BaseLoc=\"{loc}\"").expect("写入内存缓冲区不会失败");
116        }
117        xml.push_str(" />");
118        xml
119    }
120}
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn test_ct_template_page_new() {
128        let tpl = CT_TemplatePage::new(1);
129        assert_eq!(tpl.id, 1);
130        assert!(tpl.name.is_none());
131        assert!(tpl.z_order.is_none());
132        assert!(tpl.base_loc.is_none());
133    }
134
135    #[test]
136    fn test_ct_template_page_builder() {
137        let tpl = CT_TemplatePage::new(5)
138            .name("tpl1")
139            .z_order(TemplateZOrder::Back)
140            .base_loc("Tpl_5.xml");
141        assert_eq!(tpl.get_id(), 5);
142        assert_eq!(tpl.get_name(), Some("tpl1"));
143        assert_eq!(tpl.get_z_order(), Some(TemplateZOrder::Back));
144        assert_eq!(tpl.get_base_loc(), Some("Tpl_5.xml"));
145    }
146
147    #[test]
148    fn test_template_z_order_display() {
149        assert_eq!(TemplateZOrder::Back.to_string(), "Back");
150        assert_eq!(TemplateZOrder::Front.to_string(), "Front");
151    }
152
153    #[test]
154    fn test_template_z_order_as_str() {
155        assert_eq!(TemplateZOrder::Back.as_str(), "Back");
156        assert_eq!(TemplateZOrder::Front.as_str(), "Front");
157    }
158
159    #[test]
160    fn test_ct_template_page_to_xml_minimal() {
161        let tpl = CT_TemplatePage::new(1);
162        let xml = tpl.to_xml_string();
163        assert!(xml.contains("ID=\"1\""));
164        assert!(xml.contains("<ofd:TemplatePage"));
165        assert!(xml.ends_with(" />"));
166    }
167
168    #[test]
169    fn test_ct_template_page_to_xml_full() {
170        let tpl = CT_TemplatePage::new(10)
171            .name("myTpl")
172            .z_order(TemplateZOrder::Front)
173            .base_loc("Tpl_10.xml");
174        let xml = tpl.to_xml_string();
175        assert!(xml.contains("ID=\"10\""));
176        assert!(xml.contains("TemplatePageName=\"myTpl\""));
177        assert!(xml.contains("ZOrder=\"Front\""));
178        assert!(xml.contains("BaseLoc=\"Tpl_10.xml\""));
179    }
180
181    #[test]
182    fn test_ct_template_page_clone_debug() {
183        let tpl = CT_TemplatePage::new(1).name("x");
184        let tpl2 = tpl.clone();
185        assert_eq!(tpl2.get_name(), Some("x"));
186        assert!(format!("{tpl:?}").contains("CT_TemplatePage"));
187    }
188}