cursive-split-panel 0.0.6

Split panel for the Cursive TUI library
Documentation
use cursive::{direction::*, view::*, *};

//
// Pane
//

// Pane for split panel.
pub(crate) struct Pane {
    pub(crate) view: Box<dyn View>,
    pub(crate) start: usize,
    pub(crate) extent: usize,
}

impl Pane {
    // Layout view.
    pub(crate) fn layout(&mut self, size: Vec2, orientation: Orientation) {
        self.view.layout(size.with_axis(orientation, self.extent));
    }

    // Required size.
    pub(crate) fn required_size(&mut self, constraint: Vec2, orientation: Orientation) -> Vec2 {
        self.view.required_size(constraint.with_axis(orientation, self.extent))
    }

    // Draw view.
    pub(crate) fn draw(&self, printer: &Printer, orientation: Orientation, is_focused: bool) {
        if self.extent > 0 {
            self.view.draw(
                &printer
                    .offset(orientation.make_vec(self.start, 0))
                    .cropped(printer.size.with_axis(orientation, self.extent))
                    .focused(is_focused),
            );
        }
    }

    // Translate important area from local to split panel coordinates.
    pub(crate) fn important_area(&self, size: Vec2, orientation: Orientation, border: bool) -> Rect {
        let mut offset = orientation.make_vec(self.start, 0);
        if border {
            offset = offset + (1, 1);
        }

        self.view.important_area(size) + offset
    }

    // Translate mouse event from split panel to local coordinates.
    pub(crate) fn mouse_event(
        &self,
        mut offset: Vec2,
        position: Vec2,
        orientation: Orientation,
        border: bool,
        size: Option<Vec2>,
    ) -> Option<(Vec2, Vec2)> {
        if self.extent == 0 {
            return None;
        }

        let Some(mut local) = position.checked_sub(offset) else { return None };

        if border {
            if local.x == 0 || local.y == 0 {
                // On the left or top border
                return None;
            }

            if let Some(size) = size
                && ((size.x == 0) || (size.y == 0) || (local.x >= size.x - 1) || (local.y >= size.y - 1))
            {
                // On or beyond the right or bottom border
                return None;
            }

            offset = offset + (1, 1);
            local = local - (1, 1);
        }

        let local_ = *local.get(orientation);
        if local_ < self.start || local_ > self.start + self.extent - 1 {
            return None;
        }

        *offset.get_mut(orientation) += self.start;

        Some((offset, position))
    }
}

impl<ViewT> From<ViewT> for Pane
where
    ViewT: IntoBoxedView,
{
    fn from(view: ViewT) -> Self {
        Self { view: view.into_boxed_view(), start: 0, extent: 0 }
    }
}