diff --git a/src/Mod/Assembly/InitGui.py b/src/Mod/Assembly/InitGui.py index 7e90be47f8..62394c1c90 100644 --- a/src/Mod/Assembly/InitGui.py +++ b/src/Mod/Assembly/InitGui.py @@ -118,11 +118,162 @@ class AssemblyWorkbench(Workbench): # update the translation engine FreeCADGui.updateLocale() + # Add task watchers to provide contextual tools in the task panel + self.setWatchers() + def Deactivated(self): - pass + FreeCADGui.Control.clearTaskWatcher() def ContextMenu(self, recipient): pass + def setWatchers(self): + import UtilsAssembly + + translate = FreeCAD.Qt.translate + + class AssemblyCreateWatcher: + """Shows 'Create Assembly' when no assembly exists in the document.""" + + def __init__(self): + self.commands = ["Assembly_CreateAssembly"] + self.title = translate("Assembly", "Create") + + def shouldShow(self): + doc = FreeCAD.ActiveDocument + + if hasattr(doc, "RootObjects"): + for obj in doc.RootObjects: + if obj.isDerivedFrom("Assembly::AssemblyObject"): + return False + return True + + class AssemblyActivateWatcher: + """Shows 'Activate Assembly' when an assembly exists but is not active.""" + + def __init__(self): + self.commands = ["Assembly_ActivateAssembly"] + self.title = translate("Assembly", "Activate") + + def shouldShow(self): + doc = FreeCAD.ActiveDocument + + has_assembly = False + if hasattr(doc, "RootObjects"): + for obj in doc.RootObjects: + if obj.isDerivedFrom("Assembly::AssemblyObject"): + has_assembly = True + break + + assembly = UtilsAssembly.activeAssembly() + + return has_assembly and (assembly is None or assembly.Document != doc) + + class AssemblyBaseWatcher: + """Base class for watchers that require an active assembly.""" + + def __init__(self): + self.assembly = None + + def shouldShow(self): + doc = FreeCAD.ActiveDocument + + self.assembly = UtilsAssembly.activeAssembly() + return self.assembly is not None and self.assembly.Document == doc + + class AssemblyInsertWatcher(AssemblyBaseWatcher): + """Shows 'Insert Component' when an assembly is active.""" + + def __init__(self): + super().__init__() + self.commands = ["Assembly_Insert"] + self.title = translate("Assembly", "Insert") + + def shouldShow(self): + return super().shouldShow() + + class AssemblyGroundWatcher(AssemblyBaseWatcher): + """Shows 'Ground' when the active assembly has no grounded parts.""" + + def __init__(self): + super().__init__() + self.commands = ["Assembly_ToggleGrounded"] + self.title = translate("Assembly", "Grounding") + + def shouldShow(self): + if not super().shouldShow(): + return False + return ( + UtilsAssembly.assembly_has_at_least_n_parts(1) + and not UtilsAssembly.isAssemblyGrounded() + ) + + class AssemblyJointsWatcher(AssemblyBaseWatcher): + """Shows Joint, View, and BOM tools when there are enough parts.""" + + def __init__(self): + super().__init__() + self.commands = [ + "Assembly_CreateJointFixed", + "Assembly_CreateJointRevolute", + "Assembly_CreateJointCylindrical", + "Assembly_CreateJointSlider", + "Assembly_CreateJointBall", + "Separator", + "Assembly_CreateJointDistance", + "Assembly_CreateJointParallel", + "Assembly_CreateJointPerpendicular", + "Assembly_CreateJointAngle", + ] + self.title = translate("Assembly", "Constraints") + + def shouldShow(self): + if not super().shouldShow(): + return False + return UtilsAssembly.assembly_has_at_least_n_parts(2) + + class AssemblyToolsWatcher(AssemblyBaseWatcher): + """Shows Joint, View, and BOM tools when there are enough parts.""" + + def __init__(self): + super().__init__() + self.commands = [ + "Assembly_CreateView", + "Assembly_CreateBom", + ] + self.title = translate("Assembly", "Tools") + + def shouldShow(self): + if not super().shouldShow(): + return False + return UtilsAssembly.assembly_has_at_least_n_parts(1) + + class AssemblySimulationWatcher(AssemblyBaseWatcher): + """Shows 'Create Simulation' when specific motional joints exist.""" + + def __init__(self): + super().__init__() + self.commands = ["Assembly_CreateSimulation"] + self.title = translate("Assembly", "Simulation") + + def shouldShow(self): + if not super().shouldShow(): + return False + + joint_types = ["Revolute", "Slider", "Cylindrical"] + joints = UtilsAssembly.getJointsOfType(self.assembly, joint_types) + return len(joints) > 0 + + watchers = [ + AssemblyCreateWatcher(), + AssemblyActivateWatcher(), + AssemblyInsertWatcher(), + AssemblyGroundWatcher(), + AssemblyJointsWatcher(), + AssemblyToolsWatcher(), + AssemblySimulationWatcher(), + ] + FreeCADGui.Control.addTaskWatcher(watchers) + Gui.addWorkbench(AssemblyWorkbench())