Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 0 additions & 64 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,3 @@ license = "MIT"
[dependencies]
grid = "0.17.0"
thiserror = "2.0.12"
uuid = { version = "1.10.0", features = ["v4"] }
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A flexible and efficient Rust library for managing 2D grid-based layouts with automatic collision handling and dynamic vertical expansion.

PS: This crate is on the early stages of development, so expect breaking changes and limited documentation.

## Features

- 🎯 Automatic collision detection and resolution
Expand Down Expand Up @@ -33,6 +35,7 @@ The main components of the library are:
- Error types for robust error handling

For detailed API documentation, run:

```bash
cargo doc --open
```
Expand Down Expand Up @@ -72,4 +75,4 @@ at your option.

## Acknowledgments

- Built with the [grid](https://crates.io/crates/grid) crate for efficient grid operations
- Built with the [grid](https://crates.io/crates/grid) crate for efficient grid operations
6 changes: 4 additions & 2 deletions examples/managing_grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ fn print_grid(grid: &GridEngine) {
println!("{}", grid_str_formatted);
}

fn main() {
fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Grid App");

let mut grid = GridEngine::new(10, 12);

grid.events_mut().add_changes_listener(|event| {
println!("Event triggered: {:#?}", event);
});
})?;

grid.add_item("a".to_string(), 2, 2, 2, 4).unwrap();
print_grid(&grid);
Expand All @@ -69,4 +69,6 @@ fn main() {
print_grid(&grid);
grid.move_item("a", 1, 0).unwrap();
print_grid(&grid);

Ok(())
}
6 changes: 6 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ pub enum ItemError {
#[error("Item already exists: {id}")]
ItemAlreadyExists { id: String },
}

#[derive(Error, Debug)]
pub enum GridEventError {
#[error("Failed to generate listener id")]
ListenerIdNotGenerated,
}
77 changes: 53 additions & 24 deletions src/grid_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@
//! // The listener will be notified automatically
//! ```

use crate::grid_engine::Change;
use std::fmt::Debug;
use crate::{error::GridEventError, grid_engine::Change};
use std::{
fmt::Debug,
sync::{Arc, Mutex},
};

/// Event data structure containing information about grid changes.
///
Expand Down Expand Up @@ -117,6 +120,7 @@ impl Debug for ListenerFunction {
/// and remove listeners, as well as trigger events when changes happen.
#[derive(Debug, Default)]
pub struct GridEvents {
listener_id_counter: Arc<Mutex<usize>>,
/// Collection of registered change event listeners
changes_listeners: Vec<ListenerFunction>,
}
Expand Down Expand Up @@ -149,12 +153,22 @@ impl GridEvents {
pub fn add_changes_listener(
&mut self,
function: impl Fn(&ChangesEventValue) + Send + 'static + Sync,
) -> String {
let id = uuid::Uuid::new_v4().to_string();
) -> Result<String, GridEventError> {
let id = {
let mut counter = match self.listener_id_counter.lock() {
Ok(counter) => counter,
Err(_) => {
return Err(GridEventError::ListenerIdNotGenerated);
}
};
*counter += 1;
format!("l_{}", counter)
};

let listener = ListenerFunction::new(id.clone(), Box::new(function));

self.changes_listeners.push(listener);
id
Ok(id)
}

/// Removes a previously registered change event listener.
Expand All @@ -167,13 +181,18 @@ impl GridEvents {
///
/// ```
/// use grid_engine::grid_engine::GridEngine;
/// use std::error::Error;
///
/// # fn main() -> Result<(), Box<dyn Error>> {
///
/// let mut grid = GridEngine::new(10, 10);
/// let listener_id = grid.events_mut().add_changes_listener(|_| {});
/// let listener_id = grid.events_mut().add_changes_listener(|_| {})?;
/// let removed = grid.events_mut().remove_changes_listener(&listener_id); // Listener removed
///
/// assert!(removed.is_some());
///
/// # Ok(())
/// # }
/// ```
pub fn remove_changes_listener(&mut self, id: &str) -> Option<ChangesEventFn> {
if let Some(pos) = self
Expand Down Expand Up @@ -212,7 +231,7 @@ mod tests {
#[test]
fn test_add_changes_listener() {
let mut events = GridEvents::default();
let listener_id = events.add_changes_listener(|_| {});
let listener_id = events.add_changes_listener(|_| {}).unwrap();

assert_eq!(events.changes_listeners.len(), 1);
assert!(!listener_id.is_empty());
Expand All @@ -221,7 +240,7 @@ mod tests {
#[test]
fn test_remove_changes_listener() {
let mut events = GridEvents::default();
let listener_id = events.add_changes_listener(|_| {});
let listener_id = events.add_changes_listener(|_| {}).unwrap();

events.remove_changes_listener(&listener_id);
assert_eq!(events.changes_listeners.len(), 0);
Expand All @@ -230,10 +249,14 @@ mod tests {
#[test]
fn test_multiple_listeners() {
let mut events = GridEvents::default();
let _id1 = events.add_changes_listener(|_| {});
let _id2 = events.add_changes_listener(|_| {});

assert_eq!(events.changes_listeners.len(), 2);
let _id1 = events.add_changes_listener(|_| {}).unwrap();
let _id2 = events.add_changes_listener(|_| {}).unwrap();
let _id3 = events.add_changes_listener(|_| {}).unwrap();

assert_eq!(events.changes_listeners.len(), 3);
assert_ne!(_id1, _id2);
assert_ne!(_id2, _id3);
assert_ne!(_id1, _id3);
}

#[test]
Expand All @@ -242,10 +265,12 @@ mod tests {
let counter = Arc::new(Mutex::new(0));
let counter_clone = counter.clone();

events.add_changes_listener(move |_| {
let mut count = counter_clone.lock().unwrap();
*count += 1;
});
events
.add_changes_listener(move |_| {
let mut count = counter_clone.lock().unwrap();
*count += 1;
})
.unwrap();

let changes = ChangesEventValue { changes: vec![] };
events.trigger_changes_event(&changes);
Expand All @@ -261,10 +286,12 @@ mod tests {
// Add two listeners that increment the same counter
for _ in 0..2 {
let counter_clone = counter.clone();
events.add_changes_listener(move |_| {
let mut count = counter_clone.lock().unwrap();
*count += 1;
});
events
.add_changes_listener(move |_| {
let mut count = counter_clone.lock().unwrap();
*count += 1;
})
.unwrap();
}

let changes = ChangesEventValue { changes: vec![] };
Expand All @@ -279,10 +306,12 @@ mod tests {
let received_changes = Arc::new(Mutex::new(Vec::new()));
let received_changes_clone = received_changes.clone();

events.add_changes_listener(move |event| {
let mut changes = received_changes_clone.lock().unwrap();
changes.extend(event.changes.clone());
});
events
.add_changes_listener(move |event| {
let mut changes = received_changes_clone.lock().unwrap();
changes.extend(event.changes.clone());
})
.unwrap();

// Create a mock change
let node = crate::node::Node::new("test".to_string(), 0, 0, 1, 1);
Expand Down
Loading