Merge pull request #1493 from storytold/w/1450-pathfinder-group

Fix #1450: the Pathfinder panel works on a group selected alone
This commit is contained in:
BFlat 2026-10-13 03:11:14 +07:00 committed by GitHub
commit 499cd4f30c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 53 additions and 4 deletions

View File

@ -343,10 +343,12 @@ fn run_pf(s: &mut Session, op: PathfinderOp) -> Result<Value> {
continue;
}
if shape_mode
&& roots.len() > 1
&& lv.len() > 1
&& let Some(top) = lv.last()
{
// A group acts as one shape (the union of its leaves) with its top leaf's style.
// Among other objects, a group acts as one shape (the union of its leaves) with
// its top leaf's style. Selected alone, its members are the shapes (#1450).
let parts: Vec<(PathData, FillRule)> = lv.iter().filter_map(node_path).collect();
let refs: Vec<(&PathData, FillRule)> = parts.iter().map(|(p, r)| (p, *r)).collect();
let name = n.name.clone().or_else(|| lv.iter().find_map(|l| l.name.clone()));

View File

@ -191,6 +191,20 @@ fn pathfinder_undo_restores() {
assert!(s.doc().unwrap().selection.contains(a) && s.doc().unwrap().selection.contains(b));
}
/// #1450: a group selected alone gives the shape modes its members to work on.
#[test]
fn a_group_selected_alone_is_combined_member_by_member() {
let mut s = session();
let a = rect(&mut s, 0.0, 0.0, 20.0, 20.0);
let b = rect(&mut s, 10.0, 0.0, 20.0, 20.0);
s.execute("select.set", &json!({"ids": [a.0, b.0]})).unwrap();
s.execute("object.group", &json!({})).unwrap();
assert_eq!(s.doc().unwrap().selection.len(), 1);
let id = s.execute("object.pathfinder.minusFront", &json!({})).unwrap()["ids"][0].as_u64().unwrap();
let bounds = s.doc().unwrap().doc.node(NodeId(id)).unwrap().geometric_bounds().unwrap();
assert_eq!((bounds.x0, bounds.x1), (0.0, 10.0), "the back member less the front one");
}
#[test]
fn unite_with_group() {
let mut s = session();

View File

@ -4640,6 +4640,7 @@ mark-style Japanese Japonské
Use Outside Rectangle As Frame Použít vnější obdélník jako rámeček
Create Compound Path From Ellipses Vytvořit složenou cestu z elips
Fill Grid Vyplnit mřížku
Select two or more objects, or a group Vyberte dva nebo více objektů, nebo skupinu
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Zezadu
Both sides Obě strany

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4163,6 +4163,7 @@ theme Appearance Erscheinungsbild
Use Outside Rectangle As Frame Äußeres Rechteck als Rahmen verwenden
Create Compound Path From Ellipses Zusammengesetzten Pfad aus Ellipsen erstellen
Fill Grid Raster füllen
Select two or more objects, or a group Wählen Sie zwei oder mehr Objekte oder eine Gruppe aus
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Hinten
Both sides Beidseitig

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4580,6 +4580,7 @@ mark-style Japanese Japonesas
X: X:
Y: Y:
@id file.close Cerrar archivo
Select two or more objects, or a group Seleccione dos o más objetos, o un grupo
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Posterior
Both sides Ambos lados

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4216,6 +4216,7 @@ lighting Light Lumière
Use Outside Rectangle As Frame Utiliser le rectangle extérieur comme cadre
Create Compound Path From Ellipses Créer un tracé transparent à partir des ellipses
Fill Grid Remplir la grille
Select two or more objects, or a group Sélectionnez au moins deux objets, ou un groupe
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Arrière
Both sides Deux côtés

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4606,6 +4606,7 @@ theme Appearance Kinézet
Use Outside Rectangle As Frame Külső téglalap használata keretként
Create Compound Path From Ellipses Összetett útvonal létrehozása az ellipszisekből
Fill Grid Rács kitöltése
Select two or more objects, or a group Jelöljön ki két vagy több objektumot, vagy egy csoportot
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Hátulról
Both sides Mindkét oldal

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4208,6 +4208,7 @@ lighting Light Luce
Use Outside Rectangle As Frame Usa rettangolo esterno come cornice
Create Compound Path From Ellipses Crea tracciato composto dalle ellissi
Fill Grid Riempi griglia
Select two or more objects, or a group Selezionate due o più oggetti, oppure un gruppo
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Retro
Both sides Entrambi i lati

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4202,6 +4202,7 @@ lighting Light ライト
Use Outside Rectangle As Frame 外側の長方形をフレームとして使用
Create Compound Path From Ellipses 楕円形から複合パスを作成
Fill Grid グリッドを塗りつぶす
Select two or more objects, or a group 2 つ以上のオブジェクト、またはグループを選択してください
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back 背面
Both sides 両面

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4172,6 +4172,7 @@ lighting Light 광원
Use Outside Rectangle As Frame 바깥쪽 사각형을 프레임으로 사용
Create Compound Path From Ellipses 원에서 컴파운드 패스 만들기
Fill Grid 격자 칠하기
Select two or more objects, or a group 두 개 이상의 개체 또는 그룹을 선택하십시오
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back 뒷면
Both sides 양면

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -3687,3 +3687,4 @@ axis Both Ambos
Use Outside Rectangle As Frame Usar Retângulo Externo como Moldura
Create Compound Path From Ellipses Criar Caminho Composto a partir das Elipses
Fill Grid Preencher Grade
Select two or more objects, or a group Selecione dois ou mais objetos, ou um grupo

Can't render this file because it contains an unexpected character in line 6 and column 47.

View File

@ -4204,6 +4204,7 @@ lighting Light Свет
Use Outside Rectangle As Frame Использовать внешний прямоугольник как рамку
Create Compound Path From Ellipses Создать составной контур из эллипсов
Fill Grid Залить сетку
Select two or more objects, or a group Выделите два или более объектов либо группу
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Сзади
Both sides С обеих сторон

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -4188,6 +4188,7 @@ lighting Light Світло
Use Outside Rectangle As Frame Використовувати зовнішній прямокутник як рамку
Create Compound Path From Ellipses Створити складений контур з еліпсів
Fill Grid Залити сітку
Select two or more objects, or a group Виділіть два або більше об’єктів чи групу
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back Ззаду
Both sides З обох боків

Can't render this file because it has a wrong number of fields in line 13.

View File

@ -3799,6 +3799,7 @@ lighting Light 光源
Use Outside Rectangle As Frame 使用外部矩形作为框架
Create Compound Path From Ellipses 从椭圆形创建复合路径
Fill Grid 网格填色
Select two or more objects, or a group 请选择两个或更多对象,或一个组
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back 背面
Both sides 双面

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -3580,6 +3580,7 @@ lighting Light 光源
Use Outside Rectangle As Frame 使用外部矩形作為框架
Create Compound Path From Ellipses 從橢圓形建立複合路徑
Fill Grid 格線填色
Select two or more objects, or a group 請選取兩個或更多物件,或一個群組
# 3D and Materials › Extrude & Bevel, Inflate and Rotate: options, Position presets and bevel shapes.
Back 背面
Both sides 雙面

Can't render this file because it contains an unexpected character in line 6 and column 47.

View File

@ -29,14 +29,34 @@ fn run(app: &mut VectorcraftApp, ui: &Ui, op: &str, label: &str) {
}
}
/// How many objects the selection gives an operation: a group selected alone counts as its
/// members (#1450).
fn operands(app: &VectorcraftApp) -> usize {
let alone = app.session.active().filter(|d| d.selection.len() == 1).and_then(|d| d.doc.node(*d.selection.objects.first()?));
match alone.and_then(|n| n.children().filter(|_| matches!(n.kind, vectorcraft_doc::NodeKind::Group { .. }))) {
Some(members) => members.len(),
None => selection_len(app),
}
}
/// An operation's button, greyed out and saying what it needs unless the selection has `min` operands.
fn button(ui: &mut Ui, icon: &str, tip: &str, n: usize, min: usize) -> bool {
let resp = widgets::icon_button_enabled(ui, icon, tip, false, n >= min, 34.0);
if n < min {
resp.on_hover_text(tl!("Select two or more objects, or a group"));
return false;
}
resp.clicked()
}
pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
let n = selection_len(app);
let n = operands(app);
let t = crate::theme::Tokens::get(ui.ctx());
widgets::subheader(ui, tl!("Shape Modes:"));
ui.horizontal(|ui| {
ui.spacing_mut().item_spacing.x = 5.0;
for (icon, tip, op) in SHAPE_MODES {
if widgets::icon_button_enabled(ui, icon, tip, false, n >= 2, 34.0).clicked() {
if button(ui, icon, tip, n, 2) {
run(app, ui, op, tip);
}
}
@ -53,7 +73,7 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
ui.spacing_mut().item_spacing.x = 5.0;
for (icon, tip, op) in PATHFINDERS {
let min = if op == "outline" || op == "divide" { 1 } else { 2 };
if widgets::icon_button_enabled(ui, icon, tip, false, n >= min, 34.0).clicked() {
if button(ui, icon, tip, n, min) {
run(app, ui, op, tip);
}
}