karo 0.1.2

Spreadsheet export
Documentation
use std::cell::RefCell;
use std::collections::BTreeSet;
use std::rc::Rc;

#[derive(Default, Clone)]
pub(crate) struct WorkbookSheetProperties {
    inner: Rc<RefCell<Inner>>,
}

impl WorkbookSheetProperties {
    pub(crate) fn set_selected(&mut self, index: usize, selected: bool) {
        self.inner.borrow_mut().set_selected(index, selected);
    }

    pub(crate) fn selected(&self, index: usize) -> bool {
        self.inner.borrow().selected(index)
    }

    pub(crate) fn set_hidden(&mut self, index: usize, hidden: bool) {
        self.inner.borrow_mut().set_hidden(index, hidden);
    }

    pub(crate) fn hidden(&self, index: usize) -> bool {
        self.inner.borrow().hidden(index)
    }

    pub(crate) fn set_active(&self, index: usize) {
        self.inner.borrow_mut().set_active(index)
    }

    pub(crate) fn active(&self, index: usize) -> bool {
        self.inner.borrow().active(index)
    }
}

#[derive(Default)]
struct Inner {
    active: Option<usize>,
    selected: BTreeSet<usize>,
    hidden: BTreeSet<usize>,
    count: usize,
}

impl Inner {
    fn set_selected(&mut self, index: usize, selected: bool) {
        if selected {
            self.selected.insert(index);
        } else {
            self.selected.remove(&index);
        }
    }

    fn selected(&self, index: usize) -> bool {
        if self.selected.is_empty() {
            self.automatic_active() == index
        } else {
            self.selected.contains(&index)
        }
    }

    fn set_hidden(&mut self, index: usize, hidden: bool) {
        if hidden {
            self.hidden.insert(index);
        } else {
            self.hidden.remove(&index);
        }
    }

    fn hidden(&self, index: usize) -> bool {
        self.hidden.contains(&index)
            && !self.selected(index)
            && !self.active(index)
    }

    fn active(&self, index: usize) -> bool {
        match self.active {
            Some(i) if i == index => true,
            Some(_) => false,
            None if index == self.automatic_active() => true,
            None => false,
        }
    }

    fn set_active(&mut self, index: usize) {
        self.active = Some(index);
    }

    fn automatic_active(&self) -> usize {
        if let Some(i) = self.active {
            i
        } else {
            // none was selected yet, so we'll find the first that
            // is not hidden.
            for i in 0usize..self.count {
                if !self.hidden.contains(&i) {
                    return i;
                }
            }
            // all sheets are hidden, so the first one is interpreted
            // as active, it will be unhidden automatically.
            0usize
        }
    }
}