Download src/Mod/Draft/draftmake/make_label.py from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 15.7 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/draftmake/make_label.py
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Draft/draftmake/make_label.py
-
curl -L -o make_label.py https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/draftmake/make_label.py
15.7 kB
| # SPDX-License-Identifier: LGPL-2.1-or-later | |
| # *************************************************************************** | |
| # * Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> * | |
| # * Copyright (c) 2009, 2010 Ken Cline <cline@frii.com> * | |
| # * Copyright (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> * | |
| # * * | |
| # * This file is part of the FreeCAD CAx development system. * | |
| # * * | |
| # * This program is free software; you can redistribute it and/or modify * | |
| # * it under the terms of the GNU Lesser General Public License (LGPL) * | |
| # * as published by the Free Software Foundation; either version 2 of * | |
| # * the License, or (at your option) any later version. * | |
| # * for detail see the LICENCE text file. * | |
| # * * | |
| # * FreeCAD is distributed in the hope that it will be useful, * | |
| # * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| # * GNU Library General Public License for more details. * | |
| # * * | |
| # * You should have received a copy of the GNU Library General Public * | |
| # * License along with FreeCAD; if not, write to the Free Software * | |
| # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | |
| # * USA * | |
| # * * | |
| # *************************************************************************** | |
| """Provides functions to create Label objects.""" | |
| ## @package make_label | |
| # \ingroup draftmake | |
| # \brief Provides functions to create Label objects. | |
| ## \addtogroup draftmake | |
| # @{ | |
| import FreeCAD as App | |
| from draftobjects import label | |
| from draftutils import gui_utils | |
| from draftutils import params | |
| from draftutils import utils | |
| from draftutils.messages import _wrn, _err | |
| from draftutils.translate import translate | |
| if App.GuiUp: | |
| from draftviewproviders.view_label import ViewProviderLabel | |
| def make_label( | |
| target_point=App.Vector(0, 0, 0), | |
| placement=App.Vector(30, 30, 0), | |
| target_object=None, | |
| subelements=None, | |
| label_type="Custom", | |
| custom_text="Label", | |
| direction="Horizontal", | |
| distance=-10, | |
| points=None, | |
| ): | |
| """Create a Label object containing different types of information. | |
| The current color and text height and font specified in preferences | |
| are used. | |
| Parameters | |
| ---------- | |
| target_point: Base::Vector3, optional | |
| It defaults to the origin `App.Vector(0, 0, 0)`. | |
| This is the point which is pointed to by the label's leader line. | |
| This point can be adorned with a marker like an arrow or circle. | |
| placement: Base::Placement, Base::Vector3, or Base::Rotation, optional | |
| It defaults to `App.Vector(30, 30, 0)`. | |
| If it is provided, it defines the base point of the textual | |
| label. | |
| The input could be a full placement, just a vector indicating | |
| the translation, or just a rotation. | |
| target_object: Part::Feature or str, optional | |
| It defaults to `None`. | |
| 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'`. | |
| 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`. | |
| 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] | |
| target_object = sel_object.Object | |
| subelements = sel_object.SubElementNames[0] | |
| label_type: str, optional | |
| It defaults to `'Custom'`. | |
| It indicates the type of information that will be shown in the label. | |
| See the get_label_types function in label.py for supported types. | |
| Only `'Custom'` allows you to manually set the text | |
| by defining `custom_text`. The other types take their information | |
| from the object included in `target`. | |
| - `'Position'` will show the base position of the target object, | |
| or of the indicated `'VertexN'` in `target`. | |
| - `'Length'` will show the `Length` of the target object's `Shape`, | |
| or of the indicated `'EdgeN'` in `target`. | |
| - `'Area'` will show the `Area` of the target object's `Shape`, | |
| or of the indicated `'FaceN'` in `target`. | |
| custom_text: str, or list of str, optional | |
| It defaults to `'Label'`. | |
| If it is a list, each element in the list represents a new text line. | |
| It is the text that will be displayed by the label when | |
| `label_type` is `'Custom'`. | |
| direction: str, optional | |
| It defaults to `'Horizontal'`. | |
| It can be `'Horizontal'`, `'Vertical'`, or `'Custom'`. | |
| It indicates the direction of the straight segment of the leader line | |
| that ends up next to the textual label. | |
| If `'Custom'` is selected, the leader line can be manually drawn | |
| by specifying the value of `points`. | |
| Normally, the leader line has only three points, but with `'Custom'` | |
| you can specify as many points as needed. | |
| distance: int, float, Base::Quantity, optional | |
| It defaults to -10. | |
| It indicates the length of the horizontal or vertical segment | |
| of the leader line. | |
| The leader line is composed of two segments, the first segment is | |
| inclined, while the second segment is either horizontal or vertical | |
| depending on the value of `direction`. | |
| :: | |
| T | |
| | | |
| | | |
| o------- L text | |
| The `oL` segment's length is defined by `distance` | |
| while the `oT` segment is automatically calculated depending | |
| on the values of `placement` (L) and `distance` (o). | |
| This `distance` is oriented, meaning that if it is positive | |
| the segment will be to the right and above of the textual | |
| label, depending on if `direction` is `'Horizontal'` or `'Vertical'`, | |
| respectively. | |
| If it is negative, the segment will be to the left | |
| and below of the text. | |
| points: list of Base::Vector3, optional | |
| It defaults to `None`. | |
| It is a list of vectors defining the shape of the leader line; | |
| the list must have at least two points. | |
| This argument must be used together with `direction='Custom'` | |
| to display this custom leader. | |
| However, notice that if the Label's `StraightDirection` property | |
| is later changed to `'Horizontal'` or `'Vertical'`, | |
| the custom point list will be overwritten with a new, | |
| automatically calculated three-point list. | |
| For the object to use custom points, `StraightDirection` | |
| must remain `'Custom'`, and then the `Points` property | |
| can be overwritten by a suitable list of points. | |
| Returns | |
| ------- | |
| App::FeaturePython | |
| A scripted object of type `'Label'`. | |
| This object does not have a `Shape` attribute, as the text and lines | |
| are created on screen by Coin (pivy). | |
| None | |
| If there is a problem it will return `None`. | |
| """ | |
| _name = "make_label" | |
| found, doc = utils.find_doc(App.activeDocument()) | |
| if not found: | |
| _err(translate("draft", "No active document. Aborting.")) | |
| return None | |
| if not target_point: | |
| target_point = App.Vector(0, 0, 0) | |
| try: | |
| utils.type_check([(target_point, App.Vector)], name=_name) | |
| except TypeError: | |
| _err(translate("draft", "Wrong input: must be a vector.")) | |
| return None | |
| if not placement: | |
| placement = App.Placement() | |
| try: | |
| utils.type_check([(placement, (App.Placement, App.Vector, App.Rotation))], name=_name) | |
| except TypeError: | |
| _err(translate("draft", "Wrong input: must be a placement, a vector, or a rotation.")) | |
| return None | |
| # Convert the vector or rotation to a full placement | |
| if isinstance(placement, App.Vector): | |
| placement = App.Placement(placement, App.Rotation()) | |
| elif isinstance(placement, App.Rotation): | |
| placement = App.Placement(App.Vector(), placement) | |
| if target_object: | |
| if isinstance(target_object, (list, tuple)): | |
| _err(translate("draft", "Wrong input: target_object must not be a list.")) | |
| return None | |
| found, target_object = utils.find_object(target_object, doc) | |
| if not found: | |
| _err(translate("draft", "Wrong input: target_object not in document.")) | |
| return None | |
| if target_object and subelements: | |
| try: | |
| # Make a list | |
| if isinstance(subelements, str): | |
| subelements = [subelements] | |
| utils.type_check([(subelements, (list, tuple, str))], name=_name) | |
| except TypeError: | |
| _err( | |
| translate( | |
| "draft", | |
| "Wrong input: subelements 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(translate("draft", "Wrong input: subelement {} not in object.").format(sub)) | |
| return None | |
| if not label_type: | |
| label_type = "Custom" | |
| try: | |
| utils.type_check([(label_type, str)], name=_name) | |
| except TypeError: | |
| _err(translate("draft", "Wrong input: label_type must be a string.")) | |
| return None | |
| types = label.get_label_types() | |
| if label_type not in types: | |
| _err( | |
| translate("draft", "Wrong input: label_type must be one of the following:") | |
| + " " | |
| + str(types).strip("[]") | |
| ) | |
| return None | |
| if not custom_text: | |
| custom_text = "Label" | |
| try: | |
| utils.type_check([(custom_text, (str, list))], name=_name) | |
| except TypeError: | |
| _err(translate("draft", "Wrong input: must be a list of strings or a single string.")) | |
| return None | |
| if type(custom_text) is list and not all(isinstance(element, str) for element in custom_text): | |
| _err(translate("draft", "Wrong input: must be a list of strings or a single string.")) | |
| return None | |
| if not direction: | |
| direction = "Horizontal" | |
| try: | |
| utils.type_check([(direction, str)], name=_name) | |
| except TypeError: | |
| _err( | |
| translate( | |
| "draft", "Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'." | |
| ) | |
| ) | |
| return None | |
| if direction not in ("Horizontal", "Vertical", "Custom"): | |
| _err( | |
| translate( | |
| "draft", "Wrong input: must be a string, 'Horizontal', 'Vertical', or 'Custom'." | |
| ) | |
| ) | |
| return None | |
| if not distance: | |
| distance = 1 | |
| try: | |
| utils.type_check([(distance, (int, float))], name=_name) | |
| except TypeError: | |
| _err(translate("draft", "Wrong input: must be a number.")) | |
| return None | |
| if points: | |
| _err_msg = translate( | |
| "draft", "Wrong input: points {} must be a list of at least two vectors." | |
| ).format(points) | |
| try: | |
| utils.type_check([(points, (tuple, list))], name=_name) | |
| except TypeError: | |
| _err(_err_msg) | |
| return None | |
| if len(points) < 2: | |
| _err(_err_msg) | |
| return None | |
| if not all(isinstance(p, App.Vector) for p in points): | |
| _err(_err_msg) | |
| return None | |
| new_obj = doc.addObject("App::FeaturePython", "dLabel") | |
| label.Label(new_obj) | |
| new_obj.TargetPoint = target_point | |
| new_obj.Placement = placement | |
| 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 | |
| new_obj.StraightDirection = direction | |
| new_obj.StraightDistance = distance | |
| if points: | |
| if direction != "Custom": | |
| _wrn(translate("draft", "Direction is not 'Custom'; points won't be used.")) | |
| new_obj.Points = points | |
| if App.GuiUp: | |
| ViewProviderLabel(new_obj.ViewObject) | |
| h = params.get_param("textheight") | |
| new_obj.ViewObject.FontSize = h | |
| if direction == "Horizontal" and distance > 0: | |
| # StraightDistance and Justification must be in sync. | |
| new_obj.ViewObject.Justification = "Right" | |
| gui_utils.format_object(new_obj) | |
| gui_utils.select(new_obj) | |
| return new_obj | |
| def makeLabel( | |
| targetpoint=None, target=None, direction=None, distance=None, labeltype=None, placement=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( | |
| translate( | |
| "draft", | |
| "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_object=target_object, | |
| subelements=subelements, | |
| label_type=labeltype, | |
| direction=direction, | |
| distance=distance, | |
| ) | |
| ## @} | |