From 27c786fef10cae96fc8f6e51ac617abd59ae8d45 Mon Sep 17 00:00:00 2001 From: alafr Date: Tue, 24 Jun 2025 10:45:46 +0200 Subject: [PATCH] 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. --- src/Mod/Draft/draftmake/make_label.py | 3 + .../Draft/draftviewproviders/view_label.py | 170 ++++++++++-------- 2 files changed, 99 insertions(+), 74 deletions(-) diff --git a/src/Mod/Draft/draftmake/make_label.py b/src/Mod/Draft/draftmake/make_label.py index 51c58e72b0..e8c9381e06 100644 --- a/src/Mod/Draft/draftmake/make_label.py +++ b/src/Mod/Draft/draftmake/make_label.py @@ -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) diff --git a/src/Mod/Draft/draftviewproviders/view_label.py b/src/Mod/Draft/draftviewproviders/view_label.py index a93bd97f18..c701321737 100644 --- a/src/Mod/Draft/draftviewproviders/view_label.py +++ b/src/Mod/Draft/draftviewproviders/view_label.py @@ -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,