Draft: clean up ViewProviderText class
Various improvements in style, PEP8, spacing, docstrings. The list of strings is set to empty before being assigned again. This solves a problem of the text not being updated correctly. In the past some `try-except` blocks were there to catch and ignore certain exceptions that apparently were caused by a race condition, where certain properties are not assigned to the object before they are used. These errors don't seem to occur in v0.19, so we removed the exception handling. We leave comments mentioning the issue in case it re-appears. The `DisplayMode` is swapped, so now `'2D text'` means that the text always faces the camera, and `'3D text'` means that the text can be positioned in different orientations in the 3D space. This is consistent with the `Draft Label` behavior. A function `draftutils.gui_utils.migrate_text_display_mode` is provided to help migrate older objects of type `Text` or `DraftText` to the new display mode.
This commit is contained in:
@@ -131,12 +131,13 @@ def make_text(string, placement=None, screen=False):
|
||||
if App.GuiUp:
|
||||
ViewProviderText(new_obj.ViewObject)
|
||||
|
||||
h = utils.get_param("textheight", 0.20)
|
||||
h = utils.get_param("textheight", 2)
|
||||
|
||||
new_obj.ViewObject.DisplayMode = "3D text"
|
||||
if screen:
|
||||
_msg("screen: {}".format(screen))
|
||||
new_obj.ViewObject.DisplayMode = "3D text"
|
||||
h = h*10
|
||||
new_obj.ViewObject.DisplayMode = "2D text"
|
||||
h = h * 10
|
||||
|
||||
new_obj.ViewObject.FontSize = h
|
||||
new_obj.ViewObject.FontName = utils.get_param("textfont", "")
|
||||
|
||||
@@ -39,9 +39,9 @@ import os
|
||||
import six
|
||||
|
||||
import FreeCAD as App
|
||||
import draftutils.utils as utils
|
||||
|
||||
from draftutils.messages import _msg, _wrn
|
||||
from draftutils.utils import getParam
|
||||
from draftutils.utils import get_type
|
||||
from draftutils.translate import _tr, translate
|
||||
|
||||
if App.GuiUp:
|
||||
@@ -141,19 +141,19 @@ def autogroup(obj):
|
||||
App.Console.PrintMessage(err)
|
||||
return
|
||||
inverse_placement = App.Placement(matrix.inverse())
|
||||
if get_type(obj) == 'Point':
|
||||
if utils.get_type(obj) == 'Point':
|
||||
point_vector = App.Vector(obj.X, obj.Y, obj.Z)
|
||||
real_point = inverse_placement.multVec(point_vector)
|
||||
obj.X = real_point.x
|
||||
obj.Y = real_point.y
|
||||
obj.Z = real_point.z
|
||||
elif get_type(obj) in ["Dimension", "LinearDimension"]:
|
||||
elif utils.get_type(obj) in ["Dimension", "LinearDimension"]:
|
||||
obj.Start = inverse_placement.multVec(obj.Start)
|
||||
obj.End = inverse_placement.multVec(obj.End)
|
||||
obj.Dimline = inverse_placement.multVec(obj.Dimline)
|
||||
obj.Normal = inverse_placement.Rotation.multVec(obj.Normal)
|
||||
obj.Direction = inverse_placement.Rotation.multVec(obj.Direction)
|
||||
elif get_type(obj) in ["Label"]:
|
||||
elif utils.get_type(obj) in ["Label"]:
|
||||
obj.Placement = App.Placement(inverse_placement.multiply(obj.Placement))
|
||||
obj.TargetPoint = inverse_placement.multVec(obj.TargetPoint)
|
||||
elif hasattr(obj,"Placement"):
|
||||
@@ -193,7 +193,7 @@ def dim_symbol(symbol=None, invert=False):
|
||||
that will be used as a dimension symbol.
|
||||
"""
|
||||
if symbol is None:
|
||||
symbol = getParam("dimsymbol", 0)
|
||||
symbol = utils.get_param("dimsymbol", 0)
|
||||
|
||||
if symbol == 0:
|
||||
return coin.SoSphere()
|
||||
@@ -340,7 +340,7 @@ def format_object(target, origin=None):
|
||||
doc = App.ActiveDocument
|
||||
if ui.isConstructionMode():
|
||||
col = fcol = ui.getDefaultColor("constr")
|
||||
gname = getParam("constructiongroupname", "Construction")
|
||||
gname = utils.get_param("constructiongroupname", "Construction")
|
||||
grp = doc.getObject(gname)
|
||||
if not grp:
|
||||
grp = doc.addObject("App::DocumentObjectGroup", gname)
|
||||
@@ -655,3 +655,13 @@ def load_texture(filename, size=None, gui=App.GuiUp):
|
||||
|
||||
|
||||
loadTexture = load_texture
|
||||
|
||||
|
||||
def migrate_text_display_mode(obj_type="Text", mode="3D text", doc=None):
|
||||
"""Migrate the display mode of objects of certain type."""
|
||||
if not doc:
|
||||
doc = App.activeDocument()
|
||||
|
||||
for obj in doc.Objects:
|
||||
if utils.get_type(obj) == obj_type:
|
||||
obj.ViewObject.DisplayMode = mode
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# ***************************************************************************
|
||||
# * Copyright (c) 2009, 2010 Yorik van Havre <yorik@uncreated.net> *
|
||||
# * Copyright (c) 2009, 2010 Ken Cline <cline@frii.com> *
|
||||
# * Copyright (c) 2020 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> *
|
||||
# * *
|
||||
# * This file is part of the FreeCAD CAx development system. *
|
||||
# * *
|
||||
@@ -21,28 +22,28 @@
|
||||
# * USA *
|
||||
# * *
|
||||
# ***************************************************************************
|
||||
"""This module provides the Draft Text view provider classes
|
||||
"""
|
||||
## @package text
|
||||
"""Provides the Draft Text viewprovider class."""
|
||||
## @package view_text
|
||||
# \ingroup DRAFT
|
||||
# \brief This module provides the view provider code for Draft Text.
|
||||
# \brief Provides the Draft Text viewprovider class.
|
||||
|
||||
import pivy.coin as coin
|
||||
import sys
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
import FreeCAD as App
|
||||
import DraftVecUtils, DraftGeomUtils
|
||||
import math, sys
|
||||
from pivy import coin
|
||||
from PySide.QtCore import QT_TRANSLATE_NOOP
|
||||
|
||||
import draftutils.utils as utils
|
||||
import draftutils.gui_utils as gui_utils
|
||||
from draftviewproviders.view_draft_annotation import ViewProviderDraftAnnotation
|
||||
from draftviewproviders.view_draft_annotation \
|
||||
import ViewProviderDraftAnnotation
|
||||
|
||||
param = App.ParamGet("User parameter:BaseApp/Preferences/Mod/Draft")
|
||||
|
||||
|
||||
class ViewProviderText(ViewProviderDraftAnnotation):
|
||||
"""A View Provider for the Draft Text annotation"""
|
||||
"""Viewprovider for the Draft Text annotation."""
|
||||
|
||||
|
||||
def __init__(self,vobj):
|
||||
def __init__(self, vobj):
|
||||
super(ViewProviderText, self).__init__(vobj)
|
||||
|
||||
self.set_properties(vobj)
|
||||
@@ -98,66 +99,76 @@ class ViewProviderText(ViewProviderDraftAnnotation):
|
||||
_tip)
|
||||
|
||||
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):
|
||||
'''Setup the scene sub-graph of the view provider'''
|
||||
|
||||
# backwards compatibility
|
||||
self.ScaleMultiplier = 1.00
|
||||
|
||||
def attach(self, vobj):
|
||||
"""Set up the scene sub-graph of the view provider."""
|
||||
# Main attributes of the Coin scenegraph
|
||||
self.mattext = coin.SoMaterial()
|
||||
textdrawstyle = coin.SoDrawStyle()
|
||||
textdrawstyle.style = coin.SoDrawStyle.FILLED
|
||||
self.trans = coin.SoTransform()
|
||||
self.font = coin.SoFont()
|
||||
self.text2d = coin.SoAsciiText()
|
||||
self.text3d = coin.SoText2()
|
||||
self.text2d.string = self.text3d.string = "Label" # need to init with something, otherwise, crash!
|
||||
self.text2d.justification = coin.SoAsciiText.LEFT
|
||||
self.text3d.justification = coin.SoText2.LEFT
|
||||
self.text2d = coin.SoText2() # Faces the camera always
|
||||
self.text3d = coin.SoAsciiText() # Can be oriented in 3D space
|
||||
|
||||
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.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.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)
|
||||
vobj.addDisplayMode(self.node2d,"2D text")
|
||||
vobj.addDisplayMode(self.node3d,"3D text")
|
||||
self.onChanged(vobj,"TextColor")
|
||||
self.onChanged(vobj,"FontSize")
|
||||
self.onChanged(vobj,"FontName")
|
||||
self.onChanged(vobj,"Justification")
|
||||
self.onChanged(vobj,"LineSpacing")
|
||||
|
||||
def getDisplayModes(self,vobj):
|
||||
return ["2D text","3D text"]
|
||||
vobj.addDisplayMode(self.node2d, "2D text")
|
||||
vobj.addDisplayMode(self.node3d, "3D text")
|
||||
self.onChanged(vobj, "TextColor")
|
||||
self.onChanged(vobj, "FontSize")
|
||||
self.onChanged(vobj, "FontName")
|
||||
self.onChanged(vobj, "Justification")
|
||||
self.onChanged(vobj, "LineSpacing")
|
||||
self.onChanged(vobj, "ScaleMultiplier")
|
||||
|
||||
def getDisplayModes(self, vobj):
|
||||
"""Return the display modes that this viewprovider supports."""
|
||||
return ["2D text", "3D text"]
|
||||
|
||||
def setDisplayMode(self,mode):
|
||||
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("")
|
||||
|
||||
if sys.version_info.major >= 3:
|
||||
_list = [l for l in obj.Text if l]
|
||||
else:
|
||||
_list = [l.encode("utf8") for l in obj.Text if l]
|
||||
|
||||
self.text2d.string.setValues(_list)
|
||||
self.text3d.string.setValues(_list)
|
||||
|
||||
def updateData(self,obj,prop):
|
||||
if prop == "Text":
|
||||
if obj.Text:
|
||||
if sys.version_info.major >= 3:
|
||||
self.text2d.string.setValues([l for l in obj.Text if l])
|
||||
self.text3d.string.setValues([l for l in obj.Text if l])
|
||||
else:
|
||||
self.text2d.string.setValues([l.encode("utf8") for l in obj.Text if l])
|
||||
self.text3d.string.setValues([l.encode("utf8") for l in obj.Text if l])
|
||||
elif prop == "Placement":
|
||||
self.trans.translation.setValue(obj.Placement.Base)
|
||||
self.trans.rotation.setValue(obj.Placement.Rotation.Q)
|
||||
@@ -166,40 +177,51 @@ class ViewProviderText(ViewProviderDraftAnnotation):
|
||||
"""Execute when a view property is changed."""
|
||||
super(ViewProviderText, self).onChanged(vobj, prop)
|
||||
|
||||
if prop == "ScaleMultiplier":
|
||||
if "ScaleMultiplier" in vobj.PropertiesList:
|
||||
if vobj.ScaleMultiplier:
|
||||
self.ScaleMultiplier = vobj.ScaleMultiplier
|
||||
if "FontSize" in vobj.PropertiesList:
|
||||
self.font.size = vobj.FontSize.Value * self.ScaleMultiplier
|
||||
elif prop == "TextColor":
|
||||
if "TextColor" in vobj.PropertiesList:
|
||||
l = vobj.TextColor
|
||||
self.mattext.diffuseColor.setValue([l[0],l[1],l[2]])
|
||||
elif (prop == "FontName"):
|
||||
if "FontName" in vobj.PropertiesList:
|
||||
self.font.name = vobj.FontName.encode("utf8")
|
||||
elif prop == "FontSize":
|
||||
if "FontSize" in vobj.PropertiesList:
|
||||
self.font.size = vobj.FontSize.Value * self.ScaleMultiplier
|
||||
elif prop == "Justification":
|
||||
try:
|
||||
if getattr(vobj, "Justification", None) is not None:
|
||||
if vobj.Justification == "Left":
|
||||
self.text2d.justification = coin.SoAsciiText.LEFT
|
||||
self.text3d.justification = coin.SoText2.LEFT
|
||||
elif vobj.Justification == "Right":
|
||||
self.text2d.justification = coin.SoAsciiText.RIGHT
|
||||
self.text3d.justification = coin.SoText2.RIGHT
|
||||
else:
|
||||
self.text2d.justification = coin.SoAsciiText.CENTER
|
||||
self.text3d.justification = coin.SoText2.CENTER
|
||||
except AssertionError:
|
||||
pass # Race condition - Justification enum has not been set yet
|
||||
elif prop == "LineSpacing":
|
||||
if "LineSpacing" in vobj.PropertiesList:
|
||||
self.text2d.spacing = vobj.LineSpacing
|
||||
self.text3d.spacing = vobj.LineSpacing
|
||||
properties = vobj.PropertiesList
|
||||
|
||||
if (prop == "ScaleMultiplier" and "ScaleMultiplier" in properties
|
||||
and vobj.ScaleMultiplier):
|
||||
if "FontSize" in properties:
|
||||
self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier
|
||||
|
||||
elif prop == "TextColor" and "TextColor" in properties:
|
||||
col = vobj.TextColor
|
||||
self.mattext.diffuseColor.setValue([col[0], col[1], col[2]])
|
||||
|
||||
elif prop == "FontName" and "FontName" in properties:
|
||||
self.font.name = vobj.FontName.encode("utf8")
|
||||
|
||||
elif (prop == "FontSize" and "FontSize" in properties
|
||||
and "ScaleMultiplier" in properties and vobj.ScaleMultiplier):
|
||||
# In v0.19 this code causes an `AttributeError` exception
|
||||
# during loading of the document as `ScaleMultiplier`
|
||||
# apparently isn't set immediately when the document loads.
|
||||
# So the if condition tests for the existance
|
||||
# of `ScaleMultiplier` before even changing the font size.
|
||||
# A try-except block may be used as well to catch and ignore
|
||||
# this error.
|
||||
self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier
|
||||
|
||||
elif prop == "Justification" and "Justification" in properties:
|
||||
# This code was surrounded by a try-except block in order to catch
|
||||
# and ignore an `AssertionError` exception. This was the result
|
||||
# of a race condition that would result in the `Justification`
|
||||
# property not being set at the time that this code is invoked.
|
||||
# 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
|
||||
elif vobj.Justification == "Right":
|
||||
self.text2d.justification = coin.SoText2.RIGHT
|
||||
self.text3d.justification = coin.SoAsciiText.RIGHT
|
||||
else:
|
||||
self.text2d.justification = coin.SoText2.CENTER
|
||||
self.text3d.justification = coin.SoAsciiText.CENTER
|
||||
|
||||
elif prop == "LineSpacing" and "LineSpacing" in properties:
|
||||
self.text2d.spacing = vobj.LineSpacing
|
||||
self.text3d.spacing = vobj.LineSpacing
|
||||
|
||||
|
||||
# Alias for compatibility with v0.18 and earlier
|
||||
|
||||
Reference in New Issue
Block a user