feat: 完善一级关系编辑 UI 与视图体验
This commit is contained in:
@@ -8,7 +8,7 @@ PROJECT_ROOT = Path(__file__).resolve().parent.parent
|
||||
if str(PROJECT_ROOT) not in sys.path:
|
||||
sys.path.insert(0, str(PROJECT_ROOT))
|
||||
|
||||
from step_editor.window_state import WindowStateMixin
|
||||
from step_editor.window_state import WindowStateMixin, _property_table_column_widths
|
||||
from step_editor.ui_helpers import INFO_LABELS, _format_value
|
||||
|
||||
|
||||
@@ -102,6 +102,12 @@ def _assert_current_text_contains(
|
||||
raise SystemExit(f"{label} {key} text missing {missing}: {text!r}")
|
||||
|
||||
|
||||
def _assert_spans_value_columns(specs: list[dict[str, object]], key: str) -> None:
|
||||
spec = _spec(specs, key)
|
||||
if not bool(spec.get("span_value_columns")):
|
||||
raise SystemExit(f"{key} should span the value/intent/target/action columns: {spec}")
|
||||
|
||||
|
||||
def _assert_hard_range(specs: list[dict[str, object]], key: str, low: float, high: float) -> None:
|
||||
spec = _spec(specs, key)
|
||||
actual_low = spec.get("min_value")
|
||||
@@ -312,6 +318,24 @@ def _assert_target_change_detection() -> None:
|
||||
raise SystemExit("changed vector Face target was not detected")
|
||||
|
||||
|
||||
def _assert_property_table_column_widths() -> None:
|
||||
for width in (320, 340, 360, 400, 520):
|
||||
columns = _property_table_column_widths(width)
|
||||
if len(columns) != 5:
|
||||
raise SystemExit(f"property table should have five column widths, got {columns}")
|
||||
if sum(columns) != width:
|
||||
raise SystemExit(f"property table widths should fill viewport {width}, got {columns} sum={sum(columns)}")
|
||||
label_width, current_width, scope_width, target_width, action_width = columns
|
||||
if current_width < label_width + 40:
|
||||
raise SystemExit(f"current value column should be wider than parameter-name column at {width}: {columns}")
|
||||
if action_width < 70:
|
||||
raise SystemExit(f"operation column should keep row buttons visible at {width}: {columns}")
|
||||
if target_width < 56:
|
||||
raise SystemExit(f"target value column should stay usable at {width}: {columns}")
|
||||
if scope_width > label_width + 8:
|
||||
raise SystemExit(f"modeling-intent column should not take space from current values at {width}: {columns}")
|
||||
|
||||
|
||||
def _assert_holed_plane_local_scopes_disabled() -> None:
|
||||
specs = _specs(
|
||||
{
|
||||
@@ -362,7 +386,15 @@ def _assert_holed_plane_local_scopes_disabled() -> None:
|
||||
def main() -> int:
|
||||
if INFO_LABELS.get("face_id") != "当前拓扑 Face ID":
|
||||
raise SystemExit("raw face_id label should make clear that it is the current topological Face ID")
|
||||
for key in ("selection_title", "selection_display_id", "selection_topological_face_id"):
|
||||
for key in (
|
||||
"selection_title",
|
||||
"selection_display_id",
|
||||
"selection_topological_face_id",
|
||||
"feature_detection_level",
|
||||
"associated_feature_count",
|
||||
"associated_feature_face_ids",
|
||||
"feature_context_note",
|
||||
):
|
||||
if key not in INFO_LABELS:
|
||||
raise SystemExit(f"{key} should have a user-facing label")
|
||||
|
||||
@@ -393,6 +425,7 @@ def main() -> int:
|
||||
plane_specs = _specs(plane_info)
|
||||
plane_keys = {str(spec.get("key", "")) for spec in plane_specs}
|
||||
_assert_label(plane_specs, "cad_modeling_form", "建模形式")
|
||||
_assert_spans_value_columns(plane_specs, "cad_modeling_form")
|
||||
_assert_current_text_contains(
|
||||
plane_specs,
|
||||
"cad_modeling_form",
|
||||
@@ -400,6 +433,7 @@ def main() -> int:
|
||||
"plane Face",
|
||||
)
|
||||
_assert_label(plane_specs, "cad_recommended_operation", "推荐操作")
|
||||
_assert_spans_value_columns(plane_specs, "cad_recommended_operation")
|
||||
_assert_current_text_contains(
|
||||
plane_specs,
|
||||
"cad_recommended_operation",
|
||||
@@ -443,11 +477,13 @@ def main() -> int:
|
||||
plane_feature_rows = plane_feature_probe._feature_property_specs(plane_feature_specs, plane_info)
|
||||
plane_feature_keys = {str(spec.get("key", "")) for spec in plane_feature_rows}
|
||||
topology_spec = _spec(plane_feature_rows, "face_first_level_topology")
|
||||
_assert_spans_value_columns(plane_feature_rows, "face_first_level_topology")
|
||||
topology_text = str(topology_spec.get("current_text") or "")
|
||||
for fragment in ("Face 区域 1 个", "边界 Edge 4 条", "共享边相邻 Face 4 个"):
|
||||
if fragment not in topology_text:
|
||||
raise SystemExit(f"plane feature topology row should explain first-level counts, got {topology_spec}")
|
||||
_assert_label(plane_feature_rows, "face_edit_semantics", "建模意图")
|
||||
_assert_spans_value_columns(plane_feature_rows, "face_edit_semantics")
|
||||
_assert_label(plane_feature_rows, "cad_modeling_form", "建模形式")
|
||||
_assert_label(plane_feature_rows, "cad_recommended_operation", "推荐操作")
|
||||
if str(plane_feature_rows[0].get("key", "")) != "cad_modeling_form":
|
||||
@@ -889,6 +925,15 @@ def main() -> int:
|
||||
"start_point": (0.0, 0.0, 0.0),
|
||||
"end_point": (10.0, 0.0, 0.0),
|
||||
"length_center": (5.0, 0.0, 0.0),
|
||||
"topology_relation_depth": 1,
|
||||
"selected_edge_count": 1,
|
||||
"first_level_vertex_count": 2,
|
||||
"first_level_adjacent_edge_count": 4,
|
||||
"first_level_adjacent_face_count": 2,
|
||||
"first_level_edge_count": 5,
|
||||
"first_level_topology_note": "Edge first-level topology is ready.",
|
||||
"first_level_fact_summary": "一级事实=当前 Edge、端点、共享端点相邻 Edge、直接相邻 Face。",
|
||||
"topology_ignored_relation_note": "当前阶段只传播一级关系;二级、三级拓扑暂不自动递归编辑。",
|
||||
}
|
||||
)
|
||||
_assert_current_text_contains(
|
||||
@@ -903,7 +948,21 @@ def main() -> int:
|
||||
("优先改长度", "移动端面", "只改当前Edge"),
|
||||
"line Edge",
|
||||
)
|
||||
_assert_contains({str(spec.get("key", "")) for spec in edge_specs}, {"length"}, "line Edge")
|
||||
_assert_label(edge_specs, "edge_first_level_topology", "一级关系")
|
||||
_assert_current_text_contains(
|
||||
edge_specs,
|
||||
"edge_first_level_topology",
|
||||
("端点 Vertex 2 个", "相邻 Edge 4 条", "直接相邻 Face 2 个"),
|
||||
"line Edge",
|
||||
)
|
||||
edge_topology_tip = str(_spec(edge_specs, "edge_first_level_topology").get("disabled_tip") or "")
|
||||
if "二级、三级" not in edge_topology_tip:
|
||||
raise SystemExit(f"line Edge topology tip should explain ignored deeper topology: {edge_topology_tip}")
|
||||
_assert_contains(
|
||||
{str(spec.get("key", "")) for spec in edge_specs},
|
||||
{"length", "edge_first_level_topology"},
|
||||
"line Edge",
|
||||
)
|
||||
|
||||
low_recognition_specs = _specs(
|
||||
{
|
||||
@@ -928,6 +987,7 @@ def main() -> int:
|
||||
raise SystemExit(f"{key} disabled tip should explain the recognition blocker: {spec}")
|
||||
|
||||
_assert_target_change_detection()
|
||||
_assert_property_table_column_widths()
|
||||
_assert_holed_plane_local_scopes_disabled()
|
||||
_assert_no_legacy_face_source_terms()
|
||||
print("property editor specs ok")
|
||||
|
||||
Reference in New Issue
Block a user