Implement stable serialization and restoration for dock layouts, including auto-hidden and floating panels

- Add `persistence.rs` for stable serialization of dock layouts without runtime identifiers.
- Introduce `preview.rs` for geometry handling of dock drop previews.
- Create `sizing.rs` to manage content-aware sizing policies and constraint solving for dock panels.
- Implement `welcome.rs` to provide a welcome surface when no documents are open, featuring New and Open actions.
This commit is contained in:
2026-07-16 22:10:22 +03:00
parent 1240d25011
commit b09795ccff
72 changed files with 11898 additions and 3115 deletions
+22 -13
View File
@@ -17,24 +17,36 @@ fn main() {
eprintln!("Usage: panel-tuner <config.json>");
std::process::exit(1);
}
let config: Config = serde_json::from_reader(
std::fs::File::open(&args[1]).expect("Failed to open config"),
).expect("Failed to parse config");
let config: Config =
serde_json::from_reader(std::fs::File::open(&args[1]).expect("Failed to open config"))
.expect("Failed to parse config");
std::fs::create_dir_all(&config.output_dir).ok();
let mut best: Option<(Vec<f32>, f64, PathBuf)> = None;
let combinations = cartesian_product(&config.parameters.iter().map(|p| p.1.clone()).collect::<Vec<_>>());
let combinations = cartesian_product(
&config
.parameters
.iter()
.map(|p| p.1.clone())
.collect::<Vec<_>>(),
);
for (idx, values) in combinations.iter().enumerate() {
let out = config.output_dir.join(format!("capture_{}.png", idx));
let mut cmd = Command::new(&config.gui_binary);
for (name, value) in config.parameters.iter().map(|p| p.0.clone()).zip(values.iter()) {
cmd.env(format!("HCIE_TUNER_{}", name.to_uppercase()), value.to_string());
for (name, value) in config
.parameters
.iter()
.map(|p| p.0.clone())
.zip(values.iter())
{
cmd.env(
format!("HCIE_TUNER_{}", name.to_uppercase()),
value.to_string(),
);
}
cmd.arg("--screenshot-panel")
.arg(&config.panel)
.arg(&out);
cmd.arg("--screenshot-panel").arg(&config.panel).arg(&out);
let status = cmd.status().expect("Failed to run GUI binary");
if !status.success() {
@@ -44,10 +56,7 @@ fn main() {
let diff_out = config.output_dir.join(format!("diff_{}.png", idx));
let mae = run_diff(&config.target, &out, &diff_out);
eprintln!(
"Run {}: params={:?} MAE={:.6}",
idx, values, mae
);
eprintln!("Run {}: params={:?} MAE={:.6}", idx, values, mae);
if best.as_ref().map_or(true, |b| mae < b.1) {
best = Some((values.clone(), mae, out.clone()));
}
+15 -4
View File
@@ -8,12 +8,23 @@ fn main() {
}
let target_path = PathBuf::from(&args[1]);
let actual_path = PathBuf::from(&args[2]);
let save_diff = args.iter().position(|a| a == "--save-diff").and_then(|i| args.get(i + 1)).map(PathBuf::from);
let save_diff = args
.iter()
.position(|a| a == "--save-diff")
.and_then(|i| args.get(i + 1))
.map(PathBuf::from);
let target = image::open(&target_path).expect("Failed to open target").to_rgba8();
let actual = image::open(&actual_path).expect("Failed to open actual").to_rgba8();
let target = image::open(&target_path)
.expect("Failed to open target")
.to_rgba8();
let actual = image::open(&actual_path)
.expect("Failed to open actual")
.to_rgba8();
let (w, h) = (target.width().min(actual.width()), target.height().min(actual.height()));
let (w, h) = (
target.width().min(actual.width()),
target.height().min(actual.height()),
);
if w == 0 || h == 0 {
eprintln!("One of the images has zero size");
std::process::exit(1);