use glib::{Cast, CastNone};
use grx_macros::{gtk_component, props};
use gtk::glib;
use gtk::traits::TextBufferExt;
use gtk::traits::TextViewExt;
use gtk::traits::WidgetExt;
use std::rc::Rc;
use crate::{default_on_click, default_on_swipe, handlers::Handler, new_gc, Interactable, Textual};
use super::gtk_props::apply;
#[props]
#[derive(Default)]
pub struct Props {
pub on_change: Option<Handler<TextArea>>,
pub on_blur: Option<Handler<TextArea>>,
pub password: Option<bool>,
pub disabled: bool,
}
impl std::fmt::Debug for Props {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Props")
.field("id", &self.id)
.field("classes", &self.classes)
.field("styles", &self.styles)
.field("children", &self.children)
.field("on_change", &self.on_change.is_some())
.field("on_blur", &self.on_blur.is_some())
.field("password", &self.password)
.field("disabled", &self.disabled)
.finish()
}
}
pub fn text_area(mut props: Props) -> Rc<TextArea> {
let text_area: gtk::TextView = gtk::TextView::builder().build();
let on_blur = props.on_blur.take();
let on_change = props.on_change.take();
text_area.set_sensitive(!props.disabled);
let w = text_area.clone();
let component = new_gc!(TextArea { w, props });
apply(component.clone());
if let Some(onc) = on_change {
let comp = component.clone();
text_area.connect_buffer_notify(move |_| {
onc(comp.clone());
});
}
if let Some(onb) = on_blur {
let comp = component.clone();
if let Some(text) = text_area.first_child().and_downcast_ref::<gtk::Text>() {
text.connect_has_focus_notify(move |w| {
if !w.has_focus() {
onb(comp.clone())
}
});
}
}
component
}
#[gtk_component(gtk::TextView)]
#[derive(Debug)]
pub struct TextArea {}
impl Interactable for TextArea {
default_on_click! {}
default_on_swipe! {}
fn on_change(self: &Rc<Self>, handler: impl Fn(&Rc<Self>) + 'static) {
let s = self.clone();
self.widget.connect_buffer_notify(move |_| handler(&s));
}
fn on_blur(self: &Rc<Self>, handler: impl Fn(&Rc<Self>) + 'static) {
let s = self.clone();
if let Some(text) = self.widget.first_child().and_downcast_ref::<gtk::Text>() {
text.connect_has_focus_notify(move |w| {
if !w.has_focus() {
handler(&s)
}
});
}
}
}
impl Textual for TextArea {
fn text(self: &Rc<Self>) -> String {
self.widget.buffer().to_string()
}
fn set_text(self: &Rc<Self>, text: &str) {
self.widget.buffer().set_text(text)
}
}