meerk40t 0.9.7030__py2.py3-none-any.whl → 0.9.7040__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. meerk40t/balormk/clone_loader.py +3 -2
  2. meerk40t/balormk/controller.py +28 -11
  3. meerk40t/balormk/cylindermod.py +1 -0
  4. meerk40t/balormk/device.py +13 -9
  5. meerk40t/balormk/driver.py +9 -2
  6. meerk40t/balormk/galvo_commands.py +3 -1
  7. meerk40t/balormk/gui/gui.py +6 -0
  8. meerk40t/balormk/livelightjob.py +338 -321
  9. meerk40t/balormk/mock_connection.py +4 -3
  10. meerk40t/balormk/usb_connection.py +11 -2
  11. meerk40t/camera/camera.py +19 -14
  12. meerk40t/camera/gui/camerapanel.py +6 -0
  13. meerk40t/core/cutplan.py +109 -51
  14. meerk40t/core/elements/element_treeops.py +435 -140
  15. meerk40t/core/elements/elements.py +100 -9
  16. meerk40t/core/elements/shapes.py +259 -39
  17. meerk40t/core/elements/tree_commands.py +10 -5
  18. meerk40t/core/node/elem_ellipse.py +18 -8
  19. meerk40t/core/node/elem_image.py +51 -19
  20. meerk40t/core/node/elem_line.py +18 -8
  21. meerk40t/core/node/elem_path.py +18 -8
  22. meerk40t/core/node/elem_point.py +10 -4
  23. meerk40t/core/node/elem_polyline.py +19 -11
  24. meerk40t/core/node/elem_rect.py +18 -8
  25. meerk40t/core/node/elem_text.py +11 -5
  26. meerk40t/core/node/filenode.py +2 -8
  27. meerk40t/core/node/groupnode.py +11 -11
  28. meerk40t/core/node/image_processed.py +11 -5
  29. meerk40t/core/node/image_raster.py +11 -5
  30. meerk40t/core/node/node.py +64 -16
  31. meerk40t/core/node/refnode.py +2 -1
  32. meerk40t/core/svg_io.py +91 -34
  33. meerk40t/device/dummydevice.py +7 -1
  34. meerk40t/extra/vtracer.py +222 -0
  35. meerk40t/grbl/device.py +81 -8
  36. meerk40t/gui/about.py +20 -0
  37. meerk40t/gui/devicepanel.py +20 -16
  38. meerk40t/gui/gui_mixins.py +4 -0
  39. meerk40t/gui/icons.py +330 -253
  40. meerk40t/gui/laserpanel.py +8 -3
  41. meerk40t/gui/laserrender.py +41 -21
  42. meerk40t/gui/magnetoptions.py +158 -65
  43. meerk40t/gui/materialtest.py +229 -39
  44. meerk40t/gui/navigationpanels.py +229 -24
  45. meerk40t/gui/propertypanels/hatchproperty.py +2 -0
  46. meerk40t/gui/propertypanels/imageproperty.py +160 -106
  47. meerk40t/gui/ribbon.py +6 -1
  48. meerk40t/gui/scenewidgets/gridwidget.py +29 -32
  49. meerk40t/gui/scenewidgets/rectselectwidget.py +190 -192
  50. meerk40t/gui/simulation.py +75 -77
  51. meerk40t/gui/statusbarwidgets/defaultoperations.py +84 -48
  52. meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
  53. meerk40t/gui/tips.py +15 -1
  54. meerk40t/gui/toolwidgets/toolpointmove.py +3 -1
  55. meerk40t/gui/wxmmain.py +242 -114
  56. meerk40t/gui/wxmscene.py +107 -24
  57. meerk40t/gui/wxmtree.py +4 -2
  58. meerk40t/gui/wxutils.py +60 -15
  59. meerk40t/image/imagetools.py +129 -65
  60. meerk40t/internal_plugins.py +4 -0
  61. meerk40t/kernel/kernel.py +39 -18
  62. meerk40t/kernel/settings.py +28 -9
  63. meerk40t/lihuiyu/device.py +24 -12
  64. meerk40t/main.py +1 -1
  65. meerk40t/moshi/device.py +20 -6
  66. meerk40t/network/console_server.py +22 -6
  67. meerk40t/newly/device.py +10 -3
  68. meerk40t/newly/gui/gui.py +10 -0
  69. meerk40t/ruida/device.py +22 -2
  70. meerk40t/ruida/loader.py +6 -3
  71. meerk40t/tools/geomstr.py +193 -125
  72. meerk40t/tools/rasterplotter.py +179 -93
  73. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/METADATA +1 -1
  74. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/RECORD +79 -78
  75. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/LICENSE +0 -0
  76. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/WHEEL +0 -0
  77. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/entry_points.txt +0 -0
  78. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/top_level.txt +0 -0
  79. {meerk40t-0.9.7030.dist-info → meerk40t-0.9.7040.dist-info}/zip-safe +0 -0
@@ -112,7 +112,18 @@ from meerk40t.kernel import CommandSyntaxError
112
112
  from meerk40t.svgelements import Matrix, Point
113
113
  from meerk40t.tools.geomstr import Geomstr
114
114
 
115
- from .element_types import *
115
+ from .element_types import (
116
+ effect_nodes,
117
+ elem_group_nodes,
118
+ elem_nodes,
119
+ elem_ref_nodes,
120
+ non_structural_nodes,
121
+ op_burnable_nodes,
122
+ op_image_nodes,
123
+ op_nodes,
124
+ op_parent_nodes,
125
+ op_vector_nodes,
126
+ )
116
127
 
117
128
 
118
129
  def plugin(kernel, lifecycle=None):
@@ -158,7 +169,10 @@ def init_tree(kernel):
158
169
  ## @tree_separator_after()
159
170
  @tree_conditional(lambda node: len(list(self.ops(selected=True))) == 1)
160
171
  @tree_operation(
161
- _("Operation properties"), node_type=op_nodes, help=_("Open property window for operation"), grouping="00PROPS"
172
+ _("Operation properties"),
173
+ node_type=op_nodes,
174
+ help=_("Open property window for operation"),
175
+ grouping="00PROPS",
162
176
  )
163
177
  def operation_property(node, **kwargs):
164
178
  activate = self.kernel.lookup("function/open_property_window_for_node")
@@ -166,7 +180,12 @@ def init_tree(kernel):
166
180
  activate(node)
167
181
 
168
182
  ## @tree_separator_after()
169
- @tree_operation(_("Edit"), node_type="util console", help=_("Modify console command"), grouping="00PROPS")
183
+ @tree_operation(
184
+ _("Edit"),
185
+ node_type="util console",
186
+ help=_("Modify console command"),
187
+ grouping="00PROPS",
188
+ )
170
189
  def edit_console_command(node, **kwargs):
171
190
  activate = self.kernel.lookup("function/open_property_window_for_node")
172
191
  if activate is not None:
@@ -286,7 +305,10 @@ def init_tree(kernel):
286
305
  """
287
306
 
288
307
  @tree_operation(
289
- _("Remove effect"), node_type=effect_nodes, help=_("Remove hatch/wobble"), grouping="10_ELEM_DELETION"
308
+ _("Remove effect"),
309
+ node_type=effect_nodes,
310
+ help=_("Remove hatch/wobble"),
311
+ grouping="10_ELEM_DELETION",
290
312
  )
291
313
  def remove_effect(node, **kwargs):
292
314
  with self.undoscope("Remove effect"):
@@ -300,7 +322,10 @@ def init_tree(kernel):
300
322
 
301
323
  @tree_conditional(lambda node: is_hatched(node))
302
324
  @tree_operation(
303
- _("Remove effect"), node_type=elem_nodes, help=_("Remove surrounding hatch/wobble"), grouping="10_ELEM_DELETION"
325
+ _("Remove effect"),
326
+ node_type=elem_nodes,
327
+ help=_("Remove surrounding hatch/wobble"),
328
+ grouping="10_ELEM_DELETION",
304
329
  )
305
330
  def unhatch_elements(node, **kwargs):
306
331
  # Language hint: _("Remove effect")
@@ -367,7 +392,9 @@ def init_tree(kernel):
367
392
  def ungroup_elements(node, **kwargs):
368
393
  with self.undoscope("Ungroup elements"):
369
394
  to_treat = []
370
- for gnode in self.flat(selected=True, cascade=False, types=("group", "file")):
395
+ for gnode in self.flat(
396
+ selected=True, cascade=False, types=("group", "file")
397
+ ):
371
398
  enode = gnode
372
399
  while True:
373
400
  if enode.parent is None or enode.parent is self.elem_branch:
@@ -449,9 +476,9 @@ def init_tree(kernel):
449
476
  for e in dataset:
450
477
  if not hasattr(e, "hidden"):
451
478
  continue
452
- if mode==0:
479
+ if mode == 0:
453
480
  e.hidden = True
454
- elif mode==1:
481
+ elif mode == 1:
455
482
  e.hidden = False
456
483
  else:
457
484
  e.hidden = not e.hidden
@@ -706,7 +733,10 @@ def init_tree(kernel):
706
733
 
707
734
  @tree_submenu(_("Burning sequence"))
708
735
  @tree_operation(
709
- _("Burn first"), node_type=op_parent_nodes, help=_("Establish the sequence of operations during burntime"), grouping="OPS_40_SEQUENCE"
736
+ _("Burn first"),
737
+ node_type=op_parent_nodes,
738
+ help=_("Establish the sequence of operations during burntime"),
739
+ grouping="OPS_40_SEQUENCE",
710
740
  )
711
741
  def burn_first(node, **kwargs):
712
742
  move_op(node, "top")
@@ -723,14 +753,20 @@ def init_tree(kernel):
723
753
 
724
754
  @tree_submenu(_("Burning sequence"))
725
755
  @tree_operation(
726
- _("Burn later"), node_type=op_parent_nodes, help=_("Establish the sequence of operations during burntime"), grouping="OPS_40_SEQUENCE"
756
+ _("Burn later"),
757
+ node_type=op_parent_nodes,
758
+ help=_("Establish the sequence of operations during burntime"),
759
+ grouping="OPS_40_SEQUENCE",
727
760
  )
728
761
  def burn_later(node, **kwargs):
729
762
  move_op(node, "down")
730
763
 
731
764
  @tree_submenu(_("Burning sequence"))
732
765
  @tree_operation(
733
- _("Burn last"), node_type=op_parent_nodes, help=_("Establish the sequence of operations during burntime"), grouping="OPS_40_SEQUENCE"
766
+ _("Burn last"),
767
+ node_type=op_parent_nodes,
768
+ help=_("Establish the sequence of operations during burntime"),
769
+ grouping="OPS_40_SEQUENCE",
734
770
  )
735
771
  def burn_last(node, **kwargs):
736
772
  move_op(node, "bottom")
@@ -739,7 +775,9 @@ def init_tree(kernel):
739
775
  @tree_operation(
740
776
  _("Convert to Image"),
741
777
  node_type=op_parent_nodes,
742
- help=_("Convert an operation to a different type maintaining properties and assigned elements"),
778
+ help=_(
779
+ "Convert an operation to a different type maintaining properties and assigned elements"
780
+ ),
743
781
  grouping="OPS_60_CONVERSION",
744
782
  )
745
783
  def convert_operation_image(node, **kwargs):
@@ -748,6 +786,8 @@ def init_tree(kernel):
748
786
  return
749
787
  with self.undoscope("Convert to Image"):
750
788
  for n in data:
789
+ if n.type not in op_parent_nodes:
790
+ continue
751
791
  new_settings = dict(n.settings)
752
792
  new_settings["type"] = "op image"
753
793
  n.replace_node(keep_children=True, **new_settings)
@@ -757,7 +797,9 @@ def init_tree(kernel):
757
797
  @tree_operation(
758
798
  _("Convert to Raster"),
759
799
  node_type=op_parent_nodes,
760
- help=_("Convert an operation to a different type maintaining properties and assigned elements"),
800
+ help=_(
801
+ "Convert an operation to a different type maintaining properties and assigned elements"
802
+ ),
761
803
  grouping="OPS_60_CONVERSION",
762
804
  )
763
805
  def convert_operation_raster(node, **kwargs):
@@ -766,6 +808,8 @@ def init_tree(kernel):
766
808
  return
767
809
  with self.undoscope("Convert to Raster"):
768
810
  for n in data:
811
+ if n.type not in op_parent_nodes:
812
+ continue
769
813
  new_settings = dict(n.settings)
770
814
  new_settings["type"] = "op raster"
771
815
  n.replace_node(keep_children=True, **new_settings)
@@ -775,7 +819,9 @@ def init_tree(kernel):
775
819
  @tree_operation(
776
820
  _("Convert to Engrave"),
777
821
  node_type=op_parent_nodes,
778
- help=_("Convert an operation to a different type maintaining properties and assigned elements"),
822
+ help=_(
823
+ "Convert an operation to a different type maintaining properties and assigned elements"
824
+ ),
779
825
  grouping="OPS_60_CONVERSION",
780
826
  )
781
827
  def convert_operation_engrave(node, **kwargs):
@@ -784,6 +830,8 @@ def init_tree(kernel):
784
830
  return
785
831
  with self.undoscope("Convert to Engrave"):
786
832
  for n in data:
833
+ if n.type not in op_parent_nodes:
834
+ continue
787
835
  new_settings = dict(n.settings)
788
836
  new_settings["type"] = "op engrave"
789
837
  n.replace_node(keep_children=True, **new_settings)
@@ -793,7 +841,9 @@ def init_tree(kernel):
793
841
  @tree_operation(
794
842
  _("Convert to Cut"),
795
843
  node_type=op_parent_nodes,
796
- help=_("Convert an operation to a different type maintaining properties and assigned elements"),
844
+ help=_(
845
+ "Convert an operation to a different type maintaining properties and assigned elements"
846
+ ),
797
847
  grouping="OPS_60_CONVERSION",
798
848
  )
799
849
  def convert_operation_cut(node, **kwargs):
@@ -802,6 +852,8 @@ def init_tree(kernel):
802
852
  return
803
853
  with self.undoscope("Convert to Cut"):
804
854
  for n in data:
855
+ if n.type not in op_parent_nodes:
856
+ continue
805
857
  new_settings = dict(n.settings)
806
858
  new_settings["type"] = "op cut"
807
859
  n.replace_node(keep_children=True, **new_settings)
@@ -811,7 +863,9 @@ def init_tree(kernel):
811
863
  @tree_operation(
812
864
  _("Convert to Dots"),
813
865
  node_type=op_parent_nodes,
814
- help=_("Convert an operation to a different type maintaining properties and assigned elements"),
866
+ help=_(
867
+ "Convert an operation to a different type maintaining properties and assigned elements"
868
+ ),
815
869
  grouping="OPS_60_CONVERSION",
816
870
  )
817
871
  def convert_operation_dots(node, **kwargs):
@@ -820,6 +874,8 @@ def init_tree(kernel):
820
874
  return
821
875
  with self.undoscope("Convert to Dots"):
822
876
  for n in data:
877
+ if n.type not in op_parent_nodes:
878
+ continue
823
879
  new_settings = dict(n.settings)
824
880
  new_settings["type"] = "op dots"
825
881
  n.replace_node(keep_children=True, **new_settings)
@@ -827,7 +883,10 @@ def init_tree(kernel):
827
883
 
828
884
  @tree_submenu(_("Raster-Wizard"))
829
885
  @tree_operation(
830
- _("Set to None"), node_type="elem image", help=_("Remove stored image operations"), grouping="70_ELEM_IMAGES"
886
+ _("Set to None"),
887
+ node_type="elem image",
888
+ help=_("Remove stored image operations"),
889
+ grouping="70_ELEM_IMAGES",
831
890
  )
832
891
  def image_rasterwizard_apply_none(node, **kwargs):
833
892
  data = []
@@ -851,7 +910,10 @@ def init_tree(kernel):
851
910
  @tree_submenu(_("Raster-Wizard"))
852
911
  @tree_values("script", values=list(self.match("raster_script", suffix=True)))
853
912
  @tree_operation(
854
- _("Apply: {script}"), node_type="elem image", help=_("Apply a predefined script to an image"), grouping="70_ELEM_IMAGES"
913
+ _("Apply: {script}"),
914
+ node_type="elem image",
915
+ help=_("Apply a predefined script to an image"),
916
+ grouping="70_ELEM_IMAGES",
855
917
  )
856
918
  def image_rasterwizard_apply(node, script=None, **kwargs):
857
919
  raster_script = self.lookup(f"raster_script/{script}")
@@ -888,11 +950,12 @@ def init_tree(kernel):
888
950
  image, box = node.as_image()
889
951
  vertical = mode.lower() != "horizontal"
890
952
  bidirectional = self._image_2_path_bidirectional
891
- threshold = 0.5 if self._image_2_path_optimize else None # Half a percent
953
+ threshold = 0.5 if self._image_2_path_optimize else None # Half a percent
892
954
  geom = Geomstr.image(
893
- image, vertical=vertical,
894
- bidirectional=bidirectional,
895
- )
955
+ image,
956
+ vertical=vertical,
957
+ bidirectional=bidirectional,
958
+ )
896
959
  if threshold:
897
960
  geom.two_opt_distance(auto_stop_threshold=threshold, feedback=feedback)
898
961
  # self.context
@@ -915,7 +978,10 @@ def init_tree(kernel):
915
978
 
916
979
  @tree_submenu(_("Convert to Path"))
917
980
  @tree_operation(
918
- _("Horizontal"), node_type="elem image", help=_("Create a horizontal linepattern from the image"), grouping="70_ELEM_IMAGES_Y"
981
+ _("Horizontal"),
982
+ node_type="elem image",
983
+ help=_("Create a horizontal linepattern from the image"),
984
+ grouping="70_ELEM_IMAGES_Y",
919
985
  )
920
986
  def image_convert_to_path_horizontal(node, **kwargs):
921
987
  # Language hint _("To path: Horizontal")
@@ -923,7 +989,10 @@ def init_tree(kernel):
923
989
 
924
990
  @tree_submenu(_("Convert to Path"))
925
991
  @tree_operation(
926
- _("Vertical"), node_type="elem image", help=_("Create a vertical linepattern from the image"), grouping="70_ELEM_IMAGES_Y"
992
+ _("Vertical"),
993
+ node_type="elem image",
994
+ help=_("Create a vertical linepattern from the image"),
995
+ grouping="70_ELEM_IMAGES_Y",
927
996
  )
928
997
  def image_convert_to_path_vertical(node, **kwargs):
929
998
  convert_image_to_path(node, "Vertical")
@@ -940,7 +1009,9 @@ def init_tree(kernel):
940
1009
  @tree_operation(
941
1010
  _("Bidirectional"),
942
1011
  node_type="elem image",
943
- help=_("Shall the line pattern be able to travel back and forth or will it always start at the same side"),
1012
+ help=_(
1013
+ "Shall the line pattern be able to travel back and forth or will it always start at the same side"
1014
+ ),
944
1015
  grouping="70_ELEM_IMAGES_Y",
945
1016
  )
946
1017
  def set_img_2_path_option_1(node, **kwargs):
@@ -951,13 +1022,14 @@ def init_tree(kernel):
951
1022
  @tree_operation(
952
1023
  _("Optimize travel"),
953
1024
  node_type="elem image",
954
- help=_("Shall the line pattern be able to travel back and forth or will it always start at the same side"),
1025
+ help=_(
1026
+ "Shall the line pattern be able to travel back and forth or will it always start at the same side"
1027
+ ),
955
1028
  grouping="70_ELEM_IMAGES_Y",
956
1029
  )
957
1030
  def set_img_2_path_option_2(node, **kwargs):
958
1031
  self._image_2_path_optimize = not self._image_2_path_optimize
959
1032
 
960
-
961
1033
  def radio_match_speed(node, speed=0, **kwargs):
962
1034
  return node.speed == float(speed)
963
1035
 
@@ -965,7 +1037,10 @@ def init_tree(kernel):
965
1037
  @tree_radio(radio_match_speed)
966
1038
  @tree_values("speed", (5, 10, 50, 75, 100, 150, 200, 250, 300, 350, 400, 450, 500))
967
1039
  @tree_operation(
968
- _("{speed}mm/s"), node_type=op_image_nodes, help=_("Set speed for the operation"), grouping="OPS_70_MODIFY"
1040
+ _("{speed}mm/s"),
1041
+ node_type=op_image_nodes,
1042
+ help=_("Set speed for the operation"),
1043
+ grouping="OPS_70_MODIFY",
969
1044
  )
970
1045
  def set_speed_raster(node, speed=150, **kwargs):
971
1046
  data = list()
@@ -984,7 +1059,10 @@ def init_tree(kernel):
984
1059
  @tree_radio(radio_match_speed)
985
1060
  @tree_values("speed", (2, 3, 4, 5, 6, 7, 10, 15, 20, 25, 30, 35, 40, 50))
986
1061
  @tree_operation(
987
- _("{speed}mm/s"), node_type=op_vector_nodes, help=_("Set speed for the operation"), grouping="OPS_70_MODIFY"
1062
+ _("{speed}mm/s"),
1063
+ node_type=op_vector_nodes,
1064
+ help=_("Set speed for the operation"),
1065
+ grouping="OPS_70_MODIFY",
988
1066
  )
989
1067
  def set_speed_vector_cut(node, speed=20, **kwargs):
990
1068
  data = list()
@@ -1302,7 +1380,10 @@ def init_tree(kernel):
1302
1380
  activate(node)
1303
1381
 
1304
1382
  @tree_operation(
1305
- _("Clear all"), node_type="branch ops", help=_("Delete all operations"), grouping="10_OPS_DELETION"
1383
+ _("Clear all"),
1384
+ node_type="branch ops",
1385
+ help=_("Delete all operations"),
1386
+ grouping="10_OPS_DELETION",
1306
1387
  )
1307
1388
  def clear_all(node, **kwargs):
1308
1389
  if self.kernel.yesno(
@@ -1461,7 +1542,10 @@ def init_tree(kernel):
1461
1542
  # ==========
1462
1543
 
1463
1544
  @tree_operation(
1464
- _("Clear all"), node_type="branch elems", help=_("Delete all elements"), grouping="10_ELEM_DELETION"
1545
+ _("Clear all"),
1546
+ node_type="branch elems",
1547
+ help=_("Delete all elements"),
1548
+ grouping="10_ELEM_DELETION",
1465
1549
  )
1466
1550
  def clear_all_elems(node, **kwargs):
1467
1551
  # self("element* delete\n")
@@ -1477,7 +1561,10 @@ def init_tree(kernel):
1477
1561
  # ==========
1478
1562
 
1479
1563
  @tree_operation(
1480
- _("Clear all"), node_type="branch reg", help=_("Delete all registration marks"), grouping="REG_05_DELETION"
1564
+ _("Clear all"),
1565
+ node_type="branch reg",
1566
+ help=_("Delete all registration marks"),
1567
+ grouping="REG_05_DELETION",
1481
1568
  )
1482
1569
  def clear_all_regmarks(node, **kwargs):
1483
1570
  if self.kernel.yesno(
@@ -1624,10 +1711,18 @@ def init_tree(kernel):
1624
1711
  def remove_type_file(node, **kwargs):
1625
1712
  to_be_removed = [node]
1626
1713
  for e in self.elem_branch.children:
1627
- if e.type == "file" and e.filepath == node.filepath and e not in to_be_removed:
1714
+ if (
1715
+ e.type == "file"
1716
+ and e.filepath == node.filepath
1717
+ and e not in to_be_removed
1718
+ ):
1628
1719
  to_be_removed.append(e)
1629
1720
  for e in self.reg_branch.children:
1630
- if e.type == "file" and e.filepath == node.filepath and e not in to_be_removed:
1721
+ if (
1722
+ e.type == "file"
1723
+ and e.filepath == node.filepath
1724
+ and e not in to_be_removed
1725
+ ):
1631
1726
  to_be_removed.append(e)
1632
1727
  if len(to_be_removed) == 0:
1633
1728
  return
@@ -1864,9 +1959,7 @@ def init_tree(kernel):
1864
1959
  node.remove_node()
1865
1960
  return True
1866
1961
 
1867
- @tree_conditional_try(
1868
- lambda node: node.data_type == "egv"
1869
- )
1962
+ @tree_conditional_try(lambda node: node.data_type == "egv")
1870
1963
  @tree_operation(
1871
1964
  _("Convert to Elements"),
1872
1965
  node_type="blob",
@@ -1875,6 +1968,7 @@ def init_tree(kernel):
1875
1968
  )
1876
1969
  def egv2path(node, **kwargs):
1877
1970
  from meerk40t.lihuiyu.parser import LihuiyuParser
1971
+
1878
1972
  parser = LihuiyuParser()
1879
1973
  parser.fix_speeds = True
1880
1974
  parser.parse(node.data, self)
@@ -1928,7 +2022,10 @@ def init_tree(kernel):
1928
2022
 
1929
2023
  @tree_submenu(_("Clone reference"))
1930
2024
  @tree_operation(
1931
- _("Make 1 copy"), node_type=("reference",), help=_("Add an additional reference of the master element"), grouping="20_OPS_DUPLICATION"
2025
+ _("Make 1 copy"),
2026
+ node_type=("reference",),
2027
+ help=_("Add an additional reference of the master element"),
2028
+ grouping="20_OPS_DUPLICATION",
1932
2029
  )
1933
2030
  def clone_single_element_op(node, **kwargs):
1934
2031
  clone_element_op(node, copies=1, **kwargs)
@@ -2220,7 +2317,12 @@ def init_tree(kernel):
2220
2317
  @tree_values("opname", values=material_ids)
2221
2318
  @tree_submenu_list(material_menus)
2222
2319
  @tree_calc("material", lambda opname: material_name(opname))
2223
- @tree_operation("{material}", node_type="branch ops", help=_("Populate the operation template list at the bottom"), grouping="OPS_60_MATMAN")
2320
+ @tree_operation(
2321
+ "{material}",
2322
+ node_type="branch ops",
2323
+ help=_("Populate the operation template list at the bottom"),
2324
+ grouping="OPS_60_MATMAN",
2325
+ )
2224
2326
  def load_ops(node, opname, **kwargs):
2225
2327
  self(f"material load {opname}\n")
2226
2328
  if self.update_statusbar_on_material_load:
@@ -2290,7 +2392,10 @@ def init_tree(kernel):
2290
2392
  ## @tree_separator_before()
2291
2393
  @tree_submenu(_("Append operation"))
2292
2394
  @tree_operation(
2293
- _("Append Image"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2395
+ _("Append Image"),
2396
+ node_type="branch ops",
2397
+ help=_("Add an operation to the tree"),
2398
+ grouping="OPS_40_ADDITION",
2294
2399
  )
2295
2400
  def append_operation_image(node, pos=None, **kwargs):
2296
2401
  with self.undoscope("Append operation"):
@@ -2299,7 +2404,10 @@ def init_tree(kernel):
2299
2404
 
2300
2405
  @tree_submenu(_("Append operation"))
2301
2406
  @tree_operation(
2302
- _("Append Raster"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2407
+ _("Append Raster"),
2408
+ node_type="branch ops",
2409
+ help=_("Add an operation to the tree"),
2410
+ grouping="OPS_40_ADDITION",
2303
2411
  )
2304
2412
  def append_operation_raster(node, pos=None, **kwargs):
2305
2413
  with self.undoscope("Append operation"):
@@ -2308,7 +2416,10 @@ def init_tree(kernel):
2308
2416
 
2309
2417
  @tree_submenu(_("Append operation"))
2310
2418
  @tree_operation(
2311
- _("Append Engrave"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2419
+ _("Append Engrave"),
2420
+ node_type="branch ops",
2421
+ help=_("Add an operation to the tree"),
2422
+ grouping="OPS_40_ADDITION",
2312
2423
  )
2313
2424
  def append_operation_engrave(node, pos=None, **kwargs):
2314
2425
  with self.undoscope("Append operation"):
@@ -2317,7 +2428,10 @@ def init_tree(kernel):
2317
2428
 
2318
2429
  @tree_submenu(_("Append operation"))
2319
2430
  @tree_operation(
2320
- _("Append Cut"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2431
+ _("Append Cut"),
2432
+ node_type="branch ops",
2433
+ help=_("Add an operation to the tree"),
2434
+ grouping="OPS_40_ADDITION",
2321
2435
  )
2322
2436
  def append_operation_cut(node, pos=None, **kwargs):
2323
2437
  with self.undoscope("Append operation"):
@@ -2326,7 +2440,10 @@ def init_tree(kernel):
2326
2440
 
2327
2441
  @tree_submenu(_("Append operation"))
2328
2442
  @tree_operation(
2329
- _("Append new Hatch"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2443
+ _("Append new Hatch"),
2444
+ node_type="branch ops",
2445
+ help=_("Add an operation to the tree"),
2446
+ grouping="OPS_40_ADDITION",
2330
2447
  )
2331
2448
  def append_operation_hatch(node, pos=None, **kwargs):
2332
2449
  with self.undoscope("Append operation"):
@@ -2336,7 +2453,10 @@ def init_tree(kernel):
2336
2453
 
2337
2454
  @tree_submenu(_("Append operation"))
2338
2455
  @tree_operation(
2339
- _("Append Dots"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2456
+ _("Append Dots"),
2457
+ node_type="branch ops",
2458
+ help=_("Add an operation to the tree"),
2459
+ grouping="OPS_40_ADDITION",
2340
2460
  )
2341
2461
  def append_operation_dots(node, pos=None, **kwargs):
2342
2462
  self.op_branch.add("op dots", pos=pos)
@@ -2344,7 +2464,10 @@ def init_tree(kernel):
2344
2464
 
2345
2465
  @tree_submenu(_("Append special operation(s)"))
2346
2466
  @tree_operation(
2347
- _("Append Home"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2467
+ _("Append Home"),
2468
+ node_type="branch ops",
2469
+ help=_("Add an operation to the tree"),
2470
+ grouping="OPS_40_ADDITION",
2348
2471
  )
2349
2472
  def append_operation_home(node, pos=None, **kwargs):
2350
2473
  with self.undoscope("Append operation"):
@@ -2383,7 +2506,10 @@ def init_tree(kernel):
2383
2506
 
2384
2507
  @tree_submenu(_("Append special operation(s)"))
2385
2508
  @tree_operation(
2386
- _("Append Beep"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2509
+ _("Append Beep"),
2510
+ node_type="branch ops",
2511
+ help=_("Add an operation to the tree"),
2512
+ grouping="OPS_40_ADDITION",
2387
2513
  )
2388
2514
  def append_operation_beep(node, pos=None, **kwargs):
2389
2515
  with self.undoscope("Append operation"):
@@ -2413,7 +2539,10 @@ def init_tree(kernel):
2413
2539
  @tree_submenu(_("Append special operation(s)"))
2414
2540
  @tree_prompt("wait_time", _("Wait for how long (in seconds)?"), data_type=float)
2415
2541
  @tree_operation(
2416
- _("Append Wait"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2542
+ _("Append Wait"),
2543
+ node_type="branch ops",
2544
+ help=_("Add an operation to the tree"),
2545
+ grouping="OPS_40_ADDITION",
2417
2546
  )
2418
2547
  def append_operation_wait(node, wait_time, pos=None, **kwargs):
2419
2548
  with self.undoscope("Append operation"):
@@ -2426,7 +2555,10 @@ def init_tree(kernel):
2426
2555
 
2427
2556
  @tree_submenu(_("Append special operation(s)"))
2428
2557
  @tree_operation(
2429
- _("Append Output"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2558
+ _("Append Output"),
2559
+ node_type="branch ops",
2560
+ help=_("Add an operation to the tree"),
2561
+ grouping="OPS_40_ADDITION",
2430
2562
  )
2431
2563
  def append_operation_output(node, pos=None, **kwargs):
2432
2564
  with self.undoscope("Append operation"):
@@ -2441,7 +2573,10 @@ def init_tree(kernel):
2441
2573
 
2442
2574
  @tree_submenu(_("Append special operation(s)"))
2443
2575
  @tree_operation(
2444
- _("Append Input"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2576
+ _("Append Input"),
2577
+ node_type="branch ops",
2578
+ help=_("Add an operation to the tree"),
2579
+ grouping="OPS_40_ADDITION",
2445
2580
  )
2446
2581
  def append_operation_input(node, pos=None, **kwargs):
2447
2582
  with self.undoscope("Append operation"):
@@ -2532,7 +2667,10 @@ def init_tree(kernel):
2532
2667
  @tree_submenu(_("Append special operation(s)"))
2533
2668
  @tree_prompt("opname", _("Console command to append to operations?"))
2534
2669
  @tree_operation(
2535
- _("Append Console"), node_type="branch ops", help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
2670
+ _("Append Console"),
2671
+ node_type="branch ops",
2672
+ help=_("Add an operation to the tree"),
2673
+ grouping="OPS_40_ADDITION",
2536
2674
  )
2537
2675
  def append_operation_custom(node, opname, pos=None, **kwargs):
2538
2676
  with self.undoscope("Append operation"):
@@ -2627,7 +2765,12 @@ def init_tree(kernel):
2627
2765
  self.signal("updateelem_tree")
2628
2766
 
2629
2767
  @tree_submenu(_("Apply special effect"))
2630
- @tree_operation(_("Append Line-fill 0.1mm"), node_type=hatchable_elems, help=_("Apply hatch"), grouping="50_ELEM_MODIFY_ZMISC")
2768
+ @tree_operation(
2769
+ _("Append Line-fill 0.1mm"),
2770
+ node_type=hatchable_elems,
2771
+ help=_("Apply hatch"),
2772
+ grouping="50_ELEM_MODIFY_ZMISC",
2773
+ )
2631
2774
  def append_element_effect_eulerian(node, pos=None, **kwargs):
2632
2775
  hatch_me(
2633
2776
  node,
@@ -2639,7 +2782,10 @@ def init_tree(kernel):
2639
2782
 
2640
2783
  @tree_submenu(_("Apply special effect"))
2641
2784
  @tree_operation(
2642
- _("Append diagonal Line-fill 0.1mm"), node_type=hatchable_elems, help=_("Apply hatch"), grouping="50_ELEM_MODIFY_ZMISC"
2785
+ _("Append diagonal Line-fill 0.1mm"),
2786
+ node_type=hatchable_elems,
2787
+ help=_("Apply hatch"),
2788
+ grouping="50_ELEM_MODIFY_ZMISC",
2643
2789
  )
2644
2790
  def append_element_effect_eulerian_45(node, pos=None, **kwargs):
2645
2791
  hatch_me(
@@ -2651,7 +2797,12 @@ def init_tree(kernel):
2651
2797
  )
2652
2798
 
2653
2799
  @tree_submenu(_("Apply special effect"))
2654
- @tree_operation(_("Append Line-Fill 1mm"), node_type=hatchable_elems, help=_("Apply hatch"), grouping="50_ELEM_MODIFY_ZMISC")
2800
+ @tree_operation(
2801
+ _("Append Line-Fill 1mm"),
2802
+ node_type=hatchable_elems,
2803
+ help=_("Apply hatch"),
2804
+ grouping="50_ELEM_MODIFY_ZMISC",
2805
+ )
2655
2806
  def append_element_effect_line(node, pos=None, **kwargs):
2656
2807
  hatch_me(
2657
2808
  node,
@@ -2663,7 +2814,10 @@ def init_tree(kernel):
2663
2814
 
2664
2815
  @tree_submenu(_("Apply special effect"))
2665
2816
  @tree_operation(
2666
- _("Append diagonal Line-Fill 1mm"), node_type=hatchable_elems, help=_("Apply hatch"), grouping="50_ELEM_MODIFY_ZMISC"
2817
+ _("Append diagonal Line-Fill 1mm"),
2818
+ node_type=hatchable_elems,
2819
+ help=_("Apply hatch"),
2820
+ grouping="50_ELEM_MODIFY_ZMISC",
2667
2821
  )
2668
2822
  def append_element_effect_line_45(node, pos=None, **kwargs):
2669
2823
  hatch_me(
@@ -2809,7 +2963,6 @@ def init_tree(kernel):
2809
2963
  except AttributeError:
2810
2964
  pass
2811
2965
 
2812
-
2813
2966
  @tree_conditional(lambda node: node.count_children() > 1)
2814
2967
  @tree_submenu(_("Duplicate element(s)"))
2815
2968
  @tree_operation(
@@ -2884,7 +3037,7 @@ def init_tree(kernel):
2884
3037
  _("Make raster image"),
2885
3038
  node_type=op_burnable_nodes,
2886
3039
  help=_("Create an image from the assigned elements."),
2887
- grouping="OPS_75_CONVERTIMAGE"
3040
+ grouping="OPS_75_CONVERTIMAGE",
2888
3041
  )
2889
3042
  def make_raster_image(node, **kwargs):
2890
3043
  image, matrix = create_image_from_operation(node)
@@ -2913,11 +3066,12 @@ def init_tree(kernel):
2913
3066
  return
2914
3067
  vertical = mode.lower() != "horizontal"
2915
3068
  bidirectional = self._image_2_path_bidirectional
2916
- threshold = 0.5 if self._image_2_path_optimize else None # Half a percent
3069
+ threshold = 0.5 if self._image_2_path_optimize else None # Half a percent
2917
3070
  geom = Geomstr.image(
2918
- image, vertical=vertical,
2919
- bidirectional=bidirectional,
2920
- )
3071
+ image,
3072
+ vertical=vertical,
3073
+ bidirectional=bidirectional,
3074
+ )
2921
3075
  if threshold:
2922
3076
  geom.two_opt_distance(auto_stop_threshold=threshold, feedback=feedback)
2923
3077
  # self.context
@@ -2940,7 +3094,10 @@ def init_tree(kernel):
2940
3094
  @tree_submenu(_("Create image/path"))
2941
3095
  @tree_separator_before()
2942
3096
  @tree_operation(
2943
- _("Horizontal"), node_type="op raster", help=_("Create a horizontal linepattern from the raster"), grouping="OPS_75_CONVERTIMAGE"
3097
+ _("Horizontal"),
3098
+ node_type="op raster",
3099
+ help=_("Create a horizontal linepattern from the raster"),
3100
+ grouping="OPS_75_CONVERTIMAGE",
2944
3101
  )
2945
3102
  def raster_convert_to_path_horizontal(node, **kwargs):
2946
3103
  # Language hint _("To path: Horizontal")
@@ -2948,7 +3105,10 @@ def init_tree(kernel):
2948
3105
 
2949
3106
  @tree_submenu(_("Create image/path"))
2950
3107
  @tree_operation(
2951
- _("Vertical"), node_type="op raster", help=_("Create a vertical linepattern from the raster"), grouping="OPS_75_CONVERTIMAGE"
3108
+ _("Vertical"),
3109
+ node_type="op raster",
3110
+ help=_("Create a vertical linepattern from the raster"),
3111
+ grouping="OPS_75_CONVERTIMAGE",
2952
3112
  )
2953
3113
  def raster_convert_to_path_vertical(node, **kwargs):
2954
3114
  convert_raster_to_path(node, "Vertical")
@@ -2959,7 +3119,9 @@ def init_tree(kernel):
2959
3119
  @tree_operation(
2960
3120
  _("Bidirectional"),
2961
3121
  node_type="op raster",
2962
- help=_("Shall the line pattern be able to travel back and forth or will it always start at the same side"),
3122
+ help=_(
3123
+ "Shall the line pattern be able to travel back and forth or will it always start at the same side"
3124
+ ),
2963
3125
  grouping="OPS_75_CONVERTIMAGE",
2964
3126
  )
2965
3127
  def set_raster_2_path_option_1(node, **kwargs):
@@ -2970,13 +3132,14 @@ def init_tree(kernel):
2970
3132
  @tree_operation(
2971
3133
  _("Optimize travel"),
2972
3134
  node_type="op raster",
2973
- help=_("Shall the line pattern be able to travel back and forth or will it always start at the same side"),
3135
+ help=_(
3136
+ "Shall the line pattern be able to travel back and forth or will it always start at the same side"
3137
+ ),
2974
3138
  grouping="OPS_75_CONVERTIMAGE",
2975
3139
  )
2976
3140
  def set_raster_2_path_option_2(node, **kwargs):
2977
3141
  self._image_2_path_optimize = not self._image_2_path_optimize
2978
3142
 
2979
-
2980
3143
  def add_after_index(node=None):
2981
3144
  try:
2982
3145
  if node is None:
@@ -2989,49 +3152,70 @@ def init_tree(kernel):
2989
3152
  ## @tree_separator_before()
2990
3153
  @tree_submenu(_("Insert operation"))
2991
3154
  @tree_operation(
2992
- _("Add Image"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3155
+ _("Add Image"),
3156
+ node_type=op_nodes,
3157
+ help=_("Add an operation to the tree"),
3158
+ grouping="OPS_40_ADDITION",
2993
3159
  )
2994
3160
  def add_operation_image(node, **kwargs):
2995
3161
  append_operation_image(node, pos=add_after_index(node), **kwargs)
2996
3162
 
2997
3163
  @tree_submenu(_("Insert operation"))
2998
3164
  @tree_operation(
2999
- _("Add Raster"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3165
+ _("Add Raster"),
3166
+ node_type=op_nodes,
3167
+ help=_("Add an operation to the tree"),
3168
+ grouping="OPS_40_ADDITION",
3000
3169
  )
3001
3170
  def add_operation_raster(node, **kwargs):
3002
3171
  append_operation_raster(node, pos=add_after_index(node), **kwargs)
3003
3172
 
3004
3173
  @tree_submenu(_("Insert operation"))
3005
3174
  @tree_operation(
3006
- _("Add Engrave"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3175
+ _("Add Engrave"),
3176
+ node_type=op_nodes,
3177
+ help=_("Add an operation to the tree"),
3178
+ grouping="OPS_40_ADDITION",
3007
3179
  )
3008
3180
  def add_operation_engrave(node, **kwargs):
3009
3181
  append_operation_engrave(node, pos=add_after_index(node), **kwargs)
3010
3182
 
3011
3183
  @tree_submenu(_("Insert operation"))
3012
3184
  @tree_operation(
3013
- _("Add Cut"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3185
+ _("Add Cut"),
3186
+ node_type=op_nodes,
3187
+ help=_("Add an operation to the tree"),
3188
+ grouping="OPS_40_ADDITION",
3014
3189
  )
3015
3190
  def add_operation_cut(node, **kwargs):
3016
3191
  append_operation_cut(node, pos=add_after_index(node), **kwargs)
3017
3192
 
3018
3193
  @tree_submenu(_("Insert operation"))
3019
3194
  @tree_operation(
3020
- _("Add Hatch"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3195
+ _("Add Hatch"),
3196
+ node_type=op_nodes,
3197
+ help=_("Add an operation to the tree"),
3198
+ grouping="OPS_40_ADDITION",
3021
3199
  )
3022
3200
  def add_operation_hatch(node, **kwargs):
3023
3201
  append_operation_hatch(node, pos=add_after_index(node), **kwargs)
3024
3202
 
3025
3203
  @tree_submenu(_("Insert operation"))
3026
3204
  @tree_operation(
3027
- _("Add Dots"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3205
+ _("Add Dots"),
3206
+ node_type=op_nodes,
3207
+ help=_("Add an operation to the tree"),
3208
+ grouping="OPS_40_ADDITION",
3028
3209
  )
3029
3210
  def add_operation_dots(node, **kwargs):
3030
3211
  append_operation_dots(node, pos=add_after_index(node), **kwargs)
3031
3212
 
3032
3213
  @tree_submenu(_("Insert special operation(s)"))
3033
3214
  @tree_operation(
3034
- _("Add Home"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3215
+ _("Add Home"),
3216
+ node_type=op_nodes,
3217
+ help=_("Add an operation to the tree"),
3218
+ grouping="OPS_40_ADDITION",
3035
3219
  )
3036
3220
  def add_operation_home(node, **kwargs):
3037
3221
  append_operation_home(node, pos=add_after_index(node), **kwargs)
@@ -3048,14 +3232,20 @@ def init_tree(kernel):
3048
3232
 
3049
3233
  @tree_submenu(_("Insert special operation(s)"))
3050
3234
  @tree_operation(
3051
- _("Add Beep"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3235
+ _("Add Beep"),
3236
+ node_type=op_nodes,
3237
+ help=_("Add an operation to the tree"),
3238
+ grouping="OPS_40_ADDITION",
3052
3239
  )
3053
3240
  def add_operation_beep(node, **kwargs):
3054
3241
  append_operation_beep(node, pos=add_after_index(node), **kwargs)
3055
3242
 
3056
3243
  @tree_submenu(_("Insert special operation(s)"))
3057
3244
  @tree_operation(
3058
- _("Add Interrupt"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3245
+ _("Add Interrupt"),
3246
+ node_type=op_nodes,
3247
+ help=_("Add an operation to the tree"),
3248
+ grouping="OPS_40_ADDITION",
3059
3249
  )
3060
3250
  def add_operation_interrupt(node, **kwargs):
3061
3251
  append_operation_interrupt(node, pos=add_after_index(node), **kwargs)
@@ -3063,7 +3253,10 @@ def init_tree(kernel):
3063
3253
  @tree_submenu(_("Insert special operation(s)"))
3064
3254
  @tree_prompt("wait_time", _("Wait for how long (in seconds)?"), data_type=float)
3065
3255
  @tree_operation(
3066
- _("Add Wait"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3256
+ _("Add Wait"),
3257
+ node_type=op_nodes,
3258
+ help=_("Add an operation to the tree"),
3259
+ grouping="OPS_40_ADDITION",
3067
3260
  )
3068
3261
  def add_operation_wait(node, wait_time, **kwargs):
3069
3262
  append_operation_wait(
@@ -3072,28 +3265,40 @@ def init_tree(kernel):
3072
3265
 
3073
3266
  @tree_submenu(_("Insert special operation(s)"))
3074
3267
  @tree_operation(
3075
- _("Add Output"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3268
+ _("Add Output"),
3269
+ node_type=op_nodes,
3270
+ help=_("Add an operation to the tree"),
3271
+ grouping="OPS_40_ADDITION",
3076
3272
  )
3077
3273
  def add_operation_output(node, **kwargs):
3078
3274
  append_operation_output(node, pos=add_after_index(node), **kwargs)
3079
3275
 
3080
3276
  @tree_submenu(_("Insert special operation(s)"))
3081
3277
  @tree_operation(
3082
- _("Add Input"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3278
+ _("Add Input"),
3279
+ node_type=op_nodes,
3280
+ help=_("Add an operation to the tree"),
3281
+ grouping="OPS_40_ADDITION",
3083
3282
  )
3084
3283
  def add_operation_input(node, **kwargs):
3085
3284
  append_operation_input(node, pos=add_after_index(node), **kwargs)
3086
3285
 
3087
3286
  @tree_submenu(_("Insert special operation(s)"))
3088
3287
  @tree_operation(
3089
- _("Add Coolant on"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3288
+ _("Add Coolant on"),
3289
+ node_type=op_nodes,
3290
+ help=_("Add an operation to the tree"),
3291
+ grouping="OPS_40_ADDITION",
3090
3292
  )
3091
3293
  def add_operation_cool_on(node, pos=None, **kwargs):
3092
3294
  append_operation_cool_on(node, pos=add_after_index(node), **kwargs)
3093
3295
 
3094
3296
  @tree_submenu(_("Insert special operation(s)"))
3095
3297
  @tree_operation(
3096
- _("Add Coolant Off"), node_type=op_nodes, help=_("Add an operation to the tree"), grouping="OPS_40_ADDITION"
3298
+ _("Add Coolant Off"),
3299
+ node_type=op_nodes,
3300
+ help=_("Add an operation to the tree"),
3301
+ grouping="OPS_40_ADDITION",
3097
3302
  )
3098
3303
  def add_operation_cool_off(node, pos=None, **kwargs):
3099
3304
  append_operation_cool_off(node, pos=add_after_index(node), **kwargs)
@@ -3132,7 +3337,12 @@ def init_tree(kernel):
3132
3337
  pos += 1
3133
3338
  append_operation_interrupt(node, pos=pos, **kwargs)
3134
3339
 
3135
- @tree_operation(_("Reload '{name}'"), node_type="file", help=_("Reload the content of the file"), grouping="40_ELEM_FILE")
3340
+ @tree_operation(
3341
+ _("Reload '{name}'"),
3342
+ node_type="file",
3343
+ help=_("Reload the content of the file"),
3344
+ grouping="40_ELEM_FILE",
3345
+ )
3136
3346
  def reload_file(node, **kwargs):
3137
3347
  filepath = node.filepath
3138
3348
  if not os.path.exists(filepath):
@@ -3144,10 +3354,18 @@ def init_tree(kernel):
3144
3354
  return
3145
3355
  to_be_removed = [node]
3146
3356
  for e in self.elem_branch.children:
3147
- if e.type == "file" and e.filepath == node.filepath and e not in to_be_removed:
3357
+ if (
3358
+ e.type == "file"
3359
+ and e.filepath == node.filepath
3360
+ and e not in to_be_removed
3361
+ ):
3148
3362
  to_be_removed.append(e)
3149
3363
  for e in self.reg_branch.children:
3150
- if e.type == "file" and e.filepath == node.filepath and e not in to_be_removed:
3364
+ if (
3365
+ e.type == "file"
3366
+ and e.filepath == node.filepath
3367
+ and e not in to_be_removed
3368
+ ):
3151
3369
  to_be_removed.append(e)
3152
3370
  for e in to_be_removed:
3153
3371
  e.remove_node()
@@ -3225,7 +3443,10 @@ def init_tree(kernel):
3225
3443
  @tree_submenu(_("Assign Operation"))
3226
3444
  @tree_values("op_assign", values=get_values)
3227
3445
  @tree_operation(
3228
- "{op_assign}", node_type=elem_nodes, help=_("Assign an operation to the selected elements"), grouping="40_ELEM_CLASSIFY"
3446
+ "{op_assign}",
3447
+ node_type=elem_nodes,
3448
+ help=_("Assign an operation to the selected elements"),
3449
+ grouping="40_ELEM_CLASSIFY",
3229
3450
  )
3230
3451
  def menu_assign_operations(node, op_assign, **kwargs):
3231
3452
  if self.classify_inherit_stroke:
@@ -3274,6 +3495,7 @@ def init_tree(kernel):
3274
3495
  else:
3275
3496
  for ref in list(rnode.references):
3276
3497
  ref.remove_node()
3498
+
3277
3499
  # _("Remove assignments")
3278
3500
  with self.undoscope("Remove assignments"):
3279
3501
  for node in list(self.elems(emphasized=True)):
@@ -3332,7 +3554,10 @@ def init_tree(kernel):
3332
3554
  @tree_conditional(lambda node: not is_regmark(node))
3333
3555
  @tree_submenu(_("Duplicate group"))
3334
3556
  @tree_operation(
3335
- _("Make 1 copy"), node_type="group", help=_("Create one copy of the selected group"), grouping="20_ELEM_DUPLICATION"
3557
+ _("Make 1 copy"),
3558
+ node_type="group",
3559
+ help=_("Create one copy of the selected group"),
3560
+ grouping="20_ELEM_DUPLICATION",
3336
3561
  )
3337
3562
  def duplicate_groups_1(node, **kwargs):
3338
3563
  duplicate_groups_n(node, copies=1, **kwargs)
@@ -3347,7 +3572,6 @@ def init_tree(kernel):
3347
3572
  grouping="20_ELEM_DUPLICATION",
3348
3573
  )
3349
3574
  def duplicate_groups_n(node, copies, **kwargs):
3350
-
3351
3575
  def copy_a_group(groupnode, parent, dx, dy):
3352
3576
  new_group = copy(groupnode)
3353
3577
  for orgnode in groupnode.children:
@@ -3375,8 +3599,12 @@ def init_tree(kernel):
3375
3599
 
3376
3600
  if self.copy_increases_wordlist_references and hasattr(orgnode, "text"):
3377
3601
  copy_node.text = self.wordlist_delta(orgnode.text, delta_wordlist)
3378
- elif self.copy_increases_wordlist_references and hasattr(orgnode, "mktext"):
3379
- copy_node.mktext = self.wordlist_delta(orgnode.mktext, delta_wordlist)
3602
+ elif self.copy_increases_wordlist_references and hasattr(
3603
+ orgnode, "mktext"
3604
+ ):
3605
+ copy_node.mktext = self.wordlist_delta(
3606
+ orgnode.mktext, delta_wordlist
3607
+ )
3380
3608
  new_group.add_node(copy_node)
3381
3609
  if had_optional:
3382
3610
  for property_op in self.kernel.lookup_all("path_updater/.*"):
@@ -3392,7 +3620,7 @@ def init_tree(kernel):
3392
3620
  delta_wordlist = 0
3393
3621
  for n in range(copies):
3394
3622
  delta_wordlist += 1
3395
- copy_a_group(node, node.parent, (n + 1 ) * _dx, (n + 1) * _dy)
3623
+ copy_a_group(node, node.parent, (n + 1) * _dx, (n + 1) * _dy)
3396
3624
  if copy_nodes:
3397
3625
  if self.classify_new:
3398
3626
  self.classify(copy_nodes)
@@ -3402,7 +3630,10 @@ def init_tree(kernel):
3402
3630
  @tree_conditional(lambda node: not is_regmark(node))
3403
3631
  @tree_submenu(_("Duplicate element(s)"))
3404
3632
  @tree_operation(
3405
- _("Make 1 copy"), node_type=elem_nodes, help=_("Create one copy of the selected elements"), grouping="20_ELEM_DUPLICATION"
3633
+ _("Make 1 copy"),
3634
+ node_type=elem_nodes,
3635
+ help=_("Create one copy of the selected elements"),
3636
+ grouping="20_ELEM_DUPLICATION",
3406
3637
  )
3407
3638
  def duplicate_element_1(node, **kwargs):
3408
3639
  duplicate_element_n(node, copies=1, **kwargs)
@@ -3443,8 +3674,12 @@ def init_tree(kernel):
3443
3674
 
3444
3675
  if self.copy_increases_wordlist_references and hasattr(orgnode, "text"):
3445
3676
  copy_node.text = self.wordlist_delta(orgnode.text, delta_wordlist)
3446
- elif self.copy_increases_wordlist_references and hasattr(orgnode, "mktext"):
3447
- copy_node.mktext = self.wordlist_delta(orgnode.mktext, delta_wordlist)
3677
+ elif self.copy_increases_wordlist_references and hasattr(
3678
+ orgnode, "mktext"
3679
+ ):
3680
+ copy_node.mktext = self.wordlist_delta(
3681
+ orgnode.mktext, delta_wordlist
3682
+ )
3448
3683
  orgparent.add_node(copy_node)
3449
3684
  if had_optional:
3450
3685
  for property_op in self.kernel.lookup_all("path_updater/.*"):
@@ -3505,7 +3740,7 @@ def init_tree(kernel):
3505
3740
  "elem path",
3506
3741
  ),
3507
3742
  help=_("Adjusts the reference value for a wordlist, i.e. {name} to {name#+1}"),
3508
- grouping="50_ELEM_MODIFY_ZMISC"
3743
+ grouping="50_ELEM_MODIFY_ZMISC",
3509
3744
  )
3510
3745
  def wlist_plus(singlenode, **kwargs):
3511
3746
  data = list()
@@ -3537,7 +3772,7 @@ def init_tree(kernel):
3537
3772
  help=_(
3538
3773
  "Adjusts the reference value for a wordlist, i.e. {name#+3} to {name#+2}"
3539
3774
  ),
3540
- grouping="50_ELEM_MODIFY_ZMISC"
3775
+ grouping="50_ELEM_MODIFY_ZMISC",
3541
3776
  )
3542
3777
  def wlist_minus(singlenode, **kwargs):
3543
3778
  data = list()
@@ -3566,16 +3801,15 @@ def init_tree(kernel):
3566
3801
  _("...with {offset}mm distance"),
3567
3802
  node_type=elem_nodes,
3568
3803
  help=_("Create an outline around the selected elements"),
3569
- grouping="50_ELEM_MODIFY_ZMISC"
3804
+ grouping="50_ELEM_MODIFY_ZMISC",
3570
3805
  )
3571
3806
  def make_outlines(node, offset=1, **kwargs):
3572
3807
  with self.undoscope("Outline"):
3573
3808
  self(f"outline {offset}mm\n")
3574
3809
  self.signal("refresh_tree")
3575
-
3810
+
3576
3811
  @tree_conditional(
3577
- lambda node: not is_regmark(node)
3578
- and hasattr(node, "as_geometry")
3812
+ lambda node: not is_regmark(node) and hasattr(node, "as_geometry")
3579
3813
  )
3580
3814
  @tree_submenu(_("Offset shapes..."))
3581
3815
  @tree_iterate("offset", 1, 5)
@@ -3583,7 +3817,7 @@ def init_tree(kernel):
3583
3817
  _("...to outside with {offset}mm distance"),
3584
3818
  node_type=elem_nodes,
3585
3819
  help=_("Create an outer offset around the selected elements"),
3586
- grouping="50_ELEM_MODIFY_ZMISC"
3820
+ grouping="50_ELEM_MODIFY_ZMISC",
3587
3821
  )
3588
3822
  def make_positive_offsets(node, offset=1, **kwargs):
3589
3823
  with self.undoscope("Offset"):
@@ -3591,8 +3825,7 @@ def init_tree(kernel):
3591
3825
  self.signal("refresh_tree")
3592
3826
 
3593
3827
  @tree_conditional(
3594
- lambda node: not is_regmark(node)
3595
- and hasattr(node, "as_geometry")
3828
+ lambda node: not is_regmark(node) and hasattr(node, "as_geometry")
3596
3829
  )
3597
3830
  @tree_submenu(_("Offset shapes..."))
3598
3831
  @tree_iterate("offset", 1, 5)
@@ -3600,7 +3833,7 @@ def init_tree(kernel):
3600
3833
  _("...to inside with {offset}mm distance"),
3601
3834
  node_type=elem_nodes,
3602
3835
  help=_("Create an inner offset around the selected elements"),
3603
- grouping="50_ELEM_MODIFY_ZMISC"
3836
+ grouping="50_ELEM_MODIFY_ZMISC",
3604
3837
  )
3605
3838
  def make_negative_offsets(node, offset=1, **kwargs):
3606
3839
  with self.undoscope("Offset"):
@@ -3712,6 +3945,9 @@ def init_tree(kernel):
3712
3945
  result = True
3713
3946
  return result
3714
3947
 
3948
+ def has_vtrace_vectorize(node):
3949
+ return self.kernel.has_command("vtracer")
3950
+
3715
3951
  @tree_submenu(_("Vectorization..."))
3716
3952
  @tree_separator_after()
3717
3953
  @tree_conditional(lambda node: has_vectorize(node))
@@ -3722,20 +3958,29 @@ def init_tree(kernel):
3722
3958
  "elem image",
3723
3959
  ),
3724
3960
  help=_("Vectorize the given element"),
3725
- grouping="70_ELEM_IMAGES_Z", # test
3961
+ grouping="70_ELEM_IMAGES_Z", # test
3726
3962
  )
3727
3963
  def trace_bitmap(node, **kwargs):
3728
3964
  with self.undoscope("Trace bitmap"):
3729
3965
  self("vectorize\n")
3730
3966
 
3967
+ @tree_submenu(_("Vectorization..."))
3968
+ @tree_conditional(lambda node: has_vtrace_vectorize(node))
3969
+ @tree_operation(
3970
+ _("Trace bitmap via vtracer"),
3971
+ node_type=("elem image",),
3972
+ help=_("Vectorize the given element"),
3973
+ grouping="70_ELEM_IMAGES_Z", # test
3974
+ )
3975
+ def trace_bitmap_vtrace(node, **kwargs):
3976
+ self("vtracer\n")
3977
+
3731
3978
  @tree_submenu(_("Vectorization..."))
3732
3979
  @tree_operation(
3733
3980
  _("Contour detection - shapes"),
3734
- node_type=(
3735
- "elem image",
3736
- ),
3981
+ node_type=("elem image",),
3737
3982
  help=_("Recognize contours=shapes on the given element"),
3738
- grouping="70_ELEM_IMAGES_Z", # test
3983
+ grouping="70_ELEM_IMAGES_Z", # test
3739
3984
  )
3740
3985
  def contour_bitmap_polyline(node, **kwargs):
3741
3986
  current = self.setting(str, "contour_size", "big")
@@ -3754,11 +3999,9 @@ def init_tree(kernel):
3754
3999
  @tree_separator_after()
3755
4000
  @tree_operation(
3756
4001
  _("Contour detection - bounding"),
3757
- node_type=(
3758
- "elem image",
3759
- ),
4002
+ node_type=("elem image",),
3760
4003
  help=_("Recognize contours=shapes on the given element"),
3761
- grouping="70_ELEM_IMAGES_Z", # test
4004
+ grouping="70_ELEM_IMAGES_Z", # test
3762
4005
  )
3763
4006
  def contour_bitmap_rectangles(node, **kwargs):
3764
4007
  current = self.setting(str, "contour_size", "big")
@@ -3789,7 +4032,7 @@ def init_tree(kernel):
3789
4032
  @tree_check(inner_check)
3790
4033
  @tree_operation(
3791
4034
  _("Ignore inner areas"),
3792
- node_type=("elem image", ),
4035
+ node_type=("elem image",),
3793
4036
  help=_("Inner areas will be ignored"),
3794
4037
  grouping="70_ELEM_IMAGES_Z",
3795
4038
  )
@@ -3802,10 +4045,8 @@ def init_tree(kernel):
3802
4045
  @tree_check(sizecheck("big"))
3803
4046
  @tree_operation(
3804
4047
  _("Big objects"),
3805
- node_type=("elem image", ),
3806
- help=_(
3807
- "Only large object will be recognized if checked"
3808
- ),
4048
+ node_type=("elem image",),
4049
+ help=_("Only large object will be recognized if checked"),
3809
4050
  grouping="70_ELEM_IMAGES_Z",
3810
4051
  )
3811
4052
  def set_contour_size_big(node, **kwargs):
@@ -3816,10 +4057,8 @@ def init_tree(kernel):
3816
4057
  @tree_check(sizecheck("normal"))
3817
4058
  @tree_operation(
3818
4059
  _("Normal objects"),
3819
- node_type=("elem image", ),
3820
- help=_(
3821
- "Also medium sized objects will be recognized if checked"
3822
- ),
4060
+ node_type=("elem image",),
4061
+ help=_("Also medium sized objects will be recognized if checked"),
3823
4062
  grouping="70_ELEM_IMAGES_Z",
3824
4063
  )
3825
4064
  def set_contour_size_normal(node, **kwargs):
@@ -3830,10 +4069,8 @@ def init_tree(kernel):
3830
4069
  @tree_check(sizecheck("small"))
3831
4070
  @tree_operation(
3832
4071
  _("Small objects"),
3833
- node_type=("elem image", ),
3834
- help=_(
3835
- "Also small objects will be recognized if checked"
3836
- ),
4072
+ node_type=("elem image",),
4073
+ help=_("Also small objects will be recognized if checked"),
3837
4074
  grouping="70_ELEM_IMAGES_Z",
3838
4075
  )
3839
4076
  def set_contour_size_small(node, **kwargs):
@@ -3933,7 +4170,9 @@ def init_tree(kernel):
3933
4170
  grouping="50_ELEM_MODIFY_ZMISC",
3934
4171
  )
3935
4172
  def convert_to_path(singlenode, **kwargs):
3936
- nodes = (node for node in self.elems(emphasized=True) if hasattr(node, "as_geometry"))
4173
+ nodes = (
4174
+ node for node in self.elems(emphasized=True) if hasattr(node, "as_geometry")
4175
+ )
3937
4176
  if not nodes:
3938
4177
  return
3939
4178
  with self.undoscope("Convert to path"):
@@ -3962,7 +4201,11 @@ def init_tree(kernel):
3962
4201
  grouping="50_ELEM_MODIFY_ZMISC",
3963
4202
  )
3964
4203
  def convert_to_path_effect(singlenode, **kwargs):
3965
- nodes = (node for node in self.flat(types=effect_nodes, emphasized=True) if hasattr(node, "as_geometry"))
4204
+ nodes = (
4205
+ node
4206
+ for node in self.flat(types=effect_nodes, emphasized=True)
4207
+ if hasattr(node, "as_geometry")
4208
+ )
3966
4209
  if not nodes:
3967
4210
  return
3968
4211
  with self.undoscope("Convert to path"):
@@ -4193,7 +4436,9 @@ def init_tree(kernel):
4193
4436
  @tree_conditional(lambda node: node.lock)
4194
4437
  ## @tree_separator_before()
4195
4438
  @tree_operation(
4196
- _("Unlock element, allows manipulation"), node_type=elem_nodes, help=_("Remove manipulation protection flag")
4439
+ _("Unlock element, allows manipulation"),
4440
+ node_type=elem_nodes,
4441
+ help=_("Remove manipulation protection flag"),
4197
4442
  )
4198
4443
  def element_unlock_manipulations(node, **kwargs):
4199
4444
  self("element unlock\n")
@@ -4297,7 +4542,10 @@ def init_tree(kernel):
4297
4542
  @tree_conditional(lambda node: is_regmark(node))
4298
4543
  @tree_submenu(_("Toggle magnet-lines"))
4299
4544
  @tree_operation(
4300
- _("Around border"), node_type=elem_group_nodes, help=_("Set/remove magnet lines around the regmark element"), grouping="SCENE"
4545
+ _("Around border"),
4546
+ node_type=elem_group_nodes,
4547
+ help=_("Set/remove magnet lines around the regmark element"),
4548
+ grouping="SCENE",
4301
4549
  )
4302
4550
  def regmark_to_magnet_1(node, **kwargs):
4303
4551
  if not hasattr(node, "bounds"):
@@ -4307,7 +4555,12 @@ def init_tree(kernel):
4307
4555
  @tree_conditional(lambda node: is_regmark(node))
4308
4556
  @tree_submenu(_("Toggle magnet-lines"))
4309
4557
  @tree_operation(
4310
- _("At center"), node_type=elem_group_nodes, help=_("Set/remove magnet lines right through the middle of the regmark element"), grouping="SCENE"
4558
+ _("At center"),
4559
+ node_type=elem_group_nodes,
4560
+ help=_(
4561
+ "Set/remove magnet lines right through the middle of the regmark element"
4562
+ ),
4563
+ grouping="SCENE",
4311
4564
  )
4312
4565
  def regmark_to_magnet_2(node, **kwargs):
4313
4566
  if not hasattr(node, "bounds"):
@@ -4370,7 +4623,10 @@ def init_tree(kernel):
4370
4623
  @tree_conditional(lambda node: not node.lock)
4371
4624
  @tree_submenu(_("Image"))
4372
4625
  @tree_operation(
4373
- _("Invert image"), node_type="elem image", help=_("Invert the image"), grouping="70_ELEM_IMAGES"
4626
+ _("Invert image"),
4627
+ node_type="elem image",
4628
+ help=_("Invert the image"),
4629
+ grouping="70_ELEM_IMAGES",
4374
4630
  )
4375
4631
  def image_invert(node, **kwargs):
4376
4632
  with self.undoscope("Invert image"):
@@ -4391,7 +4647,10 @@ def init_tree(kernel):
4391
4647
  @tree_conditional(lambda node: not node.lock)
4392
4648
  @tree_submenu(_("Image"))
4393
4649
  @tree_operation(
4394
- _("Flip vertical"), node_type="elem image", help=_("Mirror the image along the X-Axis"), grouping="70_ELEM_IMAGES"
4650
+ _("Flip vertical"),
4651
+ node_type="elem image",
4652
+ help=_("Mirror the image along the X-Axis"),
4653
+ grouping="70_ELEM_IMAGES",
4395
4654
  )
4396
4655
  def image_flip(node, **kwargs):
4397
4656
  with self.undoscope("Flip vertical"):
@@ -4400,7 +4659,10 @@ def init_tree(kernel):
4400
4659
  @tree_conditional(lambda node: not node.lock)
4401
4660
  @tree_submenu(_("Image"))
4402
4661
  @tree_operation(
4403
- _("Rotate 90° CW"), node_type="elem image", help=_("Rotate the image by 90° clockwise"), grouping="70_ELEM_IMAGES"
4662
+ _("Rotate 90° CW"),
4663
+ node_type="elem image",
4664
+ help=_("Rotate the image by 90° clockwise"),
4665
+ grouping="70_ELEM_IMAGES",
4404
4666
  )
4405
4667
  def image_cw(node, **kwargs):
4406
4668
  with self.undoscope("Rotate 90° CW"):
@@ -4409,7 +4671,10 @@ def init_tree(kernel):
4409
4671
  @tree_conditional(lambda node: not node.lock)
4410
4672
  @tree_submenu(_("Image"))
4411
4673
  @tree_operation(
4412
- _("Rotate 90° CCW"), node_type="elem image", help=_("Rotate the image by 90° counterclockwise"), grouping="70_ELEM_IMAGES"
4674
+ _("Rotate 90° CCW"),
4675
+ node_type="elem image",
4676
+ help=_("Rotate the image by 90° counterclockwise"),
4677
+ grouping="70_ELEM_IMAGES",
4413
4678
  )
4414
4679
  def image_ccw(node, **kwargs):
4415
4680
  with self.undoscope("Rotate 90° CCW"):
@@ -4526,7 +4791,12 @@ def init_tree(kernel):
4526
4791
  node.notify_collapse()
4527
4792
 
4528
4793
  @tree_submenu(_("Magnets"))
4529
- @tree_operation(_("...around horizontal edges"), node_type=elem_group_nodes, help=_("Create magnets around horizontal edges"), grouping="Magnet")
4794
+ @tree_operation(
4795
+ _("...around horizontal edges"),
4796
+ node_type=elem_group_nodes,
4797
+ help=_("Create magnets around horizontal edges"),
4798
+ grouping="Magnet",
4799
+ )
4530
4800
  def create_horiz_edges(node, **kwargs):
4531
4801
  if not hasattr(node, "bounds") or node.bounds is None:
4532
4802
  return
@@ -4535,7 +4805,12 @@ def init_tree(kernel):
4535
4805
  self.signal("create_magnets", to_create)
4536
4806
 
4537
4807
  @tree_submenu(_("Magnets"))
4538
- @tree_operation(_("...including center"), node_type=elem_group_nodes, help=_("Create magnets around horizontal edges + center"), grouping="Magnet")
4808
+ @tree_operation(
4809
+ _("...including center"),
4810
+ node_type=elem_group_nodes,
4811
+ help=_("Create magnets around horizontal edges + center"),
4812
+ grouping="Magnet",
4813
+ )
4539
4814
  def create_horiz_edges_plus_center(node, **kwargs):
4540
4815
  if not hasattr(node, "bounds") or node.bounds is None:
4541
4816
  return
@@ -4545,7 +4820,12 @@ def init_tree(kernel):
4545
4820
 
4546
4821
  @tree_submenu(_("Magnets"))
4547
4822
  @tree_iterate("steps", 3, 6)
4548
- @tree_operation(_("...create edges plus every 1/{steps}"), node_type=elem_group_nodes, help=_("Create magnets equally spaced along horizontal extension"), grouping="Magnet")
4823
+ @tree_operation(
4824
+ _("...create edges plus every 1/{steps}"),
4825
+ node_type=elem_group_nodes,
4826
+ help=_("Create magnets equally spaced along horizontal extension"),
4827
+ grouping="Magnet",
4828
+ )
4549
4829
  def create_x_horiz_edges(node, steps=3, **kwargs):
4550
4830
  if not hasattr(node, "bounds") or node.bounds is None:
4551
4831
  return
@@ -4562,7 +4842,12 @@ def init_tree(kernel):
4562
4842
 
4563
4843
  @tree_submenu(_("Magnets"))
4564
4844
  @tree_separator_before()
4565
- @tree_operation(_("...around vertical edges"), node_type=elem_group_nodes, help=_("Create magnets around vertical edges"), grouping="Magnet")
4845
+ @tree_operation(
4846
+ _("...around vertical edges"),
4847
+ node_type=elem_group_nodes,
4848
+ help=_("Create magnets around vertical edges"),
4849
+ grouping="Magnet",
4850
+ )
4566
4851
  def create_vert_edges(node, **kwargs):
4567
4852
  if not hasattr(node, "bounds") or node.bounds is None:
4568
4853
  return
@@ -4571,17 +4856,27 @@ def init_tree(kernel):
4571
4856
  self.signal("create_magnets", to_create)
4572
4857
 
4573
4858
  @tree_submenu(_("Magnets"))
4574
- @tree_operation(_("...including center"), node_type=elem_group_nodes, help=_("Create magnets around vertical edges + center"), grouping="Magnet")
4859
+ @tree_operation(
4860
+ _("...including center"),
4861
+ node_type=elem_group_nodes,
4862
+ help=_("Create magnets around vertical edges + center"),
4863
+ grouping="Magnet",
4864
+ )
4575
4865
  def create_vert_edges_plus_center(node, **kwargs):
4576
4866
  if not hasattr(node, "bounds") or node.bounds is None:
4577
4867
  return
4578
4868
  bb = node.bounds
4579
4869
  to_create = (("y", bb[1]), ("y", bb[3]), ("y", (bb[1] + bb[3]) / 2))
4580
4870
  self.signal("create_magnets", to_create)
4581
- @tree_submenu(_("Magnets"))
4582
4871
 
4872
+ @tree_submenu(_("Magnets"))
4583
4873
  @tree_iterate("steps", 3, 6)
4584
- @tree_operation(_("...create edges plus every 1/{steps}"), node_type=elem_group_nodes, help=_("Create magnets equally spaced along vertical extension"), grouping="Magnet")
4874
+ @tree_operation(
4875
+ _("...create edges plus every 1/{steps}"),
4876
+ node_type=elem_group_nodes,
4877
+ help=_("Create magnets equally spaced along vertical extension"),
4878
+ grouping="Magnet",
4879
+ )
4585
4880
  def create_x_vert_edges(node, steps=3, **kwargs):
4586
4881
  if not hasattr(node, "bounds") or node.bounds is None:
4587
4882
  return