2026-03-22 14:56:27 +03:00
|
|
|
// build.rs — auto-generates src/modules/registry.rs
|
|
|
|
|
//
|
|
|
|
|
// Scans src/modules/ for subdirectories containing a mod.rs file.
|
|
|
|
|
// Each subdirectory name like "home" maps to a struct "HomeModule"
|
|
|
|
|
// defined in src/modules/home/mod.rs.
|
|
|
|
|
//
|
|
|
|
|
// Rules for a directory to be picked up:
|
|
|
|
|
// • Located directly in src/modules/
|
|
|
|
|
// • Contains a mod.rs file
|
|
|
|
|
// • Defines a pub struct {PascalCase}Module implementing CadModule
|
|
|
|
|
// (unit struct — no ::new() needed)
|
|
|
|
|
//
|
|
|
|
|
// Tab display order: the PRIORITY list below controls order.
|
|
|
|
|
// Unlisted modules appear after priority modules, sorted alphabetically.
|
|
|
|
|
//
|
|
|
|
|
// Adding a new module:
|
|
|
|
|
// 1. Create src/modules/my_name/mod.rs (implement CadModule as MyNameModule)
|
|
|
|
|
// 2. Add `pub mod my_name;` to src/modules/mod.rs
|
|
|
|
|
// 3. cargo build → module appears in the ribbon
|
|
|
|
|
|
|
|
|
|
use std::fs;
|
|
|
|
|
use std::path::Path;
|
|
|
|
|
|
|
|
|
|
// Display order for known modules; unknown modules follow alphabetically.
|
feat: redesign View tab and fix Annotate/tab order
- Redesign View ribbon tab with 8 groups matching AutoCAD layout:
Viewport Tools (UCS Icon, ViewCube, Navigation Bar),
Navigate, Model Viewports (Viewport Configuration, Named, Join, Restore),
Visual Style (dropdown), Projection, Preset,
Palettes (Tool Palettes, Properties, Sheet Set Manager),
Interface (File Tabs, Layout Tabs, Tile Horiz/Vert, Cascade)
- Add Extract Data and Link Data tools to Annotate → Tables group
- Fix tab order to Home → Insert → Annotate → View → Manage via build.rs PRIORITY list
- Add 17 new SVG icons for all new commands
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 12:25:15 +03:00
|
|
|
const PRIORITY: &[&str] = &["home", "insert", "annotate", "view", "manage"];
|
2026-03-22 14:56:27 +03:00
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
let mods_dir = Path::new("src/modules");
|
|
|
|
|
println!("cargo:rerun-if-changed=src/modules");
|
|
|
|
|
|
|
|
|
|
// Collect subdirectories that contain mod.rs.
|
|
|
|
|
let mut modules: Vec<String> = fs::read_dir(mods_dir)
|
|
|
|
|
.expect("src/modules/ not found")
|
|
|
|
|
.filter_map(|e| {
|
|
|
|
|
let entry = e.ok()?;
|
|
|
|
|
if !entry.file_type().ok()?.is_dir() {
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
let name = entry.file_name().into_string().ok()?;
|
|
|
|
|
let mod_file = mods_dir.join(&name).join("mod.rs");
|
|
|
|
|
if mod_file.exists() {
|
|
|
|
|
Some(name)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
// Sort: priority order first, then alphabetical for the rest.
|
|
|
|
|
modules.sort_by_key(|name| {
|
|
|
|
|
let pri = PRIORITY.iter().position(|p| *p == name.as_str());
|
|
|
|
|
(pri.map(|i| i as u32).unwrap_or(u32::MAX), name.clone())
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// snake_case → PascalCase + "Module"
|
|
|
|
|
let to_struct = |s: &str| -> String {
|
|
|
|
|
s.split('_')
|
|
|
|
|
.map(|w| {
|
|
|
|
|
let mut c = w.chars();
|
|
|
|
|
match c.next() {
|
|
|
|
|
None => String::new(),
|
|
|
|
|
Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.collect::<String>()
|
|
|
|
|
+ "Module"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let mut out = String::from(
|
|
|
|
|
"// AUTO-GENERATED by build.rs — do not edit by hand.\n\
|
|
|
|
|
// To add a module: create src/modules/my_name/mod.rs + add `pub mod my_name;` to modules/mod.rs.\n\n\
|
|
|
|
|
use crate::modules::CadModule;\n\n\
|
|
|
|
|
/// Returns one boxed instance of every registered CAD module.\n\
|
|
|
|
|
/// Called once at startup by `Ribbon::new()`.\n\
|
|
|
|
|
pub fn all_modules() -> Vec<Box<dyn CadModule>> {\n\
|
|
|
|
|
\tvec![\n",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for module in &modules {
|
|
|
|
|
let s = to_struct(module);
|
|
|
|
|
out.push_str(&format!("\t\tBox::new(super::{module}::{s}),\n"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
out.push_str("\t]\n}\n");
|
|
|
|
|
|
|
|
|
|
let out_path = mods_dir.join("registry.rs");
|
|
|
|
|
let current = fs::read_to_string(&out_path).unwrap_or_default();
|
|
|
|
|
if current != out {
|
|
|
|
|
fs::write(&out_path, &out).expect("failed to write registry.rs");
|
|
|
|
|
}
|
|
|
|
|
}
|