📝 Document Pane

main
Shad Amethyst 2 years ago
parent 33946a4c18
commit 92d5b882a4
Signed by: amethyst
GPG Key ID: D970C8DD1D6DEE36

@ -10,6 +10,28 @@ pub struct Pane {
}
impl Pane {
/// Creates a new, empty `Pane` with the given dimensions.
/// If `width == 0` or `height == 0`, returns `None`.
///
/// # Example
///
/// ```
/// use stackline::prelude::*;
/// use stackline::tile::Wire;
///
/// // Create a new Pane with width 6 and height 4
/// let mut pane = Pane::empty(6, 4).unwrap();
///
/// // Place a horizontal wire on (2, 1) and (3, 1)
/// pane.set_tile((2, 1), Wire::new(Orientation::Horizontal));
/// pane.set_tile((3, 1), Wire::new(Orientation::Horizontal));
///
/// // Put a signal on (2, 1)
/// pane.set_signal((2, 1), stackline::signal!((2, 1)));
///
/// // Perform a simulation step
/// pane.step();
/// ```
pub fn empty(width: usize, height: usize) -> Option<Self> {
// TODO: check that width * height is a valid usize
let length = width.checked_mul(height)?;
@ -23,7 +45,24 @@ impl Pane {
})
}
/// Returns `Some((x + Δx, y + Δy))` iff `(x + Δx, y + Δy)` is inside the world
/// Given a `position = (x, y)` and an `offset = (Δx, Δy)`,
/// returns `Some((x + Δx, y + Δy))` if `(x + Δx, y + Δy)` is inside the `Pane`.
///
/// If `(x + Δx, y + Δy)` fall outside of the bounds of `Pane`, returns `None`.
///
/// # Example
///
/// ```
/// # use stackline::prelude::*;
/// #
/// let pane = Pane::empty(4, 2).unwrap();
///
/// assert_eq!(pane.offset((1, 0), (2, 1)), Some((3, 1))); // (1 + 2, 0 + 1) = (3, 1), inside
///
/// assert_eq!(pane.offset((1, 0), (-2, 0)), None); // (1 - 2, 0 + 0) = (-1, 0), outside
///
/// assert_eq!(pane.offset((1, 0), (3, 0)), None); // (1 + 3, 0 + 0) = (4, 0), outside
/// ```
#[inline]
pub fn offset(&self, position: (usize, usize), offset: (i8, i8)) -> Option<(usize, usize)> {
if offset.0 < 0 && (-offset.0) as usize > position.0
@ -46,6 +85,21 @@ impl Pane {
}
// TODO: Have a Result instead of an Option
/// Returns an immutable referenec to the [`Tile`] at `position`.
/// If `position` is out of bounds, returns `None`.
///
/// # Example
///
/// ```
/// use stackline::prelude::*;
/// use stackline::tile::{FullTile, Wire};
///
/// let mut pane = Pane::empty(4, 4).unwrap();
///
/// pane.set_tile((0, 0), Wire::new(Orientation::Horizontal));
///
/// let tile = pane.get((0, 0)).unwrap();
/// ```
#[inline]
pub fn get<'b>(&'b self, position: (usize, usize)) -> Option<&'b FullTile> {
if !self.in_bounds(position) {
@ -93,16 +147,58 @@ impl Pane {
Some(())
}
/// Returns the [`State`] of the tile at `position`, if it exists.
/// Returns the [`State`] of the tile at `position`, if that tile exists.
/// If `position` is out of bounds, returns `None`.
///
/// # Example
///
/// ```
/// use stackline::prelude::*;
/// use stackline::tile::Wire;
///
/// let mut pane = Pane::empty(1, 1).unwrap();
///
/// // All tiles are initialized with the Idle state
/// assert_eq!(pane.get_state((0, 0)), Some(State::Idle));
///
/// // Creating a new tile gives it the Idle state
/// pane.set_tile((0, 0), Wire::new(Orientation::Horizontal));
/// assert_eq!(pane.get_state((0, 0)), Some(State::Idle));
///
/// // We manually set the state to Dormant and observe the change
/// pane.get_mut((0, 0)).unwrap().set_state(State::Dormant);
/// assert_eq!(pane.get_state((0, 0)), Some(State::Dormant));
/// ```
#[inline]
pub fn get_state(&self, position: (usize, usize)) -> Option<State> {
self.get(position).map(|x| x.state().clone())
}
/// Sets the signal for the tile at `position` to `signal`.
/// Returns `Some` iff:
/// - the tile exists
/// - the tile accepts a signal (ie. it isn't empty)
/// Returns `Some(())` if the tile exists and the tile can have a signal.
///
/// This function does not check the tile's [`accepts_signal`](Tile::accepts_signal) method.
/// It will also overwrite any signal already present.
///
/// # Example
///
/// ```
/// use stackline::prelude::*;
/// use stackline::tile::Diode;
///
/// let mut pane = Pane::empty(2, 1).unwrap();
///
/// pane.set_tile((0, 0), Diode::new(Direction::Right));
/// pane.set_tile((1, 0), Diode::new(Direction::Down));
///
/// // The signal for a tile is initially None
/// assert!(pane.get((0, 0)).unwrap().signal().is_none());
///
/// // We set it to something else
/// pane.set_signal((0, 0), stackline::signal!((0, 0), Direction::Right)).unwrap();
///
/// assert!(pane.get((0, 0)).unwrap().signal().is_some());
/// ```
#[inline]
pub fn set_signal(&mut self, position: (usize, usize), mut signal: Signal) -> Option<()> {
signal.set_position(position);
@ -116,6 +212,19 @@ impl Pane {
}
}
/// Returns `true` if `position` is within the bounds of the pane.
/// Returns `false` otherwise.
///
/// # Examples
///
/// ```
/// # use stackline::prelude::*;
/// let pane = Pane::empty(2, 3).unwrap();
///
/// assert!(pane.in_bounds((0, 0)));
/// assert!(pane.in_bounds((1, 2)));
/// assert!(!pane.in_bounds((10, 10)));
/// ```
#[inline]
pub fn in_bounds(&self, position: (usize, usize)) -> bool {
position.0 < self.width.get() && position.1 < self.height.get()

Loading…
Cancel
Save