Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
feat(lib): Add support for popups
Erik Kundt committed 1 year ago
commit 9411ee31f8d6da08ce5727f4bec663e509a9662b
parent dcc51b9
4 files changed +86 -2
modified CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog

+
## [0.7.0] - Unreleased
+

+
### Added
+

+
**Library features**
+

+
- imUI: Support for popups
+

## [0.6.0] - 2025-01-29

### Added
modified src/ui/im.rs
@@ -14,7 +14,7 @@ use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};

use termion::event::Key;

-
use ratatui::layout::{Constraint, Position, Rect};
+
use ratatui::layout::{Constraint, Flex, Position, Rect};
use ratatui::{Frame, Viewport};

use crate::event::Event;
@@ -29,6 +29,8 @@ use crate::ui::im::widget::{HeaderedTable, Widget};

use self::widget::AddContentFn;

+
use super::layout;
+

const RENDERING_TICK_RATE: Duration = Duration::from_millis(250);

/// The main UI trait for the ability to render an application.
@@ -202,6 +204,10 @@ pub enum Layout {
    Expandable3 {
        left_only: bool,
    },
+
    Popup {
+
        percent_x: u16,
+
        percent_y: u16,
+
    },
}

impl From<ratatui::layout::Layout> for Layout {
@@ -222,6 +228,10 @@ impl Layout {
                    3
                }
            }
+
            Layout::Popup {
+
                percent_x: _,
+
                percent_y: _,
+
            } => 1,
        }
    }

@@ -258,6 +268,21 @@ impl Layout {
                    .split(area)
                }
            }
+
            Layout::Popup {
+
                percent_x,
+
                percent_y,
+
            } => {
+
                use ratatui::layout::Layout;
+

+
                let vertical =
+
                    Layout::vertical([Constraint::Percentage(*percent_y)]).flex(Flex::Center);
+
                let horizontal =
+
                    Layout::horizontal([Constraint::Percentage(*percent_x)]).flex(Flex::Center);
+
                let [area] = vertical.areas(area);
+
                let [area] = horizontal.areas(area);
+

+
                [area].into()
+
            }
        }
    }
}
@@ -349,6 +374,11 @@ impl<M> Ui<M> {
        self
    }

+
    pub fn without_focus(mut self) -> Self {
+
        self.has_focus = false;
+
        self
+
    }
+

    pub fn theme(&self) -> &Theme {
        &self.theme
    }
@@ -487,6 +517,21 @@ where
        widget::Composite::new(focus).show(&mut child_ui, add_contents)
    }

+
    pub fn popup<R>(
+
        &mut self,
+
        layout: impl Into<Layout>,
+
        add_contents: impl FnOnce(&mut Ui<M>) -> R,
+
    ) -> InnerResponse<R> {
+
        let layout: Layout = layout.into();
+
        let areas = layout.split(self.area());
+
        let area = areas.first().cloned().unwrap_or(self.area());
+

+
        let mut child_ui = self.child_ui(area, layout::fill());
+
        child_ui.has_focus = true;
+

+
        widget::Popup::default().show(&mut child_ui, add_contents)
+
    }
+

    pub fn label<'a>(&mut self, frame: &mut Frame, content: impl Into<Text<'a>>) -> Response {
        widget::Label::new(content).ui(self, frame)
    }
modified src/ui/im/widget.rs
@@ -215,6 +215,34 @@ impl Composite {
    }
}

+
#[derive(Default)]
+
pub struct Popup {}
+

+
impl Popup {
+
    pub fn show<M, R>(
+
        self,
+
        ui: &mut Ui<M>,
+
        add_contents: impl FnOnce(&mut Ui<M>) -> R,
+
    ) -> InnerResponse<R>
+
    where
+
        M: Clone,
+
    {
+
        self.show_dyn(ui, Box::new(add_contents))
+
    }
+

+
    pub fn show_dyn<M, R>(
+
        self,
+
        ui: &mut Ui<M>,
+
        add_contents: Box<AddContentFn<M, R>>,
+
    ) -> InnerResponse<R>
+
    where
+
        M: Clone,
+
    {
+
        let inner = add_contents(ui);
+
        InnerResponse::new(inner, Response::default())
+
    }
+
}
+

pub struct Label<'a> {
    content: Text<'a>,
}
modified src/ui/layout.rs
@@ -1,5 +1,4 @@
use ratatui::layout::{Constraint, Direction, Layout, Rect};
-

pub struct DefaultPage {
    pub component: Rect,
    pub context: Rect,
@@ -51,3 +50,7 @@ pub fn centered_rect(r: Rect, percent_x: u16, percent_y: u16) -> Rect {
        ])
        .split(layout[1])[1]
}
+

+
pub fn fill() -> Layout {
+
    Layout::vertical([Constraint::Fill(1)].to_vec())
+
}