feat: add clickable space-mode button to status bar
Replaces the static MODEL/LAYOUT pill with an interactive button that shows and toggles the current editing context: Model tab → "MODEL" (non-clickable, informational) Layout PSPACE → "PAPER" (click → MspaceCommand: enter MSPACE) Layout MSPACE → "MODEL" (click → ExitViewport: return to PSPACE) Highlights in blue when in MSPACE to signal active model editing. Mirrors the AutoCAD status-bar convention for MODEL/PAPER switching. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2c5405aa49
commit
c2df63c4cc
2 changed files with 56 additions and 6 deletions
|
|
@ -313,6 +313,7 @@ impl H7CAD {
|
||||||
self.layout_rename_state.as_ref(),
|
self.layout_rename_state.as_ref(),
|
||||||
tab.scene.first_viewport_scale(),
|
tab.scene.first_viewport_scale(),
|
||||||
tab.scene.viewport_count(),
|
tab.scene.viewport_count(),
|
||||||
|
tab.scene.active_viewport.is_some(),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
.width(Fill)
|
.width(Fill)
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ impl StatusBar {
|
||||||
viewport_scale: Option<f64>,
|
viewport_scale: Option<f64>,
|
||||||
// Number of user viewports in the current paper layout (0 = model space).
|
// Number of user viewports in the current paper layout (0 = model space).
|
||||||
viewport_count: usize,
|
viewport_count: usize,
|
||||||
|
// True when the user is editing inside a paper-space viewport (MSPACE).
|
||||||
|
in_mspace: bool,
|
||||||
) -> Element<'a, Message> {
|
) -> Element<'a, Message> {
|
||||||
let menu_btn = button(text("≡").size(14).color(ICON_COLOR))
|
let menu_btn = button(text("≡").size(14).color(ICON_COLOR))
|
||||||
.on_press(Message::Command("MENU".into()))
|
.on_press(Message::Command("MENU".into()))
|
||||||
|
|
@ -59,11 +61,6 @@ impl StatusBar {
|
||||||
let osnap_active = snapper.is_active();
|
let osnap_active = snapper.is_active();
|
||||||
let snap_grid_on = snapper.is_on(crate::snap::SnapType::Grid) && snapper.snap_enabled;
|
let snap_grid_on = snapper.is_on(crate::snap::SnapType::Grid) && snapper.snap_enabled;
|
||||||
|
|
||||||
let space_label = if current_layout == "Model" {
|
|
||||||
"MODEL"
|
|
||||||
} else {
|
|
||||||
"LAYOUT"
|
|
||||||
};
|
|
||||||
let scale_label = format_scale(viewport_scale);
|
let scale_label = format_scale(viewport_scale);
|
||||||
let vp_label = if viewport_count > 0 {
|
let vp_label = if viewport_count > 0 {
|
||||||
format!("{} VP", viewport_count)
|
format!("{} VP", viewport_count)
|
||||||
|
|
@ -93,7 +90,10 @@ impl StatusBar {
|
||||||
"Object Snap Tracking\nF11"
|
"Object Snap Tracking\nF11"
|
||||||
),
|
),
|
||||||
osnap_btn(osnap_active, snapper.snap_enabled, popup_open),
|
osnap_btn(osnap_active, snapper.snap_enabled, popup_open),
|
||||||
status_pill(space_label),
|
tip(
|
||||||
|
space_mode_btn(¤t_layout, in_mspace),
|
||||||
|
"Toggle Model/Paper space\nDouble-click viewport to enter MSPACE",
|
||||||
|
),
|
||||||
status_pill(scale_label),
|
status_pill(scale_label),
|
||||||
]
|
]
|
||||||
.spacing(2);
|
.spacing(2);
|
||||||
|
|
@ -448,6 +448,55 @@ fn space_tab<'a>(label: String, is_active: bool, rename_edit: Option<&'a str>) -
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Space-mode toggle button in the status bar.
|
||||||
|
///
|
||||||
|
/// - Model tab → "MODEL" (non-clickable, informational)
|
||||||
|
/// - Layout, PSPACE → "PAPER" (click → MspaceCommand: enter MSPACE)
|
||||||
|
/// - Layout, MSPACE → "MODEL" (click → ExitViewport: return to PSPACE)
|
||||||
|
fn space_mode_btn(current_layout: &str, in_mspace: bool) -> Element<'static, Message> {
|
||||||
|
let is_model_tab = current_layout == "Model";
|
||||||
|
|
||||||
|
// Labels and styling follow AutoCAD convention:
|
||||||
|
// PAPER = currently in paper-space editing
|
||||||
|
// MODEL = currently in model-space editing (either the Model tab or MSPACE)
|
||||||
|
let (label, active, on_press) = if is_model_tab {
|
||||||
|
("MODEL", false, None)
|
||||||
|
} else if in_mspace {
|
||||||
|
("MODEL", true, Some(Message::ExitViewport))
|
||||||
|
} else {
|
||||||
|
("PAPER", false, Some(Message::MspaceCommand))
|
||||||
|
};
|
||||||
|
|
||||||
|
let text_color = if active { SNAP_BORDER_ON } else { OSNAP_OFF_TEXT };
|
||||||
|
let bg_normal = if active { SNAP_ON_BG } else { SNAP_OFF_BG };
|
||||||
|
let bg_hover = if active { SNAP_ON_HOVER } else { SNAP_OFF_HOVER };
|
||||||
|
let border_color = if active { SNAP_BORDER_ON } else { BORDER_COLOR };
|
||||||
|
|
||||||
|
let clickable = on_press.is_some();
|
||||||
|
let mut btn = button(text(label).size(10).color(text_color))
|
||||||
|
.style(move |_: &Theme, status| button::Style {
|
||||||
|
background: Some(Background::Color(match status {
|
||||||
|
button::Status::Hovered if clickable => bg_hover,
|
||||||
|
_ => bg_normal,
|
||||||
|
})),
|
||||||
|
border: Border {
|
||||||
|
color: border_color,
|
||||||
|
width: 1.0,
|
||||||
|
radius: 2.0.into(),
|
||||||
|
},
|
||||||
|
text_color,
|
||||||
|
shadow: iced::Shadow::default(),
|
||||||
|
snap: false,
|
||||||
|
})
|
||||||
|
.padding([2, 6]);
|
||||||
|
|
||||||
|
if let Some(msg) = on_press {
|
||||||
|
btn = btn.on_press(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.into()
|
||||||
|
}
|
||||||
|
|
||||||
fn status_pill(label: impl Into<String>) -> Element<'static, Message> {
|
fn status_pill(label: impl Into<String>) -> Element<'static, Message> {
|
||||||
container(text(label.into()).size(10).color(Color {
|
container(text(label.into()).size(10).color(Color {
|
||||||
r: 0.65,
|
r: 0.65,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue