2026-03-22 14:56:27 +03:00
|
|
|
// Home module — Draw, Modify, Annotation and Layer tools.
|
|
|
|
|
|
2026-04-22 22:22:33 +03:00
|
|
|
mod about;
|
|
|
|
|
mod changelog;
|
2026-05-12 10:36:15 +03:00
|
|
|
pub mod clipboard;
|
|
|
|
|
pub mod defaults;
|
2026-03-22 14:56:27 +03:00
|
|
|
mod donate;
|
|
|
|
|
pub mod draw;
|
2026-03-22 23:21:29 +03:00
|
|
|
pub mod groups;
|
2026-04-02 23:36:53 +03:00
|
|
|
pub mod inquiry;
|
2026-03-22 23:21:29 +03:00
|
|
|
pub mod layers;
|
2026-03-22 14:56:27 +03:00
|
|
|
pub mod modify;
|
2026-03-22 23:21:29 +03:00
|
|
|
pub mod properties;
|
2026-05-12 10:36:15 +03:00
|
|
|
mod report;
|
2026-03-22 23:21:29 +03:00
|
|
|
pub mod select;
|
2026-03-22 14:56:27 +03:00
|
|
|
|
|
|
|
|
use crate::modules::{CadModule, RibbonGroup, RibbonItem};
|
|
|
|
|
|
|
|
|
|
pub struct HomeModule;
|
|
|
|
|
|
|
|
|
|
impl CadModule for HomeModule {
|
|
|
|
|
fn id(&self) -> &'static str {
|
|
|
|
|
"home"
|
|
|
|
|
}
|
|
|
|
|
fn title(&self) -> &'static str {
|
|
|
|
|
"Home"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ribbon_groups(&self) -> Vec<RibbonGroup> {
|
2026-05-12 10:36:15 +03:00
|
|
|
use crate::modules::annotate::{
|
|
|
|
|
angular_dim, leader_cmd, linear_dim, mleader_cmd, mtext, radius_dim, text,
|
|
|
|
|
};
|
2026-03-22 14:56:27 +03:00
|
|
|
use crate::modules::insert::{create_block, insert_block};
|
2026-05-12 10:36:15 +03:00
|
|
|
use clipboard::{copy_clip, cut, paste};
|
2026-03-22 14:56:27 +03:00
|
|
|
use draw::{arc, circle, ellipse, hatch, line, polyline, shapes};
|
2026-03-22 23:21:29 +03:00
|
|
|
use groups::{group, ungroup};
|
2026-05-12 10:36:15 +03:00
|
|
|
use layers::{
|
|
|
|
|
layfrz, laylck, layoff, layon, laythw, layulk, make_current, match_layer, panel,
|
|
|
|
|
};
|
2026-03-22 14:56:27 +03:00
|
|
|
use modify::{
|
2026-03-22 23:21:29 +03:00
|
|
|
array, copy, delete, explode, fillet, mirror, offset, rotate, scale, stretch,
|
|
|
|
|
translate, trim,
|
2026-03-22 14:56:27 +03:00
|
|
|
};
|
|
|
|
|
use properties::match_prop;
|
|
|
|
|
|
|
|
|
|
vec![
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Draw",
|
|
|
|
|
tools: vec![
|
|
|
|
|
RibbonItem::LargeTool(line::tool()),
|
|
|
|
|
RibbonItem::LargeTool(polyline::tool()),
|
|
|
|
|
RibbonItem::LargeDropdown {
|
|
|
|
|
id: circle::DROPDOWN_ID,
|
|
|
|
|
label: "Circle",
|
|
|
|
|
icon: circle::ICON,
|
|
|
|
|
items: circle::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "CIRCLE",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::LargeDropdown {
|
|
|
|
|
id: arc::DROPDOWN_ID,
|
|
|
|
|
label: "Arc",
|
|
|
|
|
icon: arc::ICON,
|
|
|
|
|
items: arc::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "ARC",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::Dropdown {
|
|
|
|
|
id: shapes::DROPDOWN_ID,
|
|
|
|
|
icon: shapes::ICON,
|
|
|
|
|
items: shapes::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "RECT",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::Dropdown {
|
|
|
|
|
id: ellipse::DROPDOWN_ID,
|
|
|
|
|
icon: ellipse::ICON,
|
|
|
|
|
items: ellipse::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "ELLIPSE",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::Dropdown {
|
|
|
|
|
id: hatch::DROPDOWN_ID,
|
|
|
|
|
icon: hatch::ICON,
|
|
|
|
|
items: hatch::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "HATCH",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Modify",
|
|
|
|
|
tools: vec![
|
|
|
|
|
translate::tool().into(),
|
|
|
|
|
copy::tool().into(),
|
|
|
|
|
stretch::tool().into(),
|
|
|
|
|
rotate::tool().into(),
|
|
|
|
|
mirror::tool().into(),
|
|
|
|
|
scale::tool().into(),
|
|
|
|
|
RibbonItem::Dropdown {
|
|
|
|
|
id: trim::DROPDOWN_ID,
|
|
|
|
|
icon: trim::ICON,
|
|
|
|
|
items: trim::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "TRIM",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::Dropdown {
|
|
|
|
|
id: fillet::DROPDOWN_ID,
|
|
|
|
|
icon: fillet::ICON,
|
|
|
|
|
items: fillet::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "FILLET",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::Dropdown {
|
|
|
|
|
id: array::DROPDOWN_ID,
|
|
|
|
|
icon: array::ICON,
|
|
|
|
|
items: array::DROPDOWN_ITEMS.to_vec(),
|
|
|
|
|
default: "ARRAYRECT",
|
|
|
|
|
},
|
|
|
|
|
delete::tool().into(),
|
|
|
|
|
explode::tool().into(),
|
|
|
|
|
offset::tool().into(),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Annotation",
|
|
|
|
|
tools: vec![
|
|
|
|
|
RibbonItem::LargeDropdown {
|
|
|
|
|
id: "ANNOTATION_TEXT",
|
|
|
|
|
label: "Text",
|
|
|
|
|
icon: text::ICON,
|
|
|
|
|
items: vec![
|
|
|
|
|
(text::tool().id, text::tool().label, text::tool().icon),
|
|
|
|
|
(mtext::tool().id, mtext::tool().label, mtext::tool().icon),
|
|
|
|
|
],
|
|
|
|
|
default: "TEXT",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::LargeDropdown {
|
|
|
|
|
id: "ANNOTATION_DIMENSIONS",
|
|
|
|
|
label: "Dimensions",
|
|
|
|
|
icon: linear_dim::ICON,
|
|
|
|
|
items: vec![
|
2026-05-12 10:36:15 +03:00
|
|
|
(
|
|
|
|
|
linear_dim::tool().id,
|
|
|
|
|
linear_dim::tool().label,
|
|
|
|
|
linear_dim::tool().icon,
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
radius_dim::tool().id,
|
|
|
|
|
radius_dim::tool().label,
|
|
|
|
|
radius_dim::tool().icon,
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
angular_dim::tool().id,
|
|
|
|
|
angular_dim::tool().label,
|
|
|
|
|
angular_dim::tool().icon,
|
|
|
|
|
),
|
2026-03-22 14:56:27 +03:00
|
|
|
],
|
|
|
|
|
default: "DIMLINEAR",
|
|
|
|
|
},
|
|
|
|
|
RibbonItem::LargeDropdown {
|
|
|
|
|
id: "ANNOTATION_LEADER",
|
|
|
|
|
label: "Leader",
|
|
|
|
|
icon: leader_cmd::ICON,
|
|
|
|
|
items: vec![
|
2026-05-12 10:36:15 +03:00
|
|
|
(
|
|
|
|
|
mleader_cmd::tool().id,
|
|
|
|
|
mleader_cmd::tool().label,
|
|
|
|
|
mleader_cmd::tool().icon,
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
leader_cmd::tool().id,
|
|
|
|
|
leader_cmd::tool().label,
|
|
|
|
|
leader_cmd::tool().icon,
|
|
|
|
|
),
|
2026-03-22 14:56:27 +03:00
|
|
|
],
|
|
|
|
|
default: "MLEADER",
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Layers",
|
|
|
|
|
tools: vec![
|
|
|
|
|
RibbonItem::LargeTool(panel::tool()),
|
|
|
|
|
RibbonItem::LayerComboGroup {
|
2026-05-12 10:36:15 +03:00
|
|
|
row2: vec![
|
|
|
|
|
layoff::tool(),
|
|
|
|
|
layfrz::tool(),
|
|
|
|
|
laylck::tool(),
|
|
|
|
|
make_current::tool(),
|
|
|
|
|
],
|
|
|
|
|
row3: vec![
|
|
|
|
|
layon::tool(),
|
|
|
|
|
laythw::tool(),
|
|
|
|
|
layulk::tool(),
|
|
|
|
|
match_layer::tool(),
|
|
|
|
|
],
|
2026-03-22 14:56:27 +03:00
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Block",
|
|
|
|
|
tools: vec![
|
|
|
|
|
RibbonItem::LargeTool(create_block::tool()),
|
|
|
|
|
RibbonItem::LargeTool(insert_block::tool()),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Properties",
|
2026-05-12 10:36:15 +03:00
|
|
|
tools: vec![RibbonItem::PropertiesGroup {
|
|
|
|
|
match_prop: match_prop::tool(),
|
|
|
|
|
}],
|
2026-03-22 14:56:27 +03:00
|
|
|
},
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Groups",
|
|
|
|
|
tools: vec![
|
|
|
|
|
RibbonItem::LargeTool(group::tool()),
|
|
|
|
|
RibbonItem::LargeTool(ungroup::tool()),
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
RibbonGroup {
|
|
|
|
|
title: "Clipboard",
|
|
|
|
|
tools: vec![
|
|
|
|
|
RibbonItem::LargeTool(paste::tool()),
|
|
|
|
|
copy_clip::tool().into(),
|
|
|
|
|
cut::tool().into(),
|
|
|
|
|
],
|
|
|
|
|
},
|
feat(app): add fixed Start tab with welcome page and recent documents
A pinned "Start" tab now lives at index 0. It cannot be closed, opens
on launch, and replaces the model-space viewport with a welcome page —
similar to Thunderbird's first-run screen.
- Boot opens with only the Start tab; Drawing1 is no longer auto-spawned.
- The Properties left panel becomes a Recent Documents rail on the
Start tab. Recents persist to disk
(%APPDATA%/H7CAD/recent.txt on Windows, $XDG_CONFIG_HOME/H7CAD/recent.txt
on Linux, ~/Library/Application Support/H7CAD/recent.txt on macOS), up
to 20 entries, saved on every open and rehydrated at boot.
Each row opens or removes the file in place.
- The Support ribbon group (Donate / Report / About / Changelog) is
retired; the same actions surface on the welcome page instead. The
Donate button is the primary call-to-action — solid #B03020 brand
fill with a soft brand-tinted ambient glow halo behind the action row
(Thunderbird-style coloured glow against the neutral page).
- Drawing-only overlays (mouse-area, viewcube, navbar, dynamic input,
selection markers) are suppressed on the Start tab so its clicks
don't trigger CAD commands. OpenFile's "current_is_empty" check
refuses to replace the Start tab, and TabClose ignores requests on
it.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-21 16:19:31 +03:00
|
|
|
// Support group lives on the Start tab now (see view.rs:
|
|
|
|
|
// start_page_view). Removed from the Home ribbon to declutter.
|
2026-03-22 14:56:27 +03:00
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|