Skip to main content

script/dom/
selection_range.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use crate::dom::abstractrange::BoundaryPoint;
6use crate::dom::bindings::root::Dom;
7use crate::dom::node::Node;
8use crate::dom::range::Range;
9
10/// A selection boundary. This is similar to `BoundaryPoint`, but supports
11/// positions in the composed tree.
12#[derive(Clone, JSTraceable, PartialEq, MallocSizeOf)]
13#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
14pub(crate) struct SelectionBoundary {
15    pub container: Dom<Node>,
16    pub offset: u32,
17}
18
19impl SelectionBoundary {
20    pub(crate) fn new(container: &Node, offset: u32) -> Self {
21        Self {
22            container: Dom::from_ref(container),
23            offset,
24        }
25    }
26}
27
28impl PartialEq<BoundaryPoint> for SelectionBoundary {
29    fn eq(&self, boundary_point: &BoundaryPoint) -> bool {
30        *self.container == *boundary_point.node().get() &&
31            self.offset as usize == boundary_point.offset().0
32    }
33}
34
35#[derive(JSTraceable, PartialEq, MallocSizeOf)]
36#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
37pub(crate) struct SelectionRange {
38    pub start: SelectionBoundary,
39    pub end: SelectionBoundary,
40}
41
42impl SelectionRange {
43    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
44    pub(crate) fn new(start: SelectionBoundary, end: SelectionBoundary) -> Self {
45        Self { start, end }
46    }
47
48    #[cfg_attr(crown, expect(crown::unrooted_must_root))]
49    pub(crate) fn collapsed_at(at: SelectionBoundary) -> Self {
50        Self {
51            start: at.clone(),
52            end: at,
53        }
54    }
55
56    pub(crate) fn collapsed(&self) -> bool {
57        self.start == self.end
58    }
59
60    pub(crate) fn start_and_end_are_in_document_tree(&self) -> bool {
61        self.start.container.is_in_a_document_tree() && self.end.container.is_in_a_document_tree()
62    }
63}
64
65impl From<&Range> for SelectionRange {
66    fn from(range: &Range) -> Self {
67        Self::new(
68            SelectionBoundary::new(&range.start_container(), range.start_offset()),
69            SelectionBoundary::new(&range.end_container(), range.end_offset()),
70        )
71    }
72}