Skip to content

Commit

Permalink
polish grid resize feature further
Browse files Browse the repository at this point in the history
  • Loading branch information
wooster0 committed Aug 19, 2021
1 parent 4b9bbbd commit 09e3755
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 44 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Binaries are also provided in the [Releases](https://github.com/r00ster91/yayagr
* Runs in the terminal!
* Cross-platform: runs on Linux, Windows and macOS.
* Helpful features and tools like undo, redo and clear.
* [Create your own grids](#Editor) for others to play.
* Random grids.
* Custom grids: [create your own grids](#Editor) for others to play.
* A new kind of cell: [maybed](#Maybed).
* Very well suited for [big grids](#Big-grids).
* Intuitive to play.
Expand Down Expand Up @@ -108,6 +109,7 @@ yayagram is very well suited for big grids, up to size 99x99. Here are the reaso
- Try to avoid guesssing and play it safe! Guessing can come back later to bite you. Guessing is `unsafe`.
- Don't forget to cross out cells that you are sure won't be filled.
This helps immensely at ruling out possibilities.
- If you want a new random grid, drag the litle resize icon in the grid's bottom right, next to the progress bar, to the size you want.
- Be careful about accidentally pasting in your clipboard data. Some terminals paste with the press of a mouse button.
If the data contains `'c'` for instance, the grid will be cleared because it's recognized as the `C` key being pressed.
This clear can be undone using the `A` key of course, but it may be confusing.
Expand Down
97 changes: 56 additions & 41 deletions src/event/input/mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::{super::alert, Alert, State};
use crate::grid::{self, builder::Builder, Cell, CellPlacement, Grid};
use terminal::{
event::{Event, Key, MouseButton, MouseEvent, MouseEventKind},
util::Point,
util::{Point, Size},
Terminal,
};

Expand Down Expand Up @@ -41,13 +41,13 @@ pub fn handle_event(
x: builder.point.x + builder.grid.size.width * 2,
y: builder.point.y + builder.grid.size.height,
};
let resize_arrow = Point {
let resize_icon = Point {
x: grid_corner.x + 1,
..grid_corner
};

if selected_cell_point == resize_arrow {
resize_grid(terminal, builder, alert, resize_arrow)
if selected_cell_point == resize_icon {
resize_grid(terminal, builder, alert, resize_icon)
} else {
State::Continue
}
Expand Down Expand Up @@ -79,12 +79,14 @@ fn resize_grid(
terminal: &mut Terminal,
builder: &mut Builder,
alert: &mut Option<Alert>,
resize_arrow: Point,
resize_icon: Point,
) -> State {
let original_grid_size = builder.grid.size.clone();

crate::clear_basic_controls_help(terminal, builder);

builder.clear_progress_bar_and_resize_icon(terminal);

loop {
let event = terminal.read_event();

Expand All @@ -101,12 +103,12 @@ fn resize_grid(

use std::cmp::Ordering;

match point.x.cmp(&resize_arrow.x) {
match point.x.cmp(&resize_icon.x) {
Ordering::Greater => {
builder.clear_empty_grid(terminal);

builder.grid.size.width =
original_grid_size.width + ((point.x - resize_arrow.x) / 2);
original_grid_size.width + (point.x - resize_icon.x) / 2;

draw(terminal, builder);
}
Expand All @@ -115,7 +117,7 @@ fn resize_grid(

builder.grid.size.width = original_grid_size
.width
.saturating_sub(resize_arrow.x.saturating_sub(point.x) / 2);
.saturating_sub(resize_icon.x.saturating_sub(point.x) / 2);

if builder.grid.size.width < 1 {
builder.grid.size.width = 1;
Expand All @@ -126,14 +128,14 @@ fn resize_grid(
Ordering::Equal => {}
}

match point.y.cmp(&resize_arrow.y) {
match point.y.cmp(&resize_icon.y) {
Ordering::Greater |
Ordering::Equal // This prevents some weird behavior on expansion or contraction of the grid over the original grid size
=> {
builder.clear_empty_grid(terminal);

builder.grid.size.height =
original_grid_size.height + (point.y - resize_arrow.y);
original_grid_size.height + (point.y - resize_icon.y);

draw(terminal, builder);
}
Expand All @@ -142,7 +144,7 @@ fn resize_grid(

builder.grid.size.height = original_grid_size
.height
.saturating_sub(resize_arrow.y.saturating_sub(point.y));
.saturating_sub(resize_icon.y.saturating_sub(point.y));

if builder.grid.size.height < 1 {
builder.grid.size.height = 1;
Expand All @@ -164,48 +166,61 @@ fn resize_grid(
builder.draw_all(terminal);
}

crate::draw_basic_controls_help(terminal, builder);

State::Continue
} else {
let message = "Press Enter to confirm new random grid in this size. Esc to abort".into();
let confirmed = confirmation_prompt(terminal, builder, original_grid_size.clone(), alert);

// Temporarily set the builder grid size back to the old size to render the alert properly.
let new_grid_size = builder.grid.size.clone();
builder.grid.size = original_grid_size.clone();
alert::draw(terminal, builder, alert, message);
builder.grid.size = new_grid_size;
if confirmed {
// Currently the new game simply runs inside of this existing game and the new game creates an entirely new state.
// At some point we would probably hit a stack overflow if the user keeps resizing the grid within the same session.

terminal.flush();
terminal.clear();
crate::start_game(terminal, Grid::random(builder.grid.size.clone()));

loop {
let input = terminal.read_event();
State::Exit
} else {
builder.grid.size = original_grid_size;

match input {
Some(Event::Key(Key::Enter)) => {
// Currently the new game simply runs inside of this existing game and the new game creates an entirely new state.
// At some point we would probably hit a stack overflow if the user keeps resizing the grid within the same session.
terminal.clear();

terminal.clear();
crate::start_game(terminal, Grid::random(builder.grid.size.clone()));
// Only the grid's size was mutated
#[allow(unused_must_use)]
{
builder.draw_all(terminal);
}

break State::Exit;
}
Some(Event::Resize | Event::Mouse(_)) => {}
_ => {
builder.grid.size = original_grid_size;
crate::draw_basic_controls_help(terminal, builder);

terminal.clear();
State::Alert("Aborted".into())
}
}
}

// Only the grid's size was mutated
#[allow(unused_must_use)]
{
builder.draw_all(terminal);
}
fn confirmation_prompt(
terminal: &mut Terminal,
builder: &mut Builder,
original_grid_size: Size,
alert: &mut Option<Alert>,
) -> bool {
let message = "Press Enter to confirm new random grid in this size. Esc to abort".into();

crate::draw_basic_controls_help(terminal, builder);
// Temporarily set the builder grid size back to the old size to render the alert properly.
let new_grid_size = builder.grid.size.clone();
builder.grid.size = original_grid_size.clone();
alert::draw(terminal, builder, alert, message);
builder.grid.size = new_grid_size;

break State::Alert("Aborted".into());
}
}
terminal.flush();

loop {
let input = terminal.read_event();

match input {
Some(Event::Key(Key::Enter)) => break true,
Some(Event::Resize | Event::Mouse(_)) => {}
_ => break false,
}
}
}
27 changes: 25 additions & 2 deletions src/grid/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,24 @@ impl Builder {
}
}

pub fn draw_resize_arrow(&mut self, terminal: &mut Terminal) {
/// Clears the progress bar as well as the resize icon.
pub fn clear_progress_bar_and_resize_icon(&mut self, terminal: &mut Terminal) {
terminal.set_cursor(Point {
y: self.point.y + self.grid.size.height,
..self.point
});

let grid_width = self.grid.size.width * 2;

for _ in 0..grid_width {
terminal.write(" ");
}

self.clear_resize_icon(terminal);
}

/// Draws the resize icon, at the bottom right, next to the progress bar.
fn draw_resize_icon(&mut self, terminal: &mut Terminal) {
terminal.set_foreground_color(Color::DarkGray);

#[cfg(not(windows))]
Expand All @@ -325,6 +342,7 @@ impl Builder {
// until the situation improves (and https://en.wikipedia.org/wiki/Windows_Terminal becomes the new default on Windows?),
// this is used as an alternative.
// Someday the arrow could be used on Windows too.
// Then the resize icon could also be renamed to a resize arrow.
//
// In the future it might be helpful to take a look at the market share of Windows 10 or 11 and decide by that.
//
Expand All @@ -334,6 +352,11 @@ impl Builder {
terminal.write(" +");
}

/// Clears the resize icon.
fn clear_resize_icon(&mut self, terminal: &mut Terminal) {
terminal.write(" ");
}

/// Draws the grid, the picture and the clues while also returning whether all the drawn clues were solved ones (i.e. whether the grid was solved).
#[must_use]
pub fn draw_all(&mut self, terminal: &mut Terminal) -> bool {
Expand All @@ -345,7 +368,7 @@ impl Builder {

self.draw_progress_bar(terminal, solved_rows);

self.draw_resize_arrow(terminal);
self.draw_resize_icon(terminal);

solved_rows == (self.grid.size.width + self.grid.size.height) as usize
}
Expand Down

0 comments on commit 09e3755

Please sign in to comment.