basic/
basic.rs

1//! Basic example demonstrating observable property usage
2//!
3//! Run with: cargo run --example basic
4
5use observable_property::ObservableProperty;
6use std::sync::Arc;
7
8/// A simple person struct that demonstrates observable properties
9#[derive(Clone, Debug)]
10struct Person {
11    name: ObservableProperty<String>,
12    age: ObservableProperty<i32>,
13}
14
15impl Person {
16    fn new(name: String, age: i32) -> Self {
17        Self {
18            name: ObservableProperty::new(name),
19            age: ObservableProperty::new(age),
20        }
21    }
22
23    fn get_name(&self) -> Result<String, observable_property::PropertyError> {
24        self.name.get()
25    }
26
27    fn set_name(&self, new_name: String) -> Result<(), observable_property::PropertyError> {
28        self.name.set(new_name)
29    }
30
31    fn get_age(&self) -> Result<i32, observable_property::PropertyError> {
32        self.age.get()
33    }
34
35    fn set_age(&self, new_age: i32) -> Result<(), observable_property::PropertyError> {
36        self.age.set(new_age)
37    }
38
39    fn celebrate_birthday(&self) -> Result<(), observable_property::PropertyError> {
40        let current_age = self.age.get()?;
41        self.age.set(current_age + 1)
42    }
43}
44
45fn main() -> Result<(), Box<dyn std::error::Error>> {
46    println!("=== Observable Property Basic Example ===\n");
47
48    // Create a person
49    let person = Person::new("Alice".to_string(), 25);
50
51    // Subscribe to name changes
52    let name_observer_id = person.name.subscribe(Arc::new(|old_name, new_name| {
53        println!("šŸ“ Name changed: '{}' → '{}'", old_name, new_name);
54    }))?;
55
56    // Subscribe to age changes
57    let age_observer_id = person.age.subscribe(Arc::new(|old_age, new_age| {
58        println!("šŸŽ‚ Age changed: {} → {}", old_age, new_age);
59    }))?;
60
61    // Subscribe to only significant age changes (milestones)
62    let milestone_observer_id = person.age.subscribe_filtered(
63        Arc::new(|_old_age, new_age| {
64            println!("šŸŽ‰ Milestone reached! {} is now a special age: {}", 
65                    if *new_age >= 18 { "Adult" } else { "Child" }, new_age);
66        }),
67        |old_age, new_age| {
68            // Notify on milestone ages
69            let milestones = [18, 21, 30, 40, 50, 65];
70            milestones.contains(new_age) || 
71            (milestones.contains(old_age) && !milestones.contains(new_age))
72        }
73    )?;
74
75    println!("Initial state:");
76    println!("  Name: {}", person.get_name()?);
77    println!("  Age: {}\n", person.get_age()?);
78
79    // Demonstrate property changes
80    println!("Making changes...\n");
81
82    // Change name
83    person.set_name("Alice Johnson".to_string())?;
84
85    // Age up a few times
86    person.celebrate_birthday()?;
87    person.celebrate_birthday()?;
88    person.celebrate_birthday()?;
89
90    // Change to milestone age
91    person.set_age(21)?;
92
93    // Direct property access
94    println!("\nDirect property access:");
95    let simple_property = ObservableProperty::new(100);
96    
97    simple_property.subscribe(Arc::new(|old, new| {
98        println!("šŸ’° Value changed: {} → {}", old, new);
99    }))?;
100
101    simple_property.set(200)?;
102    simple_property.set(150)?;
103
104    // Cleanup observers
105    person.name.unsubscribe(name_observer_id)?;
106    person.age.unsubscribe(age_observer_id)?;
107    person.age.unsubscribe(milestone_observer_id)?;
108
109    println!("\nāœ… Example completed successfully!");
110    Ok(())
111}