2026-07-15 03:34:13 +03:00
|
|
|
//! Tests for selection types: SelectionTransform, TransformHandle, CropState.
|
|
|
|
|
|
2026-07-16 18:41:05 +03:00
|
|
|
use hcie_iced_gui::selection::clipboard::centered_transform;
|
|
|
|
|
use hcie_iced_gui::selection::state::{combine_masks, mask_bounds, selected_spans};
|
|
|
|
|
use hcie_iced_gui::selection::{CropState, SelectionMode, SelectionTransform, TransformHandle};
|
2026-07-15 03:34:13 +03:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_selection_transform_is_empty() {
|
|
|
|
|
let tr = SelectionTransform {
|
|
|
|
|
pixels: vec![],
|
|
|
|
|
width: 0,
|
|
|
|
|
height: 0,
|
|
|
|
|
pos: iced::Vector::ZERO,
|
|
|
|
|
size: iced::Vector::ZERO,
|
|
|
|
|
rotation: 0.0,
|
|
|
|
|
};
|
|
|
|
|
assert!(tr.is_empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_selection_transform_with_data() {
|
|
|
|
|
let tr = SelectionTransform {
|
|
|
|
|
pixels: vec![255; 100],
|
|
|
|
|
width: 5,
|
|
|
|
|
height: 5,
|
|
|
|
|
pos: iced::Vector::new(10.0, 20.0),
|
|
|
|
|
size: iced::Vector::new(5.0, 5.0),
|
|
|
|
|
rotation: 0.0,
|
|
|
|
|
};
|
|
|
|
|
assert!(!tr.is_empty());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_crop_state_lifecycle() {
|
|
|
|
|
let mut crop = CropState::default();
|
|
|
|
|
assert!(!crop.active);
|
|
|
|
|
assert!(crop.rect.is_none());
|
|
|
|
|
|
|
|
|
|
crop.start_drag(10.0, 10.0);
|
|
|
|
|
assert!(crop.active);
|
|
|
|
|
assert!(crop.is_dragging);
|
|
|
|
|
|
|
|
|
|
crop.update_drag(100.0, 100.0);
|
|
|
|
|
assert!(crop.rect.is_some());
|
|
|
|
|
let (x, y, w, h) = crop.rect.unwrap();
|
|
|
|
|
assert_eq!(x, 10.0);
|
|
|
|
|
assert_eq!(y, 10.0);
|
|
|
|
|
assert_eq!(w, 90.0);
|
|
|
|
|
assert_eq!(h, 90.0);
|
|
|
|
|
|
|
|
|
|
crop.end_drag();
|
|
|
|
|
assert!(!crop.is_dragging);
|
|
|
|
|
|
|
|
|
|
let result = crop.confirm();
|
|
|
|
|
assert!(result.is_some());
|
|
|
|
|
assert!(!crop.active);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_crop_cancel() {
|
|
|
|
|
let mut crop = CropState::default();
|
|
|
|
|
crop.start_drag(10.0, 10.0);
|
|
|
|
|
crop.update_drag(100.0, 100.0);
|
|
|
|
|
crop.cancel();
|
|
|
|
|
assert!(!crop.active);
|
|
|
|
|
assert!(crop.rect.is_none());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn test_transform_handle_cursor_hints() {
|
|
|
|
|
assert_eq!(TransformHandle::Move.cursor_hint(), "move");
|
|
|
|
|
assert_eq!(TransformHandle::TopLeft.cursor_hint(), "nwse-resize");
|
|
|
|
|
assert_eq!(TransformHandle::Rotate.cursor_hint(), "crosshair");
|
|
|
|
|
}
|
2026-07-16 18:41:05 +03:00
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn selection_modes_combine_alpha_without_losing_soft_edges() {
|
|
|
|
|
let old = [0, 64, 255, 255];
|
|
|
|
|
let new = [255, 128, 64, 0];
|
|
|
|
|
assert_eq!(combine_masks(Some(&old), &new, SelectionMode::Replace), new);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
combine_masks(Some(&old), &new, SelectionMode::Add),
|
|
|
|
|
[255, 128, 255, 255]
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
combine_masks(Some(&old), &new, SelectionMode::Subtract),
|
|
|
|
|
[0, 0, 191, 255]
|
|
|
|
|
);
|
|
|
|
|
assert_eq!(
|
|
|
|
|
combine_masks(Some(&old), &new, SelectionMode::Intersect),
|
|
|
|
|
[0, 64, 64, 0]
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn irregular_mask_bounds_and_fill_spans_are_exact() {
|
|
|
|
|
let mask = [0, 255, 0, 0, 255, 255, 0, 0, 0, 255, 0, 0];
|
|
|
|
|
assert_eq!(mask_bounds(&mask, 4, 3), Some((0, 0, 2, 3)));
|
|
|
|
|
assert_eq!(
|
|
|
|
|
selected_spans(&mask, 4, 3),
|
|
|
|
|
vec![(1, 0, 2), (0, 1, 2), (1, 2, 2)]
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn crop_clamps_drag_and_cancel_restores_idle_state() {
|
|
|
|
|
let mut crop = CropState::default();
|
|
|
|
|
crop.start_drag_clamped(-20.0, 5.0, 100, 80);
|
|
|
|
|
crop.update_drag(140.0, 120.0);
|
|
|
|
|
assert_eq!(crop.rect, Some((0.0, 5.0, 100.0, 75.0)));
|
|
|
|
|
crop.cancel();
|
|
|
|
|
assert_eq!(crop.canvas_size, None);
|
|
|
|
|
assert!(!crop.active);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn clipboard_transform_is_centered_and_transform_geometry_is_safe() {
|
|
|
|
|
let mut transform = centered_transform(vec![255; 8 * 4 * 4], 8, 4, 100, 50).unwrap();
|
|
|
|
|
assert_eq!(transform.pos, iced::Vector::new(46.0, 23.0));
|
|
|
|
|
transform.size = iced::Vector::new(-20.0, f32::NAN);
|
|
|
|
|
transform.sanitize_geometry(true);
|
|
|
|
|
assert!(transform.size.x > 0.0 && transform.size.y > 0.0);
|
|
|
|
|
assert!((transform.size.x / transform.size.y - 2.0).abs() < 0.001);
|
|
|
|
|
}
|