gpui-component/crates/ui/src/clipboard.rs
2024-08-23 18:43:26 +08:00

72 lines
2.1 KiB
Rust

use gpui::{
prelude::FluentBuilder, AnyElement, ClipboardItem, ElementId, IntoElement, ParentElement,
RenderOnce, SharedString, Styled, WindowContext,
};
use crate::{button::Button, h_flex, IconName, Sizable};
#[derive(IntoElement)]
pub struct Clipboard {
id: ElementId,
value: SharedString,
content_builder: Option<Box<dyn Fn(&mut WindowContext) -> AnyElement>>,
copied_callback: Option<Box<dyn Fn(SharedString, &mut WindowContext)>>,
}
impl Clipboard {
pub fn new(id: impl Into<ElementId>) -> Self {
Self {
id: id.into(),
value: "".into(),
content_builder: None,
copied_callback: None,
}
}
pub fn value(mut self, value: impl Into<SharedString>) -> Self {
self.value = value.into();
self
}
pub fn content<E, F>(mut self, element_builder: F) -> Self
where
E: IntoElement,
F: Fn(&mut WindowContext) -> E + 'static,
{
self.content_builder = Some(Box::new(move |cx| element_builder(cx).into_any_element()));
self
}
pub fn on_copied<F>(mut self, handler: F) -> Self
where
F: Fn(SharedString, &mut WindowContext) + 'static,
{
self.copied_callback = Some(Box::new(handler));
self
}
}
impl RenderOnce for Clipboard {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
h_flex()
.gap_1()
.items_center()
.when_some(self.content_builder, |this, builder| {
this.child(builder(cx))
})
.child(
Button::new(self.id, cx)
.icon(IconName::Copy)
.ghost()
.xsmall()
.on_click(move |_, cx| {
cx.stop_propagation();
cx.write_to_clipboard(ClipboardItem::new_string(self.value.to_string()));
if let Some(copied) = &self.copied_callback {
copied(self.value.clone(), cx);
}
}),
)
}
}