forked from 1b-agent/opencadstudio-upstream
feat(ui): show ribbon command icons in menus and suggestions
The ribbon definition beside each command stays the one source of its label and icon. One cached lookup (modules::registry::ribbon_commands) walks the core ribbon and the expanded Draw/Modify panels; the shortcut list, the right-click menu, the grip menu and the command-line suggestions read it. - Context menu: command rows carry their ribbon icon; Undo/Redo and Isolate use interface glyphs, Draw Order its ribbon icon; icons and the caret fade on disabled rows. - Grip menu: Stretch, Move, Rotate, Scale, Mirror and Copy icons. - Suggestions: an icon column, aligned when a command has none. - Shortcut list: dropdown entries were read as (label, command) though the ribbon stores (command, label), so they never got a label or icon. Reworked from #1449. Co-Authored-By: MarcelP102 <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
6b37476687
commit
7ed6a362dc
8 files changed
+195
-81
No files matched your search
+64
-1
@@ -7,7 +7,9 @@
|
||||
// 2. Add `pub mod my_name;` to src/modules/mod.rs
|
||||
// 3. Add one `Box::new(super::my_name::MyNameModule)` line below, in the
|
||||
// position you want its tab to appear.
|
||||
use crate::modules::CadModule;
|
||||
use crate::modules::{CadModule, IconKind, ModuleEvent, RibbonItem, ToolDef};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
/// Returns one boxed instance of every registered core CAD module.
|
||||
/// Called once at startup by `Ribbon::new()`.
|
||||
@@ -23,3 +25,64 @@ pub fn all_modules() -> Vec<Box<dyn CadModule>> {
|
||||
Box::new(super::layout::LayoutModule),
|
||||
]
|
||||
}
|
||||
|
||||
/// Label and icon of every core ribbon command, keyed by its upper-case
|
||||
/// command line (`LINE`, `ZOOM EXTENTS`). The ribbon definition beside each
|
||||
/// command stays the one source; the shortcut list, the context menus and the
|
||||
/// command-line suggestions read it from here.
|
||||
pub fn ribbon_commands() -> &'static HashMap<String, (&'static str, IconKind)> {
|
||||
static COMMANDS: OnceLock<HashMap<String, (&'static str, IconKind)>> = OnceLock::new();
|
||||
COMMANDS.get_or_init(|| {
|
||||
let mut out = HashMap::new();
|
||||
let tool = |out: &mut HashMap<_, _>, t: &ToolDef| {
|
||||
if let ModuleEvent::Command(command) = &t.event {
|
||||
out.insert(command.to_ascii_uppercase(), (t.label, t.icon));
|
||||
}
|
||||
};
|
||||
for module in all_modules() {
|
||||
for group in module.ribbon_groups() {
|
||||
for item in &group.tools {
|
||||
match item {
|
||||
RibbonItem::Tool(t)
|
||||
| RibbonItem::LabeledTool(t)
|
||||
| RibbonItem::LargeTool(t) => tool(&mut out, t),
|
||||
RibbonItem::Dropdown { items, .. }
|
||||
| RibbonItem::LabeledDropdown { items, .. }
|
||||
| RibbonItem::LargeDropdown { items, .. } => {
|
||||
for (command, label, icon) in items {
|
||||
out.insert(command.to_ascii_uppercase(), (*label, *icon));
|
||||
}
|
||||
}
|
||||
RibbonItem::ToolGrid { columns }
|
||||
| RibbonItem::StyleComboGroup { rows: columns, .. } => {
|
||||
for t in columns.iter().flatten() {
|
||||
tool(&mut out, t);
|
||||
}
|
||||
}
|
||||
RibbonItem::LayerComboGroup { row2, row3 } => {
|
||||
for t in row2.iter().chain(row3) {
|
||||
tool(&mut out, t);
|
||||
}
|
||||
}
|
||||
RibbonItem::PropertiesGroup { match_prop } => tool(&mut out, match_prop),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (command, label, icon) in crate::ui::ribbon::panel_tools() {
|
||||
out.entry(command.to_string())
|
||||
.or_insert((label, IconKind::Svg(icon)));
|
||||
}
|
||||
out
|
||||
})
|
||||
}
|
||||
|
||||
/// The ribbon icon of a command line, for surfaces that show the command
|
||||
/// outside the ribbon. A leading `'` (transparent use) is ignored.
|
||||
pub fn command_icon(command: &str) -> Option<&'static [u8]> {
|
||||
let key = command.trim().trim_start_matches('\'').to_ascii_uppercase();
|
||||
match ribbon_commands().get(&key)?.1 {
|
||||
IconKind::Svg(bytes) => Some(bytes),
|
||||
IconKind::Glyph(_) => None,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user