mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-13 12:23:38 +01:00
Ported from komorebi-for-mac (feature/moar-scrolling). The crate has no dependencies and no knowledge of windows; it is not used by komorebi yet.
722 lines
20 KiB
Rust
722 lines
20 KiB
Rust
//! Columns of more than one tile, which sit one above the other and share the height.
|
|
//!
|
|
//! The viewport is 1200 by 800, there are no gaps unless a test says so, and columns are a quarter
|
|
//! of the viewport wide (300). A strip of four is keyed 0, 1, 2 and 3 in reading order.
|
|
|
|
mod common;
|
|
|
|
use common::*;
|
|
use komorebi_scrolling::ColumnWidth;
|
|
use komorebi_scrolling::Options;
|
|
use komorebi_scrolling::Rect;
|
|
use komorebi_scrolling::ScrollingSpace;
|
|
|
|
fn ids(space: &ScrollingSpace<u32>) -> Vec<u32> {
|
|
space.ids()
|
|
}
|
|
|
|
/// The columns, each as the keys of its tiles from the top.
|
|
fn columns(space: &ScrollingSpace<u32>) -> Vec<Vec<u32>> {
|
|
let mut seen = vec![];
|
|
let mut columns = vec![];
|
|
|
|
for id in space.ids() {
|
|
if seen.contains(&id) {
|
|
continue;
|
|
}
|
|
|
|
let column = space.column_of(&id).unwrap();
|
|
seen.extend(column.iter().copied());
|
|
columns.push(column);
|
|
}
|
|
|
|
columns
|
|
}
|
|
|
|
// Making columns of tiles
|
|
|
|
#[test]
|
|
fn consuming_to_the_right_takes_the_next_columns_tile_to_the_bottom_of_this_one() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&0);
|
|
|
|
assert!(space.consume_right());
|
|
|
|
assert_eq!(columns(&space), [vec![0, 1], vec![2], vec![3]]);
|
|
// the order of the tiles is the order that they were in
|
|
assert_eq!(ids(&space), [0, 1, 2, 3]);
|
|
assert_eq!(space.len(), 3);
|
|
assert_eq!(space.tile_count(), 4);
|
|
|
|
// one above the other, in the column that was 0's, sharing the height
|
|
assert_eq!(
|
|
rect(&space, 0),
|
|
Rect {
|
|
x: 0,
|
|
y: 0,
|
|
width: 300,
|
|
height: 400
|
|
}
|
|
);
|
|
assert_eq!(
|
|
rect(&space, 1),
|
|
Rect {
|
|
x: 0,
|
|
y: 400,
|
|
width: 300,
|
|
height: 400
|
|
}
|
|
);
|
|
|
|
// and the columns after it have moved up to where the one that went was
|
|
assert_eq!(x_of(&space, 2), 300);
|
|
assert_eq!(x_of(&space, 3), 600);
|
|
}
|
|
|
|
#[test]
|
|
fn consuming_takes_only_the_first_tile_of_a_column_that_has_others() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&1);
|
|
space.consume_right();
|
|
space.set_width(&1, ColumnWidth::Fixed(500));
|
|
assert_eq!(columns(&space), [vec![0], vec![1, 2], vec![3]]);
|
|
|
|
space.focus(&0);
|
|
assert!(space.consume_right());
|
|
|
|
// 1 left its column, and 2 is a column of its own that has the width that the column had
|
|
assert_eq!(columns(&space), [vec![0, 1], vec![2], vec![3]]);
|
|
assert_eq!(width_of(&space, 2), 500);
|
|
assert_eq!(width_of(&space, 1), 300);
|
|
}
|
|
|
|
#[test]
|
|
fn there_is_nothing_to_consume_after_the_last_column_or_before_the_first() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&2);
|
|
assert!(!space.consume_right());
|
|
|
|
space.focus(&0);
|
|
assert!(!space.consume_left());
|
|
|
|
assert_eq!(columns(&space), [vec![0], vec![1], vec![2]]);
|
|
}
|
|
|
|
#[test]
|
|
fn consuming_to_the_left_takes_the_last_tile_of_the_column_before_to_the_top_of_this_one() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&1);
|
|
|
|
assert!(space.consume_left());
|
|
|
|
assert_eq!(columns(&space), [vec![0, 1], vec![2], vec![3]]);
|
|
assert_eq!(ids(&space), [0, 1, 2, 3]);
|
|
assert_eq!(space.active_id(), Some(&1), "focus stays on the same tile");
|
|
assert_eq!(space.active_tile_index(), Some(1));
|
|
}
|
|
|
|
#[test]
|
|
fn consuming_to_the_left_leaves_the_tiles_above_the_one_that_goes() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.focus(&2);
|
|
|
|
assert!(space.consume_left());
|
|
|
|
assert_eq!(columns(&space), [vec![0], vec![1, 2], vec![3]]);
|
|
assert_eq!(space.active_id(), Some(&2));
|
|
}
|
|
|
|
#[test]
|
|
fn consuming_does_not_move_the_focused_column_on_screen() {
|
|
let mut space = strip(options(0.25), 8);
|
|
space.focus(&5);
|
|
let x = space.active_x();
|
|
|
|
space.consume_left();
|
|
assert_eq!(space.active_x(), x);
|
|
space.consume_right();
|
|
assert_eq!(space.active_x(), x);
|
|
assert_eq!(space.active_id(), Some(&5));
|
|
}
|
|
|
|
#[test]
|
|
fn consuming_does_not_change_the_width_of_the_focused_column() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.set_width(&1, ColumnWidth::Fixed(450));
|
|
space.focus(&1);
|
|
|
|
space.consume_right();
|
|
assert_eq!(width_of(&space, 1), 450);
|
|
assert_eq!(
|
|
width_of(&space, 2),
|
|
450,
|
|
"the tile has the width of its column"
|
|
);
|
|
space.consume_left();
|
|
assert_eq!(width_of(&space, 1), 450);
|
|
}
|
|
|
|
// Taking tiles out of a column
|
|
|
|
#[test]
|
|
fn expelling_the_last_tile_puts_it_in_a_column_of_its_own_on_the_right() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.set_width(&0, ColumnWidth::Fixed(500));
|
|
space.focus(&1);
|
|
|
|
assert!(space.expel());
|
|
|
|
assert_eq!(columns(&space), [vec![0], vec![1], vec![2]]);
|
|
assert_eq!(
|
|
ids(&space),
|
|
[0, 1, 2],
|
|
"it was last, so it did not move in the order"
|
|
);
|
|
// 0 keeps what it was given and the new column has the default
|
|
assert_eq!(width_of(&space, 0), 500);
|
|
assert_eq!(width_of(&space, 1), 300);
|
|
// and focus goes with it
|
|
assert_eq!(space.active_id(), Some(&1));
|
|
assert_eq!(space.active_index(), Some(1));
|
|
}
|
|
|
|
#[test]
|
|
fn expelling_a_tile_that_has_others_below_it_moves_it_past_them() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
assert_eq!(columns(&space), [vec![0, 1, 2]]);
|
|
|
|
space.focus_down();
|
|
assert_eq!(space.active_id(), Some(&1));
|
|
assert!(space.expel());
|
|
|
|
assert_eq!(columns(&space), [vec![0, 2], vec![1]]);
|
|
assert_eq!(
|
|
ids(&space),
|
|
[0, 2, 1],
|
|
"the host has to change its list to match"
|
|
);
|
|
assert_eq!(space.active_id(), Some(&1));
|
|
}
|
|
|
|
#[test]
|
|
fn a_tile_that_is_alone_cannot_be_expelled() {
|
|
let mut space = strip(options(0.25), 3);
|
|
|
|
assert!(!space.expel());
|
|
assert_eq!(columns(&space), [vec![0], vec![1], vec![2]]);
|
|
}
|
|
|
|
#[test]
|
|
fn expelling_scrolls_only_if_the_new_column_is_out_of_view() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&3);
|
|
space.consume_left();
|
|
space.set_width(&3, ColumnWidth::Fixed(900));
|
|
let before = x_of(&space, 3);
|
|
|
|
space.expel();
|
|
|
|
// 3 was 900 wide and had the right of the screen. The new column is 300 wide and fits
|
|
assert_eq!(space.active_id(), Some(&3));
|
|
assert!(placement(&space, 3).rect.right() <= 1200);
|
|
assert!(x_of(&space, 3) >= 0, "{before}");
|
|
}
|
|
|
|
// Moving around
|
|
|
|
#[test]
|
|
fn focus_moves_between_the_tiles_of_a_column_and_stops_at_the_ends() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
assert_eq!(space.active_id(), Some(&0));
|
|
|
|
assert!(!space.focus_up());
|
|
assert!(space.focus_down());
|
|
assert_eq!(space.active_id(), Some(&1));
|
|
assert!(space.focus_down());
|
|
assert_eq!(space.active_id(), Some(&2));
|
|
assert!(!space.focus_down(), "and it does not go round");
|
|
assert!(space.focus_up());
|
|
assert_eq!(space.active_id(), Some(&1));
|
|
|
|
// and nothing in the strip moved
|
|
assert_eq!(x_of(&space, 0), 0);
|
|
assert!(placement(&space, 1).active);
|
|
}
|
|
|
|
#[test]
|
|
fn a_column_remembers_which_of_its_tiles_had_focus() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.focus(&1);
|
|
|
|
space.focus(&2);
|
|
assert_eq!(space.active_id(), Some(&2));
|
|
|
|
space.focus_left();
|
|
assert_eq!(space.active_id(), Some(&1), "it was the one that had it");
|
|
|
|
space.focus_right();
|
|
space.focus_right();
|
|
space.focus_left();
|
|
space.focus_left();
|
|
assert_eq!(space.active_id(), Some(&1));
|
|
}
|
|
|
|
#[test]
|
|
fn focusing_a_tile_in_another_column_goes_to_that_column_and_that_tile() {
|
|
let mut space = strip(options(0.25), 6);
|
|
space.focus(&3);
|
|
space.consume_right();
|
|
space.focus(&0);
|
|
|
|
space.focus(&4);
|
|
|
|
assert_eq!(space.active_id(), Some(&4));
|
|
assert_eq!(space.active_index(), Some(3), "columns, not tiles");
|
|
assert_eq!(
|
|
space.active_tile_index(),
|
|
Some(4),
|
|
"tiles, in reading order"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn moving_a_tile_swaps_it_with_its_neighbour_and_keeps_focus_on_it() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
|
|
assert!(!space.move_tile_up(), "it is at the top");
|
|
assert!(space.move_tile_down());
|
|
assert_eq!(ids(&space), [1, 0, 2]);
|
|
assert_eq!(space.active_id(), Some(&0));
|
|
assert_eq!(columns(&space), [vec![1, 0, 2]]);
|
|
|
|
assert!(space.move_tile_down());
|
|
assert!(!space.move_tile_down(), "it is at the bottom");
|
|
assert_eq!(ids(&space), [1, 2, 0]);
|
|
|
|
assert!(space.move_tile_up());
|
|
assert_eq!(ids(&space), [1, 0, 2]);
|
|
assert_eq!(space.active_id(), Some(&0));
|
|
}
|
|
|
|
#[test]
|
|
fn moving_a_column_moves_all_of_its_tiles() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&1);
|
|
space.consume_right();
|
|
assert_eq!(columns(&space), [vec![0], vec![1, 2], vec![3]]);
|
|
|
|
space.move_column(&1, 2);
|
|
|
|
assert_eq!(columns(&space), [vec![0], vec![3], vec![1, 2]]);
|
|
assert_eq!(ids(&space), [0, 3, 1, 2]);
|
|
}
|
|
|
|
// What a column of tiles looks like
|
|
|
|
#[test]
|
|
fn tiles_share_the_height_of_the_column_with_a_gap_between_them() {
|
|
let options = Options {
|
|
gaps: 10,
|
|
..options(0.25)
|
|
};
|
|
let mut space = strip(options, 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
|
|
// 800 less a gap above, a gap below and a gap between each of the three: 800 - 40 = 760
|
|
let tiles: Vec<_> = [0, 1, 2].iter().map(|id| rect(&space, *id)).collect();
|
|
let heights: Vec<_> = tiles.iter().map(|tile| tile.height).collect();
|
|
assert_eq!(tiles[0].y, 10);
|
|
assert_eq!(tiles[2].bottom(), 790);
|
|
for pair in tiles.windows(2) {
|
|
assert_eq!(pair[1].y - pair[0].bottom(), 10);
|
|
}
|
|
assert!(heights.iter().all(|h| (*h - 253).abs() <= 1), "{heights:?}");
|
|
}
|
|
|
|
#[test]
|
|
fn only_one_tile_in_the_strip_is_active() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.focus(&1);
|
|
|
|
let active: Vec<_> = space
|
|
.layout()
|
|
.into_iter()
|
|
.filter(|placement| placement.active)
|
|
.map(|placement| placement.id)
|
|
.collect();
|
|
assert_eq!(active, [1]);
|
|
}
|
|
|
|
#[test]
|
|
fn a_fullscreen_column_gives_its_tiles_the_whole_height() {
|
|
let options = Options {
|
|
gaps: 10,
|
|
..options(0.25)
|
|
};
|
|
let mut space = strip(options, 2);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
|
|
space.set_fullscreen(&0, true);
|
|
|
|
assert_eq!(rect(&space, 0).y, 0);
|
|
assert_eq!(rect(&space, 1).bottom(), 800);
|
|
assert_eq!(rect(&space, 1).y, rect(&space, 0).bottom());
|
|
}
|
|
|
|
// Closing tiles
|
|
|
|
#[test]
|
|
fn closing_a_tile_leaves_the_column_with_its_width() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.set_width(&0, ColumnWidth::Fixed(500));
|
|
|
|
assert!(space.remove_column(&1));
|
|
|
|
assert_eq!(columns(&space), [vec![0], vec![2]]);
|
|
assert_eq!(width_of(&space, 0), 500);
|
|
assert_eq!(rect(&space, 0).height, 800, "and it has the height again");
|
|
}
|
|
|
|
#[test]
|
|
fn closing_the_first_tile_of_a_column_leaves_the_others_as_the_column() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
space.set_width(&0, ColumnWidth::Fixed(500));
|
|
|
|
space.remove_column(&0);
|
|
|
|
assert_eq!(columns(&space), [vec![1, 2]]);
|
|
assert_eq!(width_of(&space, 1), 500);
|
|
assert_eq!(width_of(&space, 2), 500);
|
|
}
|
|
|
|
#[test]
|
|
fn closing_the_focused_tile_gives_focus_to_the_one_that_takes_its_place() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
space.focus(&1);
|
|
|
|
space.remove_column(&1);
|
|
assert_eq!(space.active_id(), Some(&2), "the one below");
|
|
|
|
space.remove_column(&2);
|
|
assert_eq!(
|
|
space.active_id(),
|
|
Some(&0),
|
|
"and the one above if there is none"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn closing_a_tile_that_does_not_have_focus_leaves_focus_where_it_is() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
space.focus(&2);
|
|
|
|
space.remove_column(&0);
|
|
assert_eq!(space.active_id(), Some(&2));
|
|
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
space.focus(&1);
|
|
space.remove_column(&2);
|
|
assert_eq!(space.active_id(), Some(&1));
|
|
}
|
|
|
|
// A host that keeps a list
|
|
|
|
#[test]
|
|
fn saying_what_is_there_changes_nothing_with_columns_of_tiles() {
|
|
let mut space = strip(options(0.25), 6);
|
|
space.focus(&1);
|
|
space.consume_right();
|
|
space.focus(&4);
|
|
space.consume_left();
|
|
space.set_width(&1, ColumnWidth::Fixed(450));
|
|
let before = space.clone();
|
|
|
|
let all = space.ids();
|
|
let focused = space.active_id().copied();
|
|
space.reconcile(&all, focused.as_ref());
|
|
|
|
assert_eq!(space, before);
|
|
}
|
|
|
|
#[test]
|
|
fn a_tile_that_is_new_starts_a_column_of_its_own() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
|
|
// after the last tile of the column, which is where the host puts a window that is opened
|
|
space.reconcile(&[0, 1, 9, 2], Some(&9));
|
|
|
|
assert_eq!(columns(&space), [vec![0, 1], vec![9], vec![2]]);
|
|
assert_eq!(width_of(&space, 9), 300);
|
|
}
|
|
|
|
#[test]
|
|
fn a_tile_that_is_put_in_the_middle_of_a_column_splits_it() {
|
|
// the list wins over what the model had: this is the reason that a host puts a window that
|
|
// is opened after the last tile of the column that has focus, and not after the focused tile
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
|
|
space.reconcile(&[0, 9, 1, 2], Some(&9));
|
|
|
|
assert_eq!(columns(&space), [vec![0], vec![9, 1, 2]]);
|
|
}
|
|
|
|
#[test]
|
|
fn tiles_that_go_are_taken_out_of_their_columns() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
space.set_width(&0, ColumnWidth::Fixed(500));
|
|
|
|
space.reconcile(&[0, 2, 3], Some(&0));
|
|
|
|
assert_eq!(columns(&space), [vec![0, 2], vec![3]]);
|
|
assert_eq!(width_of(&space, 0), 500);
|
|
}
|
|
|
|
#[test]
|
|
fn a_list_that_swaps_two_columns_moves_the_tiles_with_them() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&1);
|
|
space.consume_right();
|
|
space.set_width(&1, ColumnWidth::Fixed(450));
|
|
|
|
space.reconcile(&[3, 1, 2, 0], Some(&1));
|
|
|
|
assert_eq!(columns(&space), [vec![3], vec![1, 2], vec![0]]);
|
|
assert_eq!(width_of(&space, 1), 450);
|
|
}
|
|
|
|
#[test]
|
|
fn a_list_that_moves_a_tile_into_another_column_is_followed() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&0);
|
|
space.consume_right();
|
|
|
|
// the tile that was below 0 is now below 2, which is in a column of its own
|
|
space.reconcile(&[0, 2, 1], Some(&0));
|
|
|
|
assert_eq!(columns(&space), [vec![0], vec![2, 1]]);
|
|
}
|
|
|
|
#[test]
|
|
fn a_column_that_does_not_have_focus_keeps_its_focused_tile_when_the_list_reorders_its_tiles() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&1);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
assert_eq!(columns(&space), [vec![0], vec![1, 2, 3]]);
|
|
space.focus(&3);
|
|
space.focus(&0);
|
|
|
|
// the host swapped the last two tiles of the column on the right
|
|
space.reconcile(&[0, 1, 3, 2], Some(&0));
|
|
space.focus_right();
|
|
|
|
assert_eq!(
|
|
space.active_id(),
|
|
Some(&3),
|
|
"it is still the one that had focus"
|
|
);
|
|
assert_eq!(space.active_tile_index(), Some(2));
|
|
}
|
|
|
|
#[test]
|
|
fn a_column_that_loses_its_first_tile_to_consuming_keeps_its_focused_tile() {
|
|
let mut space = strip(options(0.25), 4);
|
|
space.focus(&1);
|
|
space.consume_right();
|
|
space.consume_right();
|
|
space.focus(&3);
|
|
space.focus(&0);
|
|
assert_eq!(columns(&space), [vec![0], vec![1, 2, 3]]);
|
|
|
|
assert!(space.consume_right());
|
|
space.focus_right();
|
|
|
|
assert_eq!(columns(&space), [vec![0, 1], vec![2, 3]]);
|
|
assert_eq!(space.active_id(), Some(&3));
|
|
}
|
|
|
|
#[test]
|
|
fn consuming_to_the_left_forgets_which_column_a_new_window_was_opened_next_to() {
|
|
let mut space = strip(options(0.25), 3);
|
|
space.focus(&1);
|
|
// 9 is opened next to 1, so closing it would go back to 1
|
|
space.add_column(9, None, None, true);
|
|
assert_eq!(ids(&space), [0, 1, 9, 2]);
|
|
|
|
// but 1 is now in a column with it, and 1 is not what is to the left of 9 any more
|
|
space.consume_left();
|
|
assert_eq!(columns(&space), [vec![0], vec![1, 9], vec![2]]);
|
|
space.remove_column(&9);
|
|
space.remove_column(&1);
|
|
|
|
// so the column that takes its place is the one on the right, as when anything else is closed
|
|
assert_eq!(space.active_id(), Some(&2));
|
|
}
|
|
|
|
// Going to another strip
|
|
|
|
#[test]
|
|
fn a_tile_that_comes_from_another_strip_is_as_wide_as_it_was_there() {
|
|
let mut there = strip(options(0.25), 3);
|
|
there.set_width(&1, ColumnWidth::Fixed(555));
|
|
there.set_width_limits(&1, Some(500), None);
|
|
let record = there.column_record(&1).unwrap();
|
|
|
|
let mut here = strip(options(0.25), 2);
|
|
here.arrive(9, record);
|
|
here.reconcile(&[0, 1, 9], Some(&9));
|
|
|
|
assert_eq!(width_of(&here, 9), 555);
|
|
assert_eq!(here.width_limits(&9), Some((Some(500), None)));
|
|
assert_eq!(width_of(&here, 0), 300, "and nothing else changed");
|
|
}
|
|
|
|
#[test]
|
|
fn a_tile_that_comes_from_a_column_with_a_preset_carries_on_from_it() {
|
|
let mut there = strip(options(0.25), 2);
|
|
there.cycle_preset_width(&0, true);
|
|
there.cycle_preset_width(&0, true);
|
|
assert_eq!(width_of(&there, 0), 600);
|
|
let record = there.column_record(&0).unwrap();
|
|
|
|
let mut here = strip(options(0.25), 1);
|
|
here.arrive(9, record);
|
|
here.reconcile(&[0, 9], Some(&9));
|
|
here.cycle_preset_width(&9, true);
|
|
|
|
// 600 is the second preset, so the next is the third
|
|
assert_eq!(width_of(&here, 9), 800);
|
|
}
|
|
|
|
#[test]
|
|
fn the_width_of_a_full_width_column_is_carried_with_it() {
|
|
let mut there = strip(options(0.25), 2);
|
|
there.toggle_full_width(&0);
|
|
let record = there.column_record(&0).unwrap();
|
|
|
|
let mut here = strip(options(0.25), 1);
|
|
here.arrive(9, record);
|
|
here.reconcile(&[0, 9], Some(&9));
|
|
|
|
assert_eq!(width_of(&here, 9), 1200);
|
|
}
|
|
|
|
#[test]
|
|
fn a_tile_that_was_in_a_column_of_several_arrives_as_a_column_of_its_own() {
|
|
let mut there = strip(options(0.25), 3);
|
|
there.focus(&0);
|
|
there.consume_right();
|
|
there.set_width(&0, ColumnWidth::Fixed(450));
|
|
there.set_tile_height(&1, komorebi_scrolling::TileHeight::Fixed(600));
|
|
let record = there.column_record(&1).unwrap();
|
|
|
|
let mut here = strip(options(0.25), 1);
|
|
here.arrive(1, record);
|
|
here.reconcile(&[0, 1], Some(&1));
|
|
|
|
// it has the width of the column that it left, and the height of a column of its own
|
|
assert_eq!(width_of(&here, 1), 450);
|
|
assert_eq!(rect(&here, 1).height, 800);
|
|
assert_eq!(here.column_of(&1), Some(vec![1]));
|
|
}
|
|
|
|
#[test]
|
|
fn what_arrives_is_used_once_and_only_by_a_tile_that_is_added() {
|
|
let mut there = strip(options(0.25), 2);
|
|
there.set_width(&0, ColumnWidth::Fixed(555));
|
|
let record = there.column_record(&0).unwrap();
|
|
|
|
let mut here = strip(options(0.25), 2);
|
|
// 1 is there already, so there is nothing to be told about it
|
|
here.arrive(1, record.clone());
|
|
here.arrive(9, record);
|
|
|
|
here.reconcile(&[0, 1, 9], Some(&9));
|
|
assert_eq!(width_of(&here, 1), 300);
|
|
assert_eq!(width_of(&here, 9), 555);
|
|
|
|
// and it is not remembered: a tile that goes and comes back is the default
|
|
here.remove_column(&9);
|
|
here.reconcile(&[0, 1, 9], Some(&9));
|
|
assert_eq!(width_of(&here, 9), 300);
|
|
}
|
|
|
|
#[test]
|
|
fn a_tile_that_is_added_with_a_width_of_its_own_has_it() {
|
|
let mut there = strip(options(0.25), 2);
|
|
there.set_width(&0, ColumnWidth::Fixed(555));
|
|
let record = there.column_record(&0).unwrap();
|
|
|
|
let mut here = strip(options(0.25), 1);
|
|
here.arrive(9, record);
|
|
here.add_column(9, None, Some(ColumnWidth::Fixed(222)), true);
|
|
|
|
assert_eq!(width_of(&here, 9), 222);
|
|
}
|
|
|
|
#[test]
|
|
fn a_strip_does_not_wait_for_ever_for_tiles_that_never_come() {
|
|
let mut there = strip(options(0.25), 2);
|
|
there.set_width(&0, ColumnWidth::Fixed(555));
|
|
let record = there.column_record(&0).unwrap();
|
|
|
|
let mut here = strip(options(0.25), 1);
|
|
for id in 100..140 {
|
|
here.arrive(id, record.clone());
|
|
}
|
|
|
|
// the oldest were forgotten, and the newest are there
|
|
here.reconcile(&[0, 100, 139], Some(&0));
|
|
assert_eq!(width_of(&here, 100), 300);
|
|
assert_eq!(width_of(&here, 139), 555);
|
|
}
|
|
|
|
#[test]
|
|
fn nothing_is_known_about_a_tile_that_is_not_there() {
|
|
let space = strip(options(0.25), 2);
|
|
|
|
assert_eq!(space.column_record(&9), None);
|
|
}
|