about summary refs log tree commit diff
path: root/src/display/viewport.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/display/viewport.rs')
-rw-r--r--src/display/viewport.rs303
1 files changed, 0 insertions, 303 deletions
diff --git a/src/display/viewport.rs b/src/display/viewport.rs
deleted file mode 100644
index c44316cdaad5..000000000000
--- a/src/display/viewport.rs
+++ /dev/null
@@ -1,303 +0,0 @@
-use super::BoxStyle;
-use super::DrawWithNeighbors;
-use crate::display::draw_box::draw_box;
-use crate::display::utils::clone_times;
-use crate::entities::entity::Entity;
-use crate::types::menu::MenuInfo;
-use crate::types::Neighbors;
-use crate::types::{pos, BoundingBox, Direction, Position, Positioned};
-use std::fmt::{self, Debug};
-use std::io::{self, Write};
-
-pub enum CursorState {
-    Game,
-    Prompt(Position),
-}
-
-impl Default for CursorState {
-    fn default() -> Self {
-        CursorState::Game
-    }
-}
-
-pub struct Viewport<W> {
-    /// The box describing the visible part of the viewport.
-    ///
-    /// Generally the size of the terminal, and positioned at 0, 0
-    pub outer: BoundingBox,
-
-    /// The box describing the game part of the viewport.
-    pub game: BoundingBox,
-
-    /// The box describing the inner part of the viewport
-    ///
-    /// Its position is relative to `outer.inner()`, and its size should
-    /// generally not be smaller than outer
-    pub inner: BoundingBox,
-
-    /// The actual screen that the viewport writes to
-    pub out: W,
-
-    cursor_state: CursorState,
-
-    /// Reset the cursor back to this position after every draw
-    pub game_cursor_position: Position,
-}
-
-impl<W> Viewport<W> {
-    pub fn new(outer: BoundingBox, inner: BoundingBox, out: W) -> Self {
-        Viewport {
-            outer,
-            inner,
-            out,
-            game: outer.move_tr_corner(Position { x: 0, y: 1 }),
-            cursor_state: Default::default(),
-            game_cursor_position: pos(0, 0),
-        }
-    }
-
-    /// Returns true if the (inner-relative) position of the given entity is
-    /// visible within this viewport
-    pub fn visible<E: Positioned>(&self, ent: &E) -> bool {
-        self.on_screen(ent.position()).within(self.game.inner())
-    }
-
-    /// Convert the given inner-relative position to one on the actual screen
-    fn on_screen(&self, pos: Position) -> Position {
-        pos + self.inner.position + self.game.inner().position
-    }
-}
-
-impl<W> Debug for Viewport<W> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "Viewport {{ outer: {:?}, inner: {:?}, out: <OUT> }}",
-            self.outer, self.inner
-        )
-    }
-}
-
-impl<W: Write> Viewport<W> {
-    /// Draw the given entity to the viewport at its position, if visible
-    #[allow(clippy::borrowed_box)]
-    pub fn draw<T: DrawWithNeighbors>(
-        &mut self,
-        entity: &T,
-        neighbors: &Neighbors<Vec<&Box<dyn Entity>>>,
-    ) -> io::Result<()> {
-        if !self.visible(entity) {
-            return Ok(());
-        }
-        self.cursor_goto(entity.position())?;
-        entity.do_draw_with_neighbors(self, neighbors)?;
-        self.reset_cursor()
-    }
-
-    fn reset_cursor(&mut self) -> io::Result<()> {
-        self.cursor_goto(self.game_cursor_position)
-    }
-
-    /// Move the cursor to the given inner-relative position
-    pub fn cursor_goto(&mut self, pos: Position) -> io::Result<()> {
-        write!(self, "{}", self.on_screen(pos).cursor_goto())
-    }
-
-    /// Clear whatever single character is drawn at the given inner-relative
-    /// position, if visible
-    pub fn clear(&mut self, pos: Position) -> io::Result<()> {
-        write!(self, "{} ", self.on_screen(pos).cursor_goto(),)?;
-        self.reset_cursor()
-    }
-
-    /// Initialize this viewport by drawing its outer box to the screen
-    pub fn init(&mut self) -> io::Result<()> {
-        draw_box(self, self.game, BoxStyle::Thin)
-    }
-
-    /// Write a message to the message area on the screen
-    ///
-    /// Will overwrite any message already present, and if the given message is
-    /// longer than the screen will truncate. This means callers should handle
-    /// message buffering and ellipsisization
-    pub fn write_message(&mut self, msg: &str) -> io::Result<usize> {
-        let msg_to_write = if msg.len() <= self.outer.dimensions.w as usize {
-            msg
-        } else {
-            &msg[0..self.outer.dimensions.w as usize]
-        };
-        write!(
-            self,
-            "{}{}{}",
-            self.outer.position.cursor_goto(),
-            msg_to_write,
-            clone_times::<_, String>(
-                " ".to_string(),
-                self.outer.dimensions.w - msg.len() as u16
-            ),
-        )?;
-        self.reset_cursor()?;
-        Ok(msg_to_write.len())
-    }
-
-    pub fn clear_message(&mut self) -> io::Result<()> {
-        write!(
-            self,
-            "{}{}",
-            self.outer.position.cursor_goto(),
-            clone_times::<_, String>(
-                " ".to_string(),
-                self.outer.dimensions.w as u16
-            )
-        )?;
-        self.reset_cursor()
-    }
-
-    /// Write a prompt requesting text input to the message area on the screen.
-    ///
-    /// Will overwrite any message already present, and if the given message is
-    /// longer than the screen will truncate. This means callers should handle
-    /// message buffering and ellipsisization
-    pub fn write_prompt<'a, 'b>(&'a mut self, msg: &'b str) -> io::Result<()> {
-        let len = self.write_message(msg)? + 1;
-        let pos = self.outer.position + pos(len as i16, 0);
-        self.cursor_state = CursorState::Prompt(pos);
-        write!(self, "{}", pos.cursor_goto())?;
-        self.flush()
-    }
-
-    pub fn push_prompt_chr(&mut self, chr: char) -> io::Result<()> {
-        if let CursorState::Prompt(pos) = self.cursor_state {
-            write!(self, "{}", chr)?;
-            self.cursor_state = CursorState::Prompt(pos + Direction::Right);
-        }
-        Ok(())
-    }
-
-    pub fn pop_prompt_chr(&mut self) -> io::Result<()> {
-        if let CursorState::Prompt(pos) = self.cursor_state {
-            let new_pos = pos + Direction::Left;
-            write!(
-                self,
-                "{} {}",
-                new_pos.cursor_goto(),
-                new_pos.cursor_goto()
-            )?;
-            self.cursor_state = CursorState::Prompt(new_pos);
-        }
-        Ok(())
-    }
-
-    pub fn clear_prompt(&mut self) -> io::Result<()> {
-        self.clear_message()?;
-        self.cursor_state = CursorState::Game;
-        Ok(())
-    }
-
-    pub fn write_menu(&mut self, menu: &MenuInfo) -> io::Result<()> {
-        let menu_dims = menu.dimensions();
-
-        // TODO: check if the menu is too big
-
-        let menu_position = self.game.position + pos(1, 1);
-
-        let menu_box = BoundingBox {
-            dimensions: menu_dims,
-            position: menu_position,
-        };
-
-        debug!("writing menu at: {:?}", menu_box);
-
-        draw_box(self, menu_box, BoxStyle::Thin)?;
-
-        write!(
-            self,
-            "{}{}",
-            (menu_position + pos(2, 2)).cursor_goto(),
-            menu.prompt
-        )?;
-
-        for (idx, option) in menu.options.iter().enumerate() {
-            write!(
-                self,
-                "{}{}",
-                (menu_position + pos(2, 4 + idx as i16)).cursor_goto(),
-                option
-            )?;
-        }
-
-        Ok(())
-    }
-}
-
-impl<W> Positioned for Viewport<W> {
-    fn position(&self) -> Position {
-        self.outer.position
-    }
-}
-
-impl<W: Write> Write for Viewport<W> {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.out.write(buf)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        self.out.flush()
-    }
-
-    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
-        self.out.write_all(buf)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use crate::types::Dimensions;
-
-    #[test]
-    fn test_visible() {
-        assert!(Viewport::new(
-            BoundingBox::at_origin(Dimensions { w: 10, h: 10 }),
-            BoundingBox {
-                position: Position { x: -10, y: -10 },
-                dimensions: Dimensions { w: 15, h: 15 },
-            },
-            ()
-        )
-        .visible(&Position { x: 13, y: 13 }));
-
-        assert!(!Viewport::new(
-            BoundingBox::at_origin(Dimensions { w: 10, h: 10 }),
-            BoundingBox {
-                position: Position { x: -10, y: -10 },
-                dimensions: Dimensions { w: 15, h: 15 },
-            },
-            (),
-        )
-        .visible(&Position { x: 1, y: 1 }));
-    }
-
-    #[test]
-    fn test_write_menu() {
-        let buf: Vec<u8> = Vec::new();
-
-        let mut viewport = Viewport::new(
-            BoundingBox::at_origin(Dimensions::default()),
-            BoundingBox::at_origin(Dimensions::default()),
-            buf,
-        );
-
-        let menu = MenuInfo::new(
-            "Test menu".to_string(),
-            vec!["option 1".to_string(), "option 2".to_string()],
-        );
-
-        viewport.write_menu(&menu).unwrap();
-
-        let res = std::str::from_utf8(&viewport.out).unwrap();
-        assert!(res.contains("Test menu"));
-        assert!(res.contains("option 1"));
-        assert!(res.contains("option 2"));
-    }
-}