use gtk::{glib, glib::clone, prelude::*, subclass::prelude::*};
use crate::utils::BoundObject;
mod imp {
use std::marker::PhantomData;
use super::*;
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::DragOverlay)]
pub struct DragOverlay {
pub overlay: gtk::Overlay,
pub revealer: gtk::Revealer,
pub status: adw::StatusPage,
#[property(get = Self::title, set = Self::set_title)]
pub title: PhantomData<glib::GString>,
#[property(get = Self::child, set = Self::set_child, nullable)]
pub child: PhantomData<Option<gtk::Widget>>,
#[property(get, set = Self::set_drop_target)]
pub drop_target: BoundObject<gtk::DropTarget>,
}
#[glib::object_subclass]
impl ObjectSubclass for DragOverlay {
const NAME: &'static str = "DragOverlay";
type Type = super::DragOverlay;
type ParentType = gtk::Widget;
fn class_init(klass: &mut Self::Class) {
klass.set_css_name("dragoverlay");
klass.set_layout_manager_type::<gtk::BinLayout>();
}
}
#[glib::derived_properties]
impl ObjectImpl for DragOverlay {
fn constructed(&self) {
let obj = self.obj();
self.overlay.set_parent(&*obj);
self.overlay.add_overlay(&self.revealer);
self.revealer.set_can_target(false);
self.revealer
.set_transition_type(gtk::RevealerTransitionType::Crossfade);
self.revealer.set_reveal_child(false);
self.revealer.set_visible(false);
self.status.set_icon_name(Some("attachment-symbolic"));
self.revealer.set_child(Some(&self.status));
self.revealer.connect_child_revealed_notify(|revealer| {
if !revealer.reveals_child() && !revealer.is_child_revealed() {
revealer.set_visible(false);
}
});
}
fn dispose(&self) {
self.overlay.unparent();
}
}
impl WidgetImpl for DragOverlay {}
impl DragOverlay {
pub fn title(&self) -> glib::GString {
self.status.title()
}
pub fn set_title(&self, title: &str) {
self.status.set_title(title);
self.obj()
.update_property(&[gtk::accessible::Property::Label(title)]);
}
pub fn child(&self) -> Option<gtk::Widget> {
self.overlay.child()
}
pub fn set_child(&self, child: Option<>k::Widget>) {
self.overlay.set_child(child)
}
fn set_drop_target(&self, drop_target: gtk::DropTarget) {
let obj = self.obj();
if let Some(target) = self.drop_target.obj() {
obj.remove_controller(&target);
}
self.drop_target.disconnect_signals();
let handler_id = drop_target.connect_current_drop_notify(clone!(
#[weak(rename_to = revealer)]
self.revealer,
move |target| {
let reveal = target.current_drop().is_some();
if reveal {
revealer.set_visible(true);
}
revealer.set_reveal_child(reveal);
}
));
obj.add_controller(drop_target.clone());
self.drop_target.set(drop_target, vec![handler_id]);
obj.notify_drop_target();
}
}
}
glib::wrapper! {
pub struct DragOverlay(ObjectSubclass<imp::DragOverlay>)
@extends gtk::Widget, @implements gtk::Accessible;
}
impl DragOverlay {
pub fn new() -> Self {
glib::Object::new()
}
}
impl Default for DragOverlay {
fn default() -> Self {
Self::new()
}
}