diff --git a/src/Mod/Draft/draftguitools/gui_labels.py b/src/Mod/Draft/draftguitools/gui_labels.py index cda89d2692..682e04ba7a 100644 --- a/src/Mod/Draft/draftguitools/gui_labels.py +++ b/src/Mod/Draft/draftguitools/gui_labels.py @@ -133,16 +133,14 @@ class Label(gui_base_original.Creator): dist = -dist tp = DraftVecUtils.toString(targetpoint) - sel = "" + sel = None if self.sel: + sel = "FreeCAD.ActiveDocument." + self.sel.Object.Name + if self.sel.SubElementNames: sub = "'" + self.sel.SubElementNames[0] + "'" else: - sub = "[]" - sel = "[" - sel += "FreeCAD.ActiveDocument." + self.sel.Object.Name + ", " - sel += sub - sel += "]" + sub = "None" pl = "FreeCAD.Placement" pl += "(" @@ -156,7 +154,8 @@ class Label(gui_base_original.Creator): _cmd += "target_point=" + tp + ", " _cmd += "placement=" + pl + ", " if sel: - _cmd += "target=" + sel + ", " + _cmd += "target_object=" + sel + ", " + _cmd += "subelements=" + sub + ", " _cmd += "label_type=" + "'" + self.labeltype + "'" + ", " # _cmd += "custom_text=" + "'Label'" + ", " _cmd += "direction=" + "'" + direction + "'" + ", " diff --git a/src/Mod/Draft/draftmake/make_label.py b/src/Mod/Draft/draftmake/make_label.py index a9b7fadb6b..d82f8b86f9 100644 --- a/src/Mod/Draft/draftmake/make_label.py +++ b/src/Mod/Draft/draftmake/make_label.py @@ -42,7 +42,7 @@ if App.GuiUp: def make_label(target_point=App.Vector(0, 0, 0), placement=App.Vector(30, 30, 0), - target=None, + target_object=None, subelements=None, label_type="Custom", custom_text="Label", direction="Horizontal", distance=-10, points=None): @@ -65,30 +65,40 @@ def make_label(target_point=App.Vector(0, 0, 0), The input could be a full placement, just a vector indicating the translation, or just a rotation. - target: list, optional + target_object: Part::Feature or str, optional It defaults to `None`. - The list should be a `LinkSubList`, that is, it should contain - two elements; the first element should be an object which will be used - to provide information to the label; the second element should be - a string indicating a subelement name, either `'VertexN'`, `'EdgeN'`, - or `'FaceN'` which exists within the first element. - In this case `'N'` is a number that starts with `1` - and goes up to the maximum number of vertices, edges, or faces. - :: - target = [Part::Feature, 'Edge1'] + If it exists it should be an object which will be used to provide + information to the label, as long as `label_type` is different + from `'Custom'`. - The target may not need a subelement, in which case the second - element of the list may be empty. - :: - target = [Part::Feature, ] + If it is a string, it must be the `Label` of that object. + Since a `Label` is not guaranteed to be unique in a document, + it will use the first object found with this `Label`. - This `LinkSubList` can be obtained from the `Gui::Selection` + subelements: str, optional + It defaults to `None`. + If `subelements` is provided, `target_object` should be provided + as well, otherwise it is ignored. + + It should be a string indicating a subelement name, either + `'VertexN'`, `'EdgeN'`, or `'FaceN'` which should exist + within `target_object`. + In this case `'N'` is an integer that indicates the specific number + of vertex, edge, or face in `target_object`. + + Both `target_object` and `subelements` are used to link the label + to a particular object, or to the particular vertex, edge, or face, + and get information from them. + :: + make_label(..., target_object=App.ActiveDocument.Box) + make_label(..., target_object="My box", subelements="Face3") + + These two parameters can be can be obtained from the `Gui::Selection` module. :: sel_object = Gui.Selection.getSelectionEx()[0] - object = sel_object.Object - subelement = sel_object.SubElementNames[0] - target = [object, subelement] + target_object = sel_object.Object + subelements = sel_object.SubElementNames[0] label_type: str, optional It defaults to `'Custom'`. @@ -209,19 +219,48 @@ def make_label(target_point=App.Vector(0, 0, 0), elif isinstance(placement, App.Rotation): placement = App.Placement(App.Vector(), placement) - _msg("target: {}".format(target)) - if target: - try: - utils.type_check([(target, (tuple, list))], - name=_name) - except TypeError: - _err(_tr("Wrong input: must be a LinkSubList of two elements. " - "For example, [object, 'Edge1']")) + if isinstance(target_object, str): + target_object_str = target_object + + if target_object: + if isinstance(target_object, (list, tuple)): + _msg("target_object: {}".format(target_object)) + _err(_tr("Wrong input: object must not be a list.")) return None - target = list(target) - if len(target) == 1: - target.append([]) + found, target_object = utils.find_object(target_object, doc) + if not found: + _msg("target_object: {}".format(target_object_str)) + _err(_tr("Wrong input: object not in document.")) + return None + + _msg("target_object: {}".format(target_object.Label)) + + if target_object and subelements: + _msg("subelements: {}".format(subelements)) + try: + # Make a list + if isinstance(subelements, str): + subelements = [subelements] + + utils.type_check([(subelements, (list, tuple, str))], + name=_name) + except TypeError: + _err(_tr("Wrong input: must be a list or tuple of strings. " + "Or a single string.")) + return None + + # The subelements list is used to build a special list + # called a LinkSub, which includes the target_object + # and the subelements. + # Single: (target_object, "Edge1") + # Multiple: (target_object, ("Edge1", "Edge2")) + for sub in subelements: + _sub = target_object.getSubObject(sub) + if not _sub: + _err("subelement: {}".format(sub)) + _err(_tr("Wrong input: subelement not in object.")) + return None _msg("label_type: {}".format(label_type)) if not label_type: @@ -298,8 +337,11 @@ def make_label(target_point=App.Vector(0, 0, 0), new_obj.TargetPoint = target_point new_obj.Placement = placement - if target: - new_obj.Target = target + if target_object: + if subelements: + new_obj.Target = [target_object, subelements] + else: + new_obj.Target = [target_object, []] new_obj.LabelType = label_type new_obj.CustomText = custom_text @@ -328,9 +370,41 @@ def makeLabel(targetpoint=None, target=None, direction=None, """Create a Label. DEPRECATED. Use 'make_label'.""" utils.use_instead("make_label") + _name = "makeLabel" + subelements = None + + if target: + try: + utils.type_check([(target, (tuple, list))], + name=_name) + except TypeError: + _err(_tr("Wrong input: must be a list of two elements. " + "For example, [object, 'Edge1'].")) + return None + + # In the old function `target` is the original parameter, + # a list of two elements, the target object itself, and the subelement. + # If the list is a single element, it is expanded to two elements + # with the second being empty + # target = [object] + # target = [object, ] + # target = [object, []] + # target = (object, ) + # target = (object, ()) + + # Parentheses can be used as well except a single pair + # target = (object) + target = list(target) + if len(target) == 1: + target.append([]) + + target_object = target[0] + subelements = target[1] + return make_label(target_point=targetpoint, placement=placement, - target=target, + target_object=target_object, + subelements=subelements, label_type=labeltype, direction=direction, distance=distance)