1use std::{
2 cell::{Cell, RefCell},
3 rc::{Rc, Weak},
4};
5
6use crate::{
7 format::{FormatChangeResult, FormattedElement, IsFormat, TextFormat},
8 text_document::{Element, ElementManager, ElementTrait, ModelError},
9 Block,
10};
11
12#[derive(Default, Clone, Debug)]
13pub struct Text {
14 uuid: Cell<usize>,
15 element_manager: Weak<ElementManager>,
16 text: RefCell<String>,
17 text_format: RefCell<TextFormat>,
18}
19
20impl PartialEq for Text {
21 fn eq(&self, other: &Self) -> bool {
22 self.uuid == other.uuid && self.text_format == other.text_format
23 }
24}
25
26impl Text {
27 pub(crate) fn new(element_manager: Weak<ElementManager>) -> Self {
28 Text {
29 element_manager,
30 uuid: Default::default(),
31 text_format: RefCell::new(TextFormat {
32 ..Default::default()
33 }),
34 text: RefCell::new(String::new()),
35 }
36 }
37
38 pub fn uuid(&self) -> usize {
39 self.uuid.get()
40 }
41 pub(crate) fn text_format(&self) -> TextFormat {
42 self.format()
43 }
44
45 pub fn plain_text(&self) -> String {
46 self.text.borrow().clone()
47 }
48
49 pub(crate) fn set_text<S: Into<String>>(&self, text: S) {
50 let plain_text: String = text.into();
51 self.text.replace(plain_text);
52 }
53
54 pub(crate) fn insert_plain_text<S: Into<String>>(&self, position_in_text: usize, text: S) {
55 let plain_text: String = text.into();
56 self.text
57 .borrow_mut()
58 .insert_str(position_in_text, plain_text.as_str())
59 }
60
61 pub(crate) fn split(&self, position_in_text: usize) -> Element {
62 let element_manager = self.element_manager.upgrade().unwrap();
64 let new_text_rc = element_manager
65 .insert_new_text(self.uuid(), crate::text_document::InsertMode::After)
66 .unwrap();
67
68 let new_element = element_manager.get(new_text_rc.uuid()).unwrap();
69
70 let original_text = self.plain_text();
72 let split = original_text.split_at(position_in_text);
73 self.set_text(&split.0.to_string());
74 new_text_rc.set_text(&split.1.to_string());
75 new_text_rc.set_format(&self.text_format()).unwrap();
76
77 new_element
78 }
79
80 pub(crate) fn remove_text(
81 &self,
82 left_position_in_text: usize,
83 right_position_in_text: usize,
84 ) -> Result<(), ModelError> {
85 let mut text = self.plain_text();
86
87 if left_position_in_text > text.len() || right_position_in_text > text.len() {
88 return Err(ModelError::OutsideElementBounds);
89 }
90
91 text.replace_range(left_position_in_text..right_position_in_text, "");
92 self.set_text(&text);
93
94 Ok(())
95 }
96
97 pub fn text_length(&self) -> usize {
98 self.text.borrow().len()
99 }
100
101 fn parent_bloc_rc(&self) -> Rc<Block> {
102 let element_manager = self.element_manager.upgrade().unwrap();
103
104 match element_manager
105 .get_parent_element_using_uuid(self.uuid())
106 .unwrap()
107 {
108 Element::BlockElement(block) => block,
109 _ => unreachable!(),
110 }
111 }
112 pub fn position_in_block(&self) -> usize {
113 let parent_block = self.parent_bloc_rc();
114 parent_block.position_of_child(self.uuid())
115 }
116
117 pub fn start(&self) -> usize {
118 let parent_block = self.parent_bloc_rc();
119
120 parent_block.position() + self.position_in_block()
121 }
122
123 pub fn end(&self) -> usize {
124 self.start() + self.text_length()
125 }
126}
127
128impl ElementTrait for Text {
129 fn set_uuid(&self, uuid: usize) {
130 self.uuid.set(uuid);
131 }
132
133 fn verify_rule_with_parent(&self, parent_element: &Element) -> Result<(), ModelError> {
134 match parent_element {
135 Element::FrameElement(_) => Err(ModelError::WrongParent),
136 Element::BlockElement(_) => Ok(()),
137 Element::TextElement(_) => Err(ModelError::WrongParent),
138 Element::ImageElement(_) => Err(ModelError::WrongParent),
139 }
140 }
141}
142impl FormattedElement<TextFormat> for Text {
143 fn format(&self) -> TextFormat {
144 self.text_format.borrow().clone()
145 }
146
147 fn set_format(&self, format: &TextFormat) -> FormatChangeResult {
148 if &*self.text_format.borrow() == format {
149 Ok(None)
150 } else {
151 self.text_format.replace(format.clone());
152 Ok(Some(()))
153 }
154 }
155
156 fn merge_format(&self, format: &TextFormat) -> FormatChangeResult {
157 self.text_format.borrow_mut().merge_with(format)
158 }
159}
160
161#[cfg(test)]
162mod tests {
163
164 use super::*;
165
166 #[test]
167 fn remove_text() {
168 let text = Text::new(Weak::new());
169 text.set_text("plain_text");
170 text.remove_text(0, 10).unwrap();
171
172 assert_eq!(text.plain_text(), "");
173
174 text.set_text("plain_text");
175 text.remove_text(1, 9).unwrap();
176 assert_eq!(text.plain_text(), "pt");
177 }
178}