From 34f43a245cfbb95c53d266e6accd4f40b23d57c7 Mon Sep 17 00:00:00 2001 From: Roy-043 Date: Fri, 23 Dec 2022 16:49:56 +0100 Subject: [PATCH] Draft: Fix inconsistent properties of Draft annotations --- .../Resources/ui/preferences-drafttexts.ui | 4 +- src/Mod/Draft/draftfunctions/svg.py | 18 +- src/Mod/Draft/draftmake/make_label.py | 2 +- src/Mod/Draft/draftmake/make_text.py | 4 +- src/Mod/Draft/draftobjects/dimension.py | 55 +-- .../Draft/draftobjects/draft_annotation.py | 55 +-- src/Mod/Draft/draftobjects/label.py | 39 +- src/Mod/Draft/draftobjects/text.py | 9 +- .../draftviewproviders/view_dimension.py | 442 +++++++----------- .../view_draft_annotation.py | 60 ++- .../Draft/draftviewproviders/view_label.py | 231 ++++----- src/Mod/Draft/draftviewproviders/view_text.py | 125 ++--- 12 files changed, 427 insertions(+), 617 deletions(-) diff --git a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui index 8b443d71e2..4a2db228c6 100644 --- a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui +++ b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui @@ -141,12 +141,12 @@ such as "Arial:Bold" - text above (2D) + World - text inside (3D) + Screen diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py index 0accf643f6..efa4309c4e 100644 --- a/src/Mod/Draft/draftfunctions/svg.py +++ b/src/Mod/Draft/draftfunctions/svg.py @@ -227,7 +227,7 @@ def _svg_shape(svg, obj, plane, def _svg_dimension(obj, plane, scale, linewidth, fontsize, - stroke, pointratio, techdraw, rotation): + stroke, tstroke, pointratio, techdraw, rotation): """Return the SVG representation of a linear dimension.""" if not App.GuiUp: _wrn("'{}': SVG can only be generated " @@ -280,7 +280,7 @@ def _svg_dimension(obj, plane, scale, linewidth, fontsize, if not nolines: svg += ' math.pi/2: tangle = tangle-math.pi @@ -361,7 +361,7 @@ def _svg_dimension(obj, plane, scale, linewidth, fontsize, # drawing text svg += svgtext.get_text(plane, techdraw, - stroke, fontsize, vobj.FontName, + tstroke, fontsize, vobj.FontName, tangle, tbase, prx.string) return svg @@ -505,7 +505,7 @@ def get_svg(obj, elif utils.get_type(obj) in ["Dimension", "LinearDimension"]: svg = _svg_dimension(obj, plane, scale, linewidth, fontsize, - stroke, pointratio, techdraw, rotation) + stroke, tstroke, pointratio, techdraw, rotation) elif utils.get_type(obj) == "AngularDimension": if not App.GuiUp: @@ -518,7 +518,7 @@ def get_svg(obj, # drawing arc fill = "none" - if obj.ViewObject.DisplayMode == "2D": + if obj.ViewObject.DisplayMode == "World": svg += get_path(obj, plane, fill, pathdata, stroke, linewidth, lstyle, fill_opacity=None, @@ -573,7 +573,7 @@ def get_svg(obj, angle2) # drawing text - if obj.ViewObject.DisplayMode == "2D": + if obj.ViewObject.DisplayMode == "World": _diff = (prx.circle.LastParameter - prx.circle.FirstParameter) t = prx.circle.tangentAt(prx.circle.FirstParameter @@ -597,7 +597,7 @@ def get_svg(obj, tbase = get_proj(prx.tbase, plane) svg += svgtext.get_text(plane, techdraw, - stroke, fontsize, + tstroke, fontsize, obj.ViewObject.FontName, tangle, tbase, prx.string) @@ -637,13 +637,13 @@ def get_svg(obj, # print text if App.GuiUp: - fontname = obj.ViewObject.TextFont + fontname = obj.ViewObject.FontName position = get_proj(obj.Placement.Base, plane) rotation = obj.Placement.Rotation justification = obj.ViewObject.Justification text = obj.Text svg += svgtext.get_text(plane, techdraw, - stroke, fontsize, fontname, + tstroke, fontsize, fontname, rotation, position, text, linespacing, justification) diff --git a/src/Mod/Draft/draftmake/make_label.py b/src/Mod/Draft/draftmake/make_label.py index 0c6a9b89a4..07fb109c46 100644 --- a/src/Mod/Draft/draftmake/make_label.py +++ b/src/Mod/Draft/draftmake/make_label.py @@ -356,7 +356,7 @@ def make_label(target_point=App.Vector(0, 0, 0), if App.GuiUp: ViewProviderLabel(new_obj.ViewObject) h = utils.get_param("textheight", 0.20) - new_obj.ViewObject.TextSize = h + new_obj.ViewObject.FontSize = h gui_utils.format_object(new_obj) gui_utils.select(new_obj) diff --git a/src/Mod/Draft/draftmake/make_text.py b/src/Mod/Draft/draftmake/make_text.py index f116119270..690950f252 100644 --- a/src/Mod/Draft/draftmake/make_text.py +++ b/src/Mod/Draft/draftmake/make_text.py @@ -124,10 +124,10 @@ def make_text(string, placement=None, screen=False): h = utils.get_param("textheight", 2) - new_obj.ViewObject.DisplayMode = "3D text" + new_obj.ViewObject.DisplayMode = "World" if screen: _msg("screen: {}".format(screen)) - new_obj.ViewObject.DisplayMode = "2D text" + new_obj.ViewObject.DisplayMode = "Screen" h = h * 10 new_obj.ViewObject.FontSize = h diff --git a/src/Mod/Draft/draftobjects/dimension.py b/src/Mod/Draft/draftobjects/dimension.py index bc4bcbecdb..47e1ec9389 100644 --- a/src/Mod/Draft/draftobjects/dimension.py +++ b/src/Mod/Draft/draftobjects/dimension.py @@ -108,6 +108,9 @@ import DraftVecUtils import DraftGeomUtils import draftutils.utils as utils +from draftutils.messages import _wrn +from draftutils.translate import translate + from draftobjects.draft_annotation import DraftAnnotation @@ -122,7 +125,7 @@ class DimensionBase(DraftAnnotation): """ def __init__(self, obj, tp="Dimension"): - super(DimensionBase, self).__init__(obj, tp) + super().__init__(obj, tp) self.set_properties(obj) obj.Proxy = self @@ -195,11 +198,23 @@ class DimensionBase(DraftAnnotation): def onDocumentRestored(self, obj): """Execute code when the document is restored. - - It calls the parent class to add missing annotation properties. """ - super(DimensionBase, self).onDocumentRestored(obj) + super().onDocumentRestored(obj) + if not hasattr(obj, "ViewObject"): + return + vobj = obj.ViewObject + if not vobj: + return + if hasattr(vobj, "TextColor"): + return + + self.update_properties_0v21(obj, vobj) + + def update_properties_0v21(self, obj, vobj): + vobj.Proxy.set_text_properties(vobj, vobj.PropertiesList) + vobj.TextColor = vobj.LineColor + _wrn("v0.21, " + obj.Label + ", " + translate("draft", "added view property 'TextColor'")) class LinearDimension(DimensionBase): """The linear dimension object. @@ -212,13 +227,12 @@ class LinearDimension(DimensionBase): """ def __init__(self, obj): - super(LinearDimension, self).__init__(obj, "LinearDimension") - super(LinearDimension, self).set_properties(obj) - self.set_properties(obj) - obj.Proxy = self + super().__init__(obj, "LinearDimension") def set_properties(self, obj): """Set basic properties only if they don't exist.""" + super().set_properties(obj) + properties = obj.PropertiesList if "Start" not in properties: @@ -290,13 +304,6 @@ class LinearDimension(DimensionBase): _tip) obj.Diameter = False - def onDocumentRestored(self, obj): - """Execute code when the document is restored. - - It calls the parent class to add missing dimension properties. - """ - super(LinearDimension, self).onDocumentRestored(obj) - def onChanged(self, obj, prop): """Execute when a property is changed. @@ -486,17 +493,12 @@ class AngularDimension(DimensionBase): """ def __init__(self, obj): - super(AngularDimension, self).__init__(obj, "AngularDimension") - super(AngularDimension, self).set_properties(obj) - self.set_properties(obj) - obj.Proxy = self - - # Inherited properties from the parent class - obj.Normal = App.Vector(0, 0, 1) - obj.Dimline = App.Vector(0, 1, 0) + super().__init__(obj, "AngularDimension") def set_properties(self, obj): """Set basic properties only if they don't exist.""" + super().set_properties(obj) + properties = obj.PropertiesList if "FirstAngle" not in properties: @@ -550,13 +552,6 @@ class AngularDimension(DimensionBase): _tip) obj.Angle = 0 - def onDocumentRestored(self, obj): - """Execute code when the document is restored. - - It calls the parent class to add missing dimension properties. - """ - super(AngularDimension, self).onDocumentRestored(obj) - def execute(self, obj): """Execute when the object is created or recomputed. diff --git a/src/Mod/Draft/draftobjects/draft_annotation.py b/src/Mod/Draft/draftobjects/draft_annotation.py index 180e4dcceb..7b128b8540 100644 --- a/src/Mod/Draft/draftobjects/draft_annotation.py +++ b/src/Mod/Draft/draftobjects/draft_annotation.py @@ -65,44 +65,27 @@ class DraftAnnotation(object): Check if new properties are present after the object is restored in order to migrate older objects. """ - if hasattr(obj, "ViewObject") and obj.ViewObject: - vobj = obj.ViewObject - self.add_missing_properties_0v19(obj, vobj) + if not hasattr(obj, "ViewObject"): + return + vobj = obj.ViewObject + if not vobj: + return + if hasattr(vobj, "ScaleMultiplier") and hasattr(vobj, "AnnotationStyle"): + return + + self.add_missing_properties_0v19(obj, vobj) def add_missing_properties_0v19(self, obj, vobj): - """Provide missing annotation properties, if they don't exist.""" - vproperties = vobj.PropertiesList - - if 'ScaleMultiplier' not in vproperties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "General scaling factor that affects " - "the annotation consistently\n" - "because it scales the text, " - "and the line decorations, if any,\n" - "in the same proportion.") - vobj.addProperty("App::PropertyFloat", - "ScaleMultiplier", - "Annotation", - _tip) - vobj.ScaleMultiplier = 1.00 - - _wrn("v0.19, " + obj.Label + ", " + translate("draft","added view property 'ScaleMultiplier'")) - - if 'AnnotationStyle' not in vproperties: - _tip = QT_TRANSLATE_NOOP("App::Property","Annotation style to apply to this object.\nWhen using a saved style some of the view properties will become read-only;\nthey will only be editable by changing the style through the 'Annotation style editor' tool.") - vobj.addProperty("App::PropertyEnumeration", - "AnnotationStyle", - "Annotation", - _tip) - styles = [] - for key in obj.Document.Meta.keys(): - if key.startswith("Draft_Style_"): - styles.append(key[12:]) - - vobj.AnnotationStyle = [""] + styles - - _info = "added view property 'AnnotationStyle'" - _wrn("v0.19, " + obj.Label + ", " + translate("draft","added view property 'ScaleMultiplier'")) + """Provide missing annotation properties.""" + multiplier = None + if not hasattr(vobj, "ScaleMultiplier"): + multiplier = 1.00 + _wrn("v0.19, " + obj.Label + ", " + translate("draft", "added view property 'ScaleMultiplier'")) + if not hasattr(vobj, "AnnotationStyle"): + _wrn("v0.19, " + obj.Label + ", " + translate("draft", "added view property 'AnnotationStyle'")) + vobj.Proxy.set_annotation_properties(vobj, vobj.PropertiesList) + if multiplier is not None: + vobj.ScaleMultiplier = multiplier def __getstate__(self): """Return a tuple of objects to save or None. diff --git a/src/Mod/Draft/draftobjects/label.py b/src/Mod/Draft/draftobjects/label.py index 9ba06e3c53..774f497292 100644 --- a/src/Mod/Draft/draftobjects/label.py +++ b/src/Mod/Draft/draftobjects/label.py @@ -33,8 +33,11 @@ from PySide.QtCore import QT_TRANSLATE_NOOP import FreeCAD as App - from FreeCAD import Units as U + +from draftutils.messages import _wrn +from draftutils.translate import translate + from draftobjects.draft_annotation import DraftAnnotation @@ -42,7 +45,7 @@ class Label(DraftAnnotation): """The Draft Label object.""" def __init__(self, obj): - super(Label, self).__init__(obj, "Label") + super().__init__(obj, "Label") self.set_properties(obj) obj.Proxy = self @@ -221,14 +224,38 @@ class Label(DraftAnnotation): def onDocumentRestored(self, obj): """Execute code when the document is restored. - - It calls the parent class to add missing annotation properties. """ - super(Label, self).onDocumentRestored(obj) + super().onDocumentRestored(obj) + + if not hasattr(obj, "ViewObject"): + return + vobj = obj.ViewObject + if not vobj: + return + if hasattr(vobj, "FontName") and hasattr(vobj, "FontSize"): + return + + self.update_properties_0v21(obj, vobj) + + def update_properties_0v21(self, obj, vobj): + old_fontname = vobj.TextFont + old_fontsize = vobj.TextSize + vobj.removeProperty("TextFont") + vobj.removeProperty("TextSize") + + vobj.Proxy.set_text_properties(vobj, vobj.PropertiesList) + vobj.FontName = old_fontname + vobj.FontSize = old_fontsize + # The DisplayMode is updated automatically but the new values are + # switched: "2D text" becomes "World" and "3D text" becomes "Screen". + # It should be the other way around: + vobj.DisplayMode = "World" if vobj.DisplayMode == "Screen" else "Screen" + _wrn("v0.21, " + obj.Label + ", " + translate("draft", "updated view property 'TextFont' to 'FontName'")) + _wrn("v0.21, " + obj.Label + ", " + translate("draft", "updated view property 'TextSize' to 'FontSize'")) def onChanged(self, obj, prop): """Execute when a property is changed.""" - super(Label, self).onChanged(obj, prop) + super().onChanged(obj, prop) self.show_and_hide(obj, prop) def show_and_hide(self, obj, prop): diff --git a/src/Mod/Draft/draftobjects/text.py b/src/Mod/Draft/draftobjects/text.py index 2996c7c417..7e0a277d1f 100644 --- a/src/Mod/Draft/draftobjects/text.py +++ b/src/Mod/Draft/draftobjects/text.py @@ -39,7 +39,7 @@ class Text(DraftAnnotation): """The Draft Text object.""" def __init__(self, obj): - super(Text, self).__init__(obj, "Text") + super().__init__(obj, "Text") self.set_properties(obj) obj.Proxy = self @@ -69,13 +69,6 @@ class Text(DraftAnnotation): _tip) obj.Text = [] - def onDocumentRestored(self, obj): - """Execute code when the document is restored. - - It calls the parent class to add missing annotation properties. - """ - super(Text, self).onDocumentRestored(obj) - # Alias for compatibility with v0.18 and earlier DraftText = Text diff --git a/src/Mod/Draft/draftviewproviders/view_dimension.py b/src/Mod/Draft/draftviewproviders/view_dimension.py index f3bdca23c2..a47861626b 100644 --- a/src/Mod/Draft/draftviewproviders/view_dimension.py +++ b/src/Mod/Draft/draftviewproviders/view_dimension.py @@ -2,6 +2,7 @@ # * Copyright (c) 2009, 2010 Yorik van Havre * # * Copyright (c) 2009, 2010 Ken Cline * # * Copyright (c) 2020 Eliud Cabrera Castillo * +# * Copyright (c) 2022 FreeCAD Project Association * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -89,66 +90,34 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): --------------------- The scenegraph is set from two main nodes. :: - vobj.node.color - .drawstyle - .lineswitch1.coords - .line - .marks - .marksDimOvershoot - .marksExtOvershoot - .label.textpos - .color - .font - .text + vobj.node_wld.linecolor + .drawstyle + .lineswitch_wld.coords + .line + .marks + .marksDimOvershoot + .marksExtOvershoot + .label_wld.textpos + .textcolor + .font + .text_wld - vobj.node3d.color - .drawstyle - .lineswitch3.coords - .line - .marks - .marksDimOvershoot - .marksExtOvershoot - .label3d.textpos - .color - .font3d - .text3d + vobj.node_scr.linecolor + .drawstyle + .lineswitch_scr.coords + .line + .marks + .marksDimOvershoot + .marksExtOvershoot + .label_scr.textpos + .textcolor + .font + .text_scr """ - def __init__(self, vobj): - super(ViewProviderDimensionBase, self).__init__(vobj) - - self.set_properties(vobj) - self.Object = vobj.Object - vobj.Proxy = self - - def set_properties(self, vobj): - """Set the properties only if they don't already exist.""" - super(ViewProviderDimensionBase, self).set_properties(vobj) - - properties = vobj.PropertiesList - self.set_text_properties(vobj, properties) - self.set_units_properties(vobj, properties) - self.set_graphics_properties(vobj, properties) - def set_text_properties(self, vobj, properties): """Set text properties only if they don't already exist.""" - if "FontName" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Font name") - vobj.addProperty("App::PropertyFont", - "FontName", - "Text", - _tip) - vobj.FontName = utils.get_param("textfont", "") - - if "FontSize" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Font size") - vobj.addProperty("App::PropertyLength", - "FontSize", - "Text", - _tip) - vobj.FontSize = utils.get_param("textheight", 0.20) + super().set_text_properties(vobj, properties) if "TextSpacing" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", @@ -191,6 +160,8 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): def set_units_properties(self, vobj, properties): """Set unit properties only if they don't already exist.""" + super().set_units_properties(vobj, properties) + if "Decimals" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "The number of decimals to show") @@ -222,8 +193,7 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): def set_graphics_properties(self, vobj, properties): """Set graphics properties only if they don't already exist.""" - super(ViewProviderDimensionBase, - self).set_graphics_properties(vobj, properties) + super().set_graphics_properties(vobj, properties) if "ArrowSize" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", @@ -292,49 +262,14 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): _tip) vobj.ShowLine = True - def updateData(self, obj, prop): - """Execute when a property from the Proxy class is changed.""" - return - - def onChanged(self, vobj, prop): - """Execute when a view property is changed.""" - super(ViewProviderDimensionBase, self).onChanged(vobj, prop) - - def getDisplayModes(self, vobj): - """Return the display modes that this viewprovider supports.""" - return ["2D", "3D"] - def getDefaultDisplayMode(self): """Return the default display mode.""" - if hasattr(self, "defaultmode"): - return self.defaultmode - else: - return ["2D", "3D"][utils.get_param("dimstyle", 0)] - - def setDisplayMode(self, mode): - """Return the saved display mode.""" - return mode + return ["World", "Screen"][utils.get_param("dimstyle", 0)] def getIcon(self): """Return the path to the icon used by the viewprovider.""" return ":/icons/Draft_Dimension_Tree.svg" - def __getstate__(self): - """Return a tuple of objects to save or None. - - Save the display mode. - """ - return self.Object.ViewObject.DisplayMode - - def __setstate__(self, state): - """Set the internal properties from the restored state. - - Restore the display mode. - """ - if state: - self.defaultmode = state - self.setDisplayMode(state) - class ViewProviderLinearDimension(ViewProviderDimensionBase): """The viewprovider for the Linear Dimension objects. @@ -343,42 +278,34 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): of circular edges, and circumferences. """ - def __init__(self, vobj): - super(ViewProviderLinearDimension, self).__init__(vobj) - super(ViewProviderLinearDimension, self).set_properties(vobj) - - self.Object = vobj.Object - vobj.Proxy = self - def attach(self, vobj): """Set up the scene sub-graph of the viewprovider.""" self.Object = vobj.Object - self.color = coin.SoBaseColor() + self.textpos = coin.SoTransform() + self.textcolor = coin.SoBaseColor() self.font = coin.SoFont() - self.font3d = coin.SoFont() - self.text = coin.SoAsciiText() # Can be oriented in 3D space - self.text3d = coin.SoText2() # Faces the camera always + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. # The text string needs to be initialized to something, # otherwise it may cause a crash of the system - self.text.string = "d" - self.text3d.string = "d" - self.textpos = coin.SoTransform() - self.text.justification = coin.SoAsciiText.CENTER - self.text3d.justification = coin.SoAsciiText.CENTER + self.text_wld.string = "d" + self.text_scr.string = "d" + self.text_wld.justification = coin.SoAsciiText.CENTER + self.text_scr.justification = coin.SoAsciiText.CENTER - label = coin.SoSeparator() - label.addChild(self.textpos) - label.addChild(self.color) - label.addChild(self.font) - label.addChild(self.text) + label_wld = coin.SoSeparator() + label_wld.addChild(self.textpos) + label_wld.addChild(self.textcolor) + label_wld.addChild(self.font) + label_wld.addChild(self.text_wld) - label3d = coin.SoSeparator() - label3d.addChild(self.textpos) - label3d.addChild(self.color) - label3d.addChild(self.font3d) - label3d.addChild(self.text3d) + label_scr = coin.SoSeparator() + label_scr.addChild(self.textpos) + label_scr.addChild(self.textcolor) + label_scr.addChild(self.font) + label_scr.addChild(self.text_scr) self.coord1 = coin.SoCoordinate3() self.trans1 = coin.SoTransform() @@ -389,45 +316,47 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.transExtOvershoot1 = coin.SoTransform() self.transExtOvershoot2 = coin.SoTransform() + self.linecolor = coin.SoBaseColor() + self.drawstyle = coin.SoDrawStyle() + self.coords = coin.SoCoordinate3() + import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object). + self.line = coin.SoType.fromName("SoBrepEdgeSet").createInstance() self.marks = coin.SoSeparator() self.marksDimOvershoot = coin.SoSeparator() self.marksExtOvershoot = coin.SoSeparator() - self.drawstyle = coin.SoDrawStyle() - import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object). - self.line = coin.SoType.fromName("SoBrepEdgeSet").createInstance() - self.coords = coin.SoCoordinate3() - self.node = coin.SoGroup() - self.node.addChild(self.color) - self.node.addChild(self.drawstyle) - self.lineswitch2 = coin.SoSwitch() - self.lineswitch2.whichChild = -3 - self.node.addChild(self.lineswitch2) - self.lineswitch2.addChild(self.coords) - self.lineswitch2.addChild(self.line) - self.lineswitch2.addChild(self.marks) - self.lineswitch2.addChild(self.marksDimOvershoot) - self.lineswitch2.addChild(self.marksExtOvershoot) - self.node.addChild(label) + self.node_wld = coin.SoGroup() + self.node_wld.addChild(self.linecolor) + self.node_wld.addChild(self.drawstyle) + self.lineswitch_wld = coin.SoSwitch() + self.lineswitch_wld.whichChild = -3 + self.node_wld.addChild(self.lineswitch_wld) + self.lineswitch_wld.addChild(self.coords) + self.lineswitch_wld.addChild(self.line) + self.lineswitch_wld.addChild(self.marks) + self.lineswitch_wld.addChild(self.marksDimOvershoot) + self.lineswitch_wld.addChild(self.marksExtOvershoot) + self.node_wld.addChild(label_wld) - self.node3d = coin.SoGroup() - self.node3d.addChild(self.color) - self.node3d.addChild(self.drawstyle) - self.lineswitch3 = coin.SoSwitch() - self.lineswitch3.whichChild = -3 - self.node3d.addChild(self.lineswitch3) - self.lineswitch3.addChild(self.coords) - self.lineswitch3.addChild(self.line) - self.lineswitch3.addChild(self.marks) - self.lineswitch3.addChild(self.marksDimOvershoot) - self.lineswitch3.addChild(self.marksExtOvershoot) - self.node3d.addChild(label3d) + self.node_scr = coin.SoGroup() + self.node_scr.addChild(self.linecolor) + self.node_scr.addChild(self.drawstyle) + self.lineswitch_scr = coin.SoSwitch() + self.lineswitch_scr.whichChild = -3 + self.node_scr.addChild(self.lineswitch_scr) + self.lineswitch_scr.addChild(self.coords) + self.lineswitch_scr.addChild(self.line) + self.lineswitch_scr.addChild(self.marks) + self.lineswitch_scr.addChild(self.marksDimOvershoot) + self.lineswitch_scr.addChild(self.marksExtOvershoot) + self.node_scr.addChild(label_scr) - vobj.addDisplayMode(self.node, "2D") - vobj.addDisplayMode(self.node3d, "3D") + vobj.addDisplayMode(self.node_wld, "World") + vobj.addDisplayMode(self.node_scr, "Screen") self.updateData(vobj.Object, "Start") self.onChanged(vobj, "FontSize") self.onChanged(vobj, "FontName") + self.onChanged(vobj, "TextColor") self.onChanged(vobj, "ArrowType") self.onChanged(vobj, "LineColor") self.onChanged(vobj, "DimOvershoot") @@ -444,7 +373,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): if obj.Start == obj.End: return - if not hasattr(self, "node"): + if not hasattr(self, "node_wld"): return vobj = obj.ViewObject @@ -605,9 +534,9 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): try: m = vobj.DisplayMode except AssertionError: - m = ["2D", "3D"][utils.get_param("dimstyle", 0)] + m = ["World", "Screen"][utils.get_param("dimstyle", 0)] - if m == "3D": + if m == "Screen": offset = offset.negative() # The position of the text element in the dimension is provided @@ -658,11 +587,11 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): if hasattr(vobj, "Override") and vobj.Override: self.string = vobj.Override.replace("$dim", self.string) - self.text.string = utils.string_encode_coin(self.string) - self.text3d.string = utils.string_encode_coin(self.string) + self.text_wld.string = utils.string_encode_coin(self.string) + self.text_scr.string = utils.string_encode_coin(self.string) # Set the lines - if m == "3D": + if m == "Screen": # Calculate the spacing of the text textsize = len(self.string) * vobj.FontSize.Value / 4.0 spacing = (self.p3 - self.p2).Length/2.0 - textsize @@ -689,7 +618,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): def onChanged(self, vobj, prop): """Execute when a view property is changed.""" - super(ViewProviderLinearDimension, self).onChanged(vobj, prop) + super().onChanged(vobj, prop) obj = vobj.Object properties = vobj.PropertiesList @@ -698,10 +627,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): # Update all dimension values if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - if hasattr(self, "font3d"): - self.font3d.size = \ - vobj.FontSize.Value * 10 * vobj.ScaleMultiplier - if (hasattr(self, "node") and hasattr(self, "p2") + if (hasattr(self, "node_wld") and hasattr(self, "p2") and "ArrowSize" in properties): self.remove_dim_arrows() self.draw_dim_arrows(vobj) @@ -713,27 +639,25 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.draw_ext_overshoot(vobj) self.updateData(obj, "Start") - # obj.touch() elif (prop == "FontSize" and "FontSize" in properties and "ScaleMultiplier" in properties): if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - if hasattr(self, "font3d"): - self.font3d.size = \ - vobj.FontSize.Value * 10 * vobj.ScaleMultiplier - # obj.touch() elif (prop == "FontName" and "FontName" in properties - and hasattr(self, "font") and hasattr(self, "font3d")): + and hasattr(self, "font")): self.font.name = str(vobj.FontName) - self.font3d.name = str(vobj.FontName) - # obj.touch() + + elif (prop == "TextColor" and "TextColor" in properties + and hasattr(self, "textcolor")): + col = vobj.TextColor + self.textcolor.rgb.setValue(col[0], col[1], col[2]) elif (prop == "LineColor" and "LineColor" in properties - and hasattr(self, "color")): + and hasattr(self, "linecolor")): col = vobj.LineColor - self.color.rgb.setValue(col[0], col[1], col[2]) + self.linecolor.rgb.setValue(col[0], col[1], col[2]) elif (prop == "LineWidth" and "LineWidth" in properties and hasattr(self, "drawstyle")): @@ -742,32 +666,29 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): elif (prop in ("ArrowSize", "ArrowType") and "ArrowSize" in properties and "ScaleMultiplier" in properties - and hasattr(self, "node") and hasattr(self, "p2")): + and hasattr(self, "node_wld") and hasattr(self, "p2")): self.remove_dim_arrows() self.draw_dim_arrows(vobj) - # obj.touch() elif (prop == "DimOvershoot" and "DimOvershoot" in properties and "ScaleMultiplier" in properties): self.remove_dim_overshoot() self.draw_dim_overshoot(vobj) - # obj.touch() elif (prop == "ExtOvershoot" and "ExtOvershoot" in properties and "ScaleMultiplier" in properties): self.remove_ext_overshoot() self.draw_ext_overshoot(vobj) - # obj.touch() elif prop == "ShowLine" and "ShowLine" in properties: if vobj.ShowLine: - self.lineswitch2.whichChild = -3 - self.lineswitch3.whichChild = -3 + self.lineswitch_wld.whichChild = -3 + self.lineswitch_scr.whichChild = -3 else: - self.lineswitch2.whichChild = -1 - self.lineswitch3.whichChild = -1 + self.lineswitch_wld.whichChild = -1 + self.lineswitch_scr.whichChild = -1 else: self.updateData(obj, "Start") @@ -776,8 +697,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): Remove the existing nodes. """ - self.node.removeChild(self.marks) - self.node3d.removeChild(self.marks) + self.node_wld.removeChild(self.marks) + self.node_scr.removeChild(self.marks) def draw_dim_arrows(self, vobj): """Draw dimension arrows.""" @@ -797,7 +718,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): # Set new nodes self.marks = coin.SoSeparator() - self.marks.addChild(self.color) + self.marks.addChild(self.linecolor) s1 = coin.SoSeparator() if symbol == "Circle": @@ -817,13 +738,13 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): s2.addChild(gui_utils.dim_symbol(symbol, invert=inv)) self.marks.addChild(s2) - self.node.insertChild(self.marks, 2) - self.node3d.insertChild(self.marks, 2) + self.node_wld.insertChild(self.marks, 2) + self.node_scr.insertChild(self.marks, 2) def remove_dim_overshoot(self): """Remove the dimension overshoot lines.""" - self.node.removeChild(self.marksDimOvershoot) - self.node3d.removeChild(self.marksDimOvershoot) + self.node_wld.removeChild(self.marksDimOvershoot) + self.node_scr.removeChild(self.marksDimOvershoot) def draw_dim_overshoot(self, vobj): """Draw dimension overshoot lines.""" @@ -835,7 +756,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): # Remove existing nodes, and set new nodes self.marksDimOvershoot = coin.SoSeparator() if vobj.DimOvershoot.Value: - self.marksDimOvershoot.addChild(self.color) + self.marksDimOvershoot.addChild(self.linecolor) s1 = coin.SoSeparator() s1.addChild(self.transDimOvershoot1) @@ -847,13 +768,13 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): s2.addChild(gui_utils.dimDash((0, 0, 0), (1, 0, 0))) self.marksDimOvershoot.addChild(s2) - self.node.insertChild(self.marksDimOvershoot, 2) - self.node3d.insertChild(self.marksDimOvershoot, 2) + self.node_wld.insertChild(self.marksDimOvershoot, 2) + self.node_scr.insertChild(self.marksDimOvershoot, 2) def remove_ext_overshoot(self): """Remove dimension extension overshoot lines.""" - self.node.removeChild(self.marksExtOvershoot) - self.node3d.removeChild(self.marksExtOvershoot) + self.node_wld.removeChild(self.marksExtOvershoot) + self.node_scr.removeChild(self.marksExtOvershoot) def draw_ext_overshoot(self, vobj): """Draw dimension extension overshoot lines.""" @@ -865,7 +786,7 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): # Set new nodes self.marksExtOvershoot = coin.SoSeparator() if vobj.ExtOvershoot.Value: - self.marksExtOvershoot.addChild(self.color) + self.marksExtOvershoot.addChild(self.linecolor) s1 = coin.SoSeparator() s1.addChild(self.transExtOvershoot1) s1.addChild(gui_utils.dimDash((0, 0, 0), (-1, 0, 0))) @@ -876,8 +797,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): s2.addChild(gui_utils.dimDash((0, 0, 0), (-1, 0, 0))) self.marksExtOvershoot.addChild(s2) - self.node.insertChild(self.marksExtOvershoot, 2) - self.node3d.insertChild(self.marksExtOvershoot, 2) + self.node_wld.insertChild(self.marksExtOvershoot, 2) + self.node_scr.insertChild(self.marksExtOvershoot, 2) def is_linked_to_circle(self): """Return true if the dimension measures a circular edge.""" @@ -907,79 +828,69 @@ _ViewProviderDimension = ViewProviderLinearDimension class ViewProviderAngularDimension(ViewProviderDimensionBase): """Viewprovider for the Angular dimension object.""" - def __init__(self, vobj): - super(ViewProviderAngularDimension, self).__init__(vobj) - super(ViewProviderAngularDimension, self).set_properties(vobj) - - self.Object = vobj.Object - vobj.Proxy = self - def attach(self, vobj): """Set up the scene sub-graph of the viewprovider.""" self.Object = vobj.Object - self.color = coin.SoBaseColor() - if hasattr(vobj, "LineColor"): - self.color.rgb.setValue(vobj.LineColor[0], - vobj.LineColor[1], - vobj.LineColor[2]) - + self.textpos = coin.SoTransform() + self.textcolor = coin.SoBaseColor() self.font = coin.SoFont() - self.font3d = coin.SoFont() - self.text = coin.SoAsciiText() # Can be oriented in 3D space - self.text3d = coin.SoText2() # Faces the camera always + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. # The text string needs to be initialized to something, # otherwise it may cause a crash of the system - self.text.string = "d" - self.text3d.string = "d" - self.text.justification = coin.SoAsciiText.CENTER - self.text3d.justification = coin.SoAsciiText.CENTER - self.textpos = coin.SoTransform() + self.text_wld.string = "d" + self.text_scr.string = "d" + self.text_wld.justification = coin.SoAsciiText.CENTER + self.text_scr.justification = coin.SoAsciiText.CENTER - label = coin.SoSeparator() - label.addChild(self.textpos) - label.addChild(self.color) - label.addChild(self.font) - label.addChild(self.text) + label_wld = coin.SoSeparator() + label_wld.addChild(self.textpos) + label_wld.addChild(self.textcolor) + label_wld.addChild(self.font) + label_wld.addChild(self.text_wld) - label3d = coin.SoSeparator() - label3d.addChild(self.textpos) - label3d.addChild(self.color) - label3d.addChild(self.font3d) - label3d.addChild(self.text3d) + label_scr = coin.SoSeparator() + label_scr.addChild(self.textpos) + label_scr.addChild(self.textcolor) + label_scr.addChild(self.font) + label_scr.addChild(self.text_scr) self.coord1 = coin.SoCoordinate3() self.trans1 = coin.SoTransform() self.coord2 = coin.SoCoordinate3() self.trans2 = coin.SoTransform() - self.marks = coin.SoSeparator() + + self.linecolor = coin.SoBaseColor() self.drawstyle = coin.SoDrawStyle() self.coords = coin.SoCoordinate3() import PartGui # Required for "SoBrepEdgeSet" (because a dimension is not a Part::FeaturePython object). self.arc = coin.SoType.fromName("SoBrepEdgeSet").createInstance() + self.marks = coin.SoSeparator() - self.node = coin.SoGroup() - self.node.addChild(self.color) - self.node.addChild(self.drawstyle) - self.node.addChild(self.coords) - self.node.addChild(self.arc) - self.node.addChild(self.marks) - self.node.addChild(label) + self.node_wld = coin.SoGroup() + self.node_wld.addChild(self.linecolor) + self.node_wld.addChild(self.drawstyle) + self.node_wld.addChild(self.coords) + self.node_wld.addChild(self.arc) + self.node_wld.addChild(self.marks) + self.node_wld.addChild(label_wld) - self.node3d = coin.SoGroup() - self.node3d.addChild(self.color) - self.node3d.addChild(self.drawstyle) - self.node3d.addChild(self.coords) - self.node3d.addChild(self.arc) - self.node3d.addChild(self.marks) - self.node3d.addChild(label3d) + self.node_scr = coin.SoGroup() + self.node_scr.addChild(self.linecolor) + self.node_scr.addChild(self.drawstyle) + self.node_scr.addChild(self.coords) + self.node_scr.addChild(self.arc) + self.node_scr.addChild(self.marks) + self.node_scr.addChild(label_scr) - vobj.addDisplayMode(self.node, "2D") - vobj.addDisplayMode(self.node3d, "3D") + vobj.addDisplayMode(self.node_wld, "World") + vobj.addDisplayMode(self.node_scr, "Screen") self.updateData(vobj.Object, None) self.onChanged(vobj, "FontSize") self.onChanged(vobj, "FontName") + self.onChanged(vobj, "TextColor") self.onChanged(vobj, "ArrowType") self.onChanged(vobj, "LineColor") @@ -1030,8 +941,8 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): if vobj.Override: self.string = vobj.Override.replace("$dim", self.string) - self.text.string = utils.string_encode_coin(self.string) - self.text3d.string = utils.string_encode_coin(self.string) + self.text_wld.string = utils.string_encode_coin(self.string) + self.text_scr.string = utils.string_encode_coin(self.string) # On first run the `DisplayMode` enumeration is not set, so we trap # the exception and set the display mode using the value @@ -1039,13 +950,13 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): try: m = vobj.DisplayMode except AssertionError: - m = ["2D", "3D"][utils.get_param("dimstyle", 0)] + m = ["World", "Screen"][utils.get_param("dimstyle", 0)] # Set the arc first = self.circle.FirstParameter last = self.circle.LastParameter - if m == "3D": + if m == "Screen": # Calculate the spacing of the text spacing = len(self.string) * vobj.FontSize.Value / 8.0 pts1 = [] @@ -1161,7 +1072,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): else: offset = DraftVecUtils.scaleTo(offset, 0.05) - if m == "3D": + if m == "Screen": offset = offset.negative() self.tbase = self.tbase.add(offset) @@ -1179,7 +1090,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): def onChanged(self, vobj, prop): """Execute when a view property is changed.""" - super(ViewProviderAngularDimension, self).onChanged(vobj, prop) + super().onChanged(vobj, prop) obj = vobj.Object properties = vobj.PropertiesList @@ -1190,46 +1101,39 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): if prop == "ScaleMultiplier" and "ScaleMultiplier" in properties: if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - if hasattr(self, "font3d"): - self.font3d.size = \ - vobj.FontSize.Value * 10 * vobj.ScaleMultiplier - if (hasattr(self, "node") and hasattr(self, "p2") + if (hasattr(self, "node_wld") and hasattr(self, "p2") and "ArrowSize" in properties): self.remove_dim_arrows() self.draw_dim_arrows(vobj) self.updateData(obj, None) - # obj.touch() elif prop == "FontSize" and "ScaleMultiplier" in properties: if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier - if hasattr(self, "font3d"): - self.font3d.size = \ - vobj.FontSize.Value * 10 * vobj.ScaleMultiplier - # obj.touch() - elif (prop == "FontName" - and hasattr(self, "font") and hasattr(self, "font3d")): + elif (prop == "FontName" and hasattr(self, "font")): self.font.name = str(vobj.FontName) - self.font3d.name = str(vobj.FontName) - # obj.touch() + + elif (prop == "TextColor" and "TextColor" in properties + and hasattr(self, "textcolor")): + col = vobj.TextColor + self.textcolor.rgb.setValue(col[0], col[1], col[2]) elif (prop == "LineColor" and "LineColor" in properties - and hasattr(self, "color")): + and hasattr(self, "linecolor")): col = vobj.LineColor - self.color.rgb.setValue(col[0], col[1], col[2]) + self.linecolor.rgb.setValue(col[0], col[1], col[2]) elif prop == "LineWidth" and hasattr(self, "drawstyle"): self.drawstyle.lineWidth = vobj.LineWidth elif (prop in ("ArrowSize", "ArrowType") and "ScaleMultiplier" in properties - and hasattr(self, "node") and hasattr(self, "p2")): + and hasattr(self, "node_wld") and hasattr(self, "p2")): self.updateData(obj, None) self.remove_dim_arrows() self.draw_dim_arrows(vobj) - # obj.touch() else: self.updateData(obj, None) @@ -1239,8 +1143,8 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): Remove the existing nodes. """ - self.node.removeChild(self.marks) - self.node3d.removeChild(self.marks) + self.node_wld.removeChild(self.marks) + self.node_scr.removeChild(self.marks) def draw_dim_arrows(self, vobj): """Draw dimension arrows.""" @@ -1255,7 +1159,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): # Set new nodes self.marks = coin.SoSeparator() - self.marks.addChild(self.color) + self.marks.addChild(self.linecolor) s1 = coin.SoSeparator() if symbol == "Circle": @@ -1273,8 +1177,8 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): s2.addChild(gui_utils.dim_symbol(symbol, invert=True)) self.marks.addChild(s2) - self.node.insertChild(self.marks, 2) - self.node3d.insertChild(self.marks, 2) + self.node_wld.insertChild(self.marks, 2) + self.node_scr.insertChild(self.marks, 2) def getIcon(self): """Return the path to the icon used by the viewprovider.""" diff --git a/src/Mod/Draft/draftviewproviders/view_draft_annotation.py b/src/Mod/Draft/draftviewproviders/view_draft_annotation.py index 67be770c9a..c3442a3d26 100644 --- a/src/Mod/Draft/draftviewproviders/view_draft_annotation.py +++ b/src/Mod/Draft/draftviewproviders/view_draft_annotation.py @@ -1,6 +1,7 @@ # *************************************************************************** # * Copyright (c) 2020 Carlo Pavan * # * Copyright (c) 2020 Eliud Cabrera Castillo * +# * Copyright (c) 2022 FreeCAD Project Association * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -72,6 +73,8 @@ class ViewProviderDraftAnnotation(object): """Set the properties only if they don't already exist.""" properties = vobj.PropertiesList self.set_annotation_properties(vobj, properties) + self.set_text_properties(vobj, properties) + self.set_units_properties(vobj, properties) self.set_graphics_properties(vobj, properties) def set_annotation_properties(self, vobj, properties): @@ -112,6 +115,37 @@ class ViewProviderDraftAnnotation(object): vobj.AnnotationStyle = [""] + styles + def set_text_properties(self, vobj, properties): + """Set text properties only if they don't already exist.""" + if "FontName" not in properties: + _tip = QT_TRANSLATE_NOOP("App::Property", + "Font name") + vobj.addProperty("App::PropertyFont", + "FontName", + "Text", + _tip) + vobj.FontName = utils.get_param("textfont", "sans") + + if "FontSize" not in properties: + _tip = QT_TRANSLATE_NOOP("App::Property", + "Font size") + vobj.addProperty("App::PropertyLength", + "FontSize", + "Text", + _tip) + vobj.FontSize = utils.get_param("textheight", 1) + + if "TextColor" not in properties: + _tip = QT_TRANSLATE_NOOP("App::Property", + "Text color") + vobj.addProperty("App::PropertyColor", + "TextColor", + "Text", + _tip) + + def set_units_properties(self, vobj, properties): + return + def set_graphics_properties(self, vobj, properties): """Set graphics properties only if they don't already exist.""" if "LineWidth" not in properties: @@ -146,8 +180,11 @@ class ViewProviderDraftAnnotation(object): def getDisplayModes(self, vobj): """Return the display modes that this viewprovider supports.""" - modes = [] - return modes + return ["World", "Screen"] + + def getDefaultDisplayMode(self): + """Return the default display mode.""" + return "World" def setDisplayMode(self, mode): """Return the saved display mode.""" @@ -159,7 +196,7 @@ class ViewProviderDraftAnnotation(object): meta = vobj.Object.Document.Meta if prop == "AnnotationStyle" and "AnnotationStyle" in properties: - if not vobj.AnnotationStyle or vobj.AnnotationStyle == " ": + if not vobj.AnnotationStyle or vobj.AnnotationStyle == "": # unset style _msg(16 * "-") _msg("Unset style") @@ -251,21 +288,4 @@ class ViewProviderDraftAnnotation(object): """Return the path to the icon used by the view provider.""" return ":/icons/Draft_Text.svg" - def claimChildren(self): - """Return objects that will be placed under it in the tree view. - - Editor: perhaps this is not useful??? - """ - objs = [] - if hasattr(self.Object, "Base"): - objs.append(self.Object.Base) - if hasattr(self.Object, "Objects"): - objs.extend(self.Object.Objects) - if hasattr(self.Object, "Components"): - objs.extend(self.Object.Components) - if hasattr(self.Object, "Group"): - objs.extend(self.Object.Group) - - return objs - ## @} diff --git a/src/Mod/Draft/draftviewproviders/view_label.py b/src/Mod/Draft/draftviewproviders/view_label.py index f1fe5324f2..6d1279e8be 100644 --- a/src/Mod/Draft/draftviewproviders/view_label.py +++ b/src/Mod/Draft/draftviewproviders/view_label.py @@ -51,44 +51,13 @@ param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft") class ViewProviderLabel(ViewProviderDraftAnnotation): """Viewprovider for the Label annotation object.""" - def __init__(self, vobj): - super(ViewProviderLabel, self).__init__(vobj) - - self.set_properties(vobj) - self.Object = vobj.Object - vobj.Proxy = self - - def set_properties(self, vobj): - """Set the properties only if they don't already exist.""" - super(ViewProviderLabel, self).set_properties(vobj) - - properties = vobj.PropertiesList - self.set_text_properties(vobj, properties) - self.set_graphics_properties(vobj, properties) - def set_text_properties(self, vobj, properties): """Set text properties only if they don't already exist.""" - if "TextSize" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The size of the text") - vobj.addProperty("App::PropertyLength", - "TextSize", - "Text", - _tip) - vobj.TextSize = utils.get_param("textheight", 1) - - if "TextFont" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The font of the text") - vobj.addProperty("App::PropertyFont", - "TextFont", - "Text", - _tip) - vobj.TextFont = utils.get_param("textfont") + super().set_text_properties(vobj, properties) if "TextAlignment" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", - "The vertical alignment of the text") + "Vertical alignment") vobj.addProperty("App::PropertyEnumeration", "TextAlignment", "Text", @@ -96,17 +65,9 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): vobj.TextAlignment = ["Top", "Middle", "Bottom"] vobj.TextAlignment = "Bottom" - if "TextColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Text color") - vobj.addProperty("App::PropertyColor", - "TextColor", - "Text", - _tip) - if "MaxChars" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", - "The maximum number of characters " + "Maximum number of characters " "on each line of the text box") vobj.addProperty("App::PropertyInteger", "MaxChars", @@ -115,7 +76,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if "Justification" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", - "The vertical alignment of the text") + "Horizontal alignment") vobj.addProperty("App::PropertyEnumeration", "Justification", "Text", @@ -133,9 +94,11 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): def set_graphics_properties(self, vobj, properties): """Set graphics properties only if they don't already exist.""" + super().set_graphics_properties(vobj, properties) + if "ArrowSize" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", - "The size of the arrow") + "Arrow size") vobj.addProperty("App::PropertyLength", "ArrowSize", "Graphics", @@ -144,13 +107,13 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if "ArrowType" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", - "The type of arrow of this label") + "Arrow type") vobj.addProperty("App::PropertyEnumeration", "ArrowType", "Graphics", _tip) vobj.ArrowType = utils.ARROW_TYPES - vobj.ArrowType = utils.ARROW_TYPES[utils.get_param("dimsymbol")] + vobj.ArrowType = utils.ARROW_TYPES[utils.get_param("dimsymbol", 0)] if "Frame" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", @@ -171,33 +134,14 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): _tip) vobj.Line = True - if "LineWidth" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Line width") - vobj.addProperty("App::PropertyFloat", - "LineWidth", - "Graphics", - _tip) - vobj.LineWidth = utils.get_param("linewidth", 1) - - if "LineColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Line color") - vobj.addProperty("App::PropertyColor", - "LineColor", - "Graphics", - _tip) - def getIcon(self): """Return the path to the icon used by the viewprovider.""" return ":/icons/Draft_Label.svg" - def claimChildren(self): - """Return objects that will be placed under it in the tree view.""" - return [] - def attach(self, vobj): """Set up the scene sub-graph of the viewprovider.""" + self.Object = vobj.Object + # Attributes of the Coin scenegraph self.arrow = coin.SoSeparator() self.arrowpos = coin.SoTransform() @@ -215,8 +159,8 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.mattext = coin.SoMaterial() self.textpos = coin.SoTransform() self.font = coin.SoFont() - self.text2d = coin.SoText2() # Faces the camera always - self.text3d = coin.SoAsciiText() # Can be oriented in 3D space + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. self.fcoords = coin.SoCoordinate3() self.frame = coin.SoType.fromName("SoBrepEdgeSet").createInstance() @@ -229,9 +173,9 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): # The text string needs to be initialized to something, # otherwise it crashes - self.text2d.string = self.text3d.string = "Label" - self.text2d.justification = coin.SoText2.RIGHT - self.text3d.justification = coin.SoAsciiText.RIGHT + self.text_wld.string = self.text_scr.string = "Label" + self.text_wld.justification = coin.SoAsciiText.RIGHT + self.text_scr.justification = coin.SoText2.RIGHT self.font.name = utils.get_param("textfont") switchnode = coin.SoSeparator() @@ -239,64 +183,51 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.lineswitch.addChild(switchnode) self.lineswitch.whichChild = 0 - self.node2dtxt = coin.SoGroup() - self.node2dtxt.addChild(self.font) - self.node2dtxt.addChild(self.text2d) + self.node_wld_txt = coin.SoGroup() + self.node_wld_txt.addChild(self.font) + self.node_wld_txt.addChild(self.text_wld) - self.node2d = coin.SoGroup() - self.node2d.addChild(self.matline) - self.node2d.addChild(self.arrow) - self.node2d.addChild(self.drawstyle) - self.node2d.addChild(self.lcoords) - self.node2d.addChild(self.lineswitch) - self.node2d.addChild(self.mattext) - self.node2d.addChild(textdrawstyle) - self.node2d.addChild(self.textpos) - self.node2d.addChild(self.node2dtxt) - self.node2d.addChild(self.matline) - self.node2d.addChild(self.drawstyle) - self.node2d.addChild(self.fcoords) - self.node2d.addChild(self.frame) + self.node_wld = coin.SoGroup() + self.node_wld.addChild(self.matline) + self.node_wld.addChild(self.arrow) + self.node_wld.addChild(self.drawstyle) + self.node_wld.addChild(self.lcoords) + self.node_wld.addChild(self.lineswitch) + self.node_wld.addChild(self.mattext) + self.node_wld.addChild(textdrawstyle) + self.node_wld.addChild(self.textpos) + self.node_wld.addChild(self.node_wld_txt) + self.node_wld.addChild(self.matline) + self.node_wld.addChild(self.drawstyle) + self.node_wld.addChild(self.fcoords) + self.node_wld.addChild(self.frame) - self.node3dtxt = coin.SoGroup() - self.node3dtxt.addChild(self.font) - self.node3dtxt.addChild(self.text3d) + self.node_scr_txt = coin.SoGroup() + self.node_scr_txt.addChild(self.font) + self.node_scr_txt.addChild(self.text_scr) - self.node3d = coin.SoGroup() - self.node3d.addChild(self.matline) - self.node3d.addChild(self.arrow) - self.node3d.addChild(self.drawstyle) - self.node3d.addChild(self.lcoords) - self.node3d.addChild(self.lineswitch) - self.node3d.addChild(self.mattext) - self.node3d.addChild(textdrawstyle) - self.node3d.addChild(self.textpos) - self.node3d.addChild(self.node3dtxt) - self.node3d.addChild(self.matline) - self.node3d.addChild(self.drawstyle) - self.node3d.addChild(self.fcoords) - self.node3d.addChild(self.frame) + self.node_scr = coin.SoGroup() + self.node_scr.addChild(self.matline) + self.node_scr.addChild(self.arrow) + self.node_scr.addChild(self.drawstyle) + self.node_scr.addChild(self.lcoords) + self.node_scr.addChild(self.lineswitch) + self.node_scr.addChild(self.mattext) + self.node_scr.addChild(textdrawstyle) + self.node_scr.addChild(self.textpos) + self.node_scr.addChild(self.node_scr_txt) + self.node_scr.addChild(self.matline) + self.node_scr.addChild(self.drawstyle) + self.node_scr.addChild(self.fcoords) + self.node_scr.addChild(self.frame) - vobj.addDisplayMode(self.node2d, "2D text") - vobj.addDisplayMode(self.node3d, "3D text") + vobj.addDisplayMode(self.node_wld, "World") + vobj.addDisplayMode(self.node_scr, "Screen") self.onChanged(vobj, "LineColor") self.onChanged(vobj, "TextColor") self.onChanged(vobj, "LineWidth") self.onChanged(vobj, "ArrowSize") self.onChanged(vobj, "Line") - self.Object = vobj.Object - - def getDisplayModes(self, vobj): - """Return the display modes that this viewprovider supports.""" - return ["2D text", "3D text"] - - def getDefaultDisplayMode(self): - """Return the default display mode.""" - return "3D text" - - def getDisplayMode(self, mode): - """Return the saved display mode.""" - return mode def updateData(self, obj, prop): """Execute when a property from the Proxy class is changed.""" @@ -311,28 +242,28 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.onChanged(obj.ViewObject, "ArrowType") if obj.StraightDistance > 0: - self.text2d.justification = coin.SoText2.RIGHT - self.text3d.justification = coin.SoAsciiText.RIGHT + self.text_wld.justification = coin.SoAsciiText.RIGHT + self.text_scr.justification = coin.SoText2.RIGHT else: - self.text2d.justification = coin.SoText2.LEFT - self.text3d.justification = coin.SoAsciiText.LEFT + self.text_wld.justification = coin.SoAsciiText.LEFT + self.text_scr.justification = coin.SoText2.LEFT self.onChanged(obj.ViewObject, "DisplayMode") # Property to trigger update_label and update_frame. # We could have used a different property. elif prop == "Text" and obj.Text: - self.text2d.string.setValue("") - self.text3d.string.setValue("") + self.text_wld.string.setValue("") + self.text_scr.string.setValue("") _list = [l for l in obj.Text if l] - self.text2d.string.setValues(_list) - self.text3d.string.setValues(_list) + self.text_wld.string.setValues(_list) + self.text_scr.string.setValues(_list) self.onChanged(obj.ViewObject, "DisplayMode") def onChanged(self, vobj, prop): """Execute when a view property is changed.""" - super(ViewProviderLabel, self).onChanged(vobj, prop) + super().onChanged(vobj, prop) obj = vobj.Object properties = vobj.PropertiesList @@ -341,8 +272,8 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): and "LineSpacing" in properties and "ScaleMultiplier" in properties and "TextAlignment" in properties # Top, Middle or Bottom. - and "TextFont" in properties - and "TextSize" in properties) + and "FontName" in properties + and "FontSize" in properties) can_update_frame = (can_update_label and "Frame" in properties) @@ -367,14 +298,14 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): elif prop == "LineWidth" and "LineWidth" in properties: self.drawstyle.lineWidth = vobj.LineWidth - elif prop == "TextFont" and "TextFont" in properties: - self.font.name = vobj.TextFont.encode("utf8") + 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", "TextSize"]: + elif prop in ["DisplayMode", "Frame", "TextAlignment", "FontSize"]: if can_update_label: self.update_label(obj, vobj) if can_update_frame: @@ -399,18 +330,18 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): elif prop == "Justification" and "Justification" in properties: if vobj.Justification == "Left": - self.text2d.justification = coin.SoText2.LEFT - self.text3d.justification = coin.SoAsciiText.LEFT + self.text_wld.justification = coin.SoAsciiText.LEFT + self.text_scr.justification = coin.SoText2.LEFT elif vobj.Justification == "Right": - self.text2d.justification = coin.SoText2.RIGHT - self.text3d.justification = coin.SoAsciiText.RIGHT + self.text_wld.justification = coin.SoAsciiText.RIGHT + self.text_scr.justification = coin.SoText2.RIGHT else: - self.text2d.justification = coin.SoText2.CENTER - self.text3d.justification = coin.SoAsciiText.CENTER + self.text_wld.justification = coin.SoAsciiText.CENTER + self.text_scr.justification = coin.SoText2.CENTER elif prop == "LineSpacing" and "LineSpacing" in properties: - self.text2d.spacing = max(1, vobj.LineSpacing) - self.text3d.spacing = max(1, vobj.LineSpacing) + 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: @@ -418,10 +349,10 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): def get_text_size(self, vobj): """Return the bounding box of the text element.""" - if vobj.DisplayMode == "3D text": - node = self.node3dtxt + if vobj.DisplayMode == "World": + node = self.node_wld_txt else: - node = self.node2dtxt + node = self.node_scr_txt region = coin.SbViewportRegion() action = coin.SoGetBoundingBoxAction(region) @@ -431,10 +362,10 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): def update_label(self, obj, vobj): """Update the label including text size and multiplier.""" - size = vobj.TextSize.Value * vobj.ScaleMultiplier + size = vobj.FontSize.Value * vobj.ScaleMultiplier self.font.size = size - if vobj.DisplayMode == "2D text": + if vobj.DisplayMode == "Screen": self.textpos.translation.setValue(obj.Placement.Base) return @@ -505,10 +436,10 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if vobj.Frame == "None": return - if vobj.DisplayMode == "2D text": + if vobj.DisplayMode == "Screen": return - size = vobj.TextSize.Value * vobj.ScaleMultiplier + size = vobj.FontSize.Value * vobj.ScaleMultiplier self.font.size = size line_height = size * max(1, vobj.LineSpacing) diff --git a/src/Mod/Draft/draftviewproviders/view_text.py b/src/Mod/Draft/draftviewproviders/view_text.py index 7b3e788362..f0f15a4a1a 100644 --- a/src/Mod/Draft/draftviewproviders/view_text.py +++ b/src/Mod/Draft/draftviewproviders/view_text.py @@ -2,6 +2,7 @@ # * Copyright (c) 2009, 2010 Yorik van Havre * # * Copyright (c) 2009, 2010 Ken Cline * # * Copyright (c) 2020 Eliud Cabrera Castillo * +# * Copyright (c) 2022 FreeCAD Project Association * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -45,53 +46,19 @@ from draftviewproviders.view_draft_annotation \ class ViewProviderText(ViewProviderDraftAnnotation): """Viewprovider for the Draft Text annotation.""" - def __init__(self, vobj): - super(ViewProviderText, self).__init__(vobj) - - self.set_properties(vobj) - self.Object = vobj.Object - vobj.Proxy = self - - def set_properties(self, vobj): - """Set the properties only if they don't already exist.""" - super(ViewProviderText, self).set_properties(vobj) - properties = vobj.PropertiesList - - if "FontSize" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The size of the text") - vobj.addProperty("App::PropertyLength", - "FontSize", - "Text", - _tip) - vobj.FontSize = utils.get_param("textheight", 1) - - if "FontName" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "The font of the text") - vobj.addProperty("App::PropertyFont", - "FontName", - "Text", - _tip) - vobj.FontName = utils.get_param("textfont", "sans") + def set_text_properties(self, vobj, properties): + """Set text properties only if they don't already exist.""" + super().set_text_properties(vobj, properties) if "Justification" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", - "The vertical alignment of the text") + "Horizontal alignment") vobj.addProperty("App::PropertyEnumeration", "Justification", "Text", _tip) vobj.Justification = ["Left", "Center", "Right"] - if "TextColor" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Text color") - vobj.addProperty("App::PropertyColor", - "TextColor", - "Text", - _tip) - if "LineSpacing" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Line spacing (relative to font size)") @@ -99,73 +66,63 @@ class ViewProviderText(ViewProviderDraftAnnotation): "LineSpacing", "Text", _tip) + vobj.LineSpacing = 1.0 def getIcon(self): """Return the path to the icon used by the view provider.""" return ":/icons/Draft_Text.svg" - def claimChildren(self): - """Return objects that will be placed under it in the tree view.""" - return [] - def attach(self, vobj): """Set up the scene sub-graph of the view provider.""" + self.Object = vobj.Object + # Main attributes of the Coin scenegraph - self.mattext = coin.SoMaterial() self.trans = coin.SoTransform() + self.mattext = coin.SoMaterial() self.font = coin.SoFont() - self.text2d = coin.SoText2() # Faces the camera always - self.text3d = coin.SoAsciiText() # Can be oriented in 3D space + self.text_wld = coin.SoAsciiText() # World orientation. Can be oriented in 3D space. + self.text_scr = coin.SoText2() # Screen orientation. Always faces the camera. textdrawstyle = coin.SoDrawStyle() textdrawstyle.style = coin.SoDrawStyle.FILLED # The text string needs to be initialized to something, # otherwise it may crash - self.text2d.string = self.text3d.string = "Label" - self.text2d.justification = coin.SoText2.LEFT - self.text3d.justification = coin.SoAsciiText.LEFT + self.text_wld.string = self.text_scr.string = "Label" + self.text_wld.justification = coin.SoAsciiText.LEFT + self.text_scr.justification = coin.SoText2.LEFT - self.node2d = coin.SoGroup() - self.node2d.addChild(self.trans) - self.node2d.addChild(self.mattext) - self.node2d.addChild(textdrawstyle) - self.node2d.addChild(self.font) - self.node2d.addChild(self.text2d) + self.node_wld = coin.SoGroup() + self.node_wld.addChild(self.trans) + self.node_wld.addChild(self.mattext) + self.node_wld.addChild(textdrawstyle) + self.node_wld.addChild(self.font) + self.node_wld.addChild(self.text_wld) - self.node3d = coin.SoGroup() - self.node3d.addChild(self.trans) - self.node3d.addChild(self.mattext) - self.node3d.addChild(textdrawstyle) - self.node3d.addChild(self.font) - self.node3d.addChild(self.text3d) + self.node_scr = coin.SoGroup() + self.node_scr.addChild(self.trans) + self.node_scr.addChild(self.mattext) + self.node_scr.addChild(textdrawstyle) + self.node_scr.addChild(self.font) + self.node_scr.addChild(self.text_scr) - vobj.addDisplayMode(self.node2d, "2D text") - vobj.addDisplayMode(self.node3d, "3D text") + vobj.addDisplayMode(self.node_wld, "World") + vobj.addDisplayMode(self.node_scr, "Screen") self.onChanged(vobj, "TextColor") self.onChanged(vobj, "FontSize") self.onChanged(vobj, "FontName") self.onChanged(vobj, "Justification") self.onChanged(vobj, "LineSpacing") self.onChanged(vobj, "ScaleMultiplier") - self.Object = vobj.Object - - def getDisplayModes(self, vobj): - """Return the display modes that this viewprovider supports.""" - return ["2D text", "3D text"] - - def setDisplayMode(self, mode): - """Return the saved display mode.""" - return mode def updateData(self, obj, prop): """Execute when a property from the Proxy class is changed.""" if prop == "Text" and obj.Text: - self.text2d.string.setValue("") - self.text3d.string.setValue("") + self.text_wld.string.setValue("") + self.text_scr.string.setValue("") _list = [l for l in obj.Text if l] - self.text2d.string.setValues(_list) - self.text3d.string.setValues(_list) + self.text_wld.string.setValues(_list) + self.text_scr.string.setValues(_list) elif prop == "Placement": self.trans.translation.setValue(obj.Placement.Base) @@ -173,7 +130,7 @@ class ViewProviderText(ViewProviderDraftAnnotation): def onChanged(self, vobj, prop): """Execute when a view property is changed.""" - super(ViewProviderText, self).onChanged(vobj, prop) + super().onChanged(vobj, prop) properties = vobj.PropertiesList @@ -208,18 +165,18 @@ class ViewProviderText(ViewProviderDraftAnnotation): # However, in v0.19 this problem doesn't seem to exist any more # so we removed the try-except block. if vobj.Justification == "Left": - self.text2d.justification = coin.SoText2.LEFT - self.text3d.justification = coin.SoAsciiText.LEFT + self.text_wld.justification = coin.SoAsciiText.LEFT + self.text_scr.justification = coin.SoText2.LEFT elif vobj.Justification == "Right": - self.text2d.justification = coin.SoText2.RIGHT - self.text3d.justification = coin.SoAsciiText.RIGHT + self.text_wld.justification = coin.SoAsciiText.RIGHT + self.text_scr.justification = coin.SoText2.RIGHT else: - self.text2d.justification = coin.SoText2.CENTER - self.text3d.justification = coin.SoAsciiText.CENTER + self.text_wld.justification = coin.SoAsciiText.CENTER + self.text_scr.justification = coin.SoText2.CENTER elif prop == "LineSpacing" and "LineSpacing" in properties: - self.text2d.spacing = vobj.LineSpacing - self.text3d.spacing = vobj.LineSpacing + self.text_wld.spacing = vobj.LineSpacing + self.text_scr.spacing = vobj.LineSpacing def edit(self): if not hasattr(Gui, "draftToolBar"):