mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-18 22:42:37 +00:00
Pattern/Cut/Boolean: grey the button when there is no body, and say why
Tommaso reported the array controls as missing. They were not — Shift+N opens a Pattern card with every control correct — but the report was fair. With no body the button accepts the click, opens nothing, and writes its refusal somewhere other than where the click happened. From the user's seat that is indistinguishable from a dead button, and the icon is one unlabelled glyph among fourteen, which is how I mis-clicked it into Section view while reproducing this. A control that cannot act should look like it cannot act, before it is pressed. The three FEATURE buttons carrying a body-count guard — Pattern and Cut at one body, Boolean at two — are now greyed below their threshold with a tooltip naming what is missing. Only those three. The same guard shape also appears on rows INSIDE the flyouts, and those stay live: a drawer holds sketch-only entries too, so disabling the drawer would hide tools that are perfectly usable. The keyboard shortcuts keep running the guarded action rather than being gated — a key press has no greyed-out state to see, so the sentence is the only feedback there is. Re-evaluated in feed_bodies(), before its viewport early-return since this is about the toolbar and not the canvas, and once after the toolbar is built: an empty document is the state the bug was reported in and feed_bodies has not run yet on a fresh tab. snaporca-o9j. Reviewed and compiled (RC=0), not exercised.
This commit is contained in:
@@ -751,6 +751,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
b_pattern->Bind(wxEVT_BUTTON, [act_pattern](wxCommandEvent&) { act_pattern(); });
|
||||
m_keys_feature[SHIFT('N')] = act_pattern;
|
||||
fadd("pattern", b_pattern);
|
||||
m_body_gates.push_back({b_pattern, 1, b_pattern->GetToolTipText(),
|
||||
_L("Pattern — needs a solid body to replicate")});
|
||||
|
||||
// Surface: sheet-body tools (extrude / revolve / loft / fill / offset / thicken)
|
||||
// The drawer BUTTON is design_surface, not design_extrude: sharing a face with the
|
||||
@@ -949,6 +951,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
b_boolean->Bind(wxEVT_BUTTON, [act_boolean](wxCommandEvent&) { act_boolean(); });
|
||||
m_keys_feature[SHIFT('B')] = act_boolean;
|
||||
fadd("boolean", b_boolean);
|
||||
m_body_gates.push_back({b_boolean, 2, b_boolean->GetToolTipText(),
|
||||
_L("Boolean — needs two solid bodies to combine")});
|
||||
|
||||
auto* b_cut = icon_btn("design_cut", _L("Cut (split a body with a plane)"));
|
||||
std::function<void()> act_cut = [this] {
|
||||
@@ -966,6 +970,8 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
b_cut->Bind(wxEVT_BUTTON, [act_cut](wxCommandEvent&) { act_cut(); });
|
||||
m_keys_feature[SHIFT('X')] = act_cut;
|
||||
fadd("cut", b_cut);
|
||||
m_body_gates.push_back({b_cut, 1, b_cut->GetToolTipText(),
|
||||
_L("Cut — needs a solid body to slice")});
|
||||
|
||||
// Color — override the selected body's display colour (per-body, survives recompute).
|
||||
auto* b_color = icon_btn("color_palette", _L("Color — set the selected body's display colour"));
|
||||
@@ -1559,6 +1565,9 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
tbrow->Add(m_tb_action, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, 5);
|
||||
tbrow->AddSpacer(8);
|
||||
m_toolbar->SetSizer(tbrow);
|
||||
// Apply the body gates once now: an empty document is exactly the state the bug was reported
|
||||
// in, and feed_bodies() has not run yet on a fresh tab.
|
||||
update_body_gates();
|
||||
|
||||
// Onshape-style dialog-card header: feature icon + bold title. out receives
|
||||
// the title control so open_tool() can retitle it per feature.
|
||||
@@ -6278,6 +6287,9 @@ void DesignPanel::rebuild_disp_meshes()
|
||||
|
||||
void DesignPanel::feed_bodies()
|
||||
{
|
||||
// The body count just changed, so the tools that consume a body may have become reachable or
|
||||
// unreachable. Before the early return below: the gating is about the toolbar, not the canvas.
|
||||
update_body_gates();
|
||||
// Rebuild the transformed meshes first so every display-refresh path (recompute, tint,
|
||||
// visibility, live move) shows the bodies at their current Move offsets. The solid-pick
|
||||
// keeps a STABLE pointer to m_disp_pick_mesh / m_body_visible / m_body_xform (rebuilt in
|
||||
@@ -8930,6 +8942,31 @@ void DesignPanel::update_fillet_gizmo()
|
||||
}
|
||||
|
||||
// Push the active Hole card's plane + position + diameter/depth to the viewport gizmo.
|
||||
// Grey the FEATURE buttons whose tool cannot run yet, and say why in the tooltip (snaporca-o9j).
|
||||
// Tommaso reported the array controls as MISSING; they were not, but Pattern with no body
|
||||
// accepted the click, opened nothing, and wrote its refusal somewhere other than where the click
|
||||
// happened — from the user's seat that is indistinguishable from a dead button. A control that
|
||||
// cannot act should look like it cannot act, before it is pressed.
|
||||
//
|
||||
// Only the three top-level buttons that carry a body-count guard are gated. The same guard also
|
||||
// appears on rows INSIDE the flyouts, and those stay live: a drawer holds sketch-only entries too,
|
||||
// so disabling the drawer would hide tools that are perfectly usable. Their refusal message is
|
||||
// still written, and now next to the geometry.
|
||||
//
|
||||
// The keyboard shortcuts (Shift+N / Shift+X / Shift+B) deliberately keep running the guarded
|
||||
// action rather than being gated: a key press has no greyed-out state to see, so the sentence is
|
||||
// the only feedback there is.
|
||||
void DesignPanel::update_body_gates()
|
||||
{
|
||||
const int n = int(m_doc.bodies.size());
|
||||
for (const BodyGate& g : m_body_gates) {
|
||||
if (g.btn == nullptr) continue;
|
||||
const bool live = n >= g.min_bodies;
|
||||
g.btn->Enable(live);
|
||||
g.btn->SetToolTip(live ? g.tip_live : g.tip_gated);
|
||||
}
|
||||
}
|
||||
|
||||
// Self-gates: clears the gizmo unless the Hole card is open.
|
||||
void DesignPanel::update_hole_gizmo()
|
||||
{
|
||||
|
||||
@@ -272,6 +272,11 @@ private:
|
||||
void update_fillet_gizmo(); // edge-anchored radius arrow (Dressup card)
|
||||
void sync_dressup_target(); // Dressup card: show picked edge vs group, gate the combo
|
||||
void update_hole_gizmo(); // footprint circle + diameter/depth arrows (Hole card)
|
||||
// A FEATURE button whose tool needs bodies it may not have yet. Greyed with an explanatory
|
||||
// tooltip below min_bodies, rather than accepting the click and refusing afterwards.
|
||||
struct BodyGate { wxWindow* btn{nullptr}; int min_bodies{1}; wxString tip_live, tip_gated; };
|
||||
std::vector<BodyGate> m_body_gates;
|
||||
void update_body_gates(); // re-evaluate them against the current body count
|
||||
void update_thread_gizmo(); // footprint circle + radius/length arrows (Thread card)
|
||||
void update_shell_gizmo(); // inward thickness arrow on the picked face (Shell card)
|
||||
void update_revolve_gizmo(); // angle-arc around the axis (Revolve card)
|
||||
|
||||
Reference in New Issue
Block a user