From b3e11ecd1175a911270fb0c7ab27f43262838918 Mon Sep 17 00:00:00 2001 From: Vincenzo Calligaro Date: Thu, 14 Aug 2025 10:44:49 +0200 Subject: [PATCH] [Feature Request] [Draft] [UI/UX] Allow to turn dimension arrows on/off individually (#11941) * Update additional files * The LineColor and LineWidth properties are removed from Text objects. * Arrow properties are added by the ViewProviderDraftAnnotation class only. This avoids code duplication. * gui_annotationstyleeditor.py fix except * view_draft_annotation.py fix except --------- Co-authored-by: Roy-043 Co-authored-by: Roy-043 <70520633+Roy-043@users.noreply.github.com> --- src/Mod/BIM/bimcommands/BimLeader.py | 3 +- .../Draft/Resources/ui/TaskPanel_SetStyle.ui | 78 +++++++- .../ui/dialog_AnnotationStyleEditor.ui | 108 +++++++++-- .../Resources/ui/preferences-drafttexts.ui | 117 ++++++++++-- src/Mod/Draft/draftfunctions/svg.py | 180 +++++++++++------- .../gui_annotationstyleeditor.py | 25 +-- src/Mod/Draft/draftguitools/gui_setstyle.py | 44 +++-- src/Mod/Draft/draftmake/make_dimension.py | 12 +- src/Mod/Draft/draftobjects/dimension.py | 20 +- .../Draft/draftobjects/draft_annotation.py | 45 ++++- src/Mod/Draft/draftobjects/label.py | 10 +- src/Mod/Draft/draftobjects/text.py | 29 ++- src/Mod/Draft/draftobjects/wire.py | 32 ++++ .../Draft/drafttests/draft_test_objects.py | 20 +- src/Mod/Draft/draftutils/gui_utils.py | 7 +- src/Mod/Draft/draftutils/utils.py | 46 ++++- .../draftviewproviders/view_dimension.py | 138 ++++++++------ .../view_draft_annotation.py | 78 ++++++-- .../Draft/draftviewproviders/view_label.py | 51 ++--- src/Mod/Draft/draftviewproviders/view_wire.py | 159 ++++++++++------ 20 files changed, 838 insertions(+), 364 deletions(-) diff --git a/src/Mod/BIM/bimcommands/BimLeader.py b/src/Mod/BIM/bimcommands/BimLeader.py index c5e7e8055c..92a087061d 100644 --- a/src/Mod/BIM/bimcommands/BimLeader.py +++ b/src/Mod/BIM/bimcommands/BimLeader.py @@ -61,6 +61,7 @@ class BIM_Leader(gui_lines.Line): rot, sup, pts, fil = self.getStrings() base = DraftVecUtils.toString(self.node[0]) color = params.get_param("DefaultTextColor") | 0x000000FF + arrow = params.get_param("dimsymbolend") cmd_list = [ "pl = FreeCAD.Placement()", "pl.Rotation.Q = " + rot, @@ -68,7 +69,7 @@ class BIM_Leader(gui_lines.Line): "points = " + pts, "leader = Draft.make_wire(points, placement=pl)", "leader.ViewObject.LineColor = " + str(color), - "leader.ViewObject.EndArrow = True", + "leader.ViewObject.ArrowTypeEnd = " + str(arrow), "Draft.autogroup(leader)", "FreeCAD.ActiveDocument.recompute()", ] diff --git a/src/Mod/Draft/Resources/ui/TaskPanel_SetStyle.ui b/src/Mod/Draft/Resources/ui/TaskPanel_SetStyle.ui index ecab8101d3..504461f5b0 100644 --- a/src/Mod/Draft/Resources/ui/TaskPanel_SetStyle.ui +++ b/src/Mod/Draft/Resources/ui/TaskPanel_SetStyle.ui @@ -6,8 +6,8 @@ 0 0 - 287 - 945 + 290 + 968 @@ -404,14 +404,14 @@ Annotation scale widget. If the scale is 1:100 the multiplier is 100. - + - Arrow type + Start arrow type - + Dot @@ -437,30 +437,90 @@ Annotation scale widget. If the scale is 1:100 the multiplier is 100. Tick-2 + + + None + + - + - Arrow size + Start arrow size - + + + + End arrow type + + + + + + + + Dot + + + + + Circle + + + + + Arrow + + + + + Tick + + + + + Tick-2 + + + + + None + + + + + + + + End arrow size + + + + + + + + + + + Line and arrow color - + diff --git a/src/Mod/Draft/Resources/ui/dialog_AnnotationStyleEditor.ui b/src/Mod/Draft/Resources/ui/dialog_AnnotationStyleEditor.ui index 1b4b706cef..03ccd74314 100644 --- a/src/Mod/Draft/Resources/ui/dialog_AnnotationStyleEditor.ui +++ b/src/Mod/Draft/Resources/ui/dialog_AnnotationStyleEditor.ui @@ -154,7 +154,7 @@ 0 0 383 - 589 + 732 @@ -349,15 +349,15 @@ - The type of arrows or markers to use for dimensions and labels + The type of the starting arrows or markers to use for dimensions and labels - Arrow type + Start arrow type - + 0 @@ -371,7 +371,7 @@ - The type of arrows or markers to use for dimensions and labels + The type of the starting arrows or markers to use for dimensions and labels @@ -398,22 +398,27 @@ Tick-2 + + + None + + - + - The size of the arrows or markers in system units + The size of the starting arrows or markers in system units - Arrow size + Start arrow size - + - The size of the arrows or markers in system units + The size of the starting arrows or markers in system units @@ -421,6 +426,85 @@ + + + The type of the ending arrows or markers to use for dimensions and labels + + + End arrow type + + + + + + + + 0 + 0 + + + + + 60 + 0 + + + + The type of the ending arrows or markers to use for dimensions and labels + + + + Dot + + + + + Circle + + + + + Arrow + + + + + Tick + + + + + Tick-2 + + + + + None + + + + + + + + The size of the ending arrows or markers in system units + + + End arrow size + + + + + + + The size of the ending arrows or markers in system units + + + + + + + The color of lines and arrows @@ -430,7 +514,7 @@ - + The color of lines and arrows @@ -469,7 +553,7 @@ - + Specify a valid length unit like mm, m, in, ft, to force displaying the dimension value in this unit diff --git a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui index 0b72571118..b3b57d4b90 100644 --- a/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui +++ b/src/Mod/Draft/Resources/ui/preferences-drafttexts.ui @@ -7,7 +7,7 @@ 0 0 555 - 797 + 836 @@ -261,14 +261,14 @@ in the Annotation scale widget. If the scale is 1:100 the multiplier is 100. - + - Arrow type + Start arrow type - + 140 @@ -276,10 +276,10 @@ in the Annotation scale widget. If the scale is 1:100 the multiplier is 100. - The default symbol displayed at the ends of dimension lines + The default symbol displayed at the start of dimension lines - dimsymbol + dimsymbolstart Mod/Draft @@ -309,19 +309,24 @@ in the Annotation scale widget. If the scale is 1:100 the multiplier is 100.Tick-2 + + + None + + - + - Arrow size + Start arrow size - + - The default arrow size + The default starting arrow size 0.1 @@ -336,7 +341,7 @@ in the Annotation scale widget. If the scale is 1:100 the multiplier is 100.1.0 - arrowsize + arrowsizestart Mod/Draft @@ -344,13 +349,101 @@ in the Annotation scale widget. If the scale is 1:100 the multiplier is 100. + + + End arrow type + + + + + + + + 140 + 0 + + + + The default symbol displayed at the end of dimension lines + + + dimsymbolend + + + Mod/Draft + + + + Dot + + + + + Circle + + + + + Arrow + + + + + Tick + + + + + Tick-2 + + + + + None + + + + + + + + End arrow size + + + + + + + The default ending arrow size + + + 0.1 + + + mm + + + 0.0 + + + 1.0 + + + arrowsizeend + + + Mod/Draft + + + + Line and arrow color - + The default color for lines and arrows diff --git a/src/Mod/Draft/draftfunctions/svg.py b/src/Mod/Draft/draftfunctions/svg.py index bb21394442..fd40e32d71 100644 --- a/src/Mod/Draft/draftfunctions/svg.py +++ b/src/Mod/Draft/draftfunctions/svg.py @@ -116,7 +116,7 @@ def get_arrow(obj, _scale = 'scale({size},{size})'.format(size=arrowsize) _style = 'style="stroke-miterlimit:4;stroke-dasharray:none;stroke-linecap:square"' - if vobj.ArrowType == "Circle": + if arrowtype == "Circle": svg += '= 2: - last_segment = App.Vector(obj.Points[-1] - obj.Points[-2]) - _v = get_proj(last_segment, plane) - angle = -DraftVecUtils.angle(_v) + math.pi - svg += get_arrow(obj, - vobj.ArrowType, - proj_points[-1], - vobj.ArrowSize.Value/pointratio, - stroke, linewidth, angle) if not App.GuiUp: _wrn("Export of texts to SVG is only available in GUI mode") - # print text if App.GuiUp: + + if getattr(vobj, "Line", True): + # Some Labels may have no Line property + # Draw multisegment line + proj_points = list(map(lambda x: get_proj(x, plane), obj.Points)) + path_dir_list = [format_point(proj_points[0], action='M')] + path_dir_list += map(format_point, proj_points[1:]) + path_dir_str = " ".join(path_dir_list) + + svg_path = ' 1): + last_segment = App.Vector(obj.Points[-1] - obj.Points[-2]) + _v = get_proj(last_segment, plane) + angle = -DraftVecUtils.angle(_v) + math.pi + svg += get_arrow(obj, + vobj.ArrowTypeStart, + proj_points[-1], + vobj.ArrowSizeStart.Value/pointratio, + stroke, + linewidth, + angle) + fontname = vobj.FontName position = get_proj(obj.Placement.Base, plane) rotation = obj.Placement.Rotation @@ -944,19 +970,31 @@ def get_svg(obj, fill_opacity=fill_opacity, edges=obj.Shape.Edges) - if (App.GuiUp - and hasattr(vobj, "EndArrow") - and vobj.EndArrow - and hasattr(vobj, "ArrowType") - and len(obj.Shape.Vertexes) > 1): + if App.GuiUp \ + and hasattr(vobj, "ArrowTypeStart") \ + and hasattr(vobj, "ArrowTypeEnd") \ + and hasattr(vobj, "ArrowSizeStart") \ + and hasattr(vobj, "ArrowSizeEnd") \ + and len(obj.Shape.Vertexes) > 1: + # Draft_Wire + p1 = get_proj(obj.Shape.Vertexes[0].Point, plane) + p2 = get_proj(obj.Shape.Vertexes[1].Point, plane) + svg += get_arrow(obj, + vobj.ArrowTypeStart, + p1, + vobj.ArrowSizeStart.Value/pointratio, + stroke, + linewidth, + -DraftVecUtils.angle(p2 - p1)) p1 = get_proj(obj.Shape.Vertexes[-1].Point, plane) p2 = get_proj(obj.Shape.Vertexes[-2].Point, plane) - angle = -DraftVecUtils.angle(p2 - p1) - - arrowsize = vobj.ArrowSize.Value/pointratio svg += get_arrow(obj, - vobj.ArrowType, - p1, arrowsize, stroke, linewidth, angle) + vobj.ArrowTypeEnd, + p1, + vobj.ArrowSizeEnd.Value/pointratio, + stroke, + linewidth, + -DraftVecUtils.angle(p2 - p1)) # techdraw expects bottom-to-top coordinates if techdraw: diff --git a/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py b/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py index 9e9ac9402c..fe28f95058 100644 --- a/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py +++ b/src/Mod/Draft/draftguitools/gui_annotationstyleeditor.py @@ -144,7 +144,7 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): meta = self.doc.Meta for key, value in meta.items(): if key.startswith("Draft_Style_"): - styles[key[12:]] = self.repair_style(json.loads(value)) + styles[key[12:]] = utils.repair_annotation_style(json.loads(value)) return styles def save_meta(self, styles): @@ -196,7 +196,7 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): if vobj.getTypeIdOfProperty(attr) == "App::PropertyColor": value = value | 0x000000FF setattr(vobj, attr, value) - except: + except TypeError: pass else: # the style has been removed @@ -309,7 +309,7 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): nstyles = {} with open(filename[0]) as f: for key, val in json.load(f).items(): - nstyles[key] = self.repair_style(val) + nstyles[key] = utils.repair_annotation_style(val) if nstyles: self.styles.update(nstyles) for style in self.styles.keys(): @@ -331,25 +331,6 @@ class AnnotationStyleEditor(gui_base.GuiCommandSimplest): json.dump(self.styles,f,indent=4) print("Styles saved to " + filename[0]) - def repair_style(self, style): - """Repair a V0.19 or V0.20 style. - - Some properties were missing or misspelled. - Some float values were wrongly stored as strings. - """ - default = utils.get_default_annotation_style() - new = {} - for key, val in default.items(): - if style.get(key) is None: - new[key] = val[1] - elif type(style[key]) == type(val[1]): - new[key] = style[key] - elif isinstance(style[key], str): - new[key] = float(style[key].replace(",", ".")) - else: - new[key] = val[1] - return new - def fill_editor(self, style=None): """Fill the editor fields with the contents of a style.""" default = utils.get_default_annotation_style() diff --git a/src/Mod/Draft/draftguitools/gui_setstyle.py b/src/Mod/Draft/draftguitools/gui_setstyle.py index eeade42a8f..5699571350 100644 --- a/src/Mod/Draft/draftguitools/gui_setstyle.py +++ b/src/Mod/Draft/draftguitools/gui_setstyle.py @@ -104,8 +104,10 @@ class Draft_SetStyle_TaskPanel: self.form.AnnoLineColor.setProperty("color", self.getColor(params.get_param("DefaultAnnoLineColor"))) self.form.AnnoLineWidth.setValue(params.get_param("DefaultAnnoLineWidth")) - self.form.ArrowStyle.setCurrentIndex(params.get_param("dimsymbol")) - self.form.ArrowSize.setText(U.Quantity(params.get_param("arrowsize"), U.Length).UserString) + self.form.ArrowStyleStart.setCurrentIndex(params.get_param("dimsymbolstart")) + self.form.ArrowSizeStart.setText(U.Quantity(params.get_param("arrowsizestart"), U.Length).UserString) + self.form.ArrowStyleEnd.setCurrentIndex(params.get_param("dimsymbolend")) + self.form.ArrowSizeEnd.setText(U.Quantity(params.get_param("arrowsizeend"), U.Length).UserString) self.form.ShowUnit.setChecked(params.get_param("showUnit")) self.form.UnitOverride.setText(params.get_param("overrideUnit")) self.form.DimOvershoot.setText(U.Quantity(params.get_param("dimovershoot"), U.Length).UserString) @@ -163,8 +165,10 @@ class Draft_SetStyle_TaskPanel: "AnnoLineColor": utils.argb_to_rgba(self.form.AnnoLineColor.property("color").rgba()), "AnnoLineWidth": self.form.AnnoLineWidth.value(), - "ArrowStyle": self.form.ArrowStyle.currentIndex(), - "ArrowSize": U.Quantity(self.form.ArrowSize.text()).Value, + "ArrowStyleStart": self.form.ArrowStyleStart.currentIndex(), + "ArrowSizeStart": U.Quantity(self.form.ArrowSizeStart.text()).Value, + "ArrowStyleEnd": self.form.ArrowStyleEnd.currentIndex(), + "ArrowSizeEnd": U.Quantity(self.form.ArrowSizeEnd.text()).Value, "ShowUnit": self.form.ShowUnit.isChecked(), "UnitOverride": self.form.UnitOverride.text(), "DimOvershoot": U.Quantity(self.form.DimOvershoot.text()).Value, @@ -265,11 +269,17 @@ class Draft_SetStyle_TaskPanel: self.form.AnnoLineWidth.setValue( preset.get("AnnoLineWidth", preset.get("LineWidth", getDefDraft("DefaultAnnoLineWidth"))) ) - self.form.ArrowStyle.setCurrentIndex( - preset.get("ArrowStyle", getDefDraft("dimsymbol")) + self.form.ArrowStyleStart.setCurrentIndex( + preset.get("ArrowStyleStart", getDefDraft("dimsymbolstart")) ) - self.form.ArrowSize.setText( - U.Quantity(preset.get("ArrowSize", getDefDraft("arrowsize")), U.Length).UserString + self.form.ArrowSizeStart.setText( + U.Quantity(preset.get("ArrowSizeStart", getDefDraft("arrowsizestart")), U.Length).UserString + ) + self.form.ArrowStyleEnd.setCurrentIndex( + preset.get("ArrowStyleEnd", getDefDraft("dimsymbolend")) + ) + self.form.ArrowSizeEnd.setText( + U.Quantity(preset.get("ArrowSizeEnd", getDefDraft("arrowsizeend")), U.Length).UserString ) self.form.ShowUnit.setChecked( preset.get("ShowUnit", getDefDraft("showUnit")) @@ -318,8 +328,10 @@ class Draft_SetStyle_TaskPanel: params.set_param("DefaultAnnoLineColor", utils.argb_to_rgba(self.form.AnnoLineColor.property("color").rgba())) params.set_param("DefaultAnnoLineWidth", self.form.AnnoLineWidth.value()) - params.set_param("dimsymbol", self.form.ArrowStyle.currentIndex()) - params.set_param("arrowsize", U.Quantity(self.form.ArrowSize.text()).Value) + params.set_param("dimsymbolstart", self.form.ArrowStyleStart.currentIndex()) + params.set_param("arrowsizestart", U.Quantity(self.form.ArrowSizeStart.text()).Value) + params.set_param("dimsymbolend", self.form.ArrowStyleEnd.currentIndex()) + params.set_param("arrowsizeend", U.Quantity(self.form.ArrowSizeEnd.text()).Value) params.set_param("showUnit", self.form.ShowUnit.isChecked()) params.set_param("overrideUnit", self.form.UnitOverride.text()) params.set_param("dimovershoot", U.Quantity(self.form.DimOvershoot.text()).Value) @@ -390,10 +402,14 @@ class Draft_SetStyle_TaskPanel: vobj.LineColor = self.form.AnnoLineColor.property("color").getRgbF()[:3] if "LineWidth" in properties: vobj.LineWidth = self.form.AnnoLineWidth.value() - if "ArrowType" in properties: - vobj.ArrowType = utils.ARROW_TYPES[self.form.ArrowStyle.currentIndex()] - if "ArrowSize" in properties: - vobj.ArrowSize = U.Quantity(self.form.ArrowSize.text()).Value + if "ArrowTypeStart" in properties: + vobj.ArrowTypeStart = utils.ARROW_TYPES[self.form.ArrowStyleStart.currentIndex()] + if "ArrowSizeStart" in properties: + vobj.ArrowSizeStart = U.Quantity(self.form.ArrowSizeStart.text()).Value + if "ArrowTypeEnd" in properties: + vobj.ArrowTypeEnd = utils.ARROW_TYPES[self.form.ArrowStyleEnd.currentIndex()] + if "ArrowSizeEnd" in properties: + vobj.ArrowSizeEnd = U.Quantity(self.form.ArrowSizeEnd.text()).Value if "ShowUnit" in properties: vobj.ShowUnit = self.form.ShowUnit.isChecked() if "UnitOverride" in properties: diff --git a/src/Mod/Draft/draftmake/make_dimension.py b/src/Mod/Draft/draftmake/make_dimension.py index a14d85dab8..dee7fc25fb 100644 --- a/src/Mod/Draft/draftmake/make_dimension.py +++ b/src/Mod/Draft/draftmake/make_dimension.py @@ -128,12 +128,10 @@ def make_dimension(p1, p2, p3=None, p4=None): new_obj = App.ActiveDocument.addObject("App::FeaturePython", "Dimension") LinearDimension(new_obj) - if App.GuiUp: - ViewProviderLinearDimension(new_obj.ViewObject) - wp = WorkingPlane.get_working_plane(update=False) normal = wp.axis flip_text = False + override = "" if App.GuiUp: # invert the normal if we are viewing it from the back @@ -185,13 +183,11 @@ def make_dimension(p1, p2, p3=None, p4=None): if p3 == "radius": # linked.append((p1, "Center")) - if App.GuiUp: - new_obj.ViewObject.Override = "R $dim" + override = "R $dim" new_obj.Diameter = False elif p3 == "diameter": # linked.append((p1, "Diameter")) - if App.GuiUp: - new_obj.ViewObject.Override = "Ø $dim" + override = "Ø $dim" new_obj.Diameter = True new_obj.LinkedGeometry = linked new_obj.Support = p1 @@ -211,7 +207,9 @@ def make_dimension(p1, p2, p3=None, p4=None): new_obj.Dimline = p3 if App.GuiUp: + ViewProviderLinearDimension(new_obj.ViewObject) new_obj.ViewObject.FlipText = flip_text + new_obj.ViewObject.Override = override gui_utils.format_object(new_obj) gui_utils.select(new_obj) diff --git a/src/Mod/Draft/draftobjects/dimension.py b/src/Mod/Draft/draftobjects/dimension.py index 8a6e58a475..e76fbff7fc 100644 --- a/src/Mod/Draft/draftobjects/dimension.py +++ b/src/Mod/Draft/draftobjects/dimension.py @@ -307,12 +307,12 @@ class LinearDimension(DimensionBase): obj, vp_module="view_dimension", vp_class="ViewProviderLinearDimension" ) - if not getattr(obj, "ViewObject", None): + vobj = getattr(obj, "ViewObject", None) + if vobj is None: return - vobj = obj.ViewObject - if hasattr(vobj, "TextColor"): - return - super().update_properties_0v21(obj, vobj) + + if not hasattr(vobj, "TextColor"): + self.update_properties_0v21(obj, vobj) def loads(self, state): self.Type = "LinearDimension" @@ -586,12 +586,12 @@ class AngularDimension(DimensionBase): obj, vp_module="view_dimension", vp_class="ViewProviderAngularDimension" ) - if not getattr(obj, "ViewObject", None): + vobj = getattr(obj, "ViewObject", None) + if vobj is None: return - vobj = obj.ViewObject - if hasattr(vobj, "TextColor"): - return - super().update_properties_0v21(obj, vobj) + + if not hasattr(vobj, "TextColor"): + self.update_properties_0v21(obj, vobj) def loads(self, state): self.Type = "AngularDimension" diff --git a/src/Mod/Draft/draftobjects/draft_annotation.py b/src/Mod/Draft/draftobjects/draft_annotation.py index f2b8a70fc1..20efc20613 100644 --- a/src/Mod/Draft/draftobjects/draft_annotation.py +++ b/src/Mod/Draft/draftobjects/draft_annotation.py @@ -59,16 +59,19 @@ class DraftAnnotation(object): Check if new properties are present after the object is restored in order to migrate older objects. """ - if not getattr(obj, "ViewObject", None): + vobj = getattr(obj, "ViewObject", None) + if vobj is None: return - vobj = obj.ViewObject if not getattr(vobj, "Proxy", None): # Object was saved without GUI. # onDocumentRestored in the object class should restore the ViewObject. return - if hasattr(vobj, "ScaleMultiplier") and hasattr(vobj, "AnnotationStyle"): - return - self.add_missing_properties_0v19(obj, vobj) + + if not hasattr(vobj, "ScaleMultiplier") or not hasattr(vobj, "AnnotationStyle"): + self.add_missing_properties_0v19(obj, vobj) + + if hasattr(vobj, "ArrowType") or hasattr(vobj, "ArrowSize"): + self.update_properties_1v1(obj, vobj) def add_missing_properties_0v19(self, obj, vobj): """Provide missing annotation properties.""" @@ -84,6 +87,38 @@ class DraftAnnotation(object): if multiplier is not None: vobj.ScaleMultiplier = multiplier + def update_properties_1v1(self, obj, vobj): + """Update view properties.""" + vobj.Proxy.set_graphics_properties(vobj, vobj.PropertiesList) + + if hasattr(vobj, "ArrowType"): + typ = obj.Proxy.Type + if typ == "Label": + vobj.ArrowTypeStart = vobj.ArrowType + elif typ == "AngularDimension" \ + or obj.Diameter \ + or not vobj.Proxy.is_linked_to_circle(): + vobj.ArrowTypeStart = vobj.ArrowType + vobj.ArrowTypeEnd = vobj.ArrowType + else: # Radial dimension + vobj.ArrowTypeStart = "None" + vobj.ArrowTypeEnd = vobj.ArrowType + vobj.setPropertyStatus("ArrowType", "-LockDynamic") + vobj.removeProperty("ArrowType") + if hasattr(vobj, "ArrowSize"): + vobj.ArrowSizeStart = vobj.ArrowSize + if hasattr(vobj, "ArrowSizeEnd"): + # Label objects do not have this property + vobj.ArrowSizeEnd = vobj.ArrowSize + vobj.setPropertyStatus("ArrowSize", "-LockDynamic") + vobj.removeProperty("ArrowSize") + _wrn( + "v1.1, " + + obj.Label + + ", " + + translate("draft", "migrated view properties") + ) + def dumps(self): return diff --git a/src/Mod/Draft/draftobjects/label.py b/src/Mod/Draft/draftobjects/label.py index 245452b484..d6464b75d3 100644 --- a/src/Mod/Draft/draftobjects/label.py +++ b/src/Mod/Draft/draftobjects/label.py @@ -235,12 +235,12 @@ class Label(DraftAnnotation): super().onDocumentRestored(obj) gui_utils.restore_view_object(obj, vp_module="view_label", vp_class="ViewProviderLabel") - if not getattr(obj, "ViewObject", None): + vobj = getattr(obj, "ViewObject", None) + if vobj is None: return - vobj = obj.ViewObject - if hasattr(vobj, "FontName") and hasattr(vobj, "FontSize"): - return - self.update_properties_0v21(obj, vobj) + + if not hasattr(vobj, "FontName") or not hasattr(vobj, "FontSize"): + self.update_properties_0v21(obj, vobj) def loads(self, state): self.Type = "Label" diff --git a/src/Mod/Draft/draftobjects/text.py b/src/Mod/Draft/draftobjects/text.py index eb32bfce5a..7998c721f9 100644 --- a/src/Mod/Draft/draftobjects/text.py +++ b/src/Mod/Draft/draftobjects/text.py @@ -77,12 +77,17 @@ class Text(DraftAnnotation): """Execute code when the document is restored.""" super().onDocumentRestored(obj) gui_utils.restore_view_object(obj, vp_module="view_text", vp_class="ViewProviderText") + + vobj = getattr(obj, "ViewObject", None) + if vobj is None: + return + # See loads: - if self.stored_type is None: - return - if not getattr(obj, "ViewObject", None): - return - self.update_properties_0v21(obj, obj.ViewObject) + if self.stored_type is not None: + self.update_properties_0v21(obj, vobj) + + if hasattr(vobj, "LineWidth") or hasattr(vobj, "LineColor"): + self.update_properties_1v1(obj, vobj) def update_properties_0v21(self, obj, vobj): """Update view properties.""" @@ -93,6 +98,20 @@ class Text(DraftAnnotation): _wrn("v0.21, " + obj.Label + ", " + translate("draft", "renamed 'DisplayMode' options to 'World/Screen'")) + def update_properties_1v1(self, obj, vobj): + if hasattr(vobj, "LineWidth"): + vobj.setPropertyStatus("LineWidth", "-LockDynamic") + vobj.removeProperty("LineWidth") + if hasattr(vobj, "LineColor"): + vobj.setPropertyStatus("LineColor", "-LockDynamic") + vobj.removeProperty("LineColor") + _wrn( + "v1.1, " + + obj.Label + + ", " + + translate("draft", "removed view properties") + ) + def loads(self, state): # Before update_properties_0v21 the self.Type value was stored. # We use this to identify older objects that need to be updated. diff --git a/src/Mod/Draft/draftobjects/wire.py b/src/Mod/Draft/draftobjects/wire.py index f6e0147558..67e666c8e1 100644 --- a/src/Mod/Draft/draftobjects/wire.py +++ b/src/Mod/Draft/draftobjects/wire.py @@ -36,6 +36,8 @@ import DraftVecUtils from draftobjects.base import DraftObject from draftutils import gui_utils from draftutils import params +from draftutils.messages import _wrn +from draftutils.translate import translate class Wire(DraftObject): @@ -99,6 +101,36 @@ class Wire(DraftObject): super().onDocumentRestored(obj) gui_utils.restore_view_object(obj, vp_module="view_wire", vp_class="ViewProviderWire") + vobj = getattr(obj, "ViewObject", None) + if vobj is None: + return + + if hasattr(vobj, "ArrowSize") or hasattr(vobj, "ArrowType") or hasattr(vobj, "EndArrow"): + self.update_properties_1v1(obj, vobj) + + def update_properties_1v1(self, obj, vobj): + """Update view properties.""" + vobj.Proxy._set_properties(vobj) + if getattr(vobj, "EndArrow", False) and hasattr(vobj, "ArrowType"): + vobj.ArrowTypeEnd = vobj.ArrowType + if hasattr(vobj, "ArrowSize"): + vobj.ArrowSizeStart = vobj.ArrowSize + vobj.ArrowSizeEnd = vobj.ArrowSize + vobj.setPropertyStatus("ArrowSize", "-LockDynamic") + vobj.removeProperty("ArrowSize") + if hasattr(vobj, "ArrowType"): + vobj.setPropertyStatus("ArrowType", "-LockDynamic") + vobj.removeProperty("ArrowType") + if hasattr(vobj, "EndArrow"): + vobj.setPropertyStatus("EndArrow", "-LockDynamic") + vobj.removeProperty("EndArrow") + _wrn( + "v1.1, " + + obj.Label + + ", " + + translate("draft", "migrated view properties") + ) + def execute(self, obj): if self.props_changed_placement_only(obj): # Supplying obj is required because of `Base` and `Tool`. obj.positionBySupport() diff --git a/src/Mod/Draft/drafttests/draft_test_objects.py b/src/Mod/Draft/drafttests/draft_test_objects.py index 6f9d454cdd..657f8e6d31 100644 --- a/src/Mod/Draft/drafttests/draft_test_objects.py +++ b/src/Mod/Draft/drafttests/draft_test_objects.py @@ -287,7 +287,8 @@ def _create_objects(doc=None, Vector(1500, 2400, 0), Vector(1000, 2200, 0)) if App.GuiUp: - dimension.ViewObject.ArrowSize = 15 + dimension.ViewObject.ArrowSizeStart = 15 + dimension.ViewObject.ArrowSizeEnd = 15 dimension.ViewObject.ExtLines = 0 dimension.ViewObject.ExtOvershoot = 50 dimension.ViewObject.DimOvershoot = 25 @@ -301,8 +302,10 @@ def _create_objects(doc=None, dimension = Draft.make_linear_dimension_obj(line, 1, 2, Vector(1000, 2800, 0)) if App.GuiUp: - dimension.ViewObject.ArrowSize = 15 - dimension.ViewObject.ArrowType = "Arrow" + dimension.ViewObject.ArrowSizeStart = 15 + dimension.ViewObject.ArrowSizeEnd = 15 + dimension.ViewObject.ArrowTypeStart = "Arrow" + dimension.ViewObject.ArrowTypeEnd = "Arrow" dimension.ViewObject.ExtLines = -50 dimension.ViewObject.ExtOvershoot = 50 dimension.ViewObject.DimOvershoot = 25 @@ -324,7 +327,8 @@ def _create_objects(doc=None, "radius", Vector(2300, 2300, 0)) if App.GuiUp: - dimension.ViewObject.ArrowSize = 15 + dimension.ViewObject.ArrowSizeStart = 15 + dimension.ViewObject.ArrowSizeEnd = 15 dimension.ViewObject.FontSize = 50 dimension.ViewObject.Decimals = 1 dimension.ViewObject.ShowUnit = False @@ -338,7 +342,8 @@ def _create_objects(doc=None, "diameter", Vector(2300, 2900, 0)) if App.GuiUp: - dimension.ViewObject.ArrowSize = 15 + dimension.ViewObject.ArrowSizeStart = 15 + dimension.ViewObject.ArrowSizeEnd = 15 dimension.ViewObject.FontSize = 50 dimension.ViewObject.Decimals = 1 dimension.ViewObject.ShowUnit = False @@ -354,7 +359,8 @@ def _create_objects(doc=None, [0, 45], Vector(3250, 2250, 0)) if App.GuiUp: - dimension.ViewObject.ArrowSize = 15 + dimension.ViewObject.ArrowSizeStart = 15 + dimension.ViewObject.ArrowSizeEnd = 15 dimension.ViewObject.FontSize = 50 dimension.ViewObject.Decimals = 1 _set_text(["Angle dimension"], Vector(3000, 1800, 0)) @@ -369,7 +375,7 @@ def _create_objects(doc=None, distance=-100) label.Text = "Testing" if App.GuiUp: - label.ViewObject.ArrowSize = 15 + label.ViewObject.ArrowSizeStart = 15 label.ViewObject.FontSize = 50 _set_text(["Label"], Vector(4000, 1800, 0)) diff --git a/src/Mod/Draft/draftutils/gui_utils.py b/src/Mod/Draft/draftutils/gui_utils.py index b6ab35aafc..4d8cfca573 100644 --- a/src/Mod/Draft/draftutils/gui_utils.py +++ b/src/Mod/Draft/draftutils/gui_utils.py @@ -189,7 +189,7 @@ def dim_symbol(symbol=None, invert=False): ---------- symbol: int, optional It defaults to `None`, in which it gets the value from the parameter - database, `get_param("dimsymbol")`. + database, `get_param("dimsymbolend")`. A numerical value defines different markers * 0, `SoSphere` @@ -197,6 +197,7 @@ def dim_symbol(symbol=None, invert=False): * 2, `SoSeparator` with a `soCone` * 3, `SoSeparator` with a `SoFaceSet` * 4, `SoSeparator` with a `SoLineSet`, calling `dim_dash` + * 5, Nothing * Otherwise, `SoSphere` invert: bool, optional @@ -212,7 +213,7 @@ def dim_symbol(symbol=None, invert=False): that will be used as a dimension symbol. """ if symbol is None: - symbol = params.get_param("dimsymbol") + symbol = params.get_param("dimsymbolend") if symbol == 0: # marker = coin.SoMarkerSet() @@ -262,6 +263,8 @@ def dim_symbol(symbol=None, invert=False): return marker elif symbol == 4: return dim_dash((-1.5, -1.5, 0), (1.5, 1.5, 0)) + elif symbol == 5: + return coin.SoSeparator() else: _wrn(translate("draft", "Symbol not implemented. Using a default symbol.")) return coin.SoSphere() diff --git a/src/Mod/Draft/draftutils/utils.py b/src/Mod/Draft/draftutils/utils.py index 342350249c..dcbd6b161c 100644 --- a/src/Mod/Draft/draftutils/utils.py +++ b/src/Mod/Draft/draftutils/utils.py @@ -56,17 +56,20 @@ if App.GuiUp: True if Draft_rc else False -ARROW_TYPES = ["Dot", "Circle", "Arrow", "Tick", "Tick-2"] +ARROW_TYPES = ["Dot", "Circle", "Arrow", "Tick", "Tick-2", "None"] DISPLAY_MODES = ["Flat Lines", "Shaded", "Wireframe", "Points"] DRAW_STYLES = ["Solid", "Dashed", "Dotted", "Dashdot"] arrowtypes = ARROW_TYPES def get_default_annotation_style(): - arrow_type_index = params.get_param("dimsymbol") + arrow_start_type_index = params.get_param("dimsymbolstart") + arrow_end_type_index = params.get_param("dimsymbolend") return { - "ArrowSize": ("float", params.get_param("arrowsize")), - "ArrowType": ("index", arrow_type_index, ARROW_TYPES[arrow_type_index]), + "ArrowSizeStart": ("float", params.get_param("arrowsizestart")), + "ArrowSizeEnd": ("float", params.get_param("arrowsizeend")), + "ArrowTypeStart": ("index", arrow_start_type_index, ARROW_TYPES[arrow_start_type_index]), + "ArrowTypeEnd": ("index", arrow_end_type_index, ARROW_TYPES[arrow_end_type_index]), "Decimals": ("int", params.get_param("dimPrecision")), "DimOvershoot": ("float", params.get_param("dimovershoot")), "ExtLines": ("float", params.get_param("extlines")), @@ -85,6 +88,37 @@ def get_default_annotation_style(): } +def repair_annotation_style(style): + """Repair a V0.19, V0.20 or < V1.1 style. + + V0.19 and V0.20: + Some properties were missing or misspelled. + Some float values were wrongly stored as strings. + + V1.0 -> V1.1: + ArrowSize has been replaced by ArrowSizeStart and ArrowSizeEnd. + ArrowType has been replaced by ArrowTypeStart and ArrowTypeEnd. + """ + for key in ("ArrowSize", "ArrowType"): + if style.get(key) is not None \ + and style.get(key + "Start") is None \ + and style.get(key + "End") is None: + style[key + "Start"] = style[key] + style[key + "End"] = style[key] + default = get_default_annotation_style() + new = {} + for key, val in default.items(): + if style.get(key) is None: + new[key] = val[1] + elif type(style[key]) == type(val[1]): + new[key] = style[key] + elif isinstance(style[key], str): + new[key] = float(style[key].replace(",", ".")) + else: + new[key] = val[1] + return new + + def get_default_shape_style(): # Uses the same format as get_default_annotation_style(). display_mode_index = params.get_param("DefaultDisplayMode") @@ -1095,13 +1129,13 @@ def toggle_working_plane(obj, action=None, restore=False, dialog=None): """ import FreeCADGui import Draft - + # Determine the appropriate context based on object type context = "Arch" obj_type = get_type(obj) if obj_type == "IfcBuildingStorey": context = "NativeIFC" - + # Check if the object is already active in its context is_active_arch = (FreeCADGui.ActiveDocument.ActiveView.getActiveObject("Arch") == obj) is_active_ifc = (FreeCADGui.ActiveDocument.ActiveView.getActiveObject("NativeIFC") == obj) diff --git a/src/Mod/Draft/draftviewproviders/view_dimension.py b/src/Mod/Draft/draftviewproviders/view_dimension.py index d426b285d8..75edb5a27a 100644 --- a/src/Mod/Draft/draftviewproviders/view_dimension.py +++ b/src/Mod/Draft/draftviewproviders/view_dimension.py @@ -79,7 +79,7 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): From the viewprovider class - * `b`, `ArrowType` and `ArrowSize`, the symbol shown on the endpoints + * `b`, `ArrowTypeStart`, `ArrowTypeEnd`, `ArrowSizeStart`, `ArrowSizeEnd`, the symbol shown on the endpoints * `c`, `DimOvershoot`, extension to the dimension line going through `a` * `d`, `ExtLines`, distance to target `(t)` * `e`, `ExtOvershoot`, extension in the opposite direction to `(t)` @@ -201,27 +201,6 @@ class ViewProviderDimensionBase(ViewProviderDraftAnnotation): """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", - "Arrow size") - vobj.addProperty("App::PropertyLength", - "ArrowSize", - "Graphics", - _tip, - locked=True) - vobj.ArrowSize = params.get_param("arrowsize") - - if "ArrowType" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Arrow type") - vobj.addProperty("App::PropertyEnumeration", - "ArrowType", - "Graphics", - _tip, - locked=True) - vobj.ArrowType = utils.ARROW_TYPES - vobj.ArrowType = utils.ARROW_TYPES[params.get_param("dimsymbol")] - if "FlipArrows" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Rotate the dimension arrows 180 degrees") @@ -287,6 +266,17 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): of circular edges, and circumferences. """ + def set_graphics_properties(self, vobj, properties): + """Set graphics properties only if they don't already exist.""" + super().set_graphics_properties(vobj, properties) + + self.Object = vobj.Object + if vobj.Object.Diameter or not self.is_linked_to_circle(): + vobj.ArrowTypeStart = params.get_param("dimsymbolstart") + else: + vobj.ArrowTypeStart = "None" + vobj.ArrowTypeEnd = params.get_param("dimsymbolend") + def attach(self, vobj): """Set up the scene sub-graph of the viewprovider.""" self.Object = vobj.Object @@ -366,7 +356,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): self.onChanged(vobj, "FontSize") self.onChanged(vobj, "FontName") self.onChanged(vobj, "TextColor") - self.onChanged(vobj, "ArrowType") + self.onChanged(vobj, "ArrowTypeStart") + self.onChanged(vobj, "ArrowTypeEnd") self.onChanged(vobj, "LineColor") self.onChanged(vobj, "DimOvershoot") self.onChanged(vobj, "ExtOvershoot") @@ -396,7 +387,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): else: vobj.Override = vobj.Override.replace("Ø $dim", "R $dim") - self.onChanged(vobj, "ArrowType") + self.onChanged(vobj, "ArrowTypeStart") + self.onChanged(vobj, "ArrowTypeEnd") return # Calculate the 4 points @@ -660,7 +652,8 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier if (hasattr(self, "node_wld") and hasattr(self, "p2") - and "ArrowSize" in properties): + and "ArrowSizeStart" in properties + and "ArrowSizeEnd" in properties): self.remove_dim_arrows() self.draw_dim_arrows(vobj) if "DimOvershoot" in properties: @@ -695,8 +688,9 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): and hasattr(self, "drawstyle")): self.drawstyle.lineWidth = vobj.LineWidth - elif (prop in ("ArrowSize", "ArrowType") - and "ArrowSize" in properties + elif (prop in ("ArrowSizeStart", "ArrowSizeEnd", "ArrowTypeStart", "ArrowTypeEnd") + and "ArrowSizeStart" in properties + and "ArrowSizeEnd" in properties and "ScaleMultiplier" in properties and hasattr(self, "node_wld") and hasattr(self, "p2")): self.remove_dim_arrows() @@ -734,36 +728,38 @@ class ViewProviderLinearDimension(ViewProviderDimensionBase): def draw_dim_arrows(self, vobj): """Draw dimension arrows.""" - if not hasattr(vobj, "ArrowType"): + if not (hasattr(vobj, "ArrowTypeStart") and hasattr(vobj, "ArrowTypeEnd") and + hasattr(vobj, "ArrowSizeStart") and hasattr(vobj, "ArrowSizeEnd")): return # Set scale - symbol = utils.ARROW_TYPES.index(vobj.ArrowType) - s = vobj.ArrowSize.Value * vobj.ScaleMultiplier - self.trans1.scaleFactor.setValue((s, s, s)) - self.trans2.scaleFactor.setValue((s, s, s)) + symbol_sta = utils.ARROW_TYPES.index(vobj.ArrowTypeStart) + symbol_end = utils.ARROW_TYPES.index(vobj.ArrowTypeEnd) + scale_sta = vobj.ArrowSizeStart.Value * vobj.ScaleMultiplier + scale_end = vobj.ArrowSizeEnd.Value * vobj.ScaleMultiplier + self.trans1.scaleFactor.setValue((scale_sta, scale_sta, scale_sta)) + self.trans2.scaleFactor.setValue((scale_end, scale_end, scale_end)) # Set new nodes self.marks = coin.SoSeparator() self.marks.addChild(self.linecolor) - if vobj.Object.Diameter or not self.is_linked_to_circle(): - s1 = coin.SoSeparator() - if symbol == "Circle": - s1.addChild(self.coord1) - else: - s1.addChild(self.trans1) + s1 = coin.SoSeparator() + if symbol_sta == "Circle": + s1.addChild(self.coord1) + else: + s1.addChild(self.trans1) - s1.addChild(gui_utils.dim_symbol(symbol, invert=False)) - self.marks.addChild(s1) + s1.addChild(gui_utils.dim_symbol(symbol_sta, invert=False)) + self.marks.addChild(s1) s2 = coin.SoSeparator() - if symbol == "Circle": + if symbol_end == "Circle": s2.addChild(self.coord2) else: s2.addChild(self.trans2) - s2.addChild(gui_utils.dim_symbol(symbol, invert=True)) + s2.addChild(gui_utils.dim_symbol(symbol_end, invert=True)) self.marks.addChild(s2) self.node_wld.insertChild(self.marks, 2) @@ -856,6 +852,13 @@ _ViewProviderDimension = ViewProviderLinearDimension class ViewProviderAngularDimension(ViewProviderDimensionBase): """Viewprovider for the Angular dimension object.""" + def set_graphics_properties(self, vobj, properties): + """Set graphics properties only if they don't already exist.""" + super().set_graphics_properties(vobj, properties) + + vobj.ArrowTypeStart = params.get_param("dimsymbolstart") + vobj.ArrowTypeEnd = params.get_param("dimsymbolend") + def attach(self, vobj): """Set up the scene sub-graph of the viewprovider.""" self.Object = vobj.Object @@ -919,7 +922,8 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): self.onChanged(vobj, "FontSize") self.onChanged(vobj, "FontName") self.onChanged(vobj, "TextColor") - self.onChanged(vobj, "ArrowType") + self.onChanged(vobj, "ArrowTypeStart") + self.onChanged(vobj, "ArrowTypeEnd") self.onChanged(vobj, "LineColor") def updateData(self, obj, prop): @@ -1055,19 +1059,25 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): self.coord2.point.setValue(p3) # Calculate small chords to make arrows look better - if vobj.ArrowSize.Value !=0 \ + if hasattr(vobj, "ArrowSizeStart") \ + and hasattr(vobj, "ArrowSizeEnd") \ and hasattr(vobj, "ScaleMultiplier") \ - and vobj.ScaleMultiplier != 0 \ - and hasattr(vobj, "FlipArrows"): - halfarrowlength = 2 * vobj.ArrowSize.Value * vobj.ScaleMultiplier - arrowangle = 2 * math.asin(min(1, halfarrowlength / radius)) + and hasattr(vobj, "FlipArrows") \ + and vobj.ArrowSizeStart.Value !=0 \ + and vobj.ArrowSizeEnd.Value !=0 \ + and vobj.ScaleMultiplier != 0: + half_arrow_length_sta = 2 * vobj.ArrowSizeStart.Value * vobj.ScaleMultiplier + arrow_angle_sta = 2 * math.asin(min(1, half_arrow_length_sta / radius)) + half_arrow_length_end = 2 * vobj.ArrowSizeEnd.Value * vobj.ScaleMultiplier + arrow_angle_end = 2 * math.asin(min(1, half_arrow_length_end / radius)) if vobj.FlipArrows: - arrowangle = -arrowangle + arrow_angle_sta = -arrow_angle_sta + arrow_angle_end = -arrow_angle_end - u1 = (self.circle.valueAt(first + arrowangle) + u1 = (self.circle.valueAt(first + arrow_angle_sta) - self.circle.valueAt(first)).normalize() u2 = (self.circle.valueAt(last) - - self.circle.valueAt(last - arrowangle)).normalize() + - self.circle.valueAt(last - arrow_angle_end)).normalize() w2 = self.circle.Curve.Axis w1 = w2.negative() @@ -1134,7 +1144,8 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): if hasattr(self, "font"): self.font.size = vobj.FontSize.Value * vobj.ScaleMultiplier if (hasattr(self, "node_wld") and hasattr(self, "p2") - and "ArrowSize" in properties): + and "ArrowSizeStart" in properties + and "ArrowSizeEnd" in properties): self.remove_dim_arrows() self.draw_dim_arrows(vobj) @@ -1160,7 +1171,7 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): elif prop == "LineWidth" and hasattr(self, "drawstyle"): self.drawstyle.lineWidth = vobj.LineWidth - elif (prop in ("ArrowSize", "ArrowType") + elif (prop in ("ArrowSizeStart", "ArrowTypeStart", "ArrowSizeEnd", "ArrowTypeEnd") and "ScaleMultiplier" in properties and hasattr(self, "node_wld") and hasattr(self, "p2")): self.updateData(obj, None) @@ -1180,33 +1191,36 @@ class ViewProviderAngularDimension(ViewProviderDimensionBase): def draw_dim_arrows(self, vobj): """Draw dimension arrows.""" - if not hasattr(vobj, "ArrowType"): + if not (hasattr(vobj, "ArrowTypeStart") and hasattr(vobj, "ArrowTypeEnd") and + hasattr(vobj, "ArrowSizeStart") and hasattr(vobj, "ArrowSizeEnd")): return # Set scale - symbol = utils.ARROW_TYPES.index(vobj.ArrowType) - s = vobj.ArrowSize.Value * vobj.ScaleMultiplier - self.trans1.scaleFactor.setValue((s, s, s)) - self.trans2.scaleFactor.setValue((s, s, s)) + symbol_sta = utils.ARROW_TYPES.index(vobj.ArrowTypeStart) + symbol_end = utils.ARROW_TYPES.index(vobj.ArrowTypeEnd) + scale_sta = vobj.ArrowSizeStart.Value * vobj.ScaleMultiplier + scale_end = vobj.ArrowSizeEnd.Value * vobj.ScaleMultiplier + self.trans1.scaleFactor.setValue((scale_sta, scale_sta, scale_sta)) + self.trans2.scaleFactor.setValue((scale_end, scale_end, scale_end)) # Set new nodes self.marks = coin.SoSeparator() self.marks.addChild(self.linecolor) s1 = coin.SoSeparator() - if symbol == "Circle": + if symbol_sta == "Circle": s1.addChild(self.coord1) else: s1.addChild(self.trans1) - s1.addChild(gui_utils.dim_symbol(symbol, invert=False)) + s1.addChild(gui_utils.dim_symbol(symbol_sta, invert=False)) self.marks.addChild(s1) s2 = coin.SoSeparator() - if symbol == "Circle": + if symbol_end == "Circle": s2.addChild(self.coord2) else: s2.addChild(self.trans2) - s2.addChild(gui_utils.dim_symbol(symbol, invert=True)) + s2.addChild(gui_utils.dim_symbol(symbol_end, invert=True)) self.marks.addChild(s2) self.node_wld.insertChild(self.marks, 2) diff --git a/src/Mod/Draft/draftviewproviders/view_draft_annotation.py b/src/Mod/Draft/draftviewproviders/view_draft_annotation.py index 84822255b4..2ae971188a 100644 --- a/src/Mod/Draft/draftviewproviders/view_draft_annotation.py +++ b/src/Mod/Draft/draftviewproviders/view_draft_annotation.py @@ -148,6 +148,53 @@ class ViewProviderDraftAnnotation(object): def set_graphics_properties(self, vobj, properties): """Set graphics properties only if they don't already exist.""" + if vobj.Object.Proxy.Type == "Text": + return + + if "ArrowSizeStart" not in properties: + _tip = QT_TRANSLATE_NOOP("App::Property", + "Arrow size") + vobj.addProperty("App::PropertyLength", + "ArrowSizeStart", + "Graphics", + _tip, + locked=True) + vobj.ArrowSizeStart = params.get_param("arrowsizestart") + + if "ArrowTypeStart" not in properties: + _tip = QT_TRANSLATE_NOOP("App::Property", + "Arrow type") + vobj.addProperty("App::PropertyEnumeration", + "ArrowTypeStart", + "Graphics", + _tip, + locked=True) + vobj.ArrowTypeStart = utils.ARROW_TYPES + vobj.ArrowTypeStart = "None" + + if vobj.Object.Proxy.Type != "Label": + + if "ArrowSizeEnd" not in properties: + _tip = QT_TRANSLATE_NOOP("App::Property", + "Arrow size") + vobj.addProperty("App::PropertyLength", + "ArrowSizeEnd", + "Graphics", + _tip, + locked=True) + vobj.ArrowSizeEnd = params.get_param("arrowsizeend") + + if "ArrowTypeEnd" not in properties: + _tip = QT_TRANSLATE_NOOP("App::Property", + "Arrow type") + vobj.addProperty("App::PropertyEnumeration", + "ArrowTypeEnd", + "Graphics", + _tip, + locked=True) + vobj.ArrowTypeEnd = utils.ARROW_TYPES + vobj.ArrowTypeEnd = "None" + if "LineWidth" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", "Line width") vobj.addProperty("App::PropertyFloat", @@ -208,24 +255,21 @@ class ViewProviderDraftAnnotation(object): vobj.setPropertyStatus(visprop, '-ReadOnly') else: # set style - styles = {} for key, value in meta.items(): - if key.startswith("Draft_Style_"): - styles[key[12:]] = json.loads(value) - - if vobj.AnnotationStyle in styles: - style = styles[vobj.AnnotationStyle] - for visprop in style.keys(): - if visprop in properties: - # make property read-only - vobj.setPropertyStatus(visprop, "ReadOnly") - value = style[visprop] - try: - if vobj.getTypeIdOfProperty(visprop) == "App::PropertyColor": - value = value | 0x000000FF - setattr(vobj, visprop, value) - except: - pass + if key.startswith("Draft_Style_") and key[12:] == vobj.AnnotationStyle: + style = utils.repair_annotation_style(json.loads(value)) + for visprop in style.keys(): + if visprop in properties: + # make property read-only + vobj.setPropertyStatus(visprop, "ReadOnly") + value = style[visprop] + try: + if vobj.getTypeIdOfProperty(visprop) == "App::PropertyColor": + value = value | 0x000000FF + setattr(vobj, visprop, value) + except TypeError: + pass + break def execute(self, vobj): """Execute when the object is created or recomputed.""" diff --git a/src/Mod/Draft/draftviewproviders/view_label.py b/src/Mod/Draft/draftviewproviders/view_label.py index c701321737..0a6e70418d 100644 --- a/src/Mod/Draft/draftviewproviders/view_label.py +++ b/src/Mod/Draft/draftviewproviders/view_label.py @@ -97,26 +97,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): """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", - "Arrow size") - vobj.addProperty("App::PropertyLength", - "ArrowSize", - "Graphics", - _tip, - locked=True) - vobj.ArrowSize = params.get_param("arrowsize") - - if "ArrowType" not in properties: - _tip = QT_TRANSLATE_NOOP("App::Property", - "Arrow type") - vobj.addProperty("App::PropertyEnumeration", - "ArrowType", - "Graphics", - _tip, - locked=True) - vobj.ArrowType = utils.ARROW_TYPES - vobj.ArrowType = utils.ARROW_TYPES[params.get_param("dimsymbol")] + vobj.ArrowTypeStart = params.get_param("dimsymbolstart") if "Frame" not in properties: _tip = QT_TRANSLATE_NOOP("App::Property", @@ -171,7 +152,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.frame = coin.SoType.fromName("SoBrepEdgeSet").createInstance() self.lineswitch = coin.SoSwitch() - self.symbol = gui_utils.dim_symbol() + self.startSymbol = gui_utils.dim_symbol() textdrawstyle = coin.SoDrawStyle() textdrawstyle.style = coin.SoDrawStyle.FILLED @@ -231,7 +212,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.onChanged(vobj, "LineColor") self.onChanged(vobj, "TextColor") self.onChanged(vobj, "LineWidth") - self.onChanged(vobj, "ArrowSize") + self.onChanged(vobj, "ArrowSizeStart") self.onChanged(vobj, "Line") def updateData(self, obj, prop): @@ -245,7 +226,7 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.line.coordIndex.setValues(0, n_points, range(n_points)) - self.onChanged(obj.ViewObject, "ArrowType") + self.onChanged(obj.ViewObject, "ArrowTypeStart") # When initially called (on doc open) properties of vobj are not yet available. # This function is however triggered again from update_label. @@ -302,8 +283,8 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): self.update_frame(obj, vobj) elif prop == "ScaleMultiplier" and "ScaleMultiplier" in properties: - if "ArrowSize" in properties: - s = vobj.ArrowSize.Value * vobj.ScaleMultiplier + if "ArrowSizeStart" in properties: + s = vobj.ArrowSizeStart.Value * vobj.ScaleMultiplier if s: self.arrowpos.scaleFactor.setValue((s, s, s)) if can_update_label: @@ -311,14 +292,14 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): if can_update_frame: self.update_frame(obj, vobj) - elif (prop == "ArrowSize" - and "ArrowSize" in properties + elif (prop == "ArrowSizeStart" + and "ArrowSizeStart" in properties and "ScaleMultiplier" in properties): - s = vobj.ArrowSize.Value * vobj.ScaleMultiplier + s = vobj.ArrowSizeStart.Value * vobj.ScaleMultiplier if s: self.arrowpos.scaleFactor.setValue((s, s, s)) - elif prop == "ArrowType" and "ArrowType" in properties: + elif prop == "ArrowTypeStart" and "ArrowTypeStart" in properties: if len(obj.Points) > 1: self.update_arrow(obj, vobj) @@ -428,13 +409,13 @@ class ViewProviderLabel(ViewProviderDraftAnnotation): def update_arrow(self, obj, vobj): """Update the arrow tip of the line.""" - if hasattr(self, "symbol"): - if self.arrow.findChild(self.symbol) != -1: - self.arrow.removeChild(self.symbol) + if hasattr(self, "startSymbol"): + if self.arrow.findChild(self.startSymbol) != -1: + self.arrow.removeChild(self.startSymbol) - s = utils.ARROW_TYPES.index(vobj.ArrowType) - self.symbol = gui_utils.dim_symbol(s) - self.arrow.addChild(self.symbol) + startS = utils.ARROW_TYPES.index(vobj.ArrowTypeStart) + self.startSymbol = gui_utils.dim_symbol(startS) + self.arrow.addChild(self.startSymbol) prec = 10**(-utils.precision()) x_axis = App.Vector(1,0,0) diff --git a/src/Mod/Draft/draftviewproviders/view_wire.py b/src/Mod/Draft/draftviewproviders/view_wire.py index c6c77958c7..bd5a76e236 100644 --- a/src/Mod/Draft/draftviewproviders/view_wire.py +++ b/src/Mod/Draft/draftviewproviders/view_wire.py @@ -59,90 +59,125 @@ class ViewProviderWire(ViewProviderDraft): """Set the properties of objects if they don't exist.""" super(ViewProviderWire, self)._set_properties(vobj) - if not hasattr(vobj, "EndArrow"): - _tip = QT_TRANSLATE_NOOP("App::Property", "Displays a Dimension symbol at the end of the wire.") - vobj.addProperty("App::PropertyBool", - "EndArrow", - "Draft", - _tip, - locked=True) - vobj.EndArrow = False - - if not hasattr(vobj, "ArrowSize"): + if not hasattr(vobj, "ArrowSizeStart"): _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow size") vobj.addProperty("App::PropertyLength", - "ArrowSize", + "ArrowSizeStart", "Draft", _tip, locked=True) - vobj.ArrowSize = params.get_param("arrowsize") + vobj.ArrowSizeStart = params.get_param("arrowsizestart") - if not hasattr(vobj, "ArrowType"): + if not hasattr(vobj, "ArrowTypeStart"): _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow type") vobj.addProperty("App::PropertyEnumeration", - "ArrowType", + "ArrowTypeStart", "Draft", _tip, locked=True) - vobj.ArrowType = utils.ARROW_TYPES - vobj.ArrowType = utils.ARROW_TYPES[params.get_param("dimsymbol")] + vobj.ArrowTypeStart = utils.ARROW_TYPES + vobj.ArrowTypeStart = "None" + + if not hasattr(vobj, "ArrowSizeEnd"): + _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow size") + vobj.addProperty("App::PropertyLength", + "ArrowSizeEnd", + "Draft", + _tip, + locked=True) + vobj.ArrowSizeEnd = params.get_param("arrowsizeend") + + if not hasattr(vobj, "ArrowTypeEnd"): + _tip = QT_TRANSLATE_NOOP("App::Property", "Arrow type") + vobj.addProperty("App::PropertyEnumeration", + "ArrowTypeEnd", + "Draft", + _tip, + locked=True) + vobj.ArrowTypeEnd = utils.ARROW_TYPES + vobj.ArrowTypeEnd = "None" def attach(self, vobj): self.Object = vobj.Object - col = coin.SoBaseColor() - col.rgb.setValue(vobj.LineColor[0],vobj.LineColor[1],vobj.LineColor[2]) - self.coords = coin.SoTransform() - self.pt = coin.SoSeparator() - self.pt.addChild(col) - self.pt.addChild(self.coords) - self.symbol = gui_utils.dim_symbol() - self.pt.addChild(self.symbol) + + self.color = coin.SoBaseColor() + self.color.rgb.setValue(*vobj.LineColor[:3]) + + self.startSymbol = gui_utils.dim_symbol() + self.coords1 = coin.SoTransform() + self.pt1 = coin.SoSeparator() + self.pt1.addChild(self.color) + self.pt1.addChild(self.coords1) + self.pt1.addChild(self.startSymbol) + + self.endSymbol = gui_utils.dim_symbol() + self.coords2 = coin.SoTransform() + self.pt2 = coin.SoSeparator() + self.pt2.addChild(self.color) + self.pt2.addChild(self.coords2) + self.pt2.addChild(self.endSymbol) + super(ViewProviderWire, self).attach(vobj) - self.onChanged(vobj,"EndArrow") + self.onChanged(vobj, "ArrowSizeStart") def updateData(self, obj, prop): - if prop == "Points": - if obj.Points: - p = obj.Points[-1] - if hasattr(self,"coords"): - self.coords.translation.setValue((p.x,p.y,p.z)) - if len(obj.Points) >= 2: - v1 = obj.Points[-2].sub(obj.Points[-1]) - if not DraftVecUtils.isNull(v1): - v1.normalize() - _rot = coin.SbRotation() - _rot.setValue(coin.SbVec3f(1, 0, 0), coin.SbVec3f(v1[0], v1[1], v1[2])) - self.coords.rotation.setValue(_rot) - return + if prop == "Points" \ + and len(obj.Points) >= 2 \ + and hasattr(self, "coords1") \ + and hasattr(self, "coords2"): + self.coords1.translation.setValue(*obj.Points[0]) + v1 = obj.Points[1].sub(obj.Points[0]) + if not DraftVecUtils.isNull(v1): + v1.normalize() + rot1 = coin.SbRotation() + rot1.setValue(coin.SbVec3f(1, 0, 0), coin.SbVec3f(*v1)) + self.coords1.rotation.setValue(rot1) + self.coords2.translation.setValue(*obj.Points[-1]) + v2 = obj.Points[-2].sub(obj.Points[-1]) + if not DraftVecUtils.isNull(v2): + v2.normalize() + rot2 = coin.SbRotation() + rot2.setValue(coin.SbVec3f(1, 0, 0), coin.SbVec3f(*v2)) + self.coords2.rotation.setValue(rot2) def onChanged(self, vobj, prop): - if prop in ["EndArrow","ArrowSize","ArrowType","Visibility"]: + if prop in ["ArrowSizeStart", + "ArrowSizeEnd", + "ArrowTypeStart", + "ArrowTypeEnd", + "Visibility"] \ + and hasattr(vobj, "ArrowSizeStart") \ + and hasattr(vobj, "ArrowSizeEnd") \ + and hasattr(vobj, "ArrowTypeStart") \ + and hasattr(vobj, "ArrowTypeEnd") \ + and hasattr(vobj, "Visibility") \ + and hasattr(self, "pt1") \ + and hasattr(self, "pt2"): rn = vobj.RootNode - if hasattr(self,"pt") and hasattr(vobj,"EndArrow"): - if vobj.EndArrow and vobj.Visibility: - self.pt.removeChild(self.symbol) - s = utils.ARROW_TYPES.index(vobj.ArrowType) - self.symbol = gui_utils.dim_symbol(s) - self.pt.addChild(self.symbol) - self.updateData(vobj.Object,"Points") - if hasattr(vobj,"ArrowSize"): - s = vobj.ArrowSize - else: - s = params.get_param("arrowsize") - self.coords.scaleFactor.setValue((s,s,s)) - rn.addChild(self.pt) - else: - if self.symbol: - if self.pt.findChild(self.symbol) != -1: - self.pt.removeChild(self.symbol) - if rn.findChild(self.pt) != -1: - rn.removeChild(self.pt) + rn.removeChild(self.pt1) + rn.removeChild(self.pt2) + if vobj.Visibility: + self.pt1.removeChild(self.startSymbol) + self.startSymbol = gui_utils.dim_symbol(utils.ARROW_TYPES.index(vobj.ArrowTypeStart)) + self.pt1.addChild(self.startSymbol) + self.coords1.scaleFactor.setValue([vobj.ArrowSizeStart] * 3) - if prop in ["LineColor"]: - if hasattr(self, "pt"): - self.pt[0].rgb.setValue(vobj.LineColor[0],vobj.LineColor[1],vobj.LineColor[2]) + self.pt2.removeChild(self.endSymbol) + self.endSymbol = gui_utils.dim_symbol(utils.ARROW_TYPES.index(vobj.ArrowTypeEnd)) + self.pt2.addChild(self.endSymbol) + self.coords2.scaleFactor.setValue([vobj.ArrowSizeEnd] * 3) - super(ViewProviderWire, self).onChanged(vobj, prop) + self.updateData(vobj.Object, "Points") + rn.addChild(self.pt1) + rn.addChild(self.pt2) + + if prop == "LineColor" \ + and hasattr(vobj, "LineColor") \ + and hasattr(self, "pt1") \ + and hasattr(self, "pt2"): + self.color.rgb.setValue(*vobj.LineColor[:3]) + + super().onChanged(vobj, prop) return def claimChildren(self):