122 lines
4.1 KiB
Rust
122 lines
4.1 KiB
Rust
|
|
// Copyright (c) 2022 Maximiliano Sandoval R <msandova@gnome.org>
|
||
|
|
// Copyright (c) 2023 FineFindus
|
||
|
|
//
|
||
|
|
// This program is free software: you can redistribute it and/or modify
|
||
|
|
// it under the terms of the GNU General Public License as published by
|
||
|
|
// the Free Software Foundation, either version 3 of the License, or
|
||
|
|
// (at your option) any later version.
|
||
|
|
//
|
||
|
|
// This program is distributed in the hope that it will be useful,
|
||
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
// GNU General Public License for more details.
|
||
|
|
//
|
||
|
|
// You should have received a copy of the GNU General Public License
|
||
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
//
|
||
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||
|
|
|
||
|
|
use gtk::{glib, prelude::*};
|
||
|
|
|
||
|
|
mod imp {
|
||
|
|
use std::cell::RefCell;
|
||
|
|
|
||
|
|
use adw::subclass::prelude::*;
|
||
|
|
use glib::{ParamSpec, Properties, Value};
|
||
|
|
|
||
|
|
use super::*;
|
||
|
|
|
||
|
|
#[derive(Debug, Default, Properties)]
|
||
|
|
#[properties(wrapper_type = super::LpDragOverlay)]
|
||
|
|
pub struct LpDragOverlay {
|
||
|
|
/// Usual content
|
||
|
|
#[property(set = Self::set_child)]
|
||
|
|
pub child: Option<gtk::Widget>,
|
||
|
|
/// Widget overplayed when dragging over child
|
||
|
|
#[property(set = Self::set_overlayed)]
|
||
|
|
pub overlayed: Option<gtk::Widget>,
|
||
|
|
pub overlay: gtk::Overlay,
|
||
|
|
pub revealer: gtk::Revealer,
|
||
|
|
#[property(set = Self::set_drop_target, get, explicit_notify)]
|
||
|
|
pub drop_target: RefCell<Option<gtk::DropTarget>>,
|
||
|
|
pub handler_id: RefCell<Option<glib::SignalHandlerId>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
#[glib::object_subclass]
|
||
|
|
impl ObjectSubclass for LpDragOverlay {
|
||
|
|
const NAME: &'static str = "LpDragOverlay";
|
||
|
|
type Type = super::LpDragOverlay;
|
||
|
|
type ParentType = adw::Bin;
|
||
|
|
}
|
||
|
|
|
||
|
|
impl ObjectImpl for LpDragOverlay {
|
||
|
|
fn properties() -> &'static [ParamSpec] {
|
||
|
|
Self::derived_properties()
|
||
|
|
}
|
||
|
|
|
||
|
|
fn set_property(&self, id: usize, value: &Value, pspec: &ParamSpec) {
|
||
|
|
self.derived_set_property(id, value, pspec)
|
||
|
|
}
|
||
|
|
|
||
|
|
fn property(&self, id: usize, pspec: &ParamSpec) -> Value {
|
||
|
|
self.derived_property(id, pspec)
|
||
|
|
}
|
||
|
|
|
||
|
|
fn constructed(&self) {
|
||
|
|
self.overlay.set_parent(&*self.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);
|
||
|
|
}
|
||
|
|
|
||
|
|
fn dispose(&self) {
|
||
|
|
self.overlay.unparent();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
impl WidgetImpl for LpDragOverlay {}
|
||
|
|
impl BinImpl for LpDragOverlay {}
|
||
|
|
|
||
|
|
impl LpDragOverlay {
|
||
|
|
pub fn set_child(&self, child: Option<gtk::Widget>) {
|
||
|
|
self.overlay.set_child(child.as_ref());
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_overlayed(&self, overlayed: Option<gtk::Widget>) {
|
||
|
|
self.revealer.set_child(overlayed.as_ref());
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn set_drop_target(&self, drop_target: >k::DropTarget) {
|
||
|
|
if let Some(target) = self.drop_target.borrow_mut().take() {
|
||
|
|
self.obj().remove_controller(&target);
|
||
|
|
|
||
|
|
if let Some(handler_id) = self.handler_id.borrow_mut().take() {
|
||
|
|
target.disconnect(handler_id);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
let handler_id = drop_target.connect_current_drop_notify(
|
||
|
|
glib::clone!(@weak self.revealer as revealer => move |target| {
|
||
|
|
let reveal = target.current_drop().is_some();
|
||
|
|
revealer.set_reveal_child(reveal);
|
||
|
|
}),
|
||
|
|
);
|
||
|
|
self.handler_id.replace(Some(handler_id));
|
||
|
|
|
||
|
|
// avoid `gtk_event_controller_get_widget (controller) == NULL` failing
|
||
|
|
if drop_target.widget().is_visible() {
|
||
|
|
self.obj().add_controller(drop_target.clone());
|
||
|
|
self.drop_target.replace(Some(drop_target.clone()));
|
||
|
|
self.obj().notify("drop-target");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
glib::wrapper! {
|
||
|
|
pub struct LpDragOverlay(ObjectSubclass<imp::LpDragOverlay>)
|
||
|
|
@extends gtk::Widget, adw::Bin;
|
||
|
|
}
|