use azul_core::geom::{LogicalPosition, LogicalRect, LogicalSize};
use azul_css::props::layout::{LayoutClear, LayoutFloat, LayoutWritingMode};
use azul_layout::solver3::fc::FloatingContext;
use azul_layout::solver3::geometry::EdgeSizes;
fn zero_edges() -> EdgeSizes {
EdgeSizes {
top: 0.0,
right: 0.0,
bottom: 0.0,
left: 0.0,
}
}
fn edges(top: f32, right: f32, bottom: f32, left: f32) -> EdgeSizes {
EdgeSizes {
top,
right,
bottom,
left,
}
}
#[test]
fn test_floating_context_default_is_empty() {
let ctx = FloatingContext::default();
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 0.0);
assert_eq!(end, 800.0);
}
#[test]
fn test_add_float_left() {
let mut ctx = FloatingContext::default();
let rect = LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(100.0, 50.0),
};
ctx.add_float(LayoutFloat::Left, rect, zero_edges());
let wm = LayoutWritingMode::HorizontalTb;
let (start, _end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 100.0); }
#[test]
fn test_add_float_right() {
let mut ctx = FloatingContext::default();
let rect = LogicalRect {
origin: LogicalPosition { x: 200.0, y: 0.0 },
size: LogicalSize::new(100.0, 50.0),
};
ctx.add_float(LayoutFloat::Right, rect, zero_edges());
let wm = LayoutWritingMode::HorizontalTb;
let (_start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(end, 200.0); }
#[test]
fn test_add_multiple_floats() {
let mut ctx = FloatingContext::default();
let r1 = LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(100.0, 50.0),
};
let r2 = LogicalRect {
origin: LogicalPosition { x: 200.0, y: 0.0 },
size: LogicalSize::new(100.0, 50.0),
};
ctx.add_float(LayoutFloat::Left, r1, zero_edges());
ctx.add_float(LayoutFloat::Right, r2, zero_edges());
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 100.0); assert_eq!(end, 200.0); }
#[test]
fn test_available_space_no_floats() {
let ctx = FloatingContext::default();
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 0.0);
assert_eq!(end, 800.0);
}
#[test]
fn test_available_space_left_float_narrows_from_left() {
let mut ctx = FloatingContext::default();
let rect = LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
};
ctx.add_float(LayoutFloat::Left, rect, zero_edges());
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 200.0);
assert_eq!(end, 800.0);
}
#[test]
fn test_available_space_right_float_narrows_from_right() {
let mut ctx = FloatingContext::default();
let rect = LogicalRect {
origin: LogicalPosition { x: 600.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
};
ctx.add_float(LayoutFloat::Right, rect, zero_edges());
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 0.0);
assert_eq!(end, 600.0);
}
#[test]
fn test_available_space_both_floats_narrow_both_sides() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
ctx.add_float(
LayoutFloat::Right,
LogicalRect {
origin: LogicalPosition { x: 600.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 200.0);
assert_eq!(end, 600.0);
}
#[test]
fn test_available_space_no_overlap_on_main_axis() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(150.0, 200.0, 800.0, wm);
assert_eq!(start, 0.0);
assert_eq!(end, 800.0);
}
#[test]
fn test_available_space_partial_overlap() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(80.0, 120.0, 800.0, wm);
assert_eq!(start, 200.0); assert_eq!(end, 800.0);
}
#[test]
fn test_available_space_stacked_left_floats() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(100.0, 100.0),
},
zero_edges(),
);
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 100.0, y: 0.0 },
size: LogicalSize::new(150.0, 80.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let (start, end) = ctx.available_line_box_space(0.0, 50.0, 800.0, wm);
assert_eq!(start, 250.0);
assert_eq!(end, 800.0);
}
#[test]
fn test_clearance_offset_no_floats() {
let ctx = FloatingContext::default();
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Both, 50.0, wm);
assert_eq!(offset, 50.0);
}
#[test]
fn test_clearance_none_does_nothing() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::None, 0.0, wm);
assert_eq!(offset, 0.0); }
#[test]
fn test_clear_left_clears_left_float() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Left, 0.0, wm);
assert_eq!(offset, 100.0);
}
#[test]
fn test_clear_right_clears_right_float() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Right,
LogicalRect {
origin: LogicalPosition { x: 600.0, y: 0.0 },
size: LogicalSize::new(200.0, 120.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Right, 0.0, wm);
assert_eq!(offset, 120.0);
}
#[test]
fn test_clear_left_ignores_right_float() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Right,
LogicalRect {
origin: LogicalPosition { x: 600.0, y: 0.0 },
size: LogicalSize::new(200.0, 120.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Left, 0.0, wm);
assert_eq!(offset, 0.0);
}
#[test]
fn test_clear_right_ignores_left_float() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Right, 0.0, wm);
assert_eq!(offset, 0.0);
}
#[test]
fn test_clear_both_clears_all_floats() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
ctx.add_float(
LayoutFloat::Right,
LogicalRect {
origin: LogicalPosition { x: 600.0, y: 0.0 },
size: LogicalSize::new(200.0, 150.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Both, 0.0, wm);
assert_eq!(offset, 150.0);
}
#[test]
fn test_clearance_with_margin() {
let mut ctx = FloatingContext::default();
let margin = edges(0.0, 0.0, 20.0, 0.0); ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
margin,
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Left, 0.0, wm);
assert_eq!(offset, 120.0);
}
#[test]
fn test_clearance_already_past_float() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(200.0, 100.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Left, 200.0, wm);
assert_eq!(offset, 200.0);
}
#[test]
fn test_clearance_multiple_stacked_floats() {
let mut ctx = FloatingContext::default();
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 0.0 },
size: LogicalSize::new(100.0, 50.0),
},
zero_edges(),
);
ctx.add_float(
LayoutFloat::Left,
LogicalRect {
origin: LogicalPosition { x: 0.0, y: 50.0 },
size: LogicalSize::new(100.0, 100.0),
},
zero_edges(),
);
ctx.add_float(
LayoutFloat::Right,
LogicalRect {
origin: LogicalPosition { x: 700.0, y: 0.0 },
size: LogicalSize::new(100.0, 80.0),
},
zero_edges(),
);
let wm = LayoutWritingMode::HorizontalTb;
let offset = ctx.clearance_offset(LayoutClear::Both, 0.0, wm);
assert_eq!(offset, 150.0);
}
#[test]
fn test_overflow_behavior_is_clipped() {
use azul_layout::solver3::fc::OverflowBehavior;
assert!(!OverflowBehavior::Visible.is_clipped());
assert!(OverflowBehavior::Hidden.is_clipped());
assert!(OverflowBehavior::Clip.is_clipped());
assert!(OverflowBehavior::Scroll.is_clipped());
assert!(OverflowBehavior::Auto.is_clipped());
}
#[test]
fn test_overflow_behavior_is_scroll() {
use azul_layout::solver3::fc::OverflowBehavior;
assert!(!OverflowBehavior::Visible.is_scroll());
assert!(!OverflowBehavior::Hidden.is_scroll());
assert!(!OverflowBehavior::Clip.is_scroll());
assert!(OverflowBehavior::Scroll.is_scroll());
assert!(OverflowBehavior::Auto.is_scroll());
}
#[test]
fn test_scrollbar_visible_never_needs_scrollbar() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(2000.0, 2000.0), LogicalSize::new(800.0, 600.0), OverflowBehavior::Visible,
OverflowBehavior::Visible,
16.0,
);
assert!(!result.needs_horizontal);
assert!(!result.needs_vertical);
}
#[test]
fn test_scrollbar_hidden_never_needs_scrollbar() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(2000.0, 2000.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Hidden,
OverflowBehavior::Hidden,
16.0,
);
assert!(!result.needs_horizontal);
assert!(!result.needs_vertical);
}
#[test]
fn test_scrollbar_scroll_always_shows() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(100.0, 100.0), LogicalSize::new(800.0, 600.0), OverflowBehavior::Scroll,
OverflowBehavior::Scroll,
16.0,
);
assert!(result.needs_horizontal);
assert!(result.needs_vertical);
}
#[test]
fn test_scrollbar_auto_only_when_overflowing() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(400.0, 300.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert!(!result.needs_horizontal);
assert!(!result.needs_vertical);
let result = check_scrollbar_necessity(
LogicalSize::new(400.0, 1000.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert!(!result.needs_horizontal);
assert!(result.needs_vertical);
let result = check_scrollbar_necessity(
LogicalSize::new(1200.0, 300.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert!(result.needs_horizontal);
assert!(!result.needs_vertical);
}
#[test]
fn test_scrollbar_auto_cascade_vertical_triggers_horizontal() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(790.0, 1000.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert!(result.needs_vertical);
assert!(result.needs_horizontal); }
#[test]
fn test_scrollbar_auto_cascade_horizontal_triggers_vertical() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(1200.0, 590.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert!(result.needs_horizontal);
assert!(result.needs_vertical); }
#[test]
fn test_scrollbar_overlay_zero_width() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(400.0, 1000.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
0.0, );
assert!(result.needs_vertical);
assert!(!result.needs_horizontal); assert_eq!(result.scrollbar_width, 0.0);
assert_eq!(result.scrollbar_height, 0.0);
}
#[test]
fn test_scrollbar_clip_never_needs_scrollbar() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(2000.0, 2000.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Clip,
OverflowBehavior::Clip,
16.0,
);
assert!(!result.needs_horizontal);
assert!(!result.needs_vertical);
}
#[test]
fn test_scrollbar_mixed_overflow() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(2000.0, 2000.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Hidden,
OverflowBehavior::Auto,
16.0,
);
assert!(!result.needs_horizontal); assert!(result.needs_vertical); }
#[test]
fn test_scrollbar_content_exactly_fits_epsilon() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(800.5, 600.5), LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert!(!result.needs_horizontal);
assert!(!result.needs_vertical);
}
#[test]
fn test_scrollbar_content_just_overflows() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(802.0, 602.0), LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert!(result.needs_horizontal);
assert!(result.needs_vertical);
}
#[test]
fn test_scrollbar_width_values() {
use azul_layout::solver3::fc::{check_scrollbar_necessity, OverflowBehavior};
let result = check_scrollbar_necessity(
LogicalSize::new(400.0, 1000.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert_eq!(result.scrollbar_width, 16.0); assert_eq!(result.scrollbar_height, 0.0);
let result = check_scrollbar_necessity(
LogicalSize::new(1200.0, 300.0),
LogicalSize::new(800.0, 600.0),
OverflowBehavior::Auto,
OverflowBehavior::Auto,
16.0,
);
assert_eq!(result.scrollbar_width, 0.0);
assert_eq!(result.scrollbar_height, 16.0);
}