use glib::prelude::{Cast, CastNone};
use grx_macros::{gtk_component, props};
use gtk::glib;
use gtk::{
prelude::EditableExtManual,
prelude::{EditableExt, 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<Entry>>,
pub on_blur: Option<Handler<Entry>>,
pub password: Option<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)
.finish()
}
}
pub fn entry(mut props: Props) -> Rc<Entry> {
let entry: gtk::Editable = match props.password {
Some(true) => gtk::PasswordEntry::builder().build().upcast(),
_ => gtk::Entry::builder().build().upcast(),
};
let on_blur = props.on_blur.take();
let on_change = props.on_change.take();
let w = entry.clone();
let component = new_gc!(Entry { w, props });
apply(component.clone());
if let Some(onc) = on_change {
let comp = component.clone();
entry.connect_insert_text(move |_, _, _| {
onc(comp.clone());
});
}
if let Some(onb) = on_blur {
let comp = component.clone();
if let Some(text) = entry.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::Editable)]
#[derive(Debug)]
pub struct Entry {}
impl Interactable for Entry {
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_insert_text(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 Entry {
fn text(self: &Rc<Self>) -> String {
self.widget.text().to_string()
}
fn set_text(self: &Rc<Self>, text: &str) {
self.widget.set_text(text)
}
}