Skip to content

Commit

Permalink
Draft: separate target into object and subelements in make_label
Browse files Browse the repository at this point in the history
Before, the `make_label` function had a `target` parameter
that had to be a `LinkSub`, `[Part::Feature, "Edge1"]`.
However, it is easier to pass the individual components
separately using two parameters, `target_object` and `subelements`,
which can then be assembled into `[target_object, subelements]`.

The second element is optional, so it can be set to `None`,
and then the second element will be converted to an empty list,
`[target_object, []]`, as required by the Label's underlying `Target`
property.
  • Loading branch information
vocx-fc authored and yorikvanhavre committed Jun 15, 2020
1 parent 466ae17 commit 8679bdb
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 36 deletions.
13 changes: 6 additions & 7 deletions src/Mod/Draft/draftguitools/gui_labels.py
Expand Up @@ -133,16 +133,14 @@ def create(self):
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 += "("
Expand All @@ -156,7 +154,8 @@ def create(self):
_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 + "'" + ", "
Expand Down
132 changes: 103 additions & 29 deletions src/Mod/Draft/draftmake/make_label.py
Expand Up @@ -42,7 +42,7 @@

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):
Expand All @@ -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'`.
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`.
The target may not need a subelement, in which case the second
element of the list may be empty.
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.
::
target = [Part::Feature, ]
make_label(..., target_object=App.ActiveDocument.Box)
make_label(..., target_object="My box", subelements="Face3")
This `LinkSubList` can be obtained from the `Gui::Selection`
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'`.
Expand Down Expand Up @@ -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:
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

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:
utils.type_check([(target, (tuple, list))],
# 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 LinkSubList of two elements. "
"For example, [object, 'Edge1']"))
_err(_tr("Wrong input: must be a list or tuple of strings. "
"Or a single string."))
return None

target = list(target)
if len(target) == 1:
target.append([])
# 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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

0 comments on commit 8679bdb

Please sign in to comment.