spreadsheet_ods/
sheet_.rs

1//!
2//! One sheet of the spreadsheet.
3//!
4
5use get_size::GetSize;
6use get_size_derive::GetSize;
7use std::collections::{BTreeMap, Bound};
8use std::fmt::{Debug, Display, Formatter};
9use std::iter::FusedIterator;
10use std::ops::RangeBounds;
11use std::{fmt, mem};
12
13use crate::cell_::{CellContent, CellContentRef, CellData};
14use crate::draw::{Annotation, DrawFrame};
15use crate::style::{ColStyleRef, RowStyleRef, TableStyleRef};
16use crate::validation::ValidationRef;
17use crate::value_::Value;
18use crate::xmltree::XmlTag;
19use crate::{CellRange, CellStyleRef, Length, OdsError};
20
21#[cfg(test)]
22mod tests;
23
24/// Visibility of a column or row.
25#[derive(Debug, Clone, Copy, Eq, PartialEq, Default, GetSize)]
26#[allow(missing_docs)]
27pub enum Visibility {
28    #[default]
29    Visible,
30    Collapsed,
31    Filtered,
32}
33
34impl Display for Visibility {
35    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> {
36        match self {
37            Visibility::Visible => write!(f, "visible"),
38            Visibility::Collapsed => write!(f, "collapse"),
39            Visibility::Filtered => write!(f, "filter"),
40        }
41    }
42}
43
44/// Row data
45#[derive(Debug, Clone, GetSize)]
46pub(crate) struct RowHeader {
47    pub(crate) style: Option<RowStyleRef>,
48    pub(crate) cellstyle: Option<CellStyleRef>,
49    pub(crate) visible: Visibility,
50    /// Value of the table:number-rows-repeated.
51    ///
52    /// This value is moved to span if use_repeat_for_cells is not set.
53    /// This way a programmatic set_repeat() is possible without cloning
54    /// all the row-data. When writing the necessary data is found via
55    /// the range row..row+span and doesn't interfere with any calculated
56    /// repeat-values.
57    pub(crate) repeat: u32,
58    /// Logical valid range for all the header values. Avoids duplication
59    /// on reading.
60    pub(crate) span: u32,
61    pub(crate) height: Length,
62}
63
64impl Default for RowHeader {
65    fn default() -> Self {
66        Self {
67            style: None,
68            cellstyle: None,
69            visible: Default::default(),
70            repeat: 1,
71            span: 1,
72            height: Default::default(),
73        }
74    }
75}
76
77/// Column data
78#[derive(Debug, Clone, GetSize)]
79pub(crate) struct ColHeader {
80    pub(crate) style: Option<ColStyleRef>,
81    pub(crate) cellstyle: Option<CellStyleRef>,
82    pub(crate) visible: Visibility,
83    pub(crate) width: Length,
84    /// Logical valid range for all the header values. Avoids duplication
85    /// on reading.
86    pub(crate) span: u32,
87}
88
89impl Default for ColHeader {
90    fn default() -> Self {
91        Self {
92            style: None,
93            cellstyle: None,
94            visible: Default::default(),
95            width: Default::default(),
96            span: 1,
97        }
98    }
99}
100
101/// One sheet of the spreadsheet.
102///
103/// Contains the data and the style-references. The can also be
104/// styles on the whole sheet, columns and rows. The more complicated
105/// grouping tags are not covered.
106#[derive(Clone, Default, GetSize)]
107pub struct Sheet {
108    pub(crate) name: String,
109    pub(crate) style: Option<TableStyleRef>,
110
111    pub(crate) data: BTreeMap<(u32, u32), CellData>,
112
113    pub(crate) col_header: BTreeMap<u32, ColHeader>,
114    pub(crate) row_header: BTreeMap<u32, RowHeader>,
115
116    pub(crate) display: bool,
117    pub(crate) print: bool,
118
119    pub(crate) header_rows: Option<Header>,
120    pub(crate) header_cols: Option<Header>,
121    pub(crate) print_ranges: Option<Vec<CellRange>>,
122
123    pub(crate) group_rows: Vec<Grouped>,
124    pub(crate) group_cols: Vec<Grouped>,
125
126    pub(crate) sheet_config: SheetConfig,
127
128    pub(crate) extra: Vec<XmlTag>,
129}
130
131impl<'a> IntoIterator for &'a Sheet {
132    type Item = ((u32, u32), CellContentRef<'a>);
133    type IntoIter = CellIter<'a>;
134
135    fn into_iter(self) -> Self::IntoIter {
136        CellIter {
137            iter: self.data.iter(),
138            k_data: None,
139            v_data: None,
140        }
141    }
142}
143
144/// Iterator over cells.
145#[derive(Debug)]
146pub(crate) struct CellDataIter<'a> {
147    iter: std::collections::btree_map::Range<'a, (u32, u32), CellData>,
148    k_data: Option<&'a (u32, u32)>,
149    v_data: Option<&'a CellData>,
150}
151
152impl<'a> CellDataIter<'a> {
153    pub(crate) fn new(iter: std::collections::btree_map::Range<'a, (u32, u32), CellData>) -> Self {
154        Self {
155            iter,
156            k_data: None,
157            v_data: None,
158        }
159    }
160
161    /// Returns the (row,col) of the next cell.
162    #[allow(dead_code)]
163    pub(crate) fn peek_cell(&mut self) -> Option<(u32, u32)> {
164        self.k_data.copied()
165    }
166
167    fn load_next_data(&mut self) {
168        if let Some((k, v)) = self.iter.next() {
169            self.k_data = Some(k);
170            self.v_data = Some(v);
171        } else {
172            self.k_data = None;
173            self.v_data = None;
174        }
175    }
176}
177
178impl FusedIterator for CellDataIter<'_> {}
179
180impl<'a> Iterator for CellDataIter<'a> {
181    type Item = ((u32, u32), &'a CellData);
182
183    fn next(&mut self) -> Option<Self::Item> {
184        if self.k_data.is_none() {
185            self.load_next_data();
186        }
187
188        if let Some(k_data) = self.k_data {
189            if let Some(v_data) = self.v_data {
190                let r = Some((*k_data, v_data));
191                self.load_next_data();
192                r
193            } else {
194                None
195            }
196        } else {
197            None
198        }
199    }
200
201    fn size_hint(&self) -> (usize, Option<usize>) {
202        self.iter.size_hint()
203    }
204}
205
206/// Iterator over cells.
207#[derive(Debug)]
208pub(crate) struct CellDataIterMut<'a> {
209    iter: std::collections::btree_map::RangeMut<'a, (u32, u32), CellData>,
210    k_data: Option<&'a (u32, u32)>,
211    v_data: Option<&'a mut CellData>,
212}
213
214impl<'a> CellDataIterMut<'a> {
215    pub(crate) fn new(
216        iter: std::collections::btree_map::RangeMut<'a, (u32, u32), CellData>,
217    ) -> Self {
218        Self {
219            iter,
220            k_data: None,
221            v_data: None,
222        }
223    }
224
225    /// Returns the (row,col) of the next cell.
226    pub(crate) fn peek_cell(&mut self) -> Option<(u32, u32)> {
227        self.k_data.copied()
228    }
229
230    fn load_next_data(&mut self) {
231        if let Some((k, v)) = self.iter.next() {
232            self.k_data = Some(k);
233            self.v_data = Some(v);
234        } else {
235            self.k_data = None;
236            self.v_data = None;
237        }
238    }
239}
240
241impl FusedIterator for CellDataIterMut<'_> {}
242
243impl<'a> Iterator for CellDataIterMut<'a> {
244    type Item = ((u32, u32), &'a mut CellData);
245
246    fn next(&mut self) -> Option<Self::Item> {
247        if self.k_data.is_none() {
248            self.load_next_data();
249        }
250
251        if let Some(k_data) = self.k_data {
252            if let Some(v_data) = self.v_data.take() {
253                let r = Some((*k_data, v_data));
254                self.load_next_data();
255                r
256            } else {
257                None
258            }
259        } else {
260            None
261        }
262    }
263
264    fn size_hint(&self) -> (usize, Option<usize>) {
265        self.iter.size_hint()
266    }
267}
268
269/// Iterator over cells.
270#[derive(Clone, Debug)]
271pub struct CellIter<'a> {
272    iter: std::collections::btree_map::Iter<'a, (u32, u32), CellData>,
273    k_data: Option<&'a (u32, u32)>,
274    v_data: Option<&'a CellData>,
275}
276
277impl CellIter<'_> {
278    /// Returns the (row,col) of the next cell.
279    pub fn peek_cell(&mut self) -> Option<(u32, u32)> {
280        self.k_data.copied()
281    }
282
283    fn load_next_data(&mut self) {
284        if let Some((k, v)) = self.iter.next() {
285            self.k_data = Some(k);
286            self.v_data = Some(v);
287        } else {
288            self.k_data = None;
289            self.v_data = None;
290        }
291    }
292}
293
294impl FusedIterator for CellIter<'_> {}
295
296impl<'a> Iterator for CellIter<'a> {
297    type Item = ((u32, u32), CellContentRef<'a>);
298
299    fn next(&mut self) -> Option<Self::Item> {
300        if self.k_data.is_none() {
301            self.load_next_data();
302        }
303
304        if let Some(k_data) = self.k_data {
305            if let Some(v_data) = self.v_data {
306                let r = Some((*k_data, v_data.cell_content_ref()));
307                self.load_next_data();
308                r
309            } else {
310                None
311            }
312        } else {
313            None
314        }
315    }
316
317    fn size_hint(&self) -> (usize, Option<usize>) {
318        self.iter.size_hint()
319    }
320}
321
322struct IterRows<'a> {
323    iter: std::collections::btree_map::Range<'a, (u32, u32), CellData>,
324    start: (u32, u32),
325    end: (u32, u32),
326    hint: usize,
327}
328
329impl<'a> IterRows<'a> {
330    fn new<R: RangeBounds<(u32, u32)>>(sheet: &'a Sheet, range: R) -> Self {
331        let start = match range.start_bound() {
332            Bound::Included((r, c)) => (*r, *c),
333            Bound::Excluded((r, c)) => (r + 1, c + 1),
334            Bound::Unbounded => (0, 0),
335        };
336        let end = match range.end_bound() {
337            Bound::Included((r, c)) => (r + 1, c + 1),
338            Bound::Excluded((r, c)) => (*r, *c),
339            Bound::Unbounded => sheet.used_grid_size(),
340        };
341
342        Self {
343            iter: sheet.data.range(range),
344            start,
345            end,
346            hint: (end.0 - start.0) as usize * (end.1 * start.1) as usize,
347        }
348    }
349}
350
351impl FusedIterator for IterRows<'_> {}
352
353impl<'a> Iterator for IterRows<'a> {
354    type Item = ((u32, u32), CellContentRef<'a>);
355
356    fn next(&mut self) -> Option<Self::Item> {
357        loop {
358            if let Some(((r, c), d)) = self.iter.next() {
359                if *r < self.end.0 && *c >= self.start.1 && *c < self.end.1 {
360                    return Some(((*r, *c), d.cell_content_ref()));
361                }
362            } else {
363                return None;
364            }
365        }
366    }
367
368    fn size_hint(&self) -> (usize, Option<usize>) {
369        (0, Some(self.hint))
370    }
371}
372
373struct IterCols<'a> {
374    sheet: &'a Sheet,
375    start: (u32, u32),
376    end: (u32, u32),
377    cell: (u32, u32),
378}
379
380impl Debug for IterCols<'_> {
381    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
382        f.debug_struct("IterCols")
383            .field("start", &self.start)
384            .field("end", &self.end)
385            .field("cell", &self.cell)
386            .finish()
387    }
388}
389
390impl FusedIterator for IterCols<'_> {}
391
392impl<'a> IterCols<'a> {
393    fn new<R: RangeBounds<(u32, u32)>>(sheet: &'a Sheet, range: R) -> Self {
394        let start = match range.start_bound() {
395            Bound::Included((r, c)) => (*r, *c),
396            Bound::Excluded((r, c)) => (r + 1, c + 1),
397            Bound::Unbounded => (0, 0),
398        };
399        let end = match range.end_bound() {
400            Bound::Included((r, c)) => (r + 1, c + 1),
401            Bound::Excluded((r, c)) => (*r, *c),
402            Bound::Unbounded => sheet.used_grid_size(),
403        };
404
405        Self {
406            sheet,
407            start,
408            end,
409            cell: start,
410        }
411    }
412}
413
414impl<'a> Iterator for IterCols<'a> {
415    type Item = ((u32, u32), CellContentRef<'a>);
416
417    #[allow(clippy::comparison_chain)]
418    fn next(&mut self) -> Option<Self::Item> {
419        if self.cell.0 == self.end.0 && self.cell.1 == self.end.1 {
420            return None;
421        }
422
423        loop {
424            let r = self.cell.0;
425            let c = self.cell.1;
426            let d = self.sheet.cell_ref(self.cell.0, self.cell.1);
427
428            if self.cell.0 + 1 < self.end.0 {
429                self.cell.0 += 1;
430            } else if self.cell.0 + 1 == self.end.0 {
431                if self.cell.1 + 1 < self.end.1 {
432                    self.cell.0 = self.start.0;
433                    self.cell.1 += 1;
434                } else if self.cell.1 + 1 == self.end.1 {
435                    self.cell.0 += 1;
436                    self.cell.1 += 1;
437                } else {
438                    assert_eq!(self.cell, self.end);
439                }
440            } else {
441                assert_eq!(self.cell, self.end);
442            }
443
444            if let Some(d) = d {
445                return Some(((r, c), d));
446            }
447        }
448    }
449
450    fn size_hint(&self) -> (usize, Option<usize>) {
451        (
452            0,
453            Some((self.end.0 - self.start.0) as usize * (self.end.1 - self.start.1) as usize),
454        )
455    }
456}
457
458/// Range iterator.
459#[derive(Clone, Debug)]
460pub struct Range<'a> {
461    range: std::collections::btree_map::Range<'a, (u32, u32), CellData>,
462}
463
464impl FusedIterator for Range<'_> {}
465
466impl<'a> Iterator for Range<'a> {
467    type Item = ((u32, u32), CellContentRef<'a>);
468
469    fn next(&mut self) -> Option<Self::Item> {
470        if let Some((k, v)) = self.range.next() {
471            Some((*k, v.cell_content_ref()))
472        } else {
473            None
474        }
475    }
476
477    fn size_hint(&self) -> (usize, Option<usize>) {
478        self.range.size_hint()
479    }
480}
481
482impl DoubleEndedIterator for Range<'_> {
483    fn next_back(&mut self) -> Option<Self::Item> {
484        if let Some((k, v)) = self.range.next_back() {
485            Some((*k, v.cell_content_ref()))
486        } else {
487            None
488        }
489    }
490}
491
492impl ExactSizeIterator for Range<'_> {}
493
494impl Debug for Sheet {
495    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
496        writeln!(f, "name {:?} style {:?}", self.name, self.style)?;
497        for (k, v) in self.data.iter() {
498            writeln!(f, "  data {:?} {:?}", k, v)?;
499        }
500        for (k, v) in &self.col_header {
501            writeln!(f, "{:?} {:?}", k, v)?;
502        }
503        for (k, v) in &self.row_header {
504            writeln!(f, "{:?} {:?}", k, v)?;
505        }
506        if let Some(header_rows) = &self.header_rows {
507            writeln!(f, "header rows {:?}", header_rows)?;
508        }
509        if let Some(header_cols) = &self.header_cols {
510            writeln!(f, "header cols {:?}", header_cols)?;
511        }
512        for v in &self.group_cols {
513            writeln!(f, "group cols {:?}", v)?;
514        }
515        for v in &self.group_rows {
516            writeln!(f, "group rows {:?}", v)?;
517        }
518        for xtr in &self.extra {
519            writeln!(f, "extras {:?}", xtr)?;
520        }
521        Ok(())
522    }
523}
524
525impl Sheet {
526    /// Create an empty sheet.
527    #[deprecated]
528    pub fn new_with_name<S: Into<String>>(name: S) -> Self {
529        Self::new(name)
530    }
531
532    /// Create an empty sheet.
533    ///
534    /// The name is shown as the tab-title, but also as a reference for
535    /// this sheet in formulas and sheet-metadata. Giving an empty string
536    /// here is allowed and a name will be generated, when the document is
537    /// opened. But any metadata will not be applied.
538    ///
539    /// Renaming the sheet works for metadata, but formulas will not be fixed.  
540    ///
541    pub fn new<S: Into<String>>(name: S) -> Self {
542        Sheet {
543            name: name.into(),
544            data: BTreeMap::new(),
545            col_header: Default::default(),
546            style: None,
547            header_rows: None,
548            header_cols: None,
549            print_ranges: None,
550            group_rows: Default::default(),
551            group_cols: Default::default(),
552            sheet_config: Default::default(),
553            extra: vec![],
554            row_header: Default::default(),
555            display: true,
556            print: true,
557        }
558    }
559
560    /// Copy all the attributes but not the actual data.
561    pub fn clone_no_data(&self) -> Self {
562        Self {
563            name: self.name.clone(),
564            style: self.style.clone(),
565            data: Default::default(),
566            col_header: self.col_header.clone(),
567            row_header: self.row_header.clone(),
568            display: self.display,
569            print: self.print,
570            header_rows: self.header_rows,
571            header_cols: self.header_cols,
572            print_ranges: self.print_ranges.clone(),
573            group_rows: self.group_rows.clone(),
574            group_cols: self.group_cols.clone(),
575            sheet_config: Default::default(),
576            extra: self.extra.clone(),
577        }
578    }
579
580    /// Iterate all cells.
581    pub fn iter(&self) -> CellIter<'_> {
582        self.into_iter()
583    }
584
585    /// Count all cells with any data.
586    pub fn cell_count(&self) -> usize {
587        self.data.len()
588    }
589
590    /// Iterate the range row-wise.
591    ///
592    /// If there is no upper bound this uses used_grid_size(), which
593    /// does an extra full iteration to find the bounds.
594    pub fn iter_rows<R: RangeBounds<(u32, u32)>>(
595        &self,
596        range: R,
597    ) -> impl Iterator<Item = ((u32, u32), CellContentRef<'_>)> {
598        IterRows::new(self, range)
599    }
600
601    /// Iterate the range column-wise.
602    ///
603    /// If there is no upper bound this uses used_grid_size(), which
604    /// does an extra full iteration to find the bounds.
605    pub fn iter_cols<R: RangeBounds<(u32, u32)>>(
606        &self,
607        range: R,
608    ) -> impl Iterator<Item = ((u32, u32), CellContentRef<'_>)> {
609        IterCols::new(self, range)
610    }
611
612    /// Iterate a range of cells in lexical order.
613    pub fn range<R: RangeBounds<(u32, u32)>>(
614        &self,
615        range: R,
616    ) -> impl Iterator<Item = ((u32, u32), CellContentRef<'_>)> {
617        Range {
618            range: self.data.range(range),
619        }
620    }
621
622    /// Sheet name.
623    pub fn set_name<V: Into<String>>(&mut self, name: V) {
624        self.name = name.into();
625    }
626
627    /// Sheet name.
628    pub fn name(&self) -> &String {
629        &self.name
630    }
631
632    /// Configuration for the sheet.
633    pub fn config(&self) -> &SheetConfig {
634        &self.sheet_config
635    }
636
637    /// Configuration for the sheet.
638    pub fn config_mut(&mut self) -> &mut SheetConfig {
639        &mut self.sheet_config
640    }
641
642    /// Sets the table-style
643    pub fn set_style(&mut self, style: &TableStyleRef) {
644        self.style = Some(style.clone())
645    }
646
647    /// Returns the table-style.
648    pub fn style(&self) -> Option<&TableStyleRef> {
649        self.style.as_ref()
650    }
651
652    // find the col-header with the correct data.
653    pub(crate) fn valid_col_header(&self, col: u32) -> Option<&ColHeader> {
654        if let Some((base_col, col_header)) = self.col_header.range(..=col).last() {
655            if (*base_col..*base_col + col_header.span).contains(&col) {
656                Some(col_header)
657            } else {
658                None
659            }
660        } else {
661            None
662        }
663    }
664
665    // find the col-header with the correct data and do a three-way-split
666    // to allow setting a value for a single col.
667    // Create the col-header if necessary.
668    #[allow(clippy::comparison_chain)]
669    fn create_split_col_header(&mut self, col: u32) -> &mut ColHeader {
670        let mut cloned = Vec::new();
671
672        if let Some((base_col, col_header)) = self.col_header.range_mut(..=col).last() {
673            if (*base_col..*base_col + col_header.span).contains(&col) {
674                let base_span = col_header.span;
675
676                // three-way split:
677                //      base_col .. col
678                //      col
679                //      col +1 .. base_col+span
680
681                // front + target
682                if *base_col < col {
683                    col_header.span = col - *base_col;
684
685                    let mut clone = col_header.clone();
686                    clone.span = 1;
687                    cloned.push((col, clone));
688                } else if *base_col == col {
689                    col_header.span = 1;
690                } else {
691                    unreachable!();
692                }
693
694                // back
695                if *base_col + base_span > col {
696                    let mut clone = col_header.clone();
697                    clone.span = *base_col + base_span - (col + 1);
698                    cloned.push((col + 1, clone));
699                } else if *base_col + base_span == col {
700                    // noop
701                } else {
702                    unreachable!();
703                }
704            } else {
705                self.col_header.insert(col, ColHeader::default());
706            }
707        } else {
708            self.col_header.insert(col, ColHeader::default());
709        }
710
711        for (r, ch) in cloned {
712            self.col_header.insert(r, ch);
713        }
714
715        self.col_header.get_mut(&col).expect("col-header")
716    }
717
718    /// Column style.
719    pub fn set_colstyle(&mut self, col: u32, style: &ColStyleRef) {
720        self.create_split_col_header(col).style = Some(style.clone());
721    }
722
723    /// Remove the style.
724    pub fn clear_colstyle(&mut self, col: u32) {
725        self.create_split_col_header(col).style = None;
726    }
727
728    /// Returns the column style.
729    pub fn colstyle(&self, col: u32) -> Option<&ColStyleRef> {
730        if let Some(col_header) = self.valid_col_header(col) {
731            col_header.style.as_ref()
732        } else {
733            None
734        }
735    }
736
737    /// Default cell style for this column.
738    pub fn set_col_cellstyle(&mut self, col: u32, style: &CellStyleRef) {
739        self.create_split_col_header(col).cellstyle = Some(style.clone());
740    }
741
742    /// Remove the style.
743    pub fn clear_col_cellstyle(&mut self, col: u32) {
744        self.create_split_col_header(col).cellstyle = None;
745    }
746
747    /// Returns the default cell style for this column.
748    pub fn col_cellstyle(&self, col: u32) -> Option<&CellStyleRef> {
749        if let Some(col_header) = self.valid_col_header(col) {
750            col_header.cellstyle.as_ref()
751        } else {
752            None
753        }
754    }
755
756    /// Visibility of the column
757    pub fn set_col_visible(&mut self, col: u32, visible: Visibility) {
758        self.create_split_col_header(col).visible = visible;
759    }
760
761    /// Returns the default cell style for this column.
762    pub fn col_visible(&self, col: u32) -> Visibility {
763        if let Some(col_header) = self.valid_col_header(col) {
764            col_header.visible
765        } else {
766            Default::default()
767        }
768    }
769
770    /// unstable internal method
771    pub fn _set_col_header_span(&mut self, col: u32, span: u32) {
772        self.create_split_col_header(col).span = span
773    }
774
775    /// unstable internal method
776    pub fn _col_header_span(&self, col: u32) -> u32 {
777        if let Some(col_header) = self.valid_col_header(col) {
778            col_header.span
779        } else {
780            Default::default()
781        }
782    }
783
784    /// Sets the column width for this column.
785    pub fn set_col_width(&mut self, col: u32, width: Length) {
786        self.create_split_col_header(col).width = width;
787    }
788
789    /// Returns the column-width.
790    pub fn col_width(&self, col: u32) -> Length {
791        if let Some(ch) = self.valid_col_header(col) {
792            ch.width
793        } else {
794            Length::Default
795        }
796    }
797
798    // find the row-header with the correct data.
799    pub(crate) fn valid_row_header(&self, row: u32) -> Option<&RowHeader> {
800        if let Some((base_row, row_header)) = self.row_header.range(..=row).last() {
801            if (*base_row..*base_row + row_header.span).contains(&row) {
802                Some(row_header)
803            } else {
804                None
805            }
806        } else {
807            None
808        }
809    }
810
811    // find the row-header with the correct data and do a three-way-split
812    // to allow setting a value for a single row.
813    // Create the row-header if necessary.
814    #[allow(clippy::comparison_chain)]
815    fn create_split_row_header(&mut self, row: u32) -> &mut RowHeader {
816        let mut cloned = Vec::new();
817
818        if let Some((base_row, row_header)) = self.row_header.range_mut(..=row).last() {
819            if (*base_row..*base_row + row_header.span).contains(&row) {
820                let base_span = row_header.span;
821
822                // three-way split:
823                //      base_row .. row
824                //      row
825                //      row +1 .. base_row+span
826
827                // front + target
828                if *base_row < row {
829                    row_header.span = row - *base_row;
830
831                    let mut clone = row_header.clone();
832                    clone.span = 1;
833                    cloned.push((row, clone));
834                } else if *base_row == row {
835                    row_header.span = 1;
836                } else {
837                    unreachable!();
838                }
839
840                // back
841                if *base_row + base_span > row {
842                    let mut clone = row_header.clone();
843                    clone.span = *base_row + base_span - (row + 1);
844                    cloned.push((row + 1, clone));
845                } else if *base_row + base_span == row {
846                    // noop
847                } else {
848                    unreachable!();
849                }
850            } else {
851                self.row_header.insert(row, RowHeader::default());
852            }
853        } else {
854            self.row_header.insert(row, RowHeader::default());
855        }
856
857        for (r, rh) in cloned {
858            self.row_header.insert(r, rh);
859        }
860
861        self.row_header.get_mut(&row).expect("row-header")
862    }
863
864    /// unstable internal method.
865    pub fn _row_header_span(&self, row: u32) -> Option<u32> {
866        self.row_header.get(&row).map(|v| v.span)
867    }
868
869    /// unstable internal method.
870    pub fn _set_row_header_span(&mut self, row: u32, span: u32) {
871        if let Some(row_header) = self.row_header.get_mut(&row) {
872            row_header.span = span;
873        }
874    }
875
876    /// Row style.
877    pub fn set_rowstyle(&mut self, row: u32, style: &RowStyleRef) {
878        self.create_split_row_header(row).style = Some(style.clone());
879    }
880
881    /// Remove the style.
882    pub fn clear_rowstyle(&mut self, row: u32) {
883        self.create_split_row_header(row).style = None;
884    }
885
886    /// Returns the row style.
887    pub fn rowstyle(&self, row: u32) -> Option<&RowStyleRef> {
888        if let Some(row_header) = self.valid_row_header(row) {
889            row_header.style.as_ref()
890        } else {
891            None
892        }
893    }
894
895    /// Default cell style for this row.
896    pub fn set_row_cellstyle(&mut self, row: u32, style: &CellStyleRef) {
897        self.create_split_row_header(row).cellstyle = Some(style.clone());
898    }
899
900    /// Remove the style.
901    pub fn clear_row_cellstyle(&mut self, row: u32) {
902        self.create_split_row_header(row).cellstyle = None;
903    }
904
905    /// Returns the default cell style for this row.
906    pub fn row_cellstyle(&self, row: u32) -> Option<&CellStyleRef> {
907        if let Some(row_header) = self.valid_row_header(row) {
908            row_header.cellstyle.as_ref()
909        } else {
910            None
911        }
912    }
913
914    /// Visibility of the row
915    pub fn set_row_visible(&mut self, row: u32, visible: Visibility) {
916        self.create_split_row_header(row).visible = visible;
917    }
918
919    /// Returns the default cell style for this row.
920    pub fn row_visible(&self, row: u32) -> Visibility {
921        if let Some(row_header) = self.valid_row_header(row) {
922            row_header.visible
923        } else {
924            Default::default()
925        }
926    }
927
928    /// Sets the repeat count for this row. Usually this is the last row
929    /// with data in a sheet. Setting the repeat count will not change
930    /// the row number of following rows. But they will be changed after
931    /// writing to an ODS file and reading it again.
932    ///
933    /// Panics
934    ///
935    /// Panics if the repeat is 0.
936    pub fn set_row_repeat(&mut self, row: u32, repeat: u32) {
937        assert!(repeat > 0);
938        self.create_split_row_header(row).repeat = repeat
939    }
940
941    /// Returns the repeat count for this row.
942    pub fn row_repeat(&self, row: u32) -> u32 {
943        if let Some(row_header) = self.valid_row_header(row) {
944            row_header.repeat
945        } else {
946            Default::default()
947        }
948    }
949
950    /// Sets the row-height.
951    pub fn set_row_height(&mut self, row: u32, height: Length) {
952        self.create_split_row_header(row).height = height;
953    }
954
955    /// Returns the row-height
956    pub fn row_height(&self, row: u32) -> Length {
957        if let Some(rh) = self.valid_row_header(row) {
958            rh.height
959        } else {
960            Length::Default
961        }
962    }
963
964    /// Returns the maximum used column in the column header.
965    pub fn _col_header_len(&self) -> usize {
966        self.col_header.len()
967    }
968
969    /// Returns the maximum used row in the row header.
970    pub fn _row_header_len(&self) -> usize {
971        self.row_header.len()
972    }
973
974    /// Returns the maximum used column in the column header.
975    pub fn col_header_max(&self) -> u32 {
976        *self.col_header.keys().max().unwrap_or(&0)
977    }
978
979    /// Returns the maximum used row in the row header.
980    pub fn row_header_max(&self) -> u32 {
981        *self.row_header.keys().max().unwrap_or(&0)
982    }
983
984    /// Returns a tuple of (max(row)+1, max(col)+1)
985    pub fn used_grid_size(&self) -> (u32, u32) {
986        let max = self.data.keys().fold((0, 0), |mut max, (r, c)| {
987            max.0 = u32::max(max.0, *r);
988            max.1 = u32::max(max.1, *c);
989            max
990        });
991
992        (max.0 + 1, max.1 + 1)
993    }
994
995    /// Is the sheet displayed?
996    pub fn set_display(&mut self, display: bool) {
997        self.display = display;
998    }
999
1000    /// Is the sheet displayed?
1001    pub fn display(&self) -> bool {
1002        self.display
1003    }
1004
1005    /// Is the sheet printed?
1006    pub fn set_print(&mut self, print: bool) {
1007        self.print = print;
1008    }
1009
1010    /// Is the sheet printed?
1011    pub fn print(&self) -> bool {
1012        self.print
1013    }
1014
1015    /// Returns true if there is no SCell at the given position.
1016    pub fn is_empty(&self, row: u32, col: u32) -> bool {
1017        self.data.get(&(row, col)).is_none()
1018    }
1019
1020    /// Returns a clone of the cell content.
1021    pub fn cell(&self, row: u32, col: u32) -> Option<CellContent> {
1022        self.data
1023            .get(&(row, col))
1024            .map(CellData::cloned_cell_content)
1025    }
1026
1027    /// Returns references to the cell data.
1028    pub fn cell_ref(&self, row: u32, col: u32) -> Option<CellContentRef<'_>> {
1029        self.data.get(&(row, col)).map(CellData::cell_content_ref)
1030    }
1031
1032    /// Consumes the CellContent and sets the values.
1033    pub fn add_cell(&mut self, row: u32, col: u32, cell: CellContent) {
1034        self.add_cell_data(row, col, cell.into_celldata());
1035    }
1036
1037    /// Removes the cell and returns the values as CellContent.
1038    pub fn remove_cell(&mut self, row: u32, col: u32) -> Option<CellContent> {
1039        self.data
1040            .remove(&(row, col))
1041            .map(CellData::into_cell_content)
1042    }
1043
1044    /// Add a new cell. Main use is for reading the spreadsheet.
1045    pub(crate) fn add_cell_data(&mut self, row: u32, col: u32, cell: CellData) {
1046        self.data.insert((row, col), cell);
1047    }
1048
1049    /// Sets a value for the specified cell and provides a style at the same time.
1050    #[inline]
1051    pub fn set_styled<V: Into<Value>>(
1052        &mut self,
1053        row: u32,
1054        col: u32,
1055        value: V,
1056        style: &CellStyleRef,
1057    ) {
1058        self.set_styled_value(row, col, value, style)
1059    }
1060
1061    /// Sets a value for the specified cell. Creates a new cell if necessary.
1062    pub fn set_styled_value<V: Into<Value>>(
1063        &mut self,
1064        row: u32,
1065        col: u32,
1066        value: V,
1067        style: &CellStyleRef,
1068    ) {
1069        let cell = self.data.entry((row, col)).or_default();
1070        cell.value = value.into();
1071        cell.style = Some(style.clone());
1072    }
1073
1074    /// Sets a value for the specified cell. Creates a new cell if necessary.
1075    pub fn set_value<V: Into<Value>>(&mut self, row: u32, col: u32, value: V) {
1076        let cell = self.data.entry((row, col)).or_default();
1077        cell.value = value.into();
1078    }
1079
1080    /// Returns a value
1081    pub fn value(&self, row: u32, col: u32) -> &Value {
1082        if let Some(cell) = self.data.get(&(row, col)) {
1083            &cell.value
1084        } else {
1085            &Value::Empty
1086        }
1087    }
1088
1089    /// Sets a formula for the specified cell. Creates a new cell if necessary.
1090    pub fn set_formula<V: Into<String>>(&mut self, row: u32, col: u32, formula: V) {
1091        let cell = self.data.entry((row, col)).or_default();
1092        cell.formula = Some(formula.into());
1093    }
1094
1095    /// Removes the formula.
1096    pub fn clear_formula(&mut self, row: u32, col: u32) {
1097        if let Some(cell) = self.data.get_mut(&(row, col)) {
1098            cell.formula = None;
1099        }
1100    }
1101
1102    /// Returns a value
1103    pub fn formula(&self, row: u32, col: u32) -> Option<&String> {
1104        if let Some(c) = self.data.get(&(row, col)) {
1105            c.formula.as_ref()
1106        } else {
1107            None
1108        }
1109    }
1110
1111    /// Sets a repeat counter for the cell.
1112    pub fn set_cell_repeat(&mut self, row: u32, col: u32, repeat: u32) {
1113        let cell = self.data.entry((row, col)).or_default();
1114        cell.repeat = repeat;
1115    }
1116
1117    /// Returns the repeat counter for the cell within one row.
1118    pub fn cell_repeat(&self, row: u32, col: u32) -> u32 {
1119        if let Some(c) = self.data.get(&(row, col)) {
1120            c.repeat
1121        } else {
1122            1
1123        }
1124    }
1125
1126    /// Sets the cell-style for the specified cell. Creates a new cell if necessary.
1127    pub fn set_cellstyle(&mut self, row: u32, col: u32, style: &CellStyleRef) {
1128        let cell = self.data.entry((row, col)).or_default();
1129        cell.style = Some(style.clone());
1130    }
1131
1132    /// Removes the cell-style.
1133    pub fn clear_cellstyle(&mut self, row: u32, col: u32) {
1134        if let Some(cell) = self.data.get_mut(&(row, col)) {
1135            cell.style = None;
1136        }
1137    }
1138
1139    /// Returns a value
1140    pub fn cellstyle(&self, row: u32, col: u32) -> Option<&CellStyleRef> {
1141        if let Some(c) = self.data.get(&(row, col)) {
1142            c.style.as_ref()
1143        } else {
1144            None
1145        }
1146    }
1147
1148    /// Sets a content-validation for this cell.
1149    pub fn set_validation(&mut self, row: u32, col: u32, validation: &ValidationRef) {
1150        let cell = self.data.entry((row, col)).or_default();
1151        cell.extra_mut().validation_name = Some(validation.clone());
1152    }
1153
1154    /// Removes the cell-style.
1155    pub fn clear_validation(&mut self, row: u32, col: u32) {
1156        if let Some(cell) = self.data.get_mut(&(row, col)) {
1157            cell.extra_mut().validation_name = None;
1158        }
1159    }
1160
1161    /// Returns a content-validation name for this cell.
1162    pub fn validation(&self, row: u32, col: u32) -> Option<&ValidationRef> {
1163        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1164            c.validation_name.as_ref()
1165        } else {
1166            None
1167        }
1168    }
1169
1170    /// Sets the rowspan of the cell. Must be greater than 0.
1171    pub fn set_row_span(&mut self, row: u32, col: u32, span: u32) {
1172        let cell = self.data.entry((row, col)).or_default();
1173        cell.extra_mut().span.set_row_span(span);
1174    }
1175
1176    /// Rowspan of the cell.
1177    pub fn row_span(&self, row: u32, col: u32) -> u32 {
1178        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1179            c.span.row_span()
1180        } else {
1181            1
1182        }
1183    }
1184
1185    /// Sets the colspan of the cell. Must be greater than 0.
1186    pub fn set_col_span(&mut self, row: u32, col: u32, span: u32) {
1187        assert!(span > 0);
1188        let cell = self.data.entry((row, col)).or_default();
1189        cell.extra_mut().span.set_col_span(span);
1190    }
1191
1192    /// Colspan of the cell.
1193    pub fn col_span(&self, row: u32, col: u32) -> u32 {
1194        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1195            c.span.col_span()
1196        } else {
1197            1
1198        }
1199    }
1200
1201    /// Sets the rowspan of the cell. Must be greater than 0.
1202    pub fn set_matrix_row_span(&mut self, row: u32, col: u32, span: u32) {
1203        let cell = self.data.entry((row, col)).or_default();
1204        cell.extra_mut().matrix_span.set_row_span(span);
1205    }
1206
1207    /// Rowspan of the cell.
1208    pub fn matrix_row_span(&self, row: u32, col: u32) -> u32 {
1209        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1210            c.matrix_span.row_span()
1211        } else {
1212            1
1213        }
1214    }
1215
1216    /// Sets the colspan of the cell. Must be greater than 0.
1217    pub fn set_matrix_col_span(&mut self, row: u32, col: u32, span: u32) {
1218        let cell = self.data.entry((row, col)).or_default();
1219        cell.extra_mut().matrix_span.set_col_span(span);
1220    }
1221
1222    /// Colspan of the cell.
1223    pub fn matrix_col_span(&self, row: u32, col: u32) -> u32 {
1224        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1225            c.matrix_span.col_span()
1226        } else {
1227            1
1228        }
1229    }
1230
1231    /// Sets a annotation for this cell.
1232    pub fn set_annotation(&mut self, row: u32, col: u32, annotation: Annotation) {
1233        let cell = self.data.entry((row, col)).or_default();
1234        cell.extra_mut().annotation = Some(Box::new(annotation));
1235    }
1236
1237    /// Removes the annotation.
1238    pub fn clear_annotation(&mut self, row: u32, col: u32) {
1239        if let Some(cell) = self.data.get_mut(&(row, col)) {
1240            cell.extra_mut().annotation = None;
1241        }
1242    }
1243
1244    /// Returns a content-validation name for this cell.
1245    pub fn annotation(&self, row: u32, col: u32) -> Option<&Annotation> {
1246        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1247            c.annotation.as_ref().map(|v| v.as_ref())
1248        } else {
1249            None
1250        }
1251    }
1252
1253    /// Returns a content-validation name for this cell.
1254    pub fn annotation_mut(&mut self, row: u32, col: u32) -> Option<&mut Annotation> {
1255        if let Some(CellData { extra: Some(c), .. }) = self.data.get_mut(&(row, col)) {
1256            c.annotation.as_mut().map(|v| v.as_mut())
1257        } else {
1258            None
1259        }
1260    }
1261
1262    /// Add a drawframe to a specific cell.
1263    pub fn add_draw_frame(&mut self, row: u32, col: u32, draw_frame: DrawFrame) {
1264        let cell = self.data.entry((row, col)).or_default();
1265        cell.extra_mut().draw_frames.push(draw_frame);
1266    }
1267
1268    /// Removes all drawframes.
1269    pub fn clear_draw_frames(&mut self, row: u32, col: u32) {
1270        if let Some(cell) = self.data.get_mut(&(row, col)) {
1271            cell.extra_mut().draw_frames = Vec::new();
1272        }
1273    }
1274
1275    /// Returns the draw-frames.
1276    pub fn draw_frames(&self, row: u32, col: u32) -> Option<&Vec<DrawFrame>> {
1277        if let Some(CellData { extra: Some(c), .. }) = self.data.get(&(row, col)) {
1278            Some(c.draw_frames.as_ref())
1279        } else {
1280            None
1281        }
1282    }
1283
1284    /// Returns a content-validation name for this cell.
1285    pub fn draw_frames_mut(&mut self, row: u32, col: u32) -> Option<&mut Vec<DrawFrame>> {
1286        if let Some(CellData { extra: Some(c), .. }) = self.data.get_mut(&(row, col)) {
1287            Some(c.draw_frames.as_mut())
1288        } else {
1289            None
1290        }
1291    }
1292
1293    /// Defines a range of rows as header rows.
1294    /// These rows are repeated when printing on multiple pages.
1295    pub fn set_header_rows(&mut self, row_start: u32, row_end: u32) {
1296        self.header_rows = Some(Header {
1297            from: row_start,
1298            to: row_end,
1299        });
1300    }
1301
1302    /// Clears the header-rows definition.
1303    pub fn clear_header_rows(&mut self) {
1304        self.header_rows = None;
1305    }
1306
1307    /// Returns the header rows.
1308    /// These rows are repeated when printing on multiple pages.
1309    pub fn header_rows(&self) -> Option<Header> {
1310        self.header_rows.map(Into::into)
1311    }
1312
1313    /// Defines a range of columns as header columns.
1314    /// These columns are repeated when printing on multiple pages.
1315    pub fn set_header_cols(&mut self, col_start: u32, col_end: u32) {
1316        self.header_cols = Some(Header {
1317            from: col_start,
1318            to: col_end,
1319        });
1320    }
1321
1322    /// Clears the header-columns definition.
1323    pub fn clear_header_cols(&mut self) {
1324        self.header_cols = None;
1325    }
1326
1327    /// Returns the header columns.
1328    /// These columns are repeated when printing on multiple pages.
1329    pub fn header_cols(&self) -> Option<Header> {
1330        self.header_cols.map(Into::into)
1331    }
1332
1333    /// Print ranges.
1334    pub fn add_print_range(&mut self, range: CellRange) {
1335        self.print_ranges.get_or_insert_with(Vec::new).push(range);
1336    }
1337
1338    /// Remove print ranges.
1339    pub fn clear_print_ranges(&mut self) {
1340        self.print_ranges = None;
1341    }
1342
1343    /// Return the print ranges.
1344    pub fn print_ranges(&self) -> Option<&Vec<CellRange>> {
1345        self.print_ranges.as_ref()
1346    }
1347
1348    /// Split horizontally on a cell boundary. The splitting is fixed in
1349    /// position.
1350    pub fn split_col_header(&mut self, col: u32) {
1351        self.config_mut().hor_split_mode = SplitMode::Heading;
1352        self.config_mut().hor_split_pos = col + 1;
1353        self.config_mut().position_right = col + 1;
1354        self.config_mut().cursor_x = col + 1;
1355    }
1356
1357    /// Split vertically on a cell boundary. The splitting is fixed in
1358    /// position.
1359    pub fn split_row_header(&mut self, row: u32) {
1360        self.config_mut().vert_split_mode = SplitMode::Heading;
1361        self.config_mut().vert_split_pos = row + 1;
1362        self.config_mut().position_bottom = row + 1;
1363        self.config_mut().cursor_y = row + 1;
1364    }
1365
1366    /// Split horizontally with a pixel width. The split can be moved around.
1367    /// For more control look at SheetConfig.
1368    pub fn split_horizontal(&mut self, col: u32) {
1369        self.config_mut().hor_split_mode = SplitMode::Split;
1370        self.config_mut().hor_split_pos = col;
1371    }
1372
1373    /// Split vertically with a pixel width. The split can be moved around.
1374    /// For more control look at SheetConfig.
1375    pub fn split_vertical(&mut self, col: u32) {
1376        self.config_mut().vert_split_mode = SplitMode::Split;
1377        self.config_mut().vert_split_pos = col;
1378    }
1379
1380    /// Add a column group.
1381    ///
1382    /// Panic
1383    ///
1384    /// Column groups can be contained within another, but they can't overlap.
1385    /// From must be less than or equal to.
1386    pub fn add_col_group(&mut self, from: u32, to: u32) {
1387        assert!(from <= to);
1388        let grp = Grouped::new(from, to, true);
1389        for v in &self.group_cols {
1390            assert!(grp.contains(v) || v.contains(&grp) || grp.disjunct(v));
1391        }
1392        self.group_cols.push(grp);
1393    }
1394
1395    /// Remove a column group.
1396    pub fn remove_col_group(&mut self, from: u32, to: u32) {
1397        if let Some(idx) = self
1398            .group_cols
1399            .iter()
1400            .position(|v| v.from == from && v.to == to)
1401        {
1402            self.group_cols.remove(idx);
1403        }
1404    }
1405
1406    /// Change the expansion/collapse of a col group.
1407    ///
1408    /// Does nothing if no such group exists.
1409    pub fn set_col_group_displayed(&mut self, from: u32, to: u32, display: bool) {
1410        if let Some(idx) = self
1411            .group_cols
1412            .iter()
1413            .position(|v| v.from == from && v.to == to)
1414        {
1415            self.group_cols[idx].display = display;
1416
1417            for r in from..=to {
1418                self.set_col_visible(
1419                    r,
1420                    if display {
1421                        Visibility::Visible
1422                    } else {
1423                        Visibility::Collapsed
1424                    },
1425                );
1426            }
1427        }
1428    }
1429
1430    /// Count of column groups.
1431    pub fn col_group_count(&self) -> usize {
1432        self.group_cols.len()
1433    }
1434
1435    /// Returns the nth column group.
1436    pub fn col_group(&self, idx: usize) -> Option<&Grouped> {
1437        return self.group_cols.get(idx);
1438    }
1439
1440    /// Returns the nth column group.
1441    pub fn col_group_mut(&mut self, idx: usize) -> Option<&mut Grouped> {
1442        return self.group_cols.get_mut(idx);
1443    }
1444
1445    /// Iterate the column groups.
1446    pub fn col_group_iter(&self) -> impl Iterator<Item = &Grouped> {
1447        self.group_cols.iter()
1448    }
1449
1450    /// Add a row group.
1451    ///
1452    /// Panic
1453    ///
1454    /// Row groups can be contained within another, but they can't overlap.
1455    /// From must be less than or equal to.
1456    pub fn add_row_group(&mut self, from: u32, to: u32) {
1457        assert!(from <= to);
1458        let grp = Grouped::new(from, to, true);
1459        for v in &self.group_rows {
1460            assert!(grp.contains(v) || v.contains(&grp) || grp.disjunct(v));
1461        }
1462        self.group_rows.push(grp);
1463    }
1464
1465    /// Remove a row group.
1466    pub fn remove_row_group(&mut self, from: u32, to: u32) {
1467        if let Some(idx) = self
1468            .group_rows
1469            .iter()
1470            .position(|v| v.from == from && v.to == to)
1471        {
1472            self.group_rows.remove(idx);
1473        }
1474    }
1475
1476    /// Change the expansion/collapse of a row group.
1477    ///
1478    /// Does nothing if no such group exists.
1479    pub fn set_row_group_displayed(&mut self, from: u32, to: u32, display: bool) {
1480        if let Some(idx) = self
1481            .group_rows
1482            .iter()
1483            .position(|v| v.from == from && v.to == to)
1484        {
1485            self.group_rows[idx].display = display;
1486
1487            for r in from..=to {
1488                self.set_row_visible(
1489                    r,
1490                    if display {
1491                        Visibility::Visible
1492                    } else {
1493                        Visibility::Collapsed
1494                    },
1495                );
1496            }
1497        }
1498    }
1499
1500    /// Count of row groups.
1501    pub fn row_group_count(&self) -> usize {
1502        self.group_rows.len()
1503    }
1504
1505    /// Returns the nth row group.
1506    pub fn row_group(&self, idx: usize) -> Option<&Grouped> {
1507        return self.group_rows.get(idx);
1508    }
1509
1510    /// Iterate row groups.
1511    pub fn row_group_iter(&self) -> impl Iterator<Item = &Grouped> {
1512        self.group_rows.iter()
1513    }
1514}
1515
1516/// Describes header rows/columns.
1517#[derive(Debug, Copy, Clone, Default, GetSize)]
1518pub struct Header {
1519    pub from: u32,
1520    pub to: u32,
1521}
1522
1523impl From<Header> for (u32, u32) {
1524    fn from(value: Header) -> Self {
1525        (value.from, value.to)
1526    }
1527}
1528
1529/// Describes a row/column group.
1530#[derive(Debug, PartialEq, Clone, Copy, GetSize)]
1531pub struct Grouped {
1532    /// Inclusive from row/col.
1533    pub from: u32,
1534    /// Inclusive to row/col.
1535    pub to: u32,
1536    /// Visible/Collapsed state.
1537    pub display: bool,
1538}
1539
1540impl Grouped {
1541    /// New group.
1542    pub fn new(from: u32, to: u32, display: bool) -> Self {
1543        Self { from, to, display }
1544    }
1545
1546    /// Inclusive start.
1547    pub fn from(&self) -> u32 {
1548        self.from
1549    }
1550
1551    /// Inclusive start.
1552    pub fn set_from(&mut self, from: u32) {
1553        self.from = from;
1554    }
1555
1556    /// Inclusive end.
1557    pub fn to(&self) -> u32 {
1558        self.to
1559    }
1560
1561    /// Inclusive end.
1562    pub fn set_to(&mut self, to: u32) {
1563        self.to = to
1564    }
1565
1566    /// Group is displayed?
1567    pub fn display(&self) -> bool {
1568        self.display
1569    }
1570
1571    /// Change the display state for the group.
1572    ///
1573    /// Note: Changing this does not change the visibility of the rows/columns.
1574    /// Use Sheet::set_display_col_group() and Sheet::set_display_row_group() to make
1575    /// all necessary changes.
1576    pub fn set_display(&mut self, display: bool) {
1577        self.display = display;
1578    }
1579
1580    /// Contains the other group.
1581    pub fn contains(&self, other: &Grouped) -> bool {
1582        self.from <= other.from && self.to >= other.to
1583    }
1584
1585    /// The two groups are disjunct.
1586    pub fn disjunct(&self, other: &Grouped) -> bool {
1587        self.from < other.from && self.to < other.from || self.from > other.to && self.to > other.to
1588    }
1589}
1590
1591/// There are two ways a sheet can be split. There are fixed column/row header
1592/// like splits, and there is a moveable split.
1593///
1594#[derive(Clone, Copy, Debug, GetSize)]
1595#[allow(missing_docs)]
1596pub enum SplitMode {
1597    None = 0,
1598    Split = 1,
1599    Heading = 2,
1600}
1601
1602impl TryFrom<i16> for SplitMode {
1603    type Error = OdsError;
1604
1605    fn try_from(n: i16) -> Result<Self, Self::Error> {
1606        match n {
1607            0 => Ok(SplitMode::None),
1608            1 => Ok(SplitMode::Split),
1609            2 => Ok(SplitMode::Heading),
1610            _ => Err(OdsError::Ods(format!("Invalid split mode {}", n))),
1611        }
1612    }
1613}
1614
1615/// Per sheet configurations.
1616#[derive(Clone, Debug, GetSize)]
1617pub struct SheetConfig {
1618    /// Active column.
1619    pub cursor_x: u32,
1620    /// Active row.
1621    pub cursor_y: u32,
1622    /// Splitting the table.
1623    pub hor_split_mode: SplitMode,
1624    /// Splitting the table.
1625    pub vert_split_mode: SplitMode,
1626    /// Position of the split.
1627    pub hor_split_pos: u32,
1628    /// Position of the split.
1629    pub vert_split_pos: u32,
1630    /// SplitMode is Pixel
1631    /// - 0-4 indicates the quadrant where the focus is.
1632    /// SplitMode is Cell
1633    /// - No real function.
1634    pub active_split_range: i16,
1635    /// SplitMode is Pixel
1636    /// - First visible column in the left quadrant.
1637    /// SplitMode is Cell
1638    /// - The first visible column in the left quadrant.
1639    ///   AND every column left of this one is simply invisible.
1640    pub position_left: u32,
1641    /// SplitMode is Pixel
1642    /// - First visible column in the right quadrant.
1643    /// SplitMode is Cell
1644    /// - The first visible column in the right quadrant.
1645    pub position_right: u32,
1646    /// SplitMode is Pixel
1647    /// - First visible row in the top quadrant.
1648    /// SplitMode is Cell
1649    /// - The first visible row in the top quadrant.
1650    ///   AND every row up from this one is simply invisible.
1651    pub position_top: u32,
1652    /// SplitMode is Pixel
1653    /// - The first visible row in teh right quadrant.
1654    /// SplitMode is Cell
1655    /// - The first visible row in the bottom quadrant.
1656    pub position_bottom: u32,
1657    /// If 0 then zoom_value denotes a percentage.
1658    /// If 2 then zoom_value is 50%???
1659    pub zoom_type: i16,
1660    /// Value of zoom.
1661    pub zoom_value: i32,
1662    /// Value of pageview zoom.
1663    pub page_view_zoom_value: i32,
1664    /// Grid is showing.
1665    pub show_grid: bool,
1666}
1667
1668impl Default for SheetConfig {
1669    fn default() -> Self {
1670        Self {
1671            cursor_x: 0,
1672            cursor_y: 0,
1673            hor_split_mode: SplitMode::None,
1674            vert_split_mode: SplitMode::None,
1675            hor_split_pos: 0,
1676            vert_split_pos: 0,
1677            active_split_range: 2,
1678            position_left: 0,
1679            position_right: 0,
1680            position_top: 0,
1681            position_bottom: 0,
1682            zoom_type: 0,
1683            zoom_value: 100,
1684            page_view_zoom_value: 60,
1685            show_grid: true,
1686        }
1687    }
1688}
1689
1690/// Cleanup repeat col-data.
1691pub(crate) fn dedup_colheader(sheet: &mut Sheet) -> Result<(), OdsError> {
1692    fn limited_eq(ch1: &ColHeader, ch2: &ColHeader) -> bool {
1693        ch1.style == ch2.style
1694            && ch1.cellstyle == ch2.cellstyle
1695            && ch1.visible == ch2.visible
1696            && ch1.width == ch2.width
1697    }
1698
1699    let col_header = mem::take(&mut sheet.col_header);
1700
1701    let mut new_col_header = BTreeMap::new();
1702    let mut new = None;
1703    for (col, header) in col_header {
1704        match new.as_mut() {
1705            None => {
1706                new = Some((col, header));
1707            }
1708            Some((new_col, new_header)) => {
1709                if limited_eq(new_header, &header) {
1710                    new_header.span += header.span;
1711                } else {
1712                    new_col_header
1713                        .insert(mem::replace(new_col, col), mem::replace(new_header, header));
1714                }
1715            }
1716        }
1717    }
1718    if let Some((new_col, new_header)) = new {
1719        new_col_header.insert(new_col, new_header);
1720    }
1721
1722    sheet.col_header = new_col_header;
1723
1724    Ok(())
1725}