Insert ribbon: Block Definition panel split button and labels

The Block Definition panel's Create Block is a split button listing
Create Block and Write Block; its face runs the last one chosen. The
slide-out lists Set Base Point and Synchronize with their labels, and
the large buttons read Manage Attributes and Block Editor.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ramox81andClaude Opus 5.5 committed 2026-10-15 09:48:09 +03:00
1 parent 39c3e9af58
commit 5cd87ac24b
4 files changed
+77 -6

No files matched your search

+1
View File
@@ -1184,6 +1184,7 @@ pub(super) fn message_attribute(source: &str) -> Option<(&'static str, &'static
"Could not set default app: {err}" => Some(("common", "could-not-set-default-app-err")),
"Creased Edges" => Some(("properties", "creased-edges")),
"Create Block" => Some(("insert", "create-block")),
"Block Editor" => Some(("ribbon-tab", "block-editor")),
"Created new CTB table, ACI {aci} updated." => Some(("file", "created-new-ctb-table-aci-aci-updated")),
"Croppings" => Some(("properties", "croppings")),
"Crossing" => Some(("common", "crossing")),
+23 -4
View File
@@ -32,7 +32,10 @@ pub(crate) mod xattach;
pub(crate) mod xclip;
pub(crate) mod xref_cmd;
use crate::modules::{CadModule, IconKind, RibbonGroup, RibbonItem};
use crate::modules::{CadModule, IconKind, RibbonGroup, RibbonItem, ToolDef};
/// Insert > Block Definition: the Create Block / Write Block split button.
pub(crate) const CREATE_BLOCK_DROPDOWN: &str = "CREATE_BLOCK_DROPDOWN";
const FRAMES_ICON: IconKind =
IconKind::Svg(include_bytes!("../../../assets/icons/underlay_frames.svg"));
@@ -85,10 +88,26 @@ impl CadModule for InsertModule {
RibbonGroup {
title: "Block Definition",
tools: vec![
RibbonItem::LargeTool(create_block::tool()),
// Split button: the face runs the last one chosen.
RibbonItem::LargeDropdown {
id: CREATE_BLOCK_DROPDOWN,
label: "Create Block",
icon: create_block::tool().icon,
items: vec![
("BLOCK", "Create Block", create_block::tool().icon),
("WBLOCK", "Write Block", wblock::tool().icon),
],
default: "BLOCK",
},
RibbonItem::LargeTool(attdef::tool()),
RibbonItem::LargeTool(attman::tool()),
RibbonItem::LargeTool(edit_block::tool()),
RibbonItem::LargeTool(ToolDef {
label: "Manage Attributes",
..attman::tool()
}),
RibbonItem::LargeTool(ToolDef {
label: "Block Editor",
..edit_block::tool()
}),
],
},
// ── Reference ────────────────────────────────────────────────────
+50 -1
View File
@@ -123,6 +123,8 @@ const REFERENCE_TOOLS: &[Tool] = &[Tool {
options: &[],
}];
pub(super) const REFERENCE_PANEL_ID: &str = "reference_extension";
/// Insert > Block Definition slide-out: its tools are listed with labels.
const BLOCK_DEFINITION_PANEL_ID: &str = "block_definition_extension";
const fn icon_tool(command: &'static str, label: &'static str, icon: &'static [u8]) -> Tool {
Tool {
@@ -201,7 +203,7 @@ const PANELS: &[Panel] = &[
tools: HOME_BLOCK_TOOLS,
},
Panel {
id: "block_definition_extension",
id: BLOCK_DEFINITION_PANEL_ID,
anchor: None,
title_id: "block_definition_extension_title",
title: "Block Definition",
@@ -490,11 +492,58 @@ fn reference_overlay<'a>(ribbon: &Ribbon, panel: Panel, win: (f32, f32)) -> Elem
dropdown_backdrop(position_ribbon_dropdown(body.into(), false, left, top))
}
/// A slide-out listing each tool as icon and label, one per row.
fn labeled_overlay<'a>(ribbon: &Ribbon, panel: Panel, win: (f32, f32)) -> Element<'a, Message> {
let width: f32 = 200.0_f32.min((win.0 - 8.0).max(120.0));
let (_, x, anchor_top) = ribbon.dd_anchor(panel.id, width, win.0);
let left = x.clamp(0.0, (win.0 - width).max(0.0));
let top = anchor_top.min((win.1 - 80.0).max(0.0));
let rows = panel.tools.iter().map(|tool| {
let active = tool_is_active(tool, ribbon.active_tool.as_deref());
let item = button(
row![
make_icon(IconKind::Svg(tool.icon), 16.0),
keytips::label_anchor(
|| keytips::label_id(&keytips::item_anchor(panel.id, tool.command)),
text(t!(tool.label)).size(11),
),
]
.spacing(6)
.align_y(iced::Center),
)
.on_press(Message::DropdownSelectItem {
dropdown_id: panel.id,
cmd: tool.command,
})
.style(move |theme: &Theme, status| {
if active {
tool_btn_style(theme, true, status)
} else {
popup_row_style(theme, status)
}
})
.width(Fill)
.padding([3, 6]);
keytips::anchor_with(|| keytips::item_anchor(panel.id, tool.command), item)
});
let body = container(column(rows.collect::<Vec<_>>()).spacing(2).padding(6))
.width(width)
.style(|theme: &Theme| {
let mut style = popup_panel_style(theme);
style.border.color = theme.palette().primary.base.color;
style
});
dropdown_backdrop(position_ribbon_dropdown(body.into(), false, left, top))
}
pub(super) fn overlay<'a>(ribbon: &Ribbon, id: &str, win: (f32, f32)) -> Element<'a, Message> {
let panel = panel_for_dropdown(id).expect("registered ribbon extension");
if panel.id == REFERENCE_PANEL_ID {
return reference_overlay(ribbon, panel, win);
}
if panel.id == BLOCK_DEFINITION_PANEL_ID {
return labeled_overlay(ribbon, panel, win);
}
let tools = panel.tools;
let width = (7.0 * (CELL + GAP) - GAP + 12.0).min((win.0 - 8.0).max(CELL + 12.0));
let (_, x, anchor_top) = ribbon.dd_anchor(panel.id, width, win.0);
+3 -1
View File
@@ -386,7 +386,9 @@ const CODES: &[(&str, &str, &str)] = &[
("insert", "ATTEDIT_DROPDOWN", "AE"),
("insert", "ATTMODE_DROPDOWN", "AT"),
("insert", "Block Definition", "BD"),
("insert", "BLOCK", "BC"),
("insert", "CREATE_BLOCK_DROPDOWN", "BC"),
("CREATE_BLOCK_DROPDOWN", "BLOCK", "BC"),
("CREATE_BLOCK_DROPDOWN", "WBLOCK", "WB"),
("insert", "ATTDEF", "AD"),
("insert", "ATTMAN", "AM"),
("insert", "BEDIT", "BE"),