Files
phantom b49106dc1d BIG REFACTOR GPT SOL
feat: Refactor Iced panel adapter and introduce build metadata management

- Updated Cargo.toml files across multiple crates to use workspace versioning.
- Enhanced the `iced-panel-adapter` to include a new `plain_slider` module and updated widget rendering to support theme colors.
- Added new theme color utilities for recessed and elevated surfaces in `iced-panel-adapter`.
- Introduced a new `hcie-build-info` crate to manage build metadata, including a build ID system.
- Created a build script to synchronize build IDs across the workspace.
- Added a Makefile for simplified build commands for the Iced application.
- Implemented regression tests for vector shape creation history in the engine API.
- Added a new script for managing Cargo commands with synchronized build ID increments.
- Updated line count report to reflect recent changes in codebase.
- Created a visual plan document for future improvements in the Iced history and panel systems.
2026-07-21 04:25:23 +03:00

171 lines
4.5 KiB
Rust

use hcie_history::{HistoryManager, UndoableAction};
use hcie_protocol::Layer;
struct SetPixelAction {
layer_idx: usize,
old_color: [u8; 4],
new_color: [u8; 4],
}
impl UndoableAction<Vec<Layer>> for SetPixelAction {
fn undo(&mut self, layers: &mut Vec<Layer>) {
if let Some(layer) = layers.get_mut(self.layer_idx) {
layer.set_pixel(0, 0, self.old_color);
}
}
fn redo(&mut self, layers: &mut Vec<Layer>) {
if let Some(layer) = layers.get_mut(self.layer_idx) {
layer.set_pixel(0, 0, self.new_color);
}
}
fn description(&self) -> String {
"SetPixel".to_string()
}
}
fn make_layer() -> Layer {
Layer::new_transparent("test", 10, 10)
}
#[test]
fn test_history_new_is_empty() {
let hist = HistoryManager::<Vec<Layer>>::new(10);
assert_eq!(hist.len(), 0);
assert!(!hist.can_undo());
assert!(!hist.can_redo());
assert_eq!(hist.current_index(), -1);
}
#[test]
fn test_history_push_undo_redo() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [255, 0, 0, 255],
}));
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [255, 0, 0, 255],
new_color: [0, 255, 0, 255],
}));
assert!(hist.can_undo());
assert!(!hist.can_redo());
hist.undo(&mut layers);
assert_eq!(layers[0].get_pixel(0, 0), [255, 0, 0, 255]);
assert!(hist.can_redo());
hist.redo(&mut layers);
assert_eq!(layers[0].get_pixel(0, 0), [0, 255, 0, 255]);
}
#[test]
fn test_history_undo_twice_is_stable() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [255; 4],
}));
hist.undo(&mut layers);
hist.undo(&mut layers);
assert!(!hist.can_undo(), "should reach bottom");
}
#[test]
fn test_history_redo_twice_is_stable() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [255; 4],
}));
hist.undo(&mut layers);
hist.redo(&mut layers);
hist.redo(&mut layers);
assert!(!hist.can_redo(), "should reach top");
}
#[test]
fn test_history_max_steps() {
let _layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(3);
for i in 0..10 {
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [i; 4],
}));
}
assert_eq!(hist.len(), 3, "should cap at max_steps=3");
}
#[test]
fn test_history_new_action_truncates_redo() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [1; 4],
}));
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [1; 4],
new_color: [2; 4],
}));
hist.undo(&mut layers);
assert!(hist.can_redo());
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [1; 4],
new_color: [3; 4],
}));
assert!(!hist.can_redo(), "new action should truncate redo stack");
}
#[test]
fn test_history_jump_to() {
let mut layers = vec![make_layer()];
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [1; 4],
}));
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [1; 4],
new_color: [2; 4],
}));
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [2; 4],
new_color: [3; 4],
}));
hist.jump_to(-1, &mut layers);
assert!(!hist.can_undo(), "jump to -1 should be at bottom");
assert!(
hist.can_redo(),
"jump to -1 should allow replaying the first entry"
);
assert_eq!(layers[0].get_pixel(0, 0), [0; 4]);
}
#[test]
fn test_entry_description() {
let mut hist = HistoryManager::<Vec<Layer>>::new(10);
hist.push(Box::new(SetPixelAction {
layer_idx: 0,
old_color: [0; 4],
new_color: [255; 4],
}));
assert_eq!(hist.entry_description(0), Some("SetPixel".to_string()));
assert_eq!(hist.entry_description(99), None);
}