cost items ui - update current index on item deletion

To make it less awkward to remove multiple items starting from the last.

Before - https://files.catbox.moe/wce56c.mp4
After - https://files.catbox.moe/wv1jhs.mp4
This commit is contained in:
Andrej
2025-06-06 18:36:43 +05:00
parent 14e8fad841
commit 09f6991565
6 changed files with 24 additions and 6 deletions
@@ -161,7 +161,10 @@ class CostClassificationsData(ReferencesData):
def references(cls) -> list[dict[str, Any]]:
results: list[dict[str, Any]] = []
props = tool.Cost.get_cost_props()
element = tool.Ifc.get().by_id(props.cost_items[props.active_cost_item_index].ifc_definition_id)
active_cost_item = props.active_cost_item
if not active_cost_item:
return results
element = tool.Ifc.get().by_id(active_cost_item.ifc_definition_id)
if element:
for reference in ifcopenshell.util.classification.get_references(element):
data = reference.get_info()
+5 -1
View File
@@ -34,7 +34,7 @@ from bpy.props import (
FloatVectorProperty,
CollectionProperty,
)
from typing import TYPE_CHECKING, Literal
from typing import TYPE_CHECKING, Literal, Union
def get_schedule_of_rates(self: "BIMCostProperties", context: bpy.types.Context) -> tool.Blender.BLENDER_ENUM_ITEMS:
@@ -345,3 +345,7 @@ class BIMCostProperties(PropertyGroup):
currency: str
custom_currency: str
cost_schedule_files: bpy.types.bpy_prop_collection_idprop[CostItemsMapping]
@property
def active_cost_item(self) -> Union[CostItem, None]:
return tool.Blender.get_active_uilist_element(self.cost_items, self.active_cost_item_index)
@@ -106,8 +106,7 @@ class RemoveProfileDef(bpy.types.Operator, tool.Ifc.Operator):
bpy.ops.bim.load_profiles()
# preserve selected index if possible
if props.profiles:
props.active_profile_index = min(current_index, len(props.profiles) - 1)
props.active_profile_index = tool.Blender.get_valid_uilist_index(props.active_profile_index, props.profiles)
class EnableEditingProfile(bpy.types.Operator):
+9 -1
View File
@@ -42,7 +42,7 @@ from mathutils import Vector
from pathlib import Path
from functools import lru_cache, cache
from bonsai.bim.ifc import IFC_CONNECTED_TYPE
from typing import Any, Optional, Union, Literal, Iterable, Callable, TypeVar, Generator, TYPE_CHECKING, Sequence
from typing import Any, Optional, Union, Literal, Iterable, Callable, TypeVar, Generator, TYPE_CHECKING, Sequence, Sized
from typing_extensions import assert_never
if TYPE_CHECKING:
@@ -1692,6 +1692,14 @@ class Blender(bonsai.core.tool.Blender):
return collection[index]
return None
@classmethod
def get_valid_uilist_index(cls, current_index: int, items: Sized) -> int:
"""
Method to help maintaining item selection after some uilist item was removed
and items were reloaded.
"""
return max(0, min(current_index, len(items) - 1))
@classmethod
def clear_undo_history(cls) -> None:
"""Clears the Blender history, Bonsai history, and IfcOpenShell history"""
+4
View File
@@ -168,6 +168,9 @@ class Cost(bonsai.core.tool.Cost):
for rel in cost_schedule.Controls or []
for cost_item in rel.RelatedObjects or []
]
props.active_cost_item_index = tool.Blender.get_valid_uilist_index(
props.active_cost_item_index, props.cost_items
)
props.is_cost_update_enabled = True
@classmethod
@@ -208,6 +211,7 @@ class Cost(bonsai.core.tool.Cost):
@classmethod
def clean_up_cost_item_tree(cls, cost_item_id: int) -> None:
"""Clean up cost item tree after ``cost_item_id`` was deleted."""
props = cls.get_cost_props()
if not hasattr(cls, "contracted_cost_items"):
cls.contracted_cost_items = json.loads(props.contracted_cost_items)
+1 -1
View File
@@ -475,7 +475,7 @@ class Spatial(bonsai.core.tool.Spatial):
props.containers.clear()
cls.contracted_containers = json.loads(props.contracted_containers)
cls.import_spatial_element(tool.Ifc.get().by_type("IfcProject")[0], 0)
props.active_container_index = min(previous_container_index, len(props.containers) - 1)
props.active_container_index = tool.Blender.get_valid_uilist_index(previous_container_index, props.containers)
@classmethod
def import_spatial_element(cls, element: ifcopenshell.entity_instance, level_index: int) -> None: