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
+40 -16
View File
@@ -35,17 +35,23 @@ pub fn create_ellipse_mask(w: u32, h: u32, cx: u32, cy: u32, rx: u32, ry: u32) -
/// Grow a mask by `px` pixels (4-connected dilation).
pub fn grow_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
if px == 0 { return; }
if px == 0 {
return;
}
let mut temp = mask.to_vec();
for _ in 0..px {
let old = temp.clone();
for y in 0..h {
for x in 0..w {
let i = (y * w + x) as usize;
if old[i] > 0 { continue; }
if old[i] > 0 {
continue;
}
let neighbors = [
(x.wrapping_sub(1), y), (x + 1, y),
(x, y.wrapping_sub(1)), (x, y + 1),
(x.wrapping_sub(1), y),
(x + 1, y),
(x, y.wrapping_sub(1)),
(x, y + 1),
];
for (nx, ny) in neighbors {
if nx < w && ny < h {
@@ -64,17 +70,23 @@ pub fn grow_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
/// Shrink a mask by `px` pixels (4-connected erosion).
pub fn shrink_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
if px == 0 { return; }
if px == 0 {
return;
}
let mut temp = mask.to_vec();
for _ in 0..px {
let old = temp.clone();
for y in 0..h {
for x in 0..w {
let i = (y * w + x) as usize;
if old[i] == 0 { continue; }
if old[i] == 0 {
continue;
}
let neighbors = [
(x.wrapping_sub(1), y), (x + 1, y),
(x, y.wrapping_sub(1)), (x, y + 1),
(x.wrapping_sub(1), y),
(x + 1, y),
(x, y.wrapping_sub(1)),
(x, y + 1),
];
let mut has_zero = false;
for (nx, ny) in neighbors {
@@ -96,7 +108,9 @@ pub fn shrink_mask(mask: &mut [u8], w: u32, h: u32, px: u32) {
/// a smooth falloff. This properly creates soft transitions at the border
/// by including previously-unselected pixels within the feather radius.
pub fn feather_mask(mask: &mut [u8], w: u32, h: u32, radius: f32) {
if radius <= 0.0 { return; }
if radius <= 0.0 {
return;
}
let r = radius.ceil() as i32;
let r_sq = (radius * radius) as f32;
let size = (w * h) as usize;
@@ -114,7 +128,9 @@ pub fn feather_mask(mask: &mut [u8], w: u32, h: u32, radius: f32) {
// Check if any selected pixel is within radius
'outer: for dy in -r..=r {
for dx in -r..=r {
if (dx * dx + dy * dy) as f32 > r_sq { continue; }
if (dx * dx + dy * dy) as f32 > r_sq {
continue;
}
let nx = (x as i32 + dx).clamp(0, w as i32 - 1) as u32;
let ny = (y as i32 + dy).clamp(0, h as i32 - 1) as u32;
if mask[(ny * w + nx) as usize] > 0 {
@@ -294,7 +310,9 @@ pub fn lasso_fill_mask(mask: &mut [u8], w: u32, h: u32, points: &[(u32, u32)]) {
/// - `w`, `h`: Canvas dimensions.
/// - `thickness`: Border thickness in pixels.
pub fn border_mask(mask: &mut [u8], w: u32, h: u32, thickness: u32) {
if thickness == 0 { return; }
if thickness == 0 {
return;
}
let original = mask.to_vec();
// First, create the outer border by eroding
@@ -304,10 +322,14 @@ pub fn border_mask(mask: &mut [u8], w: u32, h: u32, thickness: u32) {
for y in 0..h {
for x in 0..w {
let i = (y * w + x) as usize;
if old[i] == 0 { continue; }
if old[i] == 0 {
continue;
}
let neighbors = [
(x.wrapping_sub(1), y), (x + 1, y),
(x, y.wrapping_sub(1)), (x, y + 1),
(x.wrapping_sub(1), y),
(x + 1, y),
(x, y.wrapping_sub(1)),
(x, y + 1),
];
let mut has_zero = false;
for (nx, ny) in neighbors {
@@ -343,7 +365,9 @@ pub fn border_mask(mask: &mut [u8], w: u32, h: u32, thickness: u32) {
/// - `w`, `h`: Canvas dimensions.
/// - `radius`: Blur radius in pixels.
pub fn smooth_mask(mask: &mut [u8], w: u32, h: u32, radius: u32) {
if radius == 0 { return; }
if radius == 0 {
return;
}
let r = radius as i32;
let size = (w * h) as usize;
let mut result = vec![0u8; size];
@@ -365,4 +389,4 @@ pub fn smooth_mask(mask: &mut [u8], w: u32, h: u32, radius: u32) {
}
mask.copy_from_slice(&result);
}
}