1use crate::format::{BlockFormat, FormatChangeResult, FormattedElement, IsFormat, TextFormat};
2use crate::text::Text;
3use crate::text_document::Element::{ImageElement, TextElement};
4use crate::text_document::{Element, ElementManager, ElementTrait, ModelError};
5use crate::ElementUuid;
6use std::cell::{Cell, RefCell};
7use std::rc::{Rc, Weak};
8
9#[derive(Clone, Debug)]
10pub struct Block {
11 uuid: Cell<usize>,
12 element_manager: Weak<ElementManager>,
13 block_format: RefCell<BlockFormat>,
15}
16
17impl PartialEq for Block {
18 fn eq(&self, other: &Self) -> bool {
19 self.uuid == other.uuid && self.block_format == other.block_format
20 }
21}
22
23impl Block {
24 pub(crate) fn new(element_manager: Weak<ElementManager>) -> Self {
25 Block {
26 uuid: Default::default(),
27 element_manager,
28 block_format: Default::default(),
29 }
30 }
31
32 pub fn uuid(&self) -> usize {
33 self.uuid.get()
34 }
35
36 pub fn iter(&self) -> BlockIter {
37 BlockIter::new(self)
38 }
39
40 pub fn position(&self) -> usize {
42 let mut counter = 0;
43
44 for block in self.element_manager.upgrade().unwrap().block_list() {
45 if block.as_ref().eq(self) {
46 break;
47 }
48 counter += block.text_length();
49 counter += 1;
50 }
51
52 counter
53 }
54
55 pub fn block_number(&self) -> usize {
57 let mut counter = 0;
58
59 for block in self.element_manager.upgrade().unwrap().block_list() {
60 if block.as_ref().eq(self) {
61 break;
62 }
63
64 counter += 1;
65 }
66
67 counter
68 }
69
70 pub fn block_format(&self) -> BlockFormat {
72 self.format()
73 }
74
75 pub(crate) fn convert_position_from_document(&self, position_in_document: usize) -> usize {
76 position_in_document - self.position()
77 }
78
79 pub(crate) fn convert_position_from_block_to_child(&self, position_in_block: usize) -> usize {
80 let mut position = 0;
81 for child in self.list_all_children() {
82 if position_in_block == 0 {
83 return 0;
84 }
85
86 let child_end_position = match &child {
87 TextElement(text_rc) => position + text_rc.text_length(),
88 ImageElement(image_rc) => position + image_rc.text_length(),
89 _ => unreachable!(),
90 };
91
92 if (position..=child_end_position).contains(&position_in_block) {
93 return position_in_block - position;
94 }
95
96 position += child_end_position;
97 }
98
99 position
100 }
101
102 pub(crate) fn position_of_child(&self, uuid: ElementUuid) -> usize {
104 let mut position = 0;
105 for child in self.list_all_children() {
106 if child.uuid() == uuid {
107 break;
108 }
109
110 let length = match &child {
111 TextElement(text_rc) => text_rc.text_length(),
112 ImageElement(image_rc) => image_rc.text_length(),
113 _ => unreachable!(),
114 };
115
116 position += length;
117 }
118
119 position
120 }
121
122 pub(crate) fn text_format_at(&self, position_in_block: usize) -> Option<TextFormat> {
123 if position_in_block == 0 {
124 match self.first_child() {
125 Some(element) => match element {
126 TextElement(text) => Some(text.text_format()),
127 ImageElement(_) => None,
128 _ => None,
129 },
130 None => None,
131 }
132 } else {
133 None
134 }
135 }
136
137 fn first_child(&self) -> Option<Element> {
138 let element_manager = self.element_manager.upgrade().unwrap();
139
140 let next_element = element_manager.next_element(self.uuid())?;
141 match next_element {
142 TextElement(_) => Some(next_element),
143 ImageElement(_) => Some(next_element),
144 _ => None,
145 }
146 }
147
148 fn find_element(&self, position_in_block: usize) -> Option<Element> {
151 let mut position = 0;
152
153 for child in self.list_all_children() {
154 if position_in_block == 0 {
156 return Some(child);
157 }
158
159 let child_end_position = match &child {
160 TextElement(text_rc) => position + text_rc.text_length(),
161 ImageElement(image_rc) => position + image_rc.text_length(),
162 _ => unreachable!(),
163 };
164
165 if (position..=child_end_position).contains(&position_in_block) {
166 return Some(child);
167 }
168
169 position += child_end_position;
170 }
171
172 None
173 }
174
175 pub(crate) fn insert_plain_text(&self, plain_text: &str, position_in_block: usize) {
176 match self.find_element(position_in_block) {
177 Some(element) => match element {
178 TextElement(text_rc) => text_rc.insert_plain_text(
179 self.convert_position_from_block_to_child(position_in_block),
180 &plain_text.to_string(),
181 ),
182 ImageElement(_) => {
183 let new_text_rc = self.insert_new_text_element(position_in_block);
184 new_text_rc.set_text(&plain_text.to_string());
185 new_text_rc.set_format(&self.text_format()).unwrap();
186 }
187 _ => unreachable!(),
188 },
189 None => (),
190 }
191 }
192
193 fn insert_new_text_element(&self, position_in_block: usize) -> Rc<Text> {
194 match self.find_element(position_in_block) {
195 Some(element) => match element {
196 TextElement(text_rc) => {
197 if position_in_block != text_rc.position_in_block() + text_rc.text_length() {
199 text_rc.split(self.convert_position_from_block_to_child(position_in_block));
200 }
201 let element_manager = self.element_manager.upgrade().unwrap();
203 let new_text_rc = element_manager
204 .insert_new_text(text_rc.uuid(), crate::text_document::InsertMode::After);
205 new_text_rc.unwrap()
206 }
207 ImageElement(_) => {
208 let element_manager = self.element_manager.upgrade().unwrap();
210 let new_text_rc = element_manager
211 .insert_new_text(element.uuid(), crate::text_document::InsertMode::After);
212 new_text_rc.unwrap()
213 }
214 _ => unreachable!(),
215 },
216 None => unreachable!(),
217 }
218 }
219
220 pub(crate) fn set_plain_text(&self, plain_text: &str) {
221 self.clear();
222 self.insert_plain_text(plain_text, 0);
223 }
224
225 pub(crate) fn clear(&self) {
227 let element_manager = self.element_manager.upgrade().unwrap();
228 let children = self
229 .list_all_children()
230 .iter()
231 .map(|element| element.uuid())
232 .collect();
233
234 element_manager.remove(children);
235
236 element_manager
237 .insert_new_text(self.uuid(), crate::text_document::InsertMode::AsChild)
238 .unwrap();
239 }
240
241 pub fn list_all_children(&self) -> Vec<Element> {
242 let element_manager = self.element_manager.upgrade().unwrap();
243 element_manager.list_all_children(self.uuid())
244 }
245
246 pub fn text_format(&self) -> TextFormat {
248 match self.first_child().unwrap() {
249 TextElement(text_fragment) => text_fragment.text_format(),
250 ImageElement(_) => TextFormat::new(),
251 _ => unreachable!(),
252 }
253 }
254
255 pub(crate) fn set_text_format(&self, text_format: &TextFormat) {
257 self.list_all_children()
258 .iter()
259 .filter_map(|element| match element {
260 TextElement(text) => Some(text),
261 ImageElement(_) => None,
262 _ => unreachable!(),
263 })
264 .for_each(|text_fragment: &Rc<Text>| {
265 text_fragment.set_format(text_format).unwrap();
266 });
267 }
268
269 pub(crate) fn split(&self, position_in_block: usize) -> Result<Rc<Block>, ModelError> {
270 let element_manager = self.element_manager.upgrade().unwrap();
271
272 let new_block = element_manager
274 .insert_new_block(self.uuid(), crate::text_document::InsertMode::After)?;
275
276 let sub_element = self
279 .find_element(position_in_block)
280 .ok_or_else(|| ModelError::ElementNotFound("sub element not found".to_string()))?;
281
282 let new_text_after_text_split = match sub_element {
283 TextElement(text) => {
284 text.split(self.convert_position_from_block_to_child(position_in_block))
285 }
286 ImageElement(image) => TextElement(
287 element_manager
288 .insert_new_text(image.uuid(), crate::text_document::InsertMode::After)?,
289 ),
290 _ => unreachable!(),
291 };
292
293 let all_children_list = self.list_all_children();
295 let mut child_list: Vec<&Element> = all_children_list
296 .iter()
297 .skip_while(|element| element.uuid() != new_text_after_text_split.uuid())
298 .collect();
299 child_list.reverse();
300
301 for child in child_list {
302 element_manager.move_while_changing_parent(child.uuid(), new_block.uuid())?;
303 }
304
305 Ok(new_block)
306 }
307
308 fn analyze_for_merges(&self) {
309 let children = self.list_all_children();
310
311 'first_loop: for _ in 0..children.len() {
312 let children = self.list_all_children();
313 for element_window in children.windows(2) {
314 let first_text = match &element_window[0] {
315 TextElement(text) => text,
316 _ => continue,
317 };
318 let second_text = match &element_window[1] {
319 TextElement(text) => text,
320 _ => continue,
321 };
322
323 if first_text.text_format() == second_text.text_format() {
324 self.merge_text_elements(first_text, second_text);
325 continue 'first_loop;
326 }
327 }
328 }
329
330 }
333
334 pub(crate) fn merge_with(&self, other_block: Rc<Block>) -> Result<(), ModelError> {
335 let element_manager = self.element_manager.upgrade().unwrap();
336
337 let mut own_children = self.list_all_children();
338 let mut other_children = other_block.list_all_children();
339
340 own_children.append(&mut other_children);
341 own_children.reverse();
342
343 own_children.iter().try_for_each(|element| {
344 element_manager.move_while_changing_parent(element.uuid(), self.uuid())
345 })?;
346
347 element_manager.remove(vec![other_block.uuid()]);
348
349 Ok(())
350 }
351
352 fn merge_text_elements(&self, first_text_rc: &Rc<Text>, second_text_rc: &Rc<Text>) -> Rc<Text> {
354 first_text_rc
355 .set_text(&(first_text_rc.plain_text() + second_text_rc.plain_text().as_str()));
356 let element_manager = self.element_manager.upgrade().unwrap();
357 element_manager.remove(vec![second_text_rc.uuid()]);
358
359 first_text_rc.clone()
360 }
361
362 pub fn plain_text(&self) -> String {
364 let texts: Vec<String> = self
365 .list_all_children()
366 .iter()
367 .map(|fragment| match fragment {
368 TextElement(text_rc) => text_rc.plain_text(),
369 ImageElement(image_rc) => image_rc.plain_text(),
370 _ => unreachable!(),
371 })
372 .collect();
373 texts.join("")
374 }
375
376 pub(crate) fn plain_text_between_positions(
377 &self,
378 position_in_block: usize,
379 anchor_position_in_block: usize,
380 ) -> String {
381 let mut position_in_block = position_in_block;
382 let mut anchor_position_in_block = anchor_position_in_block;
383
384 let text_length = self.text_length();
385
386 if position_in_block > text_length {
387 position_in_block = text_length;
388 }
389 if anchor_position_in_block > text_length {
390 anchor_position_in_block = text_length;
391 }
392
393 self.plain_text()[position_in_block..anchor_position_in_block].to_string()
394 }
395
396 pub(crate) fn remove_between_positions(
398 &self,
399 position_in_block: usize,
400 anchor_position_in_block: usize,
401 ) -> Result<(usize, usize), ModelError> {
402 let left_position = position_in_block.min(anchor_position_in_block);
403 let right_position = anchor_position_in_block.max(position_in_block);
404
405 let left_element = self
406 .find_element(left_position)
407 .ok_or_else(|| ModelError::ElementNotFound("left_element not found".to_string()))?;
408 let right_element = self
409 .find_element(right_position)
410 .ok_or_else(|| ModelError::ElementNotFound("right_element not found".to_string()))?;
411
412 if left_element == right_element {
414 match left_element {
415 TextElement(text) => {
416 let left_position_in_child =
417 self.convert_position_from_block_to_child(left_position);
418 let right_position_in_child =
419 self.convert_position_from_block_to_child(right_position);
420 text.remove_text(left_position_in_child, right_position_in_child)?;
421 }
422 ImageElement(_) => return Ok((0, 0)),
424 _ => unreachable!(),
425 }
426 }
427 else {
429 let element_manager = self.element_manager.upgrade().unwrap();
430
431 match &right_element {
433 TextElement(text) => {
434 let left_position_in_child = 0;
435 let right_position_in_child =
436 self.convert_position_from_block_to_child(right_position);
437 text.remove_text(left_position_in_child, right_position_in_child)?;
438 }
439 ImageElement(image) => element_manager.remove(vec![image.uuid()]),
441 _ => unreachable!(),
442 }
443
444 match &left_element {
446 TextElement(text) => {
447 let left_position_in_child =
448 self.convert_position_from_block_to_child(left_position);
449 let right_position_in_child = text.text_length();
450 text.remove_text(left_position_in_child, right_position_in_child)?;
451 }
452 ImageElement(_) => (),
454 _ => unreachable!(),
455 }
456
457 element_manager.remove(
460 self.list_all_children()
461 .iter()
462 .skip_while(|element| element.uuid() != left_element.uuid())
463 .skip(1)
464 .take_while(|element| element.uuid() != right_element.uuid())
465 .map(|element| element.uuid())
466 .collect(),
467 )
468 }
469
470 self.analyze_for_merges();
471
472 let removed_characters_count = right_position - left_position;
473
474 let new_position_in_document = self.position() + left_position;
475
476 Ok((new_position_in_document, removed_characters_count))
477 }
478
479 pub fn text_length(&self) -> usize {
481 let all_children = self.list_all_children();
482 let mut counter: usize = 0;
483
484 for element in all_children {
485 counter += match element {
486 TextElement(text) => text.plain_text().len(),
487 ImageElement(_) => 1,
488 _ => 0,
489 };
490 }
491
492 counter
493 }
494 pub fn start(&self) -> usize {
496 self.position()
497 }
498
499 pub fn end(&self) -> usize {
501 self.start() + self.text_length()
502 }
503}
504
505impl ElementTrait for Block {
506 fn set_uuid(&self, uuid: usize) {
507 self.uuid.set(uuid);
508 }
509
510 fn verify_rule_with_parent(&self, parent_element: &Element) -> Result<(), ModelError> {
511 match parent_element {
512 Element::FrameElement(_) => Ok(()),
513 Element::BlockElement(_) => Err(ModelError::WrongParent),
514 Element::TextElement(_) => Err(ModelError::WrongParent),
515 Element::ImageElement(_) => Err(ModelError::WrongParent),
516 }
517 }
518}
519
520impl FormattedElement<BlockFormat> for Block {
521 fn format(&self) -> BlockFormat {
522 self.block_format.borrow().clone()
523 }
524
525 fn set_format(&self, format: &BlockFormat) -> FormatChangeResult {
526 if &*self.block_format.borrow() == format {
527 Ok(None)
528 } else {
529 self.block_format.replace(format.clone());
530 Ok(Some(()))
531 }
532 }
533
534 fn merge_format(&self, format: &BlockFormat) -> Result<Option<()>, ModelError> {
535 self.block_format.borrow_mut().merge_with(format)
536 }
537}
538
539pub struct BlockIter {
540 unvisited: Vec<Element>,
541}
542
543impl BlockIter {
544 fn new(block: &Block) -> Self {
545 let ordered_elements = block.list_all_children();
546
547 BlockIter {
548 unvisited: ordered_elements,
549 }
550 }
551}
552
553impl Iterator for BlockIter {
554 type Item = Element;
555
556 fn next(&mut self) -> Option<Self::Item> {
557 let element = self.unvisited.pop()?;
558
559 Some(element)
560 }
561}
562
563#[cfg(test)]
564mod tests {
565 use crate::text_document::InsertMode;
566
567 use super::*;
568
569 #[test]
570 fn list_all_children() {
571 let element_manager_rc = ElementManager::new_rc();
572 ElementManager::create_root_frame(element_manager_rc.clone());
573
574 let block = element_manager_rc
575 .insert_new_block(0, InsertMode::AsChild)
576 .unwrap();
577 let text = element_manager_rc
578 .insert_new_text(block.uuid(), InsertMode::AsChild)
579 .unwrap();
580 element_manager_rc.debug_elements();
581 assert_eq!(block.list_all_children(), vec![TextElement(text)]);
582 }
583
584 #[test]
585 fn set_plain_text() {
586 let element_manager_rc = ElementManager::new_rc();
587 ElementManager::create_root_frame(element_manager_rc.clone());
588
589 let block = element_manager_rc
590 .insert_new_block(0, InsertMode::AsChild)
591 .unwrap();
592 block.set_plain_text("plain_text");
593 element_manager_rc.debug_elements();
594 assert_eq!(block.plain_text(), "plain_text");
595 }
596
597 #[test]
598 fn remove_between_positions() {
599 let element_manager_rc = ElementManager::new_rc();
600 ElementManager::create_root_frame(element_manager_rc.clone());
601
602 let block = element_manager_rc
603 .insert_new_block(0, InsertMode::AsChild)
604 .unwrap();
605 block.set_plain_text("plain_text");
606
607 let (position, removed_count) = block.remove_between_positions(1, 6).unwrap();
608
609 assert_eq!(removed_count, 5);
610 assert_eq!(position, 2);
611 assert_eq!(block.plain_text(), "ptext");
612 }
613
614 #[test]
615 fn remove_between_positions_in_2_texts() {
616 let element_manager_rc = ElementManager::new_rc();
617 ElementManager::create_root_frame(element_manager_rc.clone());
618
619 let block = element_manager_rc
620 .insert_new_block(0, InsertMode::AsChild)
621 .unwrap();
622 block.set_plain_text("plain_text");
623
624 let new_text_rc = block.insert_new_text_element(block.text_length());
625 new_text_rc.set_text(" is life");
626 element_manager_rc.debug_elements();
627
628 assert_eq!(block.plain_text(), "plain_text is life");
629
630 let (position, removed_count) = block.remove_between_positions(1, 14).unwrap();
631
632 assert_eq!(removed_count, 13);
633 assert_eq!(position, 2);
634 assert_eq!(block.plain_text(), "plife");
635 }
636
637 #[test]
638 fn convert_position_from_block_to_child() {
639 let element_manager_rc = ElementManager::new_rc();
640 ElementManager::create_root_frame(element_manager_rc.clone());
641
642 let block = element_manager_rc
643 .insert_new_block(0, InsertMode::AsChild)
644 .unwrap();
645 block.set_plain_text("plain_text");
646
647 let new_text_rc = block.insert_new_text_element(block.text_length());
648 new_text_rc.set_text(" is life");
649 element_manager_rc.debug_elements();
650
651 assert_eq!(block.plain_text(), "plain_text is life");
652
653 assert_eq!(3, block.convert_position_from_block_to_child(3));
654 assert_eq!(4, block.convert_position_from_block_to_child(14));
655 assert_eq!(8, block.convert_position_from_block_to_child(18));
656 }
657 #[test]
658 fn plain_text_between_positions() {
659 let element_manager_rc = ElementManager::new_rc();
660 ElementManager::create_root_frame(element_manager_rc.clone());
661
662 let block = element_manager_rc
663 .insert_new_block(0, InsertMode::AsChild)
664 .unwrap();
665 block.set_plain_text("plain_text");
666
667 assert_eq!(block.plain_text_between_positions(0, 1), "p");
668 assert_eq!(block.plain_text_between_positions(2, 4), "ai");
669 assert_eq!(block.plain_text_between_positions(0, 10), "plain_text");
670 }
671
672 #[test]
673 fn split() {
674 let element_manager_rc = ElementManager::new_rc();
675 ElementManager::create_root_frame(element_manager_rc.clone());
676
677 let block = element_manager_rc
678 .insert_new_block(0, InsertMode::AsChild)
679 .unwrap();
680 block.set_plain_text("plain_text");
681
682 let new_block = block.split(2).unwrap();
683 element_manager_rc.debug_elements();
684 assert_eq!(block.plain_text(), "pl");
685 assert_eq!(new_block.plain_text(), "ain_text");
686
687 element_manager_rc.clear();
688 let block = element_manager_rc
689 .insert_new_block(0, InsertMode::AsChild)
690 .unwrap();
691 block.set_plain_text("plain_text");
692
693 let new_block = block.split(10).unwrap();
694 element_manager_rc.debug_elements();
695 assert_eq!(block.plain_text(), "plain_text");
696 assert_eq!(new_block.plain_text(), "");
697 }
698
699 #[test]
700 fn merge_text_elements() {
701 let element_manager_rc = ElementManager::new_rc();
702 ElementManager::create_root_frame(element_manager_rc.clone());
703
704 let block = element_manager_rc.first_block().unwrap();
705 block.set_plain_text("plain_text");
706
707 let first_text_rc = block.iter().next().unwrap().get_text().unwrap();
708
709 let new_text_rc = block.insert_new_text_element(block.text_length());
710 new_text_rc.set_text(" is life");
711 element_manager_rc.debug_elements();
712
713 assert_eq!(block.plain_text(), "plain_text is life");
714
715 block.merge_text_elements(&first_text_rc, &new_text_rc);
718 assert_eq!(first_text_rc.plain_text(), "plain_text is life");
719 assert_eq!(block.plain_text(), "plain_text is life");
720 element_manager_rc.debug_elements();
721
722 }
724 #[test]
725 fn analyze_for_merges_of_text_elements() {
726 let element_manager_rc = ElementManager::new_rc();
727 ElementManager::create_root_frame(element_manager_rc.clone());
728
729 let block = element_manager_rc.first_block().unwrap();
730 block.set_plain_text("plain_text");
731
732 let first_text_rc = block.iter().next().unwrap().get_text().unwrap();
733 block.insert_new_text_element(block.text_length());
734
735 let new_text_rc = block.insert_new_text_element(block.text_length());
736 new_text_rc.set_text(" is life");
737 element_manager_rc.debug_elements();
738
739 block.insert_new_text_element(block.text_length());
740 element_manager_rc.debug_elements();
741
742 assert_eq!(block.plain_text(), "plain_text is life");
743 assert_eq!(block.iter().count(), 4);
744
745 block.analyze_for_merges();
746 assert_eq!(block.iter().count(), 1);
747 assert_eq!(first_text_rc.plain_text(), "plain_text is life");
748 assert_eq!(block.plain_text(), "plain_text is life");
749
750 }
752
753 #[test]
754 fn insert_new_text_element() {
755 let element_manager_rc = ElementManager::new_rc();
756 ElementManager::create_root_frame(element_manager_rc.clone());
757
758 let block = element_manager_rc.first_block().unwrap();
759 block.set_plain_text("plain_text");
760
761 block.insert_new_text_element(block.text_length());
762 element_manager_rc.debug_elements();
763
764 let new_text_rc = block.insert_new_text_element(block.text_length());
765 new_text_rc.set_text(" is life");
766 element_manager_rc.debug_elements();
767
768 block.insert_new_text_element(block.text_length());
769 element_manager_rc.debug_elements();
770
771 assert_eq!(block.plain_text(), "plain_text is life");
772 assert_eq!(block.iter().count(), 4);
773 }
774
775 #[test]
776 fn block_text_format() {
777 let element_manager_rc = ElementManager::new_rc();
778 ElementManager::create_root_frame(element_manager_rc.clone());
779
780 let block = element_manager_rc.first_block().unwrap();
781 block.set_plain_text("bold plain_text");
782
783 block.insert_new_text_element(block.text_length());
784 element_manager_rc.debug_elements();
785
786 let new_text_rc = block.insert_new_text_element(block.text_length());
787 new_text_rc.set_text(" is life");
788 element_manager_rc.debug_elements();
789
790 block.insert_new_text_element(block.text_length());
791 element_manager_rc.debug_elements();
792
793 assert_eq!(block.plain_text(), "bold plain_text is life");
794 assert_eq!(block.iter().count(), 4);
795
796 let mut text_format = TextFormat::new();
798 text_format.set_bold(true);
799
800 block.set_text_format(&text_format);
801
802 block
803 .iter()
804 .filter_map(|element| element.get_text())
805 .for_each(|text: Rc<Text>| assert!(text.format().bold()));
806 }
807}