-
-
Notifications
You must be signed in to change notification settings - Fork 115
/
cat.rs
102 lines (87 loc) · 2.61 KB
/
cat.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use glib::prelude::*;
use glib::subclass::prelude::*;
use super::pet::*;
use super::purrable::*;
mod imp {
use std::cell::Cell;
use super::*;
#[derive(Default)]
pub struct Cat {
fed: Cell<bool>,
pub(super) purring: Cell<bool>,
}
#[glib::object_subclass]
impl ObjectSubclass for Cat {
const NAME: &'static str = "Cat";
type Type = super::Cat;
type Interfaces = (Purrable,);
type ParentType = Pet;
}
impl ObjectImpl for Cat {}
impl PurrableImpl for Cat {
fn is_purring(&self) -> bool {
if self.purring.get() {
println!("Cat::is_purring: *purr*");
true
} else {
println!("Cat::is_purring: Chaining up to parent_is_purring");
self.parent_is_purring()
}
}
}
impl PetImpl for Cat {
/// Override the parent behaviour of `pet` to indicate a successful pet
/// if we have been sufficiently fed
fn pet(&self) -> bool {
if self.fed.get() {
println!("Cat::pet: *purr*");
self.purring.set(true);
true
} else {
println!("Cat::pet: *mrrp*");
false
}
}
fn feed(&self) {
println!("Cat::feed: *mreeeow*");
self.parent_feed();
// Remember that we have been fed
self.fed.set(true);
}
}
impl Cat {
pub(super) fn meow(&self) {
// We can't be meowing and purring at the same time
self.purring.set(false);
println!("Cat::meow: *meow* *meow*");
}
}
}
glib::wrapper! {
/// The `Cat` class ties the interface and the superclass together
pub struct Cat(ObjectSubclass<imp::Cat>)
@extends Pet,
@implements Purrable;
}
/// Public methods of `Cat` classes
pub trait CatExt: IsA<Cat> {
/// A regular public method.
///
/// Resets the purring state.
fn meow(&self) {
self.upcast_ref::<Cat>().imp().meow();
}
}
impl<T: IsA<Cat>> CatExt for T {}
impl Default for Cat {
fn default() -> Self {
glib::Object::new()
}
}
/// Cat is also subclassable, but does not have any vfuncs.
///
/// By convention we still create an empty `CatImpl` trait, this allows us to add
/// 'protected' cat methods only available to be called by other Cats later.
pub trait CatImpl: PetImpl + ObjectSubclass<Type: IsA<Cat>> {}
/// To make this class subclassable we need to implement IsSubclassable
unsafe impl<Obj: CatImpl + PetImpl> IsSubclassable<Obj> for Cat {}