Spaces:
Sleeping
Sleeping
Update app/materials_library.py
Browse files- app/materials_library.py +239 -182
app/materials_library.py
CHANGED
@@ -348,7 +348,7 @@ def categorize_thermal_mass(thermal_mass: float) -> str:
|
|
348 |
def get_stable_button_key(prefix: str, name: str, action: str, unique_id: str = None) -> str:
|
349 |
"""Generate a stable button key based on prefix, name, action, and optional unique identifier."""
|
350 |
import hashlib
|
351 |
-
unique_id = unique_id or str(uuid.uuid4())[:8]
|
352 |
key_string = f"{prefix}_{name}_{action}_{unique_id}"
|
353 |
hash_key = hashlib.md5(key_string.encode()).hexdigest()[:8]
|
354 |
return f"{prefix}_{action}_{name}_{hash_key}"
|
@@ -359,20 +359,25 @@ def display_materials_page():
|
|
359 |
This is the main function called by main.py when the Material Library page is selected.
|
360 |
"""
|
361 |
# Initialize session state
|
362 |
-
if "
|
363 |
-
st.session_state.
|
364 |
if "active_tab" not in st.session_state:
|
365 |
st.session_state.active_tab = "Materials"
|
366 |
if "material_action" not in st.session_state:
|
367 |
st.session_state.material_action = {"action": None, "id": None}
|
368 |
if "fenestration_action" not in st.session_state:
|
369 |
st.session_state.fenestration_action = {"action": None, "id": None}
|
370 |
-
if "rerun_trigger" not in st.session_state:
|
371 |
-
st.session_state.rerun_trigger = None
|
372 |
|
373 |
-
#
|
374 |
-
if st.session_state.
|
375 |
-
st.session_state.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
st.rerun()
|
377 |
|
378 |
# Apply custom CSS for button styling
|
@@ -395,26 +400,186 @@ def display_materials_page():
|
|
395 |
tab1, tab2 = st.tabs(["Materials", "Fenestrations"])
|
396 |
|
397 |
with tab1:
|
398 |
-
|
399 |
-
st.session_state.active_tab = "Materials"
|
400 |
display_materials_tab()
|
401 |
|
402 |
with tab2:
|
403 |
-
|
404 |
-
st.session_state.active_tab = "Fenestrations"
|
405 |
display_fenestrations_tab()
|
406 |
|
407 |
col1, col2 = st.columns(2)
|
408 |
|
409 |
with col1:
|
410 |
if st.button("Back to Climate Data", key="back_to_climate"):
|
411 |
-
st.session_state.
|
412 |
-
st.session_state.rerun_pending = True
|
413 |
|
414 |
with col2:
|
415 |
if st.button("Continue to Construction", key="continue_to_construction"):
|
416 |
-
st.session_state.
|
417 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
418 |
|
419 |
def display_materials_tab():
|
420 |
"""Display the materials tab content."""
|
@@ -458,50 +623,21 @@ def display_materials_tab():
|
|
458 |
copy_key = get_stable_button_key("lib_mat", name, "copy")
|
459 |
|
460 |
if cols[3].button("Preview", key=preview_key):
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
"default_thickness": material["default_thickness"],
|
470 |
-
"embodied_carbon": material["embodied_carbon"],
|
471 |
-
"cost": material["cost"],
|
472 |
-
"absorptivity": material["absorptivity"],
|
473 |
-
"emissivity": material["emissivity"],
|
474 |
-
"colour": material["colour"],
|
475 |
-
"edit_mode": False,
|
476 |
-
"original_name": name,
|
477 |
-
"is_library": True
|
478 |
-
}
|
479 |
-
st.session_state.material_form_state = {
|
480 |
-
"name": name,
|
481 |
-
"category": material["category"],
|
482 |
-
"thermal_conductivity": float(material["thermal_conductivity"]),
|
483 |
-
"density": float(material["density"]),
|
484 |
-
"specific_heat": float(material["specific_heat"]),
|
485 |
-
"default_thickness": float(material["default_thickness"]),
|
486 |
-
"embodied_carbon": float(material["embodied_carbon"]),
|
487 |
-
"cost": float(material["cost"]),
|
488 |
-
"absorptivity": float(material["absorptivity"]),
|
489 |
-
"emissivity": float(material["emissivity"]),
|
490 |
-
"colour": material["colour"]
|
491 |
-
}
|
492 |
-
st.session_state.active_tab = "Materials"
|
493 |
-
st.session_state.rerun_pending = True
|
494 |
-
|
495 |
if cols[4].button("Copy", key=copy_key):
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
st.success(f"Material '{new_name}' copied to project.")
|
503 |
-
logger.info(f"Copied library material '{name}' as '{new_name}' to project")
|
504 |
-
st.session_state.rerun_pending = True
|
505 |
|
506 |
else:
|
507 |
st.info("No materials found in the selected category.")
|
@@ -538,49 +674,19 @@ def display_materials_tab():
|
|
538 |
delete_key = get_stable_button_key("proj_mat", name, "delete")
|
539 |
|
540 |
if cols[3].button("Edit", key=edit_key):
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
"specific_heat": material["specific_heat"],
|
549 |
-
"default_thickness": material["default_thickness"],
|
550 |
-
"embodied_carbon": material["embodied_carbon"],
|
551 |
-
"cost": material["cost"],
|
552 |
-
"absorptivity": material["absorptivity"],
|
553 |
-
"emissivity": material["emissivity"],
|
554 |
-
"colour": material["colour"],
|
555 |
-
"edit_mode": True,
|
556 |
-
"original_name": name,
|
557 |
-
"is_library": False
|
558 |
-
}
|
559 |
-
st.session_state.material_form_state = {
|
560 |
-
"name": name,
|
561 |
-
"category": material["category"],
|
562 |
-
"thermal_conductivity": float(material["thermal_conductivity"]),
|
563 |
-
"density": float(material["density"]),
|
564 |
-
"specific_heat": float(material["specific_heat"]),
|
565 |
-
"default_thickness": float(material["default_thickness"]),
|
566 |
-
"embodied_carbon": float(material["embodied_carbon"]),
|
567 |
-
"cost": float(material["cost"]),
|
568 |
-
"absorptivity": float(material["absorptivity"]),
|
569 |
-
"emissivity": float(material["emissivity"]),
|
570 |
-
"colour": material["colour"]
|
571 |
-
}
|
572 |
-
st.session_state.active_tab = "Materials"
|
573 |
-
st.session_state.rerun_pending = True
|
574 |
-
|
575 |
if cols[4].button("Delete", key=delete_key):
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
st.success(f"Material '{name}' deleted from project.")
|
582 |
-
logger.info(f"Deleted material '{name}' from project")
|
583 |
-
st.session_state.rerun_pending = True
|
584 |
|
585 |
else:
|
586 |
st.info("No project materials in the selected category.")
|
@@ -657,44 +763,21 @@ def display_fenestrations_tab():
|
|
657 |
copy_key = get_stable_button_key("lib_fen", name, "copy")
|
658 |
|
659 |
if cols[3].button("Preview", key=preview_key):
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
"thickness": fenestration["thickness"],
|
669 |
-
"embodied_carbon": fenestration["embodied_carbon"],
|
670 |
-
"cost": fenestration["cost"],
|
671 |
-
"edit_mode": False,
|
672 |
-
"original_name": name,
|
673 |
-
"is_library": True
|
674 |
-
}
|
675 |
-
st.session_state.fenestration_form_state = {
|
676 |
-
"name": name,
|
677 |
-
"type": fenestration["type"],
|
678 |
-
"u_value": float(fenestration["u_value"]),
|
679 |
-
"shgc": float(fenestration["shgc"]),
|
680 |
-
"visible_trans": float(fenestration["visible_transmittance"]),
|
681 |
-
"thickness": float(fenestration["thickness"]),
|
682 |
-
"embodied_carbon": float(fenestration["embodied_carbon"]),
|
683 |
-
"cost": float(fenestration["cost"])
|
684 |
-
}
|
685 |
-
st.session_state.active_tab = "Fenestrations"
|
686 |
-
st.session_state.rerun_pending = True
|
687 |
-
|
688 |
if cols[4].button("Copy", key=copy_key):
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
st.success(f"Fenestration '{new_name}' copied to project.")
|
696 |
-
logger.info(f"Copied library fenestration '{name}' as '{new_name}' to project")
|
697 |
-
st.session_state.rerun_pending = True
|
698 |
|
699 |
else:
|
700 |
st.info("No fenestrations found in the selected type.")
|
@@ -728,43 +811,19 @@ def display_fenestrations_tab():
|
|
728 |
delete_key = get_stable_button_key("proj_fen", name, "delete")
|
729 |
|
730 |
if cols[3].button("Edit", key=edit_key):
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
"visible_trans": fenestration["visible_transmittance"],
|
739 |
-
"thickness": fenestration["thickness"],
|
740 |
-
"embodied_carbon": fenestration["embodied_carbon"],
|
741 |
-
"cost": fenestration["cost"],
|
742 |
-
"edit_mode": True,
|
743 |
-
"original_name": name,
|
744 |
-
"is_library": False
|
745 |
-
}
|
746 |
-
st.session_state.fenestration_form_state = {
|
747 |
-
"name": name,
|
748 |
-
"type": fenestration["type"],
|
749 |
-
"u_value": float(fenestration["u_value"]),
|
750 |
-
"shgc": float(fenestration["shgc"]),
|
751 |
-
"visible_trans": float(fenestration["visible_transmittance"]),
|
752 |
-
"thickness": float(fenestration["thickness"]),
|
753 |
-
"embodied_carbon": float(fenestration["embodied_carbon"]),
|
754 |
-
"cost": float(fenestration["cost"])
|
755 |
-
}
|
756 |
-
st.session_state.active_tab = "Fenestrations"
|
757 |
-
st.session_state.rerun_pending = True
|
758 |
-
|
759 |
if cols[4].button("Delete", key=delete_key):
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
st.success(f"Fenestration '{name}' deleted from project.")
|
766 |
-
logger.info(f"Deleted fenestration '{name}' from project")
|
767 |
-
st.session_state.rerun_pending = True
|
768 |
|
769 |
else:
|
770 |
st.info("No project fenestrations in the selected type.")
|
@@ -880,7 +939,7 @@ def initialize_fenestrations():
|
|
880 |
|
881 |
def display_material_editor():
|
882 |
"""Display the material editor form."""
|
883 |
-
with st.form("material_editor_form"):
|
884 |
editor_state = st.session_state.material_editor
|
885 |
form_state = st.session_state.material_form_state
|
886 |
is_library = editor_state.get("is_library", False)
|
@@ -1061,15 +1120,15 @@ def display_material_editor():
|
|
1061 |
st.success(f"Material '{name}' added to your project.")
|
1062 |
logger.info(f"Added new material '{name}' to project")
|
1063 |
reset_material_editor()
|
1064 |
-
st.session_state.
|
1065 |
|
1066 |
if clear_button:
|
1067 |
reset_material_editor()
|
1068 |
-
st.session_state.
|
1069 |
|
1070 |
def display_fenestration_editor():
|
1071 |
"""Display the fenestration editor form."""
|
1072 |
-
with st.form("fenestration_editor_form"):
|
1073 |
editor_state = st.session_state.fenestration_editor
|
1074 |
form_state = st.session_state.fenestration_form_state
|
1075 |
is_library = editor_state.get("is_library", False)
|
@@ -1210,11 +1269,11 @@ def display_fenestration_editor():
|
|
1210 |
st.success(f"Fenestration '{name}' added to your project.")
|
1211 |
logger.info(f"Added new fenestration '{name}' to project")
|
1212 |
reset_fenestration_editor()
|
1213 |
-
st.session_state.
|
1214 |
|
1215 |
if clear_button:
|
1216 |
reset_fenestration_editor()
|
1217 |
-
st.session_state.
|
1218 |
|
1219 |
def validate_material(
|
1220 |
name: str, category: str, thermal_conductivity: float, density: float,
|
@@ -1344,7 +1403,6 @@ def reset_material_editor():
|
|
1344 |
"is_library": False
|
1345 |
}
|
1346 |
st.session_state.material_action = {"action": None, "id": None}
|
1347 |
-
st.session_state.rerun_trigger = None
|
1348 |
|
1349 |
def reset_fenestration_editor():
|
1350 |
"""Reset the fenestration editor and form state."""
|
@@ -1372,7 +1430,6 @@ def reset_fenestration_editor():
|
|
1372 |
"is_library": False
|
1373 |
}
|
1374 |
st.session_state.fenestration_action = {"action": None, "id": None}
|
1375 |
-
st.session_state.rerun_trigger = None
|
1376 |
|
1377 |
def check_material_in_use(material_name: str) -> bool:
|
1378 |
"""
|
|
|
348 |
def get_stable_button_key(prefix: str, name: str, action: str, unique_id: str = None) -> str:
|
349 |
"""Generate a stable button key based on prefix, name, action, and optional unique identifier."""
|
350 |
import hashlib
|
351 |
+
unique_id = unique_id or str(uuid.uuid4())[:8]
|
352 |
key_string = f"{prefix}_{name}_{action}_{unique_id}"
|
353 |
hash_key = hashlib.md5(key_string.encode()).hexdigest()[:8]
|
354 |
return f"{prefix}_{action}_{name}_{hash_key}"
|
|
|
359 |
This is the main function called by main.py when the Material Library page is selected.
|
360 |
"""
|
361 |
# Initialize session state
|
362 |
+
if "action_queue" not in st.session_state:
|
363 |
+
st.session_state.action_queue = []
|
364 |
if "active_tab" not in st.session_state:
|
365 |
st.session_state.active_tab = "Materials"
|
366 |
if "material_action" not in st.session_state:
|
367 |
st.session_state.material_action = {"action": None, "id": None}
|
368 |
if "fenestration_action" not in st.session_state:
|
369 |
st.session_state.fenestration_action = {"action": None, "id": None}
|
|
|
|
|
370 |
|
371 |
+
# Process action queue
|
372 |
+
if st.session_state.action_queue:
|
373 |
+
action = st.session_state.action_queue.pop(0)
|
374 |
+
if action["type"] == "page_change":
|
375 |
+
st.session_state.current_page = action["page"]
|
376 |
+
st.rerun()
|
377 |
+
elif action["type"] == "material_action":
|
378 |
+
handle_material_action(action)
|
379 |
+
elif action["type"] == "fenestration_action":
|
380 |
+
handle_fenestration_action(action)
|
381 |
st.rerun()
|
382 |
|
383 |
# Apply custom CSS for button styling
|
|
|
400 |
tab1, tab2 = st.tabs(["Materials", "Fenestrations"])
|
401 |
|
402 |
with tab1:
|
403 |
+
st.session_state.active_tab = "Materials"
|
|
|
404 |
display_materials_tab()
|
405 |
|
406 |
with tab2:
|
407 |
+
st.session_state.active_tab = "Fenestrations"
|
|
|
408 |
display_fenestrations_tab()
|
409 |
|
410 |
col1, col2 = st.columns(2)
|
411 |
|
412 |
with col1:
|
413 |
if st.button("Back to Climate Data", key="back_to_climate"):
|
414 |
+
st.session_state.action_queue.append({"type": "page_change", "page": "Climate Data"})
|
|
|
415 |
|
416 |
with col2:
|
417 |
if st.button("Continue to Construction", key="continue_to_construction"):
|
418 |
+
st.session_state.action_queue.append({"type": "page_change", "page": "Construction"})
|
419 |
+
|
420 |
+
def handle_material_action(action: Dict[str, Any]):
|
421 |
+
"""Handle material-related actions."""
|
422 |
+
if action["action"] == "preview":
|
423 |
+
material = action["material"]
|
424 |
+
name = action["name"]
|
425 |
+
st.session_state.material_editor = {
|
426 |
+
"name": name,
|
427 |
+
"category": material["category"],
|
428 |
+
"thermal_conductivity": material["thermal_conductivity"],
|
429 |
+
"density": material["density"],
|
430 |
+
"specific_heat": material["specific_heat"],
|
431 |
+
"default_thickness": material["default_thickness"],
|
432 |
+
"embodied_carbon": material["embodied_carbon"],
|
433 |
+
"cost": material["cost"],
|
434 |
+
"absorptivity": material["absorptivity"],
|
435 |
+
"emissivity": material["emissivity"],
|
436 |
+
"colour": material["colour"],
|
437 |
+
"edit_mode": False,
|
438 |
+
"original_name": name,
|
439 |
+
"is_library": action["is_library"]
|
440 |
+
}
|
441 |
+
st.session_state.material_form_state = {
|
442 |
+
"name": name,
|
443 |
+
"category": material["category"],
|
444 |
+
"thermal_conductivity": float(material["thermal_conductivity"]),
|
445 |
+
"density": float(material["density"]),
|
446 |
+
"specific_heat": float(material["specific_heat"]),
|
447 |
+
"default_thickness": float(material["default_thickness"]),
|
448 |
+
"embodied_carbon": float(material["embodied_carbon"]),
|
449 |
+
"cost": float(material["cost"]),
|
450 |
+
"absorptivity": float(material["absorptivity"]),
|
451 |
+
"emissivity": float(material["emissivity"]),
|
452 |
+
"colour": material["colour"]
|
453 |
+
}
|
454 |
+
elif action["action"] == "copy":
|
455 |
+
name = action["name"]
|
456 |
+
material = action["material"]
|
457 |
+
new_name = f"{name}_Project"
|
458 |
+
counter = 1
|
459 |
+
library_materials = st.session_state.project_data["materials"]["library"]
|
460 |
+
while new_name in st.session_state.project_data["materials"]["project"] or new_name in library_materials:
|
461 |
+
new_name = f"{name}_Project_{counter}"
|
462 |
+
counter += 1
|
463 |
+
st.session_state.project_data["materials"]["project"][new_name] = material.copy()
|
464 |
+
st.success(f"Material '{new_name}' copied to project.")
|
465 |
+
logger.info(f"Copied library material '{name}' as '{new_name}' to project")
|
466 |
+
elif action["action"] == "edit":
|
467 |
+
material = action["material"]
|
468 |
+
name = action["name"]
|
469 |
+
st.session_state.material_editor = {
|
470 |
+
"name": name,
|
471 |
+
"category": material["category"],
|
472 |
+
"thermal_conductivity": material["thermal_conductivity"],
|
473 |
+
"density": material["density"],
|
474 |
+
"specific_heat": material["specific_heat"],
|
475 |
+
"default_thickness": material["default_thickness"],
|
476 |
+
"embodied_carbon": material["embodied_carbon"],
|
477 |
+
"cost": material["cost"],
|
478 |
+
"absorptivity": material["absorptivity"],
|
479 |
+
"emissivity": material["emissivity"],
|
480 |
+
"colour": material["colour"],
|
481 |
+
"edit_mode": True,
|
482 |
+
"original_name": name,
|
483 |
+
"is_library": False
|
484 |
+
}
|
485 |
+
st.session_state.material_form_state = {
|
486 |
+
"name": name,
|
487 |
+
"category": material["category"],
|
488 |
+
"thermal_conductivity": float(material["thermal_conductivity"]),
|
489 |
+
"density": float(material["density"]),
|
490 |
+
"specific_heat": float(material["specific_heat"]),
|
491 |
+
"default_thickness": float(material["default_thickness"]),
|
492 |
+
"embodied_carbon": float(material["embodied_carbon"]),
|
493 |
+
"cost": float(material["cost"]),
|
494 |
+
"absorptivity": float(material["absorptivity"]),
|
495 |
+
"emissivity": float(material["emissivity"]),
|
496 |
+
"colour": material["colour"]
|
497 |
+
}
|
498 |
+
elif action["action"] == "delete":
|
499 |
+
name = action["name"]
|
500 |
+
is_in_use = check_material_in_use(name)
|
501 |
+
if is_in_use:
|
502 |
+
st.error(f"Cannot delete material '{name}' because it is in use in constructions.")
|
503 |
+
else:
|
504 |
+
del st.session_state.project_data["materials"]["project"][name]
|
505 |
+
st.success(f"Material '{name}' deleted from project.")
|
506 |
+
logger.info(f"Deleted material '{name}' from project")
|
507 |
+
|
508 |
+
def handle_fenestration_action(action: Dict[str, Any]):
|
509 |
+
"""Handle fenestration-related actions."""
|
510 |
+
if action["action"] == "preview":
|
511 |
+
fenestration = action["fenestration"]
|
512 |
+
name = action["name"]
|
513 |
+
st.session_state.fenestration_editor = {
|
514 |
+
"name": name,
|
515 |
+
"type": fenestration["type"],
|
516 |
+
"u_value": fenestration["u_value"],
|
517 |
+
"shgc": fenestration["shgc"],
|
518 |
+
"visible_trans": fenestration["visible_transmittance"],
|
519 |
+
"thickness": fenestration["thickness"],
|
520 |
+
"embodied_carbon": fenestration["embodied_carbon"],
|
521 |
+
"cost": fenestration["cost"],
|
522 |
+
"edit_mode": False,
|
523 |
+
"original_name": name,
|
524 |
+
"is_library": action["is_library"]
|
525 |
+
}
|
526 |
+
st.session_state.fenestration_form_state = {
|
527 |
+
"name": name,
|
528 |
+
"type": fenestration["type"],
|
529 |
+
"u_value": float(fenestration["u_value"]),
|
530 |
+
"shgc": float(fenestration["shgc"]),
|
531 |
+
"visible_trans": float(fenestration["visible_transmittance"]),
|
532 |
+
"thickness": float(fenestration["thickness"]),
|
533 |
+
"embodied_carbon": float(fenestration["embodied_carbon"]),
|
534 |
+
"cost": float(fenestration["cost"])
|
535 |
+
}
|
536 |
+
elif action["action"] == "copy":
|
537 |
+
name = action["name"]
|
538 |
+
fenestration = action["fenestration"]
|
539 |
+
new_name = f"{name}_Project"
|
540 |
+
counter = 1
|
541 |
+
library_fenestrations = st.session_state.project_data["fenestrations"]["library"]
|
542 |
+
while new_name in st.session_state.project_data["fenestrations"]["project"] or new_name in library_fenestrations:
|
543 |
+
new_name = f"{name}_Project_{counter}"
|
544 |
+
counter += 1
|
545 |
+
st.session_state.project_data["fenestrations"]["project"][new_name] = fenestration.copy()
|
546 |
+
st.success(f"Fenestration '{new_name}' copied to project.")
|
547 |
+
logger.info(f"Copied library fenestration '{name}' as '{new_name}' to project")
|
548 |
+
elif action["action"] == "edit":
|
549 |
+
fenestration = action["fenestration"]
|
550 |
+
name = action["name"]
|
551 |
+
st.session_state.fenestration_editor = {
|
552 |
+
"name": name,
|
553 |
+
"type": fenestration["type"],
|
554 |
+
"u_value": fenestration["u_value"],
|
555 |
+
"shgc": fenestration["shgc"],
|
556 |
+
"visible_trans": fenestration["visible_transmittance"],
|
557 |
+
"thickness": fenestration["thickness"],
|
558 |
+
"embodied_carbon": fenestration["embodied_carbon"],
|
559 |
+
"cost": fenestration["cost"],
|
560 |
+
"edit_mode": True,
|
561 |
+
"original_name": name,
|
562 |
+
"is_library": False
|
563 |
+
}
|
564 |
+
st.session_state.fenestration_form_state = {
|
565 |
+
"name": name,
|
566 |
+
"type": fenestration["type"],
|
567 |
+
"u_value": float(fenestration["u_value"]),
|
568 |
+
"shgc": float(fenestration["shgc"]),
|
569 |
+
"visible_trans": float(fenestration["visible_transmittance"]),
|
570 |
+
"thickness": float(fenestration["thickness"]),
|
571 |
+
"embodied_carbon": float(fenestration["embodied_carbon"]),
|
572 |
+
"cost": float(fenestration["cost"])
|
573 |
+
}
|
574 |
+
elif action["action"] == "delete":
|
575 |
+
name = action["name"]
|
576 |
+
is_in_use = check_fenestration_in_use(name)
|
577 |
+
if is_in_use:
|
578 |
+
st.error(f"Cannot delete fenestration '{name}' because it is in use in components.")
|
579 |
+
else:
|
580 |
+
del st.session_state.project_data["fenestrations"]["project"][name]
|
581 |
+
st.success(f"Fenestration '{name}' deleted from project.")
|
582 |
+
logger.info(f"Deleted fenestration '{name}' from project")
|
583 |
|
584 |
def display_materials_tab():
|
585 |
"""Display the materials tab content."""
|
|
|
623 |
copy_key = get_stable_button_key("lib_mat", name, "copy")
|
624 |
|
625 |
if cols[3].button("Preview", key=preview_key):
|
626 |
+
st.session_state.action_queue.append({
|
627 |
+
"type": "material_action",
|
628 |
+
"action": "preview",
|
629 |
+
"name": name,
|
630 |
+
"material": material,
|
631 |
+
"is_library": True
|
632 |
+
})
|
633 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
634 |
if cols[4].button("Copy", key=copy_key):
|
635 |
+
st.session_state.action_queue.append({
|
636 |
+
"type": "material_action",
|
637 |
+
"action": "copy",
|
638 |
+
"name": name,
|
639 |
+
"material": material
|
640 |
+
})
|
|
|
|
|
|
|
641 |
|
642 |
else:
|
643 |
st.info("No materials found in the selected category.")
|
|
|
674 |
delete_key = get_stable_button_key("proj_mat", name, "delete")
|
675 |
|
676 |
if cols[3].button("Edit", key=edit_key):
|
677 |
+
st.session_state.action_queue.append({
|
678 |
+
"type": "material_action",
|
679 |
+
"action": "edit",
|
680 |
+
"name": name,
|
681 |
+
"material": material
|
682 |
+
})
|
683 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
684 |
if cols[4].button("Delete", key=delete_key):
|
685 |
+
st.session_state.action_queue.append({
|
686 |
+
"type": "material_action",
|
687 |
+
"action": "delete",
|
688 |
+
"name": name
|
689 |
+
})
|
|
|
|
|
|
|
690 |
|
691 |
else:
|
692 |
st.info("No project materials in the selected category.")
|
|
|
763 |
copy_key = get_stable_button_key("lib_fen", name, "copy")
|
764 |
|
765 |
if cols[3].button("Preview", key=preview_key):
|
766 |
+
st.session_state.action_queue.append({
|
767 |
+
"type": "fenestration_action",
|
768 |
+
"action": "preview",
|
769 |
+
"name": name,
|
770 |
+
"fenestration": fenestration,
|
771 |
+
"is_library": True
|
772 |
+
})
|
773 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
774 |
if cols[4].button("Copy", key=copy_key):
|
775 |
+
st.session_state.action_queue.append({
|
776 |
+
"type": "fenestration_action",
|
777 |
+
"action": "copy",
|
778 |
+
"name": name,
|
779 |
+
"fenestration": fenestration
|
780 |
+
})
|
|
|
|
|
|
|
781 |
|
782 |
else:
|
783 |
st.info("No fenestrations found in the selected type.")
|
|
|
811 |
delete_key = get_stable_button_key("proj_fen", name, "delete")
|
812 |
|
813 |
if cols[3].button("Edit", key=edit_key):
|
814 |
+
st.session_state.action_queue.append({
|
815 |
+
"type": "fenestration_action",
|
816 |
+
"action": "edit",
|
817 |
+
"name": name,
|
818 |
+
"fenestration": fenestration
|
819 |
+
})
|
820 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
821 |
if cols[4].button("Delete", key=delete_key):
|
822 |
+
st.session_state.action_queue.append({
|
823 |
+
"type": "fenestration_action",
|
824 |
+
"action": "delete",
|
825 |
+
"name": name
|
826 |
+
})
|
|
|
|
|
|
|
827 |
|
828 |
else:
|
829 |
st.info("No project fenestrations in the selected type.")
|
|
|
939 |
|
940 |
def display_material_editor():
|
941 |
"""Display the material editor form."""
|
942 |
+
with st.form("material_editor_form", clear_on_submit=True):
|
943 |
editor_state = st.session_state.material_editor
|
944 |
form_state = st.session_state.material_form_state
|
945 |
is_library = editor_state.get("is_library", False)
|
|
|
1120 |
st.success(f"Material '{name}' added to your project.")
|
1121 |
logger.info(f"Added new material '{name}' to project")
|
1122 |
reset_material_editor()
|
1123 |
+
st.session_state.action_queue.append({"type": "refresh"})
|
1124 |
|
1125 |
if clear_button:
|
1126 |
reset_material_editor()
|
1127 |
+
st.session_state.action_queue.append({"type": "refresh"})
|
1128 |
|
1129 |
def display_fenestration_editor():
|
1130 |
"""Display the fenestration editor form."""
|
1131 |
+
with st.form("fenestration_editor_form", clear_on_submit=True):
|
1132 |
editor_state = st.session_state.fenestration_editor
|
1133 |
form_state = st.session_state.fenestration_form_state
|
1134 |
is_library = editor_state.get("is_library", False)
|
|
|
1269 |
st.success(f"Fenestration '{name}' added to your project.")
|
1270 |
logger.info(f"Added new fenestration '{name}' to project")
|
1271 |
reset_fenestration_editor()
|
1272 |
+
st.session_state.action_queue.append({"type": "refresh"})
|
1273 |
|
1274 |
if clear_button:
|
1275 |
reset_fenestration_editor()
|
1276 |
+
st.session_state.action_queue.append({"type": "refresh"})
|
1277 |
|
1278 |
def validate_material(
|
1279 |
name: str, category: str, thermal_conductivity: float, density: float,
|
|
|
1403 |
"is_library": False
|
1404 |
}
|
1405 |
st.session_state.material_action = {"action": None, "id": None}
|
|
|
1406 |
|
1407 |
def reset_fenestration_editor():
|
1408 |
"""Reset the fenestration editor and form state."""
|
|
|
1430 |
"is_library": False
|
1431 |
}
|
1432 |
st.session_state.fenestration_action = {"action": None, "id": None}
|
|
|
1433 |
|
1434 |
def check_material_in_use(material_name: str) -> bool:
|
1435 |
"""
|