pub struct Dialog {
pub id: WidgetId,
pub title: StyledText,
pub body: Vec<StyledText>,
pub buttons: Vec<DialogButton>,
pub severity: Option<DialogSeverity>,
pub vertical_buttons: bool,
pub table: Option<DialogTable>,
pub input: Option<DialogInput>,
}Expand description
Declarative description of a dialog.
§Examples
use quadraui::{
Dialog, DialogButton, DialogHit, DialogMeasure, Rect, StyledText, ToolbarItemMeasure,
WidgetId,
};
let dialog = Dialog {
id: WidgetId::new("dialog:confirm_close"),
title: StyledText::plain("Unsaved changes"),
body: vec![StyledText::plain("Close without saving?")],
buttons: vec![DialogButton {
id: WidgetId::new("dialog:ok"),
label: "OK".to_string(),
is_default: true,
is_cancel: false,
tint: None,
}],
severity: None,
vertical_buttons: false,
table: None,
input: None,
};
let measure = DialogMeasure {
width: 40.0,
title_height: 1.0,
body_height: 1.0,
table_height: 0.0,
input_height: 0.0,
button_row_height: 1.0,
button_width: 10.0,
button_gap: 1.0,
padding: 1.0,
};
let viewport = Rect::new(0.0, 0.0, 80.0, 24.0);
// `input` is `None` above, so `layout` never calls this closure — it's
// only reached by the `DialogInput::Toolbar` body variant.
let layout = dialog.layout(viewport, measure, |_| ToolbarItemMeasure::new(10.0));
let ok = layout.visible_buttons[0].bounds;
assert_eq!(layout.hit_test(ok.x, ok.y), DialogHit::Button(dialog.buttons[0].id.clone()));Fields§
§id: WidgetId§title: StyledText§body: Vec<StyledText>Body content lines. Each entry is one line rendered top-to-bottom. Supports per-line styled spans for keybinding references, help text, and other multi-line content.
severity: Option<DialogSeverity>Optional severity tint — backends may add an icon or edge
accent. None = neutral.
When true, buttons are stacked vertically (useful for narrow dialogs or many-choice dialogs like code-action pickers). When false, buttons are horizontal, right-aligned.
table: Option<DialogTable>Optional structured table rendered between the body text and the
DialogInput slot. Used for keybindings grids, comparison
tables, etc.
Layout order: title → body → table → input → buttons.
input: Option<DialogInput>Optional content rendered between the table and the button row.
DialogInput::TextInput— single-line text field; used for rename prompts, input-required confirms.DialogInput::Toolbar— horizontal action strip; used when the dialog wants an inline action bar (e.g. “Preview / Skip / Apply”) in addition to the modal OK/Cancel buttons.
Apps own the value; interactions resolve via DialogLayout::hit_test
/ DialogHit.
Implementations§
Source§impl Dialog
impl Dialog
Sourcepub fn layout<F>(
&self,
viewport: Rect,
measure: DialogMeasure,
measure_toolbar_item: F,
) -> DialogLayout
pub fn layout<F>( &self, viewport: Rect, measure: DialogMeasure, measure_toolbar_item: F, ) -> DialogLayout
Compute dialog layout.
§Arguments
viewport— parent surface bounds; the dialog is centered within this.measure— sub-region widths/heights. Backends measure the body text (wrapping tomeasure.width) and setbody_heightaccordingly; ditto for title and buttons.input_heightis used for both the text-input and toolbar variants — set it to the desired slot height regardless of whichDialogInputkind is present.measure_toolbar_item— per-item width callback for the toolbar variant. Whenself.inputis notDialogInput::Toolbar, this callback is never called and may be|_| ToolbarItemMeasure::new(0.0).
§Centering
The dialog box is placed at the viewport’s horizontal + vertical center. Button row is at the bottom of the box, right-aligned (horizontal) or stretched (vertical).
Convenience: find the default button’s id (first with
is_default = true, or the last button as a fallback).
Convenience: find the cancel button’s id (first with
is_cancel = true).
Sourcepub fn measure_generic(
&self,
char_width: f32,
line_height: f32,
viewport: Rect,
border_chrome_inset: f32,
) -> DialogMeasure
pub fn measure_generic( &self, char_width: f32, line_height: f32, viewport: Rect, border_chrome_inset: f32, ) -> DialogMeasure
Derive a DialogMeasure from char_width and line_height
without real text measurement. This is the char-cell approximation
used where char_width == line_height == 1.0 on TUI (one character
cell) and the backend’s real glyph metrics on pixel backends.
border_chrome_inset optionally shrinks the resulting width to
leave room for a border the rasteriser draws outside
DialogLayout::bounds rather than inside it — e.g. a TUI backend
whose box-drawing glyphs live one cell past the content box, the
same convention tui::context_menu::draw_context_menu (behind the
tui feature) already uses for ContextMenu. Pass 0.0 when the
border is painted inside the returned bounds — this crate’s own
tui::dialog::draw_dialog and every pixel backend do this.
Does not measure Self::table or Self::buttons’ rendered pixel
width beyond the char-cell approximation above; callers with real
text measurement available should prefer Self::measure_generic_measured.
Sourcepub fn measure_generic_measured(
&self,
char_width: f32,
line_height: f32,
viewport: Rect,
border_chrome_inset: f32,
measure: &dyn TextMeasure,
) -> DialogMeasure
pub fn measure_generic_measured( &self, char_width: f32, line_height: f32, viewport: Rect, border_chrome_inset: f32, measure: &dyn TextMeasure, ) -> DialogMeasure
Like Self::measure_generic, but sizes DialogMeasure::button_width
from each DialogButton::label’s real rendered width through
measure instead of the fixed char_width * 8.0 estimate — the
widest button sets a uniform width for the row (button_width is
shared by every button; see DialogMeasure::button_width’s doc),
plus 2 char-widths of horizontal padding, floored at the original
char_width * 8.0 so a row of short labels (“OK” / “No”) doesn’t
shrink below what every existing caller of Self::measure_generic
already renders.
Every other field is identical to Self::measure_generic — only
the button row’s width changes.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Dialog
impl<'de> Deserialize<'de> for Dialog
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Dialog
impl StructuralPartialEq for Dialog
Auto Trait Implementations§
impl Freeze for Dialog
impl RefUnwindSafe for Dialog
impl Send for Dialog
impl Sync for Dialog
impl Unpin for Dialog
impl UnsafeUnpin for Dialog
impl UnwindSafe for Dialog
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more