aboutsummaryrefslogtreecommitdiff
path: root/src/ui/dialogs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui/dialogs.rs')
-rw-r--r--src/ui/dialogs.rs213
1 files changed, 213 insertions, 0 deletions
diff --git a/src/ui/dialogs.rs b/src/ui/dialogs.rs
new file mode 100644
index 00000000..78f1d1cb
--- /dev/null
+++ b/src/ui/dialogs.rs
@@ -0,0 +1,213 @@
+use ratatui::{
+ layout::{Constraint, Layout, Rect},
+ style::{Modifier, Style},
+ text::{Line, Span},
+ widgets::{Clear, Paragraph},
+ Frame,
+};
+
+use super::widgets::{
+ action_button_row_rects, centered_popup_rect, panel_contrast_fg, render_action_button,
+ render_modal_header, render_modal_shell, render_panel_shell, ActionButtonSpec,
+};
+use crate::app::{AppState, Mode};
+
+pub(crate) fn rename_button_rects(inner: Rect) -> (Rect, Rect, Rect) {
+ let rects = action_button_row_rects(
+ inner,
+ &[
+ ActionButtonSpec {
+ hint: Some("↵"),
+ label: "save",
+ },
+ ActionButtonSpec {
+ hint: Some("^c"),
+ label: "clear",
+ },
+ ActionButtonSpec {
+ hint: Some("esc"),
+ label: "cancel",
+ },
+ ],
+ 2,
+ 3,
+ );
+ (rects[0], rects[1], rects[2])
+}
+
+pub(super) fn render_rename_overlay(app: &AppState, frame: &mut Frame, area: Rect) {
+ super::dim_background(frame, area);
+
+ let title = match app.mode {
+ Mode::RenameWorkspace => "rename workspace",
+ Mode::RenameTab if app.creating_new_tab => "new tab",
+ Mode::RenameTab => "rename tab",
+ _ => return,
+ };
+
+ let Some(inner) = render_modal_shell(frame, area, 56, 7, &app.palette) else {
+ return;
+ };
+ if inner.height < 4 {
+ return;
+ }
+
+ let rows = Layout::vertical([
+ Constraint::Length(1),
+ Constraint::Length(1),
+ Constraint::Length(1),
+ Constraint::Length(1),
+ Constraint::Min(0),
+ ])
+ .areas::<5>(inner);
+
+ render_modal_header(frame, rows[0], title, &app.palette);
+
+ let input_rect = Rect::new(rows[2].x, rows[2].y, rows[2].width, 1);
+ frame.render_widget(Clear, input_rect);
+ frame.render_widget(
+ Paragraph::new(format!(" {}█", app.name_input)).style(
+ Style::default()
+ .fg(app.palette.text)
+ .bg(app.palette.surface0),
+ ),
+ input_rect,
+ );
+
+ let (save_rect, clear_rect, cancel_rect) = rename_button_rects(inner);
+
+ render_action_button(
+ frame,
+ save_rect,
+ Some("↵"),
+ "save",
+ Style::default()
+ .fg(panel_contrast_fg(&app.palette))
+ .bg(app.palette.accent)
+ .add_modifier(Modifier::BOLD),
+ );
+ render_action_button(
+ frame,
+ clear_rect,
+ Some("^c"),
+ "clear",
+ Style::default()
+ .fg(app.palette.text)
+ .bg(app.palette.surface0)
+ .add_modifier(Modifier::BOLD),
+ );
+ render_action_button(
+ frame,
+ cancel_rect,
+ Some("esc"),
+ "cancel",
+ Style::default()
+ .fg(app.palette.text)
+ .bg(app.palette.surface0)
+ .add_modifier(Modifier::BOLD),
+ );
+}
+
+pub(super) fn render_confirm_close_overlay(app: &AppState, frame: &mut Frame, area: Rect) {
+ let ws_name = app
+ .workspaces
+ .get(app.selected)
+ .map(|ws| ws.display_name())
+ .unwrap_or_else(|| "?".to_string());
+ let pane_count = app
+ .workspaces
+ .get(app.selected)
+ .map(|ws| ws.layout.pane_count())
+ .unwrap_or(0);
+
+ let pane_text = if pane_count == 1 {
+ "1 pane".to_string()
+ } else {
+ format!("{pane_count} panes")
+ };
+
+ super::dim_background(frame, area);
+
+ let Some(popup) = confirm_close_popup_rect(area) else {
+ return;
+ };
+
+ let warn = Style::default()
+ .fg(app.palette.red)
+ .add_modifier(Modifier::BOLD);
+ let dim = Style::default().fg(app.palette.overlay0);
+
+ let title_line = Line::from(vec![Span::styled(" Close workspace?", warn)]);
+
+ let detail_line = Line::from(vec![
+ Span::styled(
+ format!(" {ws_name}"),
+ Style::default()
+ .fg(app.palette.text)
+ .add_modifier(Modifier::BOLD),
+ ),
+ Span::styled(format!(" — {pane_text}"), dim),
+ ]);
+
+ let Some(inner) = render_panel_shell(frame, popup, app.palette.red, app.palette.panel_bg)
+ else {
+ return;
+ };
+
+ if inner.height >= 3 {
+ let rows = Layout::vertical([
+ Constraint::Length(1),
+ Constraint::Length(1),
+ Constraint::Length(1),
+ ])
+ .areas::<3>(inner);
+
+ frame.render_widget(Paragraph::new(title_line), rows[0]);
+ frame.render_widget(Paragraph::new(detail_line), rows[1]);
+
+ let (confirm_rect, cancel_rect) = confirm_close_button_rects(inner);
+ render_action_button(
+ frame,
+ confirm_rect,
+ Some("↵"),
+ "confirm",
+ Style::default()
+ .fg(panel_contrast_fg(&app.palette))
+ .bg(app.palette.red)
+ .add_modifier(Modifier::BOLD),
+ );
+ render_action_button(
+ frame,
+ cancel_rect,
+ Some("esc"),
+ "cancel",
+ Style::default()
+ .fg(app.palette.text)
+ .bg(app.palette.surface0)
+ .add_modifier(Modifier::BOLD),
+ );
+ }
+}
+
+pub(crate) fn confirm_close_popup_rect(area: Rect) -> Option<Rect> {
+ centered_popup_rect(area, 44, 5)
+}
+
+pub(crate) fn confirm_close_button_rects(inner: Rect) -> (Rect, Rect) {
+ let rects = action_button_row_rects(
+ inner,
+ &[
+ ActionButtonSpec {
+ hint: Some("↵"),
+ label: "confirm",
+ },
+ ActionButtonSpec {
+ hint: Some("esc"),
+ label: "cancel",
+ },
+ ],
+ 2,
+ 2,
+ );
+ (rects[0], rects[1])
+}