Merge #408: Align panel: add objdistribute-* icons, reuse upstream objalign-*

Conflict: crates/ui-egui/src/icons.rs: test module keeps both (next's arrow fill test, #408's distribute icon test)
This commit is contained in:
aiongg
2026-10-12 05:48:01 +00:00
2 changed files with 49 additions and 23 deletions
+39
View File
@@ -321,6 +321,24 @@ pub fn paint(p: &Painter, r: Rect, name: &str, c: Color32) {
pen.frect(5.0, 5.0, 15.0, 9.0);
pen.frect(5.0, 11.0, 11.0, 15.0);
}
"objdistribute-h" => {
pen.frect(2.5, 5.0, 6.0, 15.0);
pen.frect(14.0, 5.0, 17.5, 15.0);
pen.line(&[(7.5, 10.0), (12.5, 10.0)]);
pen.line(&[(7.5, 10.0), (9.0, 8.5)]);
pen.line(&[(7.5, 10.0), (9.0, 11.5)]);
pen.line(&[(12.5, 10.0), (11.0, 8.5)]);
pen.line(&[(12.5, 10.0), (11.0, 11.5)]);
}
"objdistribute-v" => {
pen.frect(5.0, 2.5, 15.0, 6.0);
pen.frect(5.0, 14.0, 15.0, 17.5);
pen.line(&[(10.0, 7.5), (10.0, 12.5)]);
pen.line(&[(10.0, 7.5), (8.5, 9.0)]);
pen.line(&[(10.0, 7.5), (11.5, 9.0)]);
pen.line(&[(10.0, 12.5), (8.5, 11.0)]);
pen.line(&[(10.0, 12.5), (11.5, 11.0)]);
}
"panel-transform" => {
pen.rect(4.0, 4.0, 16.0, 16.0);
for (x, y) in [(4.0, 4.0), (16.0, 4.0), (4.0, 16.0), (16.0, 16.0), (10.0, 10.0)] {
@@ -940,4 +958,25 @@ mod tests {
assert!(arrow_filled("tool-selection"), "Selection draws a hollow arrow");
assert!(!arrow_filled("tool-direct"), "Direct Selection draws a filled arrow");
}
#[test]
fn distribute_icons_are_distinct_from_align_and_each_other() {
// `objalign-*` ship upstream and back the Properties Align row; only the
// two `objdistribute-*` icons are new here, so they must be real glyphs and
// must not collide with any `objalign-*` (one glyph per command).
let distribute = ["objdistribute-h", "objdistribute-v"];
let align = ["objalign-left", "objalign-hcenter", "objalign-right", "objalign-top", "objalign-vcenter", "objalign-bottom"];
let unknown = drawing("no-such-icon");
let d: Vec<String> = distribute.iter().map(|n| drawing(n)).collect();
for (n, g) in distribute.iter().zip(&d) {
assert_ne!(*g, unknown, "{n} falls back to the placeholder");
}
assert_ne!(d[0], d[1], "objdistribute-h and objdistribute-v draw alike");
for dn in &d {
for an in &align {
let ag = drawing(an);
assert_ne!(*dn, ag, "distribute icon draws like {an}");
}
}
}
}
+10 -23
View File
@@ -2010,37 +2010,24 @@ pub fn pathfinder_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
pub fn align_panel(app: &mut DesignApp, ui: &mut egui::Ui) {
ui.horizontal(|ui| {
for (edge, tip) in [
("left", "Align left edges"),
("hcenter", "Align horizontal centers"),
("right", "Align right edges"),
("top", "Align top edges"),
("vcenter", "Align vertical centers"),
("bottom", "Align bottom edges"),
for (edge, icon, tip) in [
("left", "objalign-left", "Align left edges"),
("hcenter", "objalign-hcenter", "Align horizontal centers"),
("right", "objalign-right", "Align right edges"),
("top", "objalign-top", "Align top edges"),
("vcenter", "objalign-vcenter", "Align vertical centers"),
("bottom", "objalign-bottom", "Align bottom edges"),
] {
if ui
.small_button(match edge {
"left" => "⇤",
"hcenter" => "↔",
"right" => "⇥",
"top" => "⤒",
"vcenter" => "↕",
_ => "⤓",
})
.on_hover_ui(|ui| {
crate::rtl::label(ui, crate::i18n::tr(&app.ui.language, tip));
})
.clicked()
{
if widgets::icon_toggle(ui, icon, false, crate::i18n::tr(&app.ui.language, tip)).clicked() {
let _ = app.run("object.align", json!({"edge": edge}));
}
}
});
ui.horizontal(|ui| {
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Distribute ↔"))).clicked() {
if widgets::icon_toggle(ui, "objdistribute-h", false, crate::i18n::tr(&app.ui.language, "Distribute ↔")).clicked() {
let _ = app.run("object.distribute", json!({"axis": "horizontal"}));
}
if ui.small_button(crate::rtl::widget(ui, crate::i18n::tr(&app.ui.language, "Distribute ↕"))).clicked() {
if widgets::icon_toggle(ui, "objdistribute-v", false, crate::i18n::tr(&app.ui.language, "Distribute ↕")).clicked() {
let _ = app.run("object.distribute", json!({"axis": "vertical"}));
}
});