godot_core/registry/signal/connect_handle.rs
1/*
2 * Copyright (c) godot-rust; Bromeon and contributors.
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 */
7
8use std::borrow::Cow;
9
10use crate::builtin::Callable;
11use crate::classes::Object;
12use crate::obj::Gd;
13use crate::sys;
14
15/// Handle representing a typed signal connection to a receiver.
16///
17/// Returned by connections made by the `connect_*` methods of
18/// [`TypedSignal`][crate::registry::signal::TypedSignal] and [`ConnectBuilder`][crate::registry::signal::ConnectBuilder].
19///
20/// Connections managed by a handle can be disconnected using [`disconnect()`][Self::disconnect].
21pub struct ConnectHandle {
22 receiver_object: Gd<Object>,
23 signal_name: Cow<'static, str>,
24 callable: Callable,
25}
26
27impl ConnectHandle {
28 // Should only be invoked by connect_* methods.
29 pub(super) fn new(
30 receiver_object: Gd<Object>,
31 signal_name: Cow<'static, str>,
32 callable: Callable,
33 ) -> Self {
34 Self {
35 receiver_object,
36 signal_name,
37 callable,
38 }
39 }
40
41 /// Disconnects the signal from the connected callable.
42 ///
43 /// # Panics (safeguards-balanced)
44 /// If the connection does not exist. Use [`is_connected()`][Self::is_connected] to make sure the connection exists.
45 pub fn disconnect(mut self) {
46 sys::balanced_assert!(self.is_connected());
47
48 self.receiver_object
49 .disconnect(&*self.signal_name, &self.callable);
50 }
51
52 /// Whether the handle represents a valid connection.
53 ///
54 /// Returns false if:
55 /// - ... the signals and callables managed by this handle have been disconnected in any other way than by using
56 /// [`disconnect()`][Self::disconnect] -- e.g. through [`Signal::disconnect()`][crate::builtin::Signal::disconnect] or
57 /// [`Object::disconnect()`][crate::classes::Object::disconnect].
58 /// - ... the broadcasting object managed by this handle is not valid -- e.g. if the object has been freed.
59 pub fn is_connected(&self) -> bool {
60 self.receiver_object.is_instance_valid()
61 && self
62 .receiver_object
63 .is_connected(&*self.signal_name, &self.callable)
64 }
65}