Draft : fix Label Justification (#13444)

Draft Label ViewObject.Justification property was overriden by Object.StraightDistance property. The Justification in the 3D view was reset after recompute. This commit fixes the problem by setting Object.StraightDistance automatically when ViewObject.Justification is changed and vice versa. Also fixes the frame position when Justification is Center.
This commit is contained in:
alafr
2025-06-24 10:45:46 +02:00
committed by GitHub
parent 96b006a2dd
commit 27c786fef1
2 changed files with 99 additions and 74 deletions

View File

@@ -339,6 +339,9 @@ def make_label(target_point=App.Vector(0, 0, 0),
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)

View File

@@ -236,6 +236,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
def updateData(self, obj, prop):
"""Execute when a property from the Proxy class is changed."""
vobj = obj.ViewObject
if prop == "Points":
n_points = len(obj.Points)
if n_points >= 2:
@@ -246,12 +247,23 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
range(n_points))
self.onChanged(obj.ViewObject, "ArrowType")
if obj.StraightDistance > 0:
self.text_wld.justification = coin.SoAsciiText.RIGHT
self.text_scr.justification = coin.SoText2.RIGHT
else:
self.text_wld.justification = coin.SoAsciiText.LEFT
self.text_scr.justification = coin.SoText2.LEFT
# When initially called (on doc open) properties of vobj are not yet available.
# This function is however triggered again from update_label.
if getattr(vobj, "Justification", "") == "Center" and obj.StraightDistance != 0.0 and obj.StraightDirection != "Custom":
if obj.StraightDirection != "Vertical":
obj.StraightDirection = "Vertical"
if not hasattr(vobj, "TextAlignment"):
pass
elif obj.StraightDistance > 0.0 and vobj.TextAlignment != "Top":
vobj.TextAlignment = "Top"
elif obj.StraightDistance < 0.0 and vobj.TextAlignment != "Bottom":
vobj.TextAlignment = "Bottom"
elif obj.StraightDistance > 0.0 and obj.StraightDirection == "Horizontal":
if vobj.Justification == "Left":
vobj.Justification = "Right"
elif obj.StraightDistance < 0.0 and obj.StraightDirection == "Horizontal":
if vobj.Justification == "Right":
vobj.Justification = "Left"
self.onChanged(obj.ViewObject, "DisplayMode") # Property to trigger update_label and update_frame.
# We could have used a different property.
@@ -274,15 +286,22 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
properties = vobj.PropertiesList
can_update_label = ("DisplayMode" in properties
and "FontName" in properties
and "FontSize" in properties
and "Justification" in properties
and "LineSpacing" in properties
and "ScaleMultiplier" in properties
and "TextAlignment" in properties # Top, Middle or Bottom.
and "FontName" in properties
and "FontSize" in properties)
and "TextAlignment" in properties) # Top, Middle or Bottom.
can_update_frame = (can_update_label
and "Frame" in properties)
if prop == "ScaleMultiplier" and "ScaleMultiplier" in properties:
if prop in ["DisplayMode", "FontName", "FontSize", "Justification", "LineSpacing", "TextAlignment", "Frame"]:
if can_update_label:
self.update_label(obj, vobj)
if can_update_frame:
self.update_frame(obj, vobj)
elif prop == "ScaleMultiplier" and "ScaleMultiplier" in properties:
if "ArrowSize" in properties:
s = vobj.ArrowSize.Value * vobj.ScaleMultiplier
if s:
@@ -292,40 +311,6 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
if can_update_frame:
self.update_frame(obj, vobj)
elif prop == "LineColor" and "LineColor" in properties:
col = vobj.LineColor
self.matline.diffuseColor.setValue([col[0], col[1], col[2]])
elif prop == "TextColor" and "TextColor" in properties:
col = vobj.TextColor
self.mattext.diffuseColor.setValue([col[0], col[1], col[2]])
elif prop == "LineWidth" and "LineWidth" in properties:
self.drawstyle.lineWidth = vobj.LineWidth
elif prop == "FontName" and "FontName" in properties:
self.font.name = vobj.FontName.encode("utf8")
if can_update_label:
self.update_label(obj, vobj)
if can_update_frame:
self.update_frame(obj, vobj)
elif prop in ["DisplayMode", "Frame", "TextAlignment", "FontSize"]:
if can_update_label:
self.update_label(obj, vobj)
if can_update_frame:
self.update_frame(obj, vobj)
elif prop == "Line" and "Line" in properties:
if vobj.Line:
self.lineswitch.whichChild = 0
else:
self.lineswitch.whichChild = -1
elif prop == "ArrowType" and "ArrowType" in properties:
if len(obj.Points) > 1:
self.update_arrow(obj, vobj)
elif (prop == "ArrowSize"
and "ArrowSize" in properties
and "ScaleMultiplier" in properties):
@@ -333,24 +318,26 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
if s:
self.arrowpos.scaleFactor.setValue((s, s, s))
elif prop == "Justification" and "Justification" in properties:
if vobj.Justification == "Left":
self.text_wld.justification = coin.SoAsciiText.LEFT
self.text_scr.justification = coin.SoText2.LEFT
elif vobj.Justification == "Right":
self.text_wld.justification = coin.SoAsciiText.RIGHT
self.text_scr.justification = coin.SoText2.RIGHT
else:
self.text_wld.justification = coin.SoAsciiText.CENTER
self.text_scr.justification = coin.SoText2.CENTER
elif prop == "ArrowType" and "ArrowType" in properties:
if len(obj.Points) > 1:
self.update_arrow(obj, vobj)
elif prop == "LineSpacing" and "LineSpacing" in properties:
self.text_wld.spacing = max(1, vobj.LineSpacing)
self.text_scr.spacing = max(1, vobj.LineSpacing)
if can_update_label:
self.update_label(obj, vobj)
if can_update_frame:
self.update_frame(obj, vobj)
elif prop == "Line" and "Line" in properties:
if vobj.Line:
self.lineswitch.whichChild = 0
else:
self.lineswitch.whichChild = -1
elif prop == "LineWidth" and "LineWidth" in properties:
self.drawstyle.lineWidth = vobj.LineWidth
elif prop == "LineColor" and "LineColor" in properties:
col = vobj.LineColor
self.matline.diffuseColor.setValue([col[0], col[1], col[2]])
elif prop == "TextColor" and "TextColor" in properties:
col = vobj.TextColor
self.mattext.diffuseColor.setValue([col[0], col[1], col[2]])
def get_text_size(self, vobj):
"""Return the bounding box of the text element."""
@@ -368,15 +355,45 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
def update_label(self, obj, vobj):
"""Update the label including text size and multiplier."""
size = vobj.FontSize.Value * vobj.ScaleMultiplier
line_spacing = max(1, vobj.LineSpacing)
self.font.size = size
self.text_wld.spacing = line_spacing
self.text_scr.spacing = line_spacing
self.font.name = vobj.FontName.encode("utf8")
if vobj.Justification == "Left":
self.text_wld.justification = coin.SoAsciiText.LEFT
self.text_scr.justification = coin.SoText2.LEFT
if obj.StraightDistance > 0.0 and obj.StraightDirection == "Horizontal":
obj.StraightDistance = -obj.StraightDistance
obj.recompute()
obj.purgeTouched()
elif vobj.Justification == "Right":
self.text_wld.justification = coin.SoAsciiText.RIGHT
self.text_scr.justification = coin.SoText2.RIGHT
if obj.StraightDistance < 0.0 and obj.StraightDirection == "Horizontal":
obj.StraightDistance = -obj.StraightDistance
obj.recompute()
obj.purgeTouched()
else:
self.text_wld.justification = coin.SoAsciiText.CENTER
self.text_scr.justification = coin.SoText2.CENTER
if obj.StraightDistance != 0.0 and obj.StraightDirection != "Custom":
if obj.StraightDirection != "Vertical":
obj.StraightDirection = "Vertical"
if (obj.StraightDistance < 0.0 and vobj.TextAlignment == "Top") \
or (obj.StraightDistance > 0.0 and vobj.TextAlignment == "Bottom"):
obj.StraightDistance = -obj.StraightDistance
obj.recompute()
obj.purgeTouched()
if vobj.DisplayMode == "Screen":
self.textpos.translation.setValue(obj.Placement.Base)
return
line_height = size * max(1, vobj.LineSpacing)
if vobj.Frame == "None":
margin = size * 0.1
line_height = size * line_spacing
if vobj.Frame == "None" and vobj.Justification != "Center":
margin = line_height * 0.1
first_line_height = size
# We need to calculate total_height without using get_text_size:
# If StraightDirection = "Horizontal" and TextAlignment = "Bottom"
@@ -390,9 +407,12 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
total_height = box[1] + (2 * margin)
# Space between endpoint of line and text:
v = App.Vector(margin, 0, 0)
if obj.StraightDistance > 0:
v = v.negative()
if vobj.Justification == "Left":
v = App.Vector(margin, 0, 0)
elif vobj.Justification == "Right":
v = App.Vector(-margin, 0, 0)
else:
v = App.Vector(0, 0, 0)
if vobj.TextAlignment == "Top":
v = v + App.Vector(0, -first_line_height, 0)
@@ -455,10 +475,12 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
total_height = box[1] + (2 * margin)
# Space between frame and text:
v = App.Vector(-margin, 0, 0)
if obj.StraightDistance > 0:
v = v.negative()
total_width = -total_width
if vobj.Justification == "Left":
first_frame_point = App.Vector(-margin, first_line_height, 0)
elif vobj.Justification == "Right":
first_frame_point = App.Vector(margin - total_width, first_line_height, 0)
else:
first_frame_point = App.Vector(-total_width / 2, first_line_height, 0)
# Shape of the rectangle
# (p5)p1 --------- p2
@@ -468,11 +490,11 @@ class ViewProviderLabel(ViewProviderDraftAnnotation):
# p4 --------- p3
#
pts = []
pts.append(v + App.Vector(0, first_line_height, 0))
pts.append(pts[-1] + App.Vector(total_width, 0, 0))
pts.append(first_frame_point)
pts.append(first_frame_point + App.Vector(total_width, 0, 0))
pts.append(pts[-1] + App.Vector(0, -total_height, 0))
pts.append(pts[-1] + App.Vector(-total_width, 0, 0))
pts.append(pts[0])
pts.append(first_frame_point)
self.fcoords.point.setValues(pts)
self.frame.coordIndex.setValues(0,