411 lines
19 KiB
Rust
411 lines
19 KiB
Rust
use gpui::{
|
|
App, AppContext, Context, Entity, FocusHandle, Focusable, InteractiveElement as _, IntoElement,
|
|
ParentElement, Render, SharedString, Styled, Window, div, px,
|
|
};
|
|
|
|
use gpui_component::{
|
|
ActiveTheme, Icon, IconName, WindowExt as _,
|
|
button::{Button, ButtonVariant, ButtonVariants as _},
|
|
checkbox::Checkbox,
|
|
date_picker::{DatePicker, DatePickerState},
|
|
dialog::DialogButtonProps,
|
|
h_flex,
|
|
input::{Input, InputState},
|
|
select::{Select, SelectState},
|
|
text::TextView,
|
|
v_flex,
|
|
};
|
|
|
|
use crate::{TestAction, section};
|
|
|
|
pub struct DialogStory {
|
|
focus_handle: FocusHandle,
|
|
selected_value: Option<SharedString>,
|
|
input1: Entity<InputState>,
|
|
input2: Entity<InputState>,
|
|
date: Entity<DatePickerState>,
|
|
select: Entity<SelectState<Vec<String>>>,
|
|
dialog_overlay: bool,
|
|
close_button: bool,
|
|
keyboard: bool,
|
|
overlay_closable: bool,
|
|
}
|
|
|
|
impl super::Story for DialogStory {
|
|
fn title() -> &'static str {
|
|
"Dialog"
|
|
}
|
|
|
|
fn description() -> &'static str {
|
|
"A dialog dialog"
|
|
}
|
|
|
|
fn new_view(window: &mut Window, cx: &mut App) -> Entity<impl Render> {
|
|
Self::view(window, cx)
|
|
}
|
|
}
|
|
|
|
impl DialogStory {
|
|
pub fn view(window: &mut Window, cx: &mut App) -> Entity<Self> {
|
|
cx.new(|cx| Self::new(window, cx))
|
|
}
|
|
|
|
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
|
let input1 = cx.new(|cx| InputState::new(window, cx).placeholder("Your Name"));
|
|
let input2 = cx.new(|cx| {
|
|
InputState::new(window, cx).placeholder("For test focus back on dialog close.")
|
|
});
|
|
let date = cx.new(|cx| DatePickerState::new(window, cx));
|
|
let select = cx.new(|cx| {
|
|
SelectState::new(
|
|
vec![
|
|
"Option 1".to_string(),
|
|
"Option 2".to_string(),
|
|
"Option 3".to_string(),
|
|
],
|
|
None,
|
|
window,
|
|
cx,
|
|
)
|
|
});
|
|
|
|
Self {
|
|
focus_handle: cx.focus_handle(),
|
|
selected_value: None,
|
|
input1,
|
|
input2,
|
|
date,
|
|
select,
|
|
dialog_overlay: true,
|
|
close_button: true,
|
|
keyboard: true,
|
|
overlay_closable: true,
|
|
}
|
|
}
|
|
|
|
fn show_dialog(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
|
let overlay = self.dialog_overlay;
|
|
let dialog_close_button = self.close_button;
|
|
let overlay_closable = self.overlay_closable;
|
|
let input1 = self.input1.clone();
|
|
let date = self.date.clone();
|
|
let select = self.select.clone();
|
|
let view = cx.entity().clone();
|
|
let keyboard = self.keyboard;
|
|
|
|
window.open_dialog(cx, move |dialog, _, _| {
|
|
dialog
|
|
.title("Form Dialog")
|
|
.overlay(overlay)
|
|
.keyboard(keyboard)
|
|
.close_button(dialog_close_button)
|
|
.overlay_closable(overlay_closable)
|
|
.child(
|
|
v_flex()
|
|
.gap_3()
|
|
.child("This is a dialog dialog.")
|
|
.child("You can put anything here.")
|
|
.child(Input::new(&input1))
|
|
.child(Select::new(&select))
|
|
.child(DatePicker::new(&date).placeholder("Date of Birth")),
|
|
)
|
|
.footer({
|
|
let view = view.clone();
|
|
let input1 = input1.clone();
|
|
let date = date.clone();
|
|
move |_, _, _, _cx| {
|
|
vec![
|
|
Button::new("confirm").primary().label("Confirm").on_click({
|
|
let view = view.clone();
|
|
let input1 = input1.clone();
|
|
let date = date.clone();
|
|
move |_, window, cx| {
|
|
window.close_dialog(cx);
|
|
|
|
view.update(cx, |view, cx| {
|
|
view.selected_value = Some(
|
|
format!(
|
|
"Hello, {}, date: {}",
|
|
input1.read(cx).value(),
|
|
date.read(cx).date()
|
|
)
|
|
.into(),
|
|
)
|
|
});
|
|
}
|
|
}),
|
|
Button::new("new-dialog")
|
|
.label("Open Other Dialog")
|
|
.on_click(move |_, window, cx| {
|
|
window.open_dialog(cx, move |dialog, _, _| {
|
|
dialog
|
|
.title("Other Dialog")
|
|
.child("This is another dialog.")
|
|
.min_h(px(100.))
|
|
.overlay(overlay)
|
|
.keyboard(keyboard)
|
|
.close_button(dialog_close_button)
|
|
.overlay_closable(overlay_closable)
|
|
});
|
|
}),
|
|
Button::new("cancel")
|
|
.label("Cancel")
|
|
.on_click(move |_, window, cx| {
|
|
window.close_dialog(cx);
|
|
}),
|
|
]
|
|
}
|
|
})
|
|
});
|
|
|
|
self.input1.focus_handle(cx).focus(window);
|
|
}
|
|
|
|
fn on_action_test_action(
|
|
&mut self,
|
|
_: &TestAction,
|
|
window: &mut Window,
|
|
cx: &mut Context<Self>,
|
|
) {
|
|
window.push_notification("You have clicked the TestAction.", cx);
|
|
}
|
|
}
|
|
|
|
impl Focusable for DialogStory {
|
|
fn focus_handle(&self, _cx: &gpui::App) -> FocusHandle {
|
|
self.focus_handle.clone()
|
|
}
|
|
}
|
|
|
|
impl Render for DialogStory {
|
|
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
|
let dialog_overlay = self.dialog_overlay;
|
|
let overlay_closable = self.overlay_closable;
|
|
|
|
div()
|
|
.id("dialog-story")
|
|
.track_focus(&self.focus_handle)
|
|
.on_action(cx.listener(Self::on_action_test_action))
|
|
.size_full()
|
|
.child(
|
|
v_flex()
|
|
.gap_6()
|
|
.child(
|
|
h_flex()
|
|
.items_center()
|
|
.gap_3()
|
|
.child(
|
|
Checkbox::new("dialog-overlay")
|
|
.label("Dialog Overlay")
|
|
.checked(self.dialog_overlay)
|
|
.on_click(cx.listener(|view, _, _, cx| {
|
|
view.dialog_overlay = !view.dialog_overlay;
|
|
cx.notify();
|
|
})),
|
|
)
|
|
.child(
|
|
Checkbox::new("overlay-closable")
|
|
.label("Overlay Closable")
|
|
.checked(self.overlay_closable)
|
|
.on_click(cx.listener(|view, _, _, cx| {
|
|
view.overlay_closable = !view.overlay_closable;
|
|
cx.notify();
|
|
})),
|
|
)
|
|
.child(
|
|
Checkbox::new("dialog-show-close")
|
|
.label("Model Close Button")
|
|
.checked(self.close_button)
|
|
.on_click(cx.listener(|view, _, _, cx| {
|
|
view.close_button = !view.close_button;
|
|
cx.notify();
|
|
})),
|
|
)
|
|
.child(
|
|
Checkbox::new("dialog-keyboard")
|
|
.label("Keyboard")
|
|
.checked(self.keyboard)
|
|
.on_click(cx.listener(|view, _, _, cx| {
|
|
view.keyboard = !view.keyboard;
|
|
cx.notify();
|
|
})),
|
|
),
|
|
)
|
|
.child(
|
|
section("Normal Dialog").child(
|
|
Button::new("show-dialog")
|
|
.outline()
|
|
.label("Open Dialog")
|
|
.on_click(
|
|
cx.listener(|this, _, window, cx| this.show_dialog(window, cx)),
|
|
),
|
|
),
|
|
)
|
|
.child(
|
|
section("Focus back test")
|
|
.max_w_md()
|
|
.child(Input::new(&self.input2))
|
|
.child(
|
|
Button::new("test-action")
|
|
.outline()
|
|
.label("Test Action")
|
|
.flex_shrink_0()
|
|
.on_click(|_, window, cx| {
|
|
window.dispatch_action(Box::new(TestAction), cx);
|
|
})
|
|
.tooltip(
|
|
"This button for test dispatch action, \
|
|
to make sure when Dialog close,\
|
|
\nthis still can handle the action.",
|
|
),
|
|
),
|
|
)
|
|
.child(
|
|
section("Confirm Dialog").child(
|
|
Button::new("confirm-dialog0")
|
|
.outline()
|
|
.label("Open Confirm Dialog")
|
|
.on_click(cx.listener(move |_, _, window, cx| {
|
|
window.open_dialog(cx, move |dialog, _, _| {
|
|
dialog
|
|
.confirm()
|
|
.overlay(dialog_overlay)
|
|
.overlay_closable(overlay_closable)
|
|
.child("Are you sure to submit?")
|
|
.on_ok(|_, window, cx| {
|
|
window
|
|
.push_notification("You have pressed ok.", cx);
|
|
true
|
|
})
|
|
.on_cancel(|_, window, cx| {
|
|
window.push_notification(
|
|
"You have pressed cancel.",
|
|
cx,
|
|
);
|
|
true
|
|
})
|
|
});
|
|
})),
|
|
),
|
|
)
|
|
.child(
|
|
section("Confirm Dialog with custom buttons").child(
|
|
Button::new("confirm-dialog1")
|
|
.outline()
|
|
.label("Custom Buttons")
|
|
.on_click(cx.listener(move |_, _, window, cx| {
|
|
window.open_dialog(cx, move |dialog, _, cx| {
|
|
dialog
|
|
.rounded_lg()
|
|
.confirm()
|
|
.overlay(dialog_overlay)
|
|
.overlay_closable(overlay_closable)
|
|
.child(
|
|
h_flex().gap_3()
|
|
.child(Icon::new(IconName::TriangleAlert).size_6().text_color(cx.theme().warning))
|
|
.child("Update successful, we need to restart the application.")
|
|
)
|
|
.button_props(
|
|
DialogButtonProps::default()
|
|
.cancel_text("Later")
|
|
.cancel_variant(ButtonVariant::Secondary)
|
|
.ok_text("Restart Now")
|
|
.ok_variant(ButtonVariant::Danger),
|
|
)
|
|
.on_ok(|_, window, cx| {
|
|
window.push_notification(
|
|
"You have pressed restart.",
|
|
cx,
|
|
);
|
|
true
|
|
})
|
|
.on_cancel(|_, window, cx| {
|
|
window.push_notification(
|
|
"You have pressed later.",
|
|
cx,
|
|
);
|
|
true
|
|
})
|
|
});
|
|
})),
|
|
),
|
|
)
|
|
.child(
|
|
section("Alert Dialog").child(
|
|
Button::new("alert-dialog")
|
|
.outline()
|
|
.label("Alert")
|
|
.on_click(cx.listener(move |_, _, window, cx| {
|
|
window.open_dialog(cx, move |dialog, _, _| {
|
|
dialog
|
|
.confirm()
|
|
.overlay(dialog_overlay)
|
|
.overlay_closable(overlay_closable)
|
|
.child("You are successfully logged in.")
|
|
.alert()
|
|
.on_close(|_, window, cx| {
|
|
window
|
|
.push_notification("You have pressed Ok.", cx);
|
|
})
|
|
});
|
|
})),
|
|
),
|
|
)
|
|
.child(
|
|
section("Scrollable Dialog").child(
|
|
Button::new("scrollable-dialog")
|
|
.outline()
|
|
.label("Scrollable Dialog")
|
|
.on_click(cx.listener(move |_, _, window, cx| {
|
|
window.open_dialog(cx, move |dialog, window, cx| {
|
|
dialog
|
|
.w(px(720.))
|
|
.h(px(600.))
|
|
.overlay(dialog_overlay)
|
|
.overlay_closable(overlay_closable)
|
|
.title("Dialog with scrollbar")
|
|
.child(TextView::markdown(
|
|
"markdown1",
|
|
include_str!("../../../README.md"),
|
|
window,
|
|
cx
|
|
))
|
|
});
|
|
})),
|
|
),
|
|
)
|
|
.child(
|
|
section("Custom Paddings").child(
|
|
Button::new("custom-dialog-paddings")
|
|
.outline()
|
|
.label("Custom Paddings")
|
|
.on_click(cx.listener(move |_, _, window, cx| {
|
|
window.open_dialog(cx, move |dialog, _, _| {
|
|
dialog
|
|
.p_3()
|
|
.title("Custom Dialog Title")
|
|
.child("This is a custom dialog content, we can use paddings to control the layout and spacing within the dialog.")
|
|
});
|
|
})),
|
|
),
|
|
)
|
|
.child(
|
|
section("Custom Style").child(
|
|
Button::new("custom-dialog-style")
|
|
.outline()
|
|
.label("Custom Dialog Style")
|
|
.on_click(cx.listener(move |_, _, window, cx| {
|
|
window.open_dialog(cx, move |dialog, _, cx| {
|
|
dialog
|
|
.rounded_lg()
|
|
.bg(cx.theme().cyan)
|
|
.text_color(cx.theme().info_foreground)
|
|
.title("Custom Dialog Title")
|
|
.child("This is a custom dialog content.")
|
|
});
|
|
})),
|
|
),
|
|
),
|
|
)
|
|
}
|
|
}
|