text_document/
text_cursor.rs

1use std::rc::{Rc, Weak};
2
3use crate::block::Block;
4use crate::format::{BlockFormat, FormattedElement, FrameFormat, TextFormat};
5use crate::frame::Frame;
6use crate::text_document::Element::BlockElement;
7use crate::text_document::{ElementManager, InsertMode, ModelError};
8use crate::{ChangeReason, Element};
9
10#[derive(Clone)]
11pub struct TextCursor {
12    element_manager: Rc<ElementManager>,
13    position: usize,
14    anchor_position: usize,
15}
16
17impl TextCursor {
18    pub(crate) fn new(element_manager: Rc<ElementManager>) -> Self {
19        Self {
20            element_manager,
21            position: Default::default(),
22            anchor_position: Default::default(),
23        }
24    }
25
26    pub fn position(&self) -> usize {
27        let mut position = self.position;
28
29        let end_of_document = self.element_manager.root_frame().end();
30        if position > end_of_document {
31            position = end_of_document;
32        }
33
34        position
35    }
36
37    pub fn anchor_position(&self) -> usize {
38        let mut anchor_position = self.anchor_position;
39
40        let end_of_document = self.element_manager.root_frame().end();
41        if anchor_position > end_of_document {
42            anchor_position = end_of_document;
43        }
44
45        anchor_position
46    }
47
48    /// set the cursor position, with or without the anchor depending of move_mode. Ensure that the cursor position is in the document.
49    pub fn set_position(&mut self, position: usize, move_mode: MoveMode) {
50        let mut position = position;
51
52        let end_of_document = self.element_manager.root_frame().end();
53        if position > end_of_document {
54            position = end_of_document;
55        }
56
57        match move_mode {
58            MoveMode::MoveAnchor => {
59                self.position = position;
60                self.anchor_position = position;
61            }
62            MoveMode::KeepAnchor => self.position = position,
63        }
64    }
65
66    /// Give the current block under the cursor position
67    pub fn current_block(&self) -> Weak<Block> {
68        Rc::downgrade(&self.current_block_rc())
69    }
70
71    fn current_block_rc(&self) -> Rc<Block> {
72        self.element_manager
73            .find_block(self.position)
74            .unwrap_or_else(|| self.element_manager.last_block().unwrap())
75    }
76
77    pub fn set_block_format(&mut self, block_format: &BlockFormat) -> Result<(), ModelError> {
78        if self.position == self.anchor_position {
79            let current_block = self.current_block().upgrade().ok_or_else(|| {
80                ModelError::ElementNotFound("current block not found".to_string())
81            })?;
82
83            match current_block.set_format(block_format) {
84                Ok(option) => match option {
85                    Some(_) => {
86                        self.element_manager.signal_for_element_change(
87                            Element::BlockElement(current_block.clone()),
88                            ChangeReason::FormatChanged,
89                        );
90                        Ok(())
91                    }
92                    None => Ok(()),
93                },
94                Err(_) => Err(ModelError::Unknown),
95            }
96        } else {
97            let left_position = self.position.min(self.anchor_position);
98            let right_position = self.anchor_position.max(self.position);
99
100            let top_block = self
101                .element_manager
102                .find_block(left_position)
103                .ok_or_else(|| ModelError::ElementNotFound("tob block not found".to_string()))?;
104            let bottom_block = self
105                .element_manager
106                .find_block(right_position)
107                .ok_or_else(|| ModelError::ElementNotFound("bottom block not found".to_string()))?;
108
109            let mut target_list: Vec<Rc<Block>> = self
110                .element_manager
111                .list_all_children(0)
112                .iter()
113                .skip_while(|element| element.uuid() != top_block.uuid())
114                .take_while(|element| element.uuid() != bottom_block.uuid())
115                .filter_map(|element| element.get_block())
116                .collect();
117
118            target_list.push(bottom_block);
119
120            // merge, keeping changed elements
121            let list_to_signal: Vec<Rc<Block>> = target_list
122                .iter()
123                .filter_map(|block| {
124                    block
125                        .set_format(block_format)
126                        .unwrap()
127                        .map(|()| block.clone())
128                })
129                .collect();
130
131            list_to_signal.iter().for_each(|block| {
132                self.element_manager.signal_for_element_change(
133                    Element::BlockElement(block.clone()),
134                    ChangeReason::FormatChanged,
135                );
136                let block_length = block.text_length();
137                self.element_manager.signal_for_text_change(
138                    block.position(),
139                    block_length,
140                    block_length,
141                );
142            });
143
144            Ok(())
145        }
146    }
147
148    pub fn merge_block_format(&mut self, block_format: &BlockFormat) -> Result<(), ModelError> {
149        if self.position == self.anchor_position {
150            let current_block = self.current_block().upgrade().ok_or_else(|| {
151                ModelError::ElementNotFound("current block not found".to_string())
152            })?;
153
154            match current_block.merge_format(block_format) {
155                Ok(option) => match option {
156                    Some(_) => {
157                        self.element_manager.signal_for_element_change(
158                            Element::BlockElement(current_block.clone()),
159                            ChangeReason::FormatChanged,
160                        );
161                        Ok(())
162                    }
163                    None => Ok(()),
164                },
165                Err(_) => Err(ModelError::Unknown),
166            }
167        } else {
168            let left_position = self.position.min(self.anchor_position);
169            let right_position = self.anchor_position.max(self.position);
170
171            let top_block = self
172                .element_manager
173                .find_block(left_position)
174                .ok_or_else(|| ModelError::ElementNotFound("tob block not found".to_string()))?;
175            let bottom_block = self
176                .element_manager
177                .find_block(right_position)
178                .ok_or_else(|| ModelError::ElementNotFound("bottom block not found".to_string()))?;
179
180            let mut target_list: Vec<Rc<Block>> = self
181                .element_manager
182                .list_all_children(0)
183                .iter()
184                .skip_while(|element| element.uuid() != top_block.uuid())
185                .take_while(|element| element.uuid() != bottom_block.uuid())
186                .filter_map(|element| element.get_block())
187                .collect();
188
189            target_list.push(bottom_block);
190
191            // merge, keeping changed elements
192            let list_to_signal: Vec<Rc<Block>> = target_list
193                .iter()
194                .filter_map(|block| {
195                    block
196                        .merge_format(block_format)
197                        .unwrap()
198                        .map(|()| block.clone())
199                })
200                .collect();
201
202            list_to_signal.iter().for_each(|block| {
203                self.element_manager.signal_for_element_change(
204                    Element::BlockElement(block.clone()),
205                    ChangeReason::FormatChanged,
206                );
207                let block_length = block.text_length();
208                self.element_manager.signal_for_text_change(
209                    block.position(),
210                    block_length,
211                    block_length,
212                );
213            });
214
215            Ok(())
216        }
217    }
218
219    // split block at position, like if a new line is inserted
220    pub fn insert_block(&mut self) -> Result<Weak<Block>, ModelError> {
221        // fix positions
222        let left_position = self.position.min(self.anchor_position);
223        let right_position = self.anchor_position.max(self.position);
224
225        let mut new_position = left_position;
226        let mut removed_characters_count = 0;
227        if left_position != right_position {
228            // for now, new_position is wrong, to be implemented
229            (new_position, removed_characters_count) = self
230                .remove_with_signal(left_position, right_position, false)
231                .unwrap();
232        }
233
234        // find reference block
235        let old_block_rc = self
236            .element_manager
237            .find_block(new_position)
238            .ok_or_else(|| {
239                ModelError::ElementNotFound(format!("block not found at {}", new_position))
240            })?;
241
242        let _u = old_block_rc.uuid();
243
244        let new_block =
245            old_block_rc.split(old_block_rc.convert_position_from_document(new_position))?;
246        let _w = new_block.uuid();
247        let _order = self
248            .element_manager
249            .get_element_order(self.element_manager.get(new_block.uuid()).unwrap())
250            .unwrap();
251
252        // if new block empty, create empty child text element
253
254        if new_block.list_all_children().is_empty() {
255            self.element_manager
256                .insert_new_text(new_block.uuid(), InsertMode::AsChild)?;
257        }
258
259        let beginning_of_new_block = new_position + 1;
260
261        // reset cursor position and selection
262        self.set_position(beginning_of_new_block, MoveMode::MoveAnchor);
263
264        // signaling changes
265        self.element_manager
266            .signal_for_text_change(new_position, removed_characters_count, 1);
267
268        self.element_manager.signal_for_element_change(
269            self.element_manager
270                .get_parent_element(&Element::BlockElement(old_block_rc))
271                .unwrap(),
272            ChangeReason::ChildrenChanged,
273        );
274
275        Ok(Rc::downgrade(&new_block))
276    }
277
278    /// Give the current frame under the cursor position
279    pub fn current_frame(&self) -> Weak<Frame> {
280        Rc::downgrade(&self.current_frame_rc())
281    }
282
283    fn current_frame_rc(&self) -> Rc<Frame> {
284        self.element_manager
285            .find_frame(self.position)
286            .unwrap_or_else(|| self.element_manager.root_frame())
287    }
288
289    pub fn set_frame_format(&mut self, frame_format: &FrameFormat) -> Result<(), ModelError> {
290        if self.position == self.anchor_position {
291            let current_frame = self.current_frame().upgrade().ok_or_else(|| {
292                ModelError::ElementNotFound("current frame not found".to_string())
293            })?;
294
295            match current_frame.set_format(frame_format) {
296                Ok(option) => match option {
297                    Some(_) => {
298                        self.element_manager.signal_for_element_change(
299                            Element::FrameElement(current_frame.clone()),
300                            ChangeReason::FormatChanged,
301                        );
302                        Ok(())
303                    }
304                    None => Ok(()),
305                },
306                Err(_) => Err(ModelError::Unknown),
307            }
308        } else {
309            let left_position = self.position.min(self.anchor_position);
310            let right_position = self.anchor_position.max(self.position);
311
312            let top_block = self
313                .element_manager
314                .find_block(left_position)
315                .ok_or_else(|| ModelError::ElementNotFound("tob block not found".to_string()))?;
316            let top_frame = self
317                .element_manager
318                .get_parent_element_using_uuid(top_block.uuid())
319                .ok_or_else(|| ModelError::ElementNotFound("tob frame not found".to_string()))?
320                .get_frame()
321                .ok_or_else(|| ModelError::ElementNotFound("bottom frame not found".to_string()))?;
322            let bottom_block = self
323                .element_manager
324                .find_block(right_position)
325                .ok_or_else(|| ModelError::ElementNotFound("bottom block not found".to_string()))?;
326            let bottom_frame = self
327                .element_manager
328                .get_parent_element_using_uuid(bottom_block.uuid())
329                .ok_or_else(|| ModelError::ElementNotFound("bottom frame not found".to_string()))?
330                .get_frame()
331                .ok_or_else(|| ModelError::ElementNotFound("bottom frame not found".to_string()))?;
332
333            let mut target_list: Vec<Rc<Frame>> = Vec::new();
334            if top_frame == bottom_frame {
335                target_list.push(top_frame);
336            } else {
337                target_list = self
338                    .element_manager
339                    .list_all_children(0)
340                    .iter()
341                    .skip_while(|element| element.uuid() != top_frame.uuid())
342                    .take_while(|element| element.uuid() != bottom_frame.uuid())
343                    .filter_map(|element| element.get_frame())
344                    .collect();
345            }
346
347            // merge, keeping changed elements
348            let list_to_signal: Vec<Rc<Frame>> = target_list
349                .iter()
350                .filter_map(|frame| {
351                    frame
352                        .set_format(frame_format)
353                        .unwrap()
354                        .map(|()| frame.clone())
355                })
356                .collect();
357
358            list_to_signal.iter().for_each(|frame| {
359                self.element_manager.signal_for_element_change(
360                    Element::FrameElement(frame.clone()),
361                    ChangeReason::FormatChanged,
362                );
363                let frame_length = frame.text_length();
364                self.element_manager.signal_for_text_change(
365                    frame.first_cursor_position(),
366                    frame_length,
367                    frame_length,
368                );
369            });
370
371            Ok(())
372        }
373    }
374
375    pub fn merge_frame_format(&mut self, frame_format: &FrameFormat) -> Result<(), ModelError> {
376        if self.position == self.anchor_position {
377            let current_frame = self.current_frame().upgrade().ok_or_else(|| {
378                ModelError::ElementNotFound("current frame not found".to_string())
379            })?;
380
381            match current_frame.merge_format(frame_format) {
382                Ok(option) => match option {
383                    Some(_) => {
384                        self.element_manager.signal_for_element_change(
385                            Element::FrameElement(current_frame.clone()),
386                            ChangeReason::FormatChanged,
387                        );
388                        Ok(())
389                    }
390                    None => Ok(()),
391                },
392                Err(_) => Err(ModelError::Unknown),
393            }
394        } else {
395            let left_position = self.position.min(self.anchor_position);
396            let right_position = self.anchor_position.max(self.position);
397
398            let top_block = self
399                .element_manager
400                .find_block(left_position)
401                .ok_or_else(|| ModelError::ElementNotFound("tob block not found".to_string()))?;
402            let top_frame = self
403                .element_manager
404                .get_parent_element_using_uuid(top_block.uuid())
405                .ok_or_else(|| ModelError::ElementNotFound("tob frame not found".to_string()))?
406                .get_frame()
407                .ok_or_else(|| ModelError::ElementNotFound("bottom frame not found".to_string()))?;
408            let bottom_block = self
409                .element_manager
410                .find_block(right_position)
411                .ok_or_else(|| ModelError::ElementNotFound("bottom block not found".to_string()))?;
412            let bottom_frame = self
413                .element_manager
414                .get_parent_element_using_uuid(bottom_block.uuid())
415                .ok_or_else(|| ModelError::ElementNotFound("bottom frame not found".to_string()))?
416                .get_frame()
417                .ok_or_else(|| ModelError::ElementNotFound("bottom frame not found".to_string()))?;
418
419            let mut target_list: Vec<Rc<Frame>> = Vec::new();
420            if top_frame == bottom_frame {
421                target_list.push(top_frame);
422            } else {
423                target_list = self
424                    .element_manager
425                    .list_all_children(0)
426                    .iter()
427                    .skip_while(|element| element.uuid() != top_frame.uuid())
428                    .take_while(|element| element.uuid() != bottom_frame.uuid())
429                    .filter_map(|element| element.get_frame())
430                    .collect();
431            }
432
433            // merge, keeping changed elements
434            let list_to_signal: Vec<Rc<Frame>> = target_list
435                .iter()
436                .filter_map(|frame| {
437                    frame
438                        .merge_format(frame_format)
439                        .unwrap()
440                        .map(|()| frame.clone())
441                })
442                .collect();
443
444            // signal change for each frame
445            list_to_signal.iter().for_each(|frame| {
446                self.element_manager.signal_for_element_change(
447                    Element::FrameElement(frame.clone()),
448                    ChangeReason::FormatChanged,
449                );
450                let frame_length = frame.text_length();
451                self.element_manager.signal_for_text_change(
452                    frame.first_cursor_position(),
453                    frame_length,
454                    frame_length,
455                );
456            });
457
458            Ok(())
459        }
460    }
461
462    /// insert a frame at the cursor position
463    pub fn insert_frame(&mut self) -> Result<Weak<Frame>, ModelError> {
464        // fix positions
465        let left_position = self.position.min(self.anchor_position);
466        let right_position = self.anchor_position.max(self.position);
467
468        let mut new_position = left_position;
469        let mut removed_characters_count = 0;
470        if left_position != right_position {
471            // for now, new_position is wrong, to be implemented
472            (new_position, removed_characters_count) = self
473                .remove_with_signal(left_position, right_position, false)
474                .unwrap();
475        }
476
477        // find reference block
478        let old_block_rc = self
479            .element_manager
480            .find_block(new_position)
481            .unwrap_or_else(|| self.element_manager.last_block().unwrap());
482
483        let new_block =
484            old_block_rc.split(old_block_rc.convert_position_from_document(new_position))?;
485
486        // if new block empty, create text
487
488        if new_block.list_all_children().is_empty() {
489            self.element_manager
490                .insert_new_text(new_block.uuid(), InsertMode::AsChild)?;
491        }
492
493        // insert frame with block and text element
494        let frame = self
495            .element_manager
496            .insert_new_frame(old_block_rc.uuid(), InsertMode::After)?;
497        let block = self
498            .element_manager
499            .insert_new_block(frame.uuid(), InsertMode::AsChild)?;
500        let _text = self
501            .element_manager
502            .insert_new_text(block.uuid(), InsertMode::AsChild)?;
503
504        // reset cursor position and selection
505        self.set_position(block.position(), MoveMode::MoveAnchor);
506
507        // signaling changes
508        self.element_manager
509            .signal_for_text_change(new_position, removed_characters_count, 1);
510
511        self.element_manager.signal_for_element_change(
512            self.element_manager
513                .get_parent_element(&Element::FrameElement(frame.clone()))
514                .unwrap(),
515            ChangeReason::ChildrenChanged,
516        );
517
518        Ok(Rc::downgrade(&frame))
519    }
520
521    /// Insert plain text and return (start position, end position)
522    pub fn insert_plain_text<S: Into<String>>(
523        &mut self,
524        plain_text: S,
525    ) -> Result<(usize, usize), ModelError> {
526        let plain_text: String = plain_text.into();
527
528        // get char format
529        // let text_format: TextFormat = match self.text_format() {
530        //     Some(text_format) => text_format,
531        //     None => self.current_block_rc().text_format(),
532        // };
533
534        // fix positions
535        let left_position = self.position.min(self.anchor_position);
536        let right_position = self.anchor_position.max(self.position);
537
538        let mut new_position = left_position;
539        let start_position = left_position;
540        let mut removed_characters_count = 0;
541
542        if left_position != right_position {
543            // for now, new_position is wrong, to be implemented
544            (new_position, removed_characters_count) = self
545                .remove_with_signal(left_position, right_position, false)
546                .unwrap();
547        }
548
549        let mut first_loop = true;
550
551        let mut block = self
552            .element_manager
553            .find_block(new_position)
554            .unwrap_or_else(|| self.element_manager.last_block().unwrap());
555
556        let mut other_block_from_split = None;
557
558        let lines = plain_text.split('\n');
559        let mut index = 0;
560
561        let count = lines.clone().count();
562
563        for text_line in lines {
564            // insert on existing targeted block
565            if first_loop {
566                let position_in_block = block.convert_position_from_document(new_position);
567
568                // split targeted block
569                if count > 1 {
570                    other_block_from_split = block.split(position_in_block).ok();
571                    new_position += 1;
572                }
573
574                block.insert_plain_text(text_line, position_in_block);
575
576                first_loop = false;
577            }
578            // insertion of last line at the beginning of the second half of the split block
579            else if count - 1 == index {
580                match &other_block_from_split {
581                    Some(block) => {
582                        block.insert_plain_text(text_line, 0);
583                    }
584                    None => continue,
585                }
586            } else {
587                // new blocks for the rest of the text_line
588                block = self
589                    .element_manager
590                    .insert_new_block(block.uuid(), InsertMode::After)
591                    .unwrap();
592                block.set_plain_text(text_line);
593                new_position += 1;
594            }
595
596            index += 1;
597            new_position += text_line.len();
598        }
599
600        // reset cursor position and selection
601        self.set_position(block.position(), MoveMode::MoveAnchor);
602
603        // signaling changes
604        self.element_manager.signal_for_text_change(
605            start_position,
606            removed_characters_count,
607            plain_text.len(),
608        );
609
610        // if only one line, so one Block element changed
611        if count == 1 {
612            self.element_manager.signal_for_element_change(
613                Element::BlockElement(block),
614                ChangeReason::ChildrenChanged,
615            );
616        } else {
617            self.element_manager.signal_for_element_change(
618                self.element_manager
619                    .get_parent_element(&Element::BlockElement(block))
620                    .unwrap(),
621                ChangeReason::ChildrenChanged,
622            );
623        }
624
625        // set new cursor position
626        self.set_position(new_position, MoveMode::MoveAnchor);
627
628        Ok((start_position, new_position))
629    }
630
631    // select plain text between cursor position and the anchor position
632    pub fn selected_text(&self) -> String {
633        // fix positions
634        let left_position = self.position.min(self.anchor_position);
635        let right_position = self.anchor_position.max(self.position);
636        if left_position == right_position {
637            return String::new();
638        }
639
640        let top_block = match self.element_manager.find_block(left_position) {
641            Some(block) => block,
642            None => return String::new(),
643        };
644        let bottom_block = match self.element_manager.find_block(right_position) {
645            Some(block) => block,
646            None => return String::new(),
647        };
648
649        let left_position_in_block = top_block.convert_position_from_document(left_position);
650        let right_position_in_block = bottom_block.convert_position_from_document(right_position);
651
652        // same block:
653        if top_block == bottom_block {
654            top_block.plain_text_between_positions(left_position_in_block, right_position_in_block)
655        } else {
656            // first block
657            let mut string_list = vec![top_block
658                .plain_text_between_positions(left_position_in_block, top_block.text_length())];
659
660            self.element_manager
661                .list_all_children(0)
662                .iter()
663                .skip_while(|element| element.uuid() != top_block.uuid())
664                .skip(1)
665                .take_while(|element| element.uuid() != bottom_block.uuid())
666                .filter_map(|element| match element {
667                    BlockElement(block) => Some(block.plain_text()),
668                    _ => None,
669                })
670                .for_each(|string| string_list.push(string));
671
672            // last block
673            string_list.push(bottom_block.plain_text_between_positions(0, right_position_in_block));
674
675            let final_string = string_list.join("\n");
676
677            // take into account \n
678            let length_of_selection = right_position - left_position;
679
680            final_string[0..length_of_selection].to_string()
681        }
682    }
683
684    // fetch the char format at the cursor position. Anchor position is ignored
685    pub fn text_format(&self) -> Option<TextFormat> {
686        let block_rc = self.current_block_rc();
687
688        block_rc.text_format_at(block_rc.convert_position_from_document(self.position))
689    }
690
691    // fetch the block format at the cursor position. Anchor position is ignored
692    pub fn block_format(&self) -> Option<BlockFormat> {
693        let block_rc = self.current_block_rc();
694
695        Some(block_rc.block_format())
696    }
697
698    // fetch the frame format at the cursor position. Anchor position is ignored
699    pub fn frame_format(&self) -> Option<FrameFormat> {
700        let frame_rc = self.current_frame_rc();
701
702        Some(frame_rc.frame_format())
703    }
704
705    /// Remove elements between two positions. Split blocks if needed. Frames in superior level (i.e. children)
706    ///  are completely removed even if only a part of it is selected
707    ///
708    /// Return new position and number of removed chars
709    pub fn remove(&mut self) -> Result<(usize, usize), ModelError> {
710        self.remove_with_signal(self.position, self.anchor_position, true)
711    }
712
713    /// same as 'remove()' but with signal argument
714    fn remove_with_signal(
715        &mut self,
716        position: usize,
717        anchor_position: usize,
718        send_change_signals: bool,
719    ) -> Result<(usize, usize), ModelError> {
720        let new_position;
721        let mut removed_characters_count;
722
723        let left_position = position.min(anchor_position);
724        let right_position = anchor_position.max(position);
725
726        let top_block = self
727            .element_manager
728            .find_block(left_position)
729            .ok_or_else(|| ModelError::ElementNotFound("tob block not found".to_string()))?;
730        let bottom_block = self
731            .element_manager
732            .find_block(right_position)
733            .ok_or_else(|| ModelError::ElementNotFound("bottom block not found".to_string()))?;
734
735        let left_position_in_block = top_block.convert_position_from_document(left_position);
736        let right_position_in_block = bottom_block.convert_position_from_document(right_position);
737
738        // if selection is in the same block:
739        if top_block == bottom_block {
740            (new_position, removed_characters_count) = top_block
741                .remove_between_positions(left_position_in_block, right_position_in_block)?;
742
743            // reset cursor position and selection
744            self.set_position(new_position, MoveMode::MoveAnchor);
745
746            // signaling changes
747            self.element_manager
748                .signal_for_text_change(new_position, removed_characters_count, 0);
749
750            if send_change_signals {
751                self.element_manager.signal_for_element_change(
752                    Element::BlockElement(top_block),
753                    ChangeReason::ChildrenChanged,
754                );
755            }
756
757            return Ok((new_position, removed_characters_count));
758        }
759
760        let top_block_level = self.element_manager.get_level(top_block.uuid());
761        let bottom_block_level = self.element_manager.get_level(bottom_block.uuid());
762
763        let mut parent_element_for_signal: Element;
764
765        // determine if any element between top and bottom block is inferior than both, in this case the common ancestor is deleted whole
766
767        // Frame  --> common ancestor, so it will be removed
768        // |- Frame
769        //    |- Block  --> top block, selection start
770        //       |- Text
771        // |- Frame
772        //    |- Block  --> bottom block, selection end
773        //       |- Text
774
775        let min_level = top_block_level.min(bottom_block_level);
776        let has_common_ancestor_element = self
777            .element_manager
778            .list_all_children(0)
779            .iter()
780            // keep all between top and bottom blocks
781            .skip_while(|element| element.uuid() != top_block.uuid())
782            .skip(1)
783            .take_while(|element| element.uuid() != bottom_block.uuid())
784            .any(|element| {
785                let level = self.element_manager.get_level(element.uuid());
786                level < min_level
787            });
788
789        if has_common_ancestor_element {
790            // find this common ancestor
791            let common_ancestor = self
792                .element_manager
793                .find_common_ancestor(top_block.uuid(), bottom_block.uuid());
794
795            removed_characters_count = self
796                .element_manager
797                .get(common_ancestor)
798                .unwrap()
799                .text_length();
800            new_position = match self.element_manager.previous_element(common_ancestor) {
801                Some(element) => element.end_of_element(),
802                // means that the common ancestor is, in fact, the root frame
803                None => 0,
804            };
805
806            parent_element_for_signal = match self
807                .element_manager
808                .get_parent_element_using_uuid(common_ancestor)
809            {
810                Some(parent_of_ancestor) => parent_of_ancestor,
811                None => Element::FrameElement(self.element_manager.root_frame()),
812            };
813
814            self.element_manager.remove(vec![common_ancestor]);
815
816            // in case root frame is removed
817            if common_ancestor == 0 {
818                self.element_manager.clear();
819
820                parent_element_for_signal =
821                    Element::FrameElement(self.element_manager.root_frame());
822            }
823        }
824        // if top block's level is superior than (is a child of) bottom block
825
826        // Frame  --> common ancestor, so it will be removed
827        // |- Frame
828        //    |- Block  --> top block, selection start
829        //       |- Text
830        // |- Block  --> bottom block, selection end
831        //    |- Text
832        else if top_block_level > bottom_block_level {
833            //find ancestor which is direct child of bottom_block parent
834            let sibling_ancestor = self
835                .element_manager
836                .find_ancestor_of_first_which_is_sibling_of_second(
837                    top_block.uuid(),
838                    bottom_block.uuid(),
839                )
840                .ok_or_else(|| {
841                    ModelError::ElementNotFound("sibling ancestor not found".to_string())
842                })?;
843
844            removed_characters_count = self
845                .element_manager
846                .get(sibling_ancestor)
847                .unwrap()
848                .text_length();
849
850            new_position = match self.element_manager.previous_element(sibling_ancestor) {
851                Some(element) => element.end_of_element(),
852                // means that the common ancestor is, in fact, the root frame
853                None => 0,
854            };
855
856            parent_element_for_signal = match self
857                .element_manager
858                .get_parent_element_using_uuid(bottom_block.uuid())
859            {
860                Some(parent_of_ancestor) => parent_of_ancestor,
861                None => Element::FrameElement(self.element_manager.root_frame()),
862            };
863
864            self.element_manager.remove(vec![sibling_ancestor]);
865
866            removed_characters_count += bottom_block
867                .remove_between_positions(0, right_position_in_block)?
868                .1;
869
870            self.element_manager.remove(
871                self.element_manager
872                    .list_all_children(0)
873                    .iter()
874                    .skip_while(|element| element.uuid() != top_block.uuid())
875                    .skip(1)
876                    .take_while(|element| element.uuid() != bottom_block.uuid())
877                    .filter_map(|element| {
878                        if element.is_block() {
879                            removed_characters_count += element.text_length() + 1;
880                            return Some(element.uuid());
881                        }
882
883                        if element.is_frame() {
884                            return Some(element.uuid());
885                        }
886                        None
887                    })
888                    .collect(),
889            );
890        }
891        // if bottom block's level is superior than (is a child of) top block
892
893        // Frame  --> common ancestor, so it will be removed
894        // |- Block  --> top block, selection start
895        //    |- Text
896        // |- Frame
897        //    |- Block  --> bottom block, selection end
898        //       |- Text
899        else if top_block_level < bottom_block_level {
900            parent_element_for_signal = match self
901                .element_manager
902                .get_parent_element_using_uuid(top_block.uuid())
903            {
904                Some(parent_of_ancestor) => parent_of_ancestor,
905                None => Element::FrameElement(self.element_manager.root_frame()),
906            };
907
908            (new_position, removed_characters_count) = top_block
909                .remove_between_positions(left_position_in_block, top_block.text_length())?;
910            self.element_manager.debug_elements();
911
912            self.element_manager.remove(
913                self.element_manager
914                    .list_all_children(0)
915                    .iter()
916                    .skip_while(|element| element.uuid() != top_block.uuid())
917                    .skip(1)
918                    .take_while(|element| element.uuid() != bottom_block.uuid())
919                    .filter_map(|element| {
920                        if element.is_block() {
921                            removed_characters_count += element.text_length() + 1;
922                            return Some(element.uuid());
923                        }
924                        if element.is_frame() {
925                            return Some(element.uuid());
926                        }
927
928                        None
929                    })
930                    .collect(),
931            );
932        }
933        // if bottom block's level is strictly at the same level than top block
934
935        // Frame
936        // |- Frame  --> common ancestor, so it will be removed
937        //    |- Block  --> top block, selection start
938        //       |- Text
939        //    |- Block  --> bottom block, selection end
940        //       |- Text
941        else {
942            parent_element_for_signal = match self
943                .element_manager
944                .get_parent_element_using_uuid(top_block.uuid())
945            {
946                Some(parent_of_ancestor) => parent_of_ancestor,
947                None => Element::FrameElement(self.element_manager.root_frame()),
948            };
949
950            (new_position, removed_characters_count) = top_block
951                .remove_between_positions(left_position_in_block, top_block.text_length())?;
952
953            self.element_manager.remove(
954                self.element_manager
955                    .list_all_children(0)
956                    .iter()
957                    .skip_while(|element| element.uuid() != top_block.uuid())
958                    .skip(1)
959                    .take_while(|element| element.uuid() != bottom_block.uuid())
960                    .filter_map(|element| {
961                        if element.is_block() {
962                            removed_characters_count += element.text_length() + 1;
963                            return Some(element.uuid());
964                        }
965                        None
966                    })
967                    .collect(),
968            );
969
970            removed_characters_count += bottom_block
971                .remove_between_positions(0, right_position_in_block)?
972                .1;
973
974            top_block.merge_with(bottom_block)?;
975            removed_characters_count += 1;
976        }
977
978        self.element_manager.fill_empty_frames();
979        self.element_manager.recalculate_sort_order();
980
981        // reset cursor position and selection
982        self.set_position(new_position, MoveMode::MoveAnchor);
983
984        // signaling changes
985        self.element_manager
986            .signal_for_text_change(new_position, removed_characters_count, 0);
987
988        if send_change_signals {
989            self.element_manager.signal_for_element_change(
990                parent_element_for_signal,
991                ChangeReason::ChildrenChanged,
992            );
993        }
994
995        Ok((new_position, removed_characters_count))
996    }
997
998    pub fn move_position(&mut self, move_operation: MoveOperation, move_mode: MoveMode) {
999        match move_operation {
1000            MoveOperation::NoMove => (),
1001            MoveOperation::Start => self.set_position(0, move_mode),
1002            MoveOperation::StartOfLine => todo!(),
1003            MoveOperation::StartOfBlock => {
1004                self.set_position(self.current_block_rc().start(), move_mode)
1005            }
1006            MoveOperation::StartOfWord => todo!(),
1007            MoveOperation::PreviousBlock => todo!(),
1008            MoveOperation::PreviousCharacter => self.set_position(self.position - 1, move_mode),
1009            MoveOperation::PreviousWord => todo!(),
1010            MoveOperation::Up => todo!(),
1011            MoveOperation::Left => self.set_position(self.position - 1, move_mode),
1012            MoveOperation::WordLeft => todo!(),
1013            MoveOperation::End => {
1014                self.set_position(self.element_manager.root_frame().end(), move_mode)
1015            }
1016            MoveOperation::EndOfLine => todo!(),
1017            MoveOperation::EndOfWord => todo!(),
1018            MoveOperation::EndOfBlock => {
1019                self.set_position(self.current_block_rc().end(), move_mode)
1020            }
1021            MoveOperation::NextBlock => todo!(),
1022            MoveOperation::NextCharacter => self.set_position(self.position + 1, move_mode),
1023            MoveOperation::NextWord => todo!(),
1024            MoveOperation::Down => todo!(),
1025            MoveOperation::Right => self.set_position(self.position + 1, move_mode),
1026            MoveOperation::WordRight => todo!(),
1027            MoveOperation::NextCell => todo!(),
1028            MoveOperation::PreviousCell => todo!(),
1029            MoveOperation::NextRow => todo!(),
1030            MoveOperation::PreviousRow => todo!(),
1031        };
1032    }
1033}
1034
1035/// If the anchor() is kept where it is and the position() is moved, the text_line in between will be selected.
1036#[derive(Clone, Copy, PartialEq)]
1037pub enum MoveMode {
1038    /// Moves the anchor to the same position as the cursor itself.
1039    MoveAnchor,
1040    /// Keeps the anchor where it is.
1041    KeepAnchor,
1042}
1043impl Default for MoveMode {
1044    fn default() -> Self {
1045        MoveMode::MoveAnchor
1046    }
1047}
1048
1049pub enum MoveOperation {
1050    /// Keep the cursor where it is.
1051    NoMove,
1052    /// Move to the start of the document.
1053    Start,
1054    /// Move to the start of the current line.
1055    StartOfLine,
1056    /// Move to the start of the current block.
1057    StartOfBlock,
1058    /// Move to the start of the current word.
1059    StartOfWord,
1060    /// Move to the start of the previous block.
1061    PreviousBlock,
1062    /// Move to the previous character.
1063    PreviousCharacter,
1064    /// Move to the beginning of the previous word.
1065    PreviousWord,
1066    /// Move up one line.
1067    Up,
1068    /// Move left one character.
1069    Left,
1070    /// Move left one word.
1071    WordLeft,
1072    /// Move to the end of the document.
1073    End,
1074    /// Move to the end of the current line.
1075    EndOfLine,
1076    /// Move to the end of the current word.
1077    EndOfWord,
1078    /// Move to the end of the current block.
1079    EndOfBlock,
1080    /// Move to the beginning of the next block.
1081    NextBlock,
1082    /// Move to the next character.
1083    NextCharacter,
1084    /// Move to the next word.
1085    NextWord,
1086    /// Move down one line.
1087    Down,
1088    /// Move right one character.
1089    Right,
1090    /// Move right one word.
1091    WordRight,
1092    /// Move to the beginning of the next table cell inside the current table. If the current cell is the last cell in the row, the cursor will move to the first cell in the next row.
1093    NextCell,
1094    /// Move to the beginning of the previous table cell inside the current table. If the current cell is the first cell in the row, the cursor will move to the last cell in the previous row.
1095    PreviousCell,
1096    /// Move to the first new cell of the next row in the current table.
1097    NextRow,
1098    /// Move to the last cell of the previous row in the current table.
1099    PreviousRow,
1100}