meerk40t 0.9.7020__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 (98) 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/cutcode/cutcode.py +1 -1
  14. meerk40t/core/cutplan.py +169 -43
  15. meerk40t/core/elements/element_treeops.py +444 -147
  16. meerk40t/core/elements/elements.py +100 -9
  17. meerk40t/core/elements/grid.py +8 -1
  18. meerk40t/core/elements/offset_mk.py +2 -1
  19. meerk40t/core/elements/shapes.py +618 -279
  20. meerk40t/core/elements/tree_commands.py +10 -5
  21. meerk40t/core/node/elem_ellipse.py +18 -8
  22. meerk40t/core/node/elem_image.py +51 -19
  23. meerk40t/core/node/elem_line.py +18 -8
  24. meerk40t/core/node/elem_path.py +18 -8
  25. meerk40t/core/node/elem_point.py +10 -4
  26. meerk40t/core/node/elem_polyline.py +19 -11
  27. meerk40t/core/node/elem_rect.py +18 -8
  28. meerk40t/core/node/elem_text.py +11 -5
  29. meerk40t/core/node/filenode.py +2 -8
  30. meerk40t/core/node/groupnode.py +11 -11
  31. meerk40t/core/node/image_processed.py +11 -5
  32. meerk40t/core/node/image_raster.py +11 -5
  33. meerk40t/core/node/node.py +70 -19
  34. meerk40t/core/node/refnode.py +2 -1
  35. meerk40t/core/planner.py +23 -0
  36. meerk40t/core/svg_io.py +91 -34
  37. meerk40t/core/undos.py +1 -1
  38. meerk40t/core/wordlist.py +1 -0
  39. meerk40t/device/dummydevice.py +7 -1
  40. meerk40t/dxf/dxf_io.py +6 -0
  41. meerk40t/extra/mk_potrace.py +1959 -0
  42. meerk40t/extra/param_functions.py +1 -1
  43. meerk40t/extra/potrace.py +14 -10
  44. meerk40t/extra/vtracer.py +222 -0
  45. meerk40t/grbl/device.py +81 -8
  46. meerk40t/grbl/interpreter.py +1 -1
  47. meerk40t/gui/about.py +21 -3
  48. meerk40t/gui/basicops.py +3 -3
  49. meerk40t/gui/choicepropertypanel.py +1 -4
  50. meerk40t/gui/devicepanel.py +20 -16
  51. meerk40t/gui/gui_mixins.py +8 -1
  52. meerk40t/gui/icons.py +330 -253
  53. meerk40t/gui/laserpanel.py +8 -3
  54. meerk40t/gui/laserrender.py +41 -21
  55. meerk40t/gui/magnetoptions.py +158 -65
  56. meerk40t/gui/materialtest.py +229 -39
  57. meerk40t/gui/navigationpanels.py +229 -24
  58. meerk40t/gui/propertypanels/hatchproperty.py +2 -0
  59. meerk40t/gui/propertypanels/imageproperty.py +160 -106
  60. meerk40t/gui/ribbon.py +6 -1
  61. meerk40t/gui/scenewidgets/gridwidget.py +29 -32
  62. meerk40t/gui/scenewidgets/rectselectwidget.py +190 -192
  63. meerk40t/gui/simulation.py +75 -77
  64. meerk40t/gui/spoolerpanel.py +6 -9
  65. meerk40t/gui/statusbarwidgets/defaultoperations.py +84 -48
  66. meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
  67. meerk40t/gui/themes.py +7 -1
  68. meerk40t/gui/tips.py +15 -1
  69. meerk40t/gui/toolwidgets/toolpointmove.py +3 -1
  70. meerk40t/gui/wxmeerk40t.py +26 -0
  71. meerk40t/gui/wxmmain.py +242 -114
  72. meerk40t/gui/wxmscene.py +180 -4
  73. meerk40t/gui/wxmtree.py +4 -2
  74. meerk40t/gui/wxutils.py +60 -15
  75. meerk40t/image/imagetools.py +130 -66
  76. meerk40t/internal_plugins.py +4 -0
  77. meerk40t/kernel/kernel.py +49 -22
  78. meerk40t/kernel/settings.py +29 -8
  79. meerk40t/lihuiyu/device.py +30 -12
  80. meerk40t/main.py +22 -5
  81. meerk40t/moshi/device.py +20 -6
  82. meerk40t/network/console_server.py +22 -6
  83. meerk40t/newly/device.py +10 -3
  84. meerk40t/newly/gui/gui.py +10 -0
  85. meerk40t/ruida/device.py +22 -2
  86. meerk40t/ruida/gui/gui.py +6 -6
  87. meerk40t/ruida/gui/ruidaoperationproperties.py +1 -10
  88. meerk40t/ruida/loader.py +6 -3
  89. meerk40t/ruida/rdjob.py +3 -3
  90. meerk40t/tools/geomstr.py +195 -39
  91. meerk40t/tools/rasterplotter.py +179 -93
  92. {meerk40t-0.9.7020.dist-info → meerk40t-0.9.7040.dist-info}/METADATA +1 -1
  93. {meerk40t-0.9.7020.dist-info → meerk40t-0.9.7040.dist-info}/RECORD +98 -96
  94. {meerk40t-0.9.7020.dist-info → meerk40t-0.9.7040.dist-info}/WHEEL +1 -1
  95. {meerk40t-0.9.7020.dist-info → meerk40t-0.9.7040.dist-info}/LICENSE +0 -0
  96. {meerk40t-0.9.7020.dist-info → meerk40t-0.9.7040.dist-info}/entry_points.txt +0 -0
  97. {meerk40t-0.9.7020.dist-info → meerk40t-0.9.7040.dist-info}/top_level.txt +0 -0
  98. {meerk40t-0.9.7020.dist-info → meerk40t-0.9.7040.dist-info}/zip-safe +0 -0
meerk40t/gui/wxmscene.py CHANGED
@@ -99,7 +99,12 @@ class ContourDetectionDialog(wx.Dialog):
99
99
  def _init_ui(self, node):
100
100
  main_sizer = wx.BoxSizer(wx.VERTICAL)
101
101
  panel = ContourPanel(
102
- self, wx.ID_ANY, context=self.context, node=node, simplified=True, direct_mode=True,
102
+ self,
103
+ wx.ID_ANY,
104
+ context=self.context,
105
+ node=node,
106
+ simplified=True,
107
+ direct_mode=True,
103
108
  )
104
109
  main_sizer.Add(panel, 1, wx.EXPAND, 0)
105
110
  buttons = self.CreateStdDialogButtonSizer(wx.OK)
@@ -158,7 +163,9 @@ class MeerK40tScenePanel(wx.Panel):
158
163
  # Save / Load the content of magnets
159
164
  from os.path import join
160
165
 
161
- self._magnet_file = join(self.context.kernel.os_information["WORKDIR"], "magnets.cfg")
166
+ self._magnet_file = join(
167
+ self.context.kernel.os_information["WORKDIR"], "magnets.cfg"
168
+ )
162
169
  self.load_magnets()
163
170
  # Add a plugin routine to be called at the time of a full new start
164
171
  context.kernel.register(
@@ -868,6 +875,167 @@ class MeerK40tScenePanel(wx.Panel):
868
875
  else:
869
876
  channel(_("Target needs to be one of primary, secondary, circular"))
870
877
 
878
+ # Establishes magnet commands
879
+ @context.console_argument(
880
+ "action", type=str, help=_("Action: clear or set / delete with coordinate")
881
+ )
882
+ @context.console_argument("axis", type=str, help=_("Axis (X or Y)"))
883
+ @context.console_argument("pos", type=str, help=_("Position for magnetline"))
884
+ @context.console_command(
885
+ "magnet",
886
+ help=_("magnet <action> <axis> <position>"),
887
+ input_type=("scene", None),
888
+ )
889
+ def magnet_set(
890
+ command,
891
+ channel,
892
+ _,
893
+ action=None,
894
+ axis=None,
895
+ pos=None,
896
+ **kwarg,
897
+ ):
898
+ def info(opt_msg):
899
+ channel(
900
+ _("You need to provide the intended action:")
901
+ + "\n"
902
+ + _("clear x - clear y : will clear all magnets on the given axis")
903
+ + "\n"
904
+ + _(
905
+ "set x <pos> - set y <pos>: will set a magnet line on the given axis"
906
+ )
907
+ + "\n"
908
+ + _(
909
+ "delete x <pos> - delete y <pos>: will delete the magnet line on the given axis"
910
+ )
911
+ + _(
912
+ "split x <count> - split y <count>: will generate <count> lines between the selection boundaries on the given axis"
913
+ )
914
+ )
915
+ if opt_msg:
916
+ channel(opt_msg)
917
+
918
+ if action is None or axis is None or axis.upper() not in ("X", "Y"):
919
+ info("")
920
+ return
921
+ action = action.lower()
922
+ axis = axis.upper()
923
+ value = None
924
+ if action == "split":
925
+ if pos:
926
+ try:
927
+ value = int(pos)
928
+ except ValueError:
929
+ info(f"Invalid count: {pos}")
930
+ return
931
+
932
+ if value is None or value <= 0:
933
+ info(_("You need to provide a number of splits"))
934
+ return
935
+ else:
936
+ if pos:
937
+ try:
938
+ rel_len = (
939
+ self.context.device.view.width
940
+ if axis == "X"
941
+ else self.context.device.view.height
942
+ )
943
+ value = float(Length(pos, relative_length=rel_len))
944
+ except ValueError:
945
+ info(f"Invalid length: {pos}")
946
+ return
947
+
948
+ if action != "clear" and value is None:
949
+ info(_("You need to provide a position"))
950
+ return
951
+
952
+ if action == "clear":
953
+ if axis == "X":
954
+ count = len(self.magnet_x)
955
+ self.magnet_x.clear()
956
+ else:
957
+ count = len(self.magnet_y)
958
+ self.magnet_y.clear()
959
+ self.save_magnets()
960
+ self.context.signal("refresh_scene", "Scene")
961
+ channel(
962
+ _("Deleted {count} magnet lines on axis {axis}").format(
963
+ axis=axis, count=count
964
+ )
965
+ )
966
+ elif action == "split":
967
+ bb = self.context.elements.selected_area()
968
+ if bb is None:
969
+ channel(_("Nothing selected"))
970
+ return
971
+
972
+ min_v = bb[0] if axis == "X" else bb[1]
973
+ max_v = bb[2] if axis == "X" else bb[3]
974
+ count = value + 1
975
+ delta = (max_v - min_v) / count
976
+ mvalue = min_v
977
+ while mvalue + delta < max_v:
978
+ mvalue += delta
979
+ if axis == "X":
980
+ if mvalue not in self.magnet_x:
981
+ self.magnet_x.append(mvalue)
982
+ else:
983
+ if mvalue not in self.magnet_y:
984
+ self.magnet_y.append(mvalue)
985
+ self.save_magnets()
986
+ channel(
987
+ _(
988
+ "Created {count} magnet lines on {axis}-axis between {min_len} and {max_len}"
989
+ ).format(
990
+ count=count,
991
+ axis=axis,
992
+ min_len=Length(min_v, digits=1).length_mm,
993
+ max_len=Length(max_v, digits=1).length_mm,
994
+ )
995
+ )
996
+ self.context.signal("refresh_scene", "Scene")
997
+
998
+ elif action == "set":
999
+ done = False
1000
+ if axis == "X":
1001
+ if not value in self.magnet_x:
1002
+ done = True
1003
+ self.magnet_x.append(value)
1004
+ else:
1005
+ if not value in self.magnet_y:
1006
+ done = True
1007
+ self.magnet_y.append(value)
1008
+ self.save_magnets()
1009
+ self.context.signal("refresh_scene", "Scene")
1010
+ if done:
1011
+ channel(
1012
+ _("Magnetline appended at {pos} on axis {axis}").format(
1013
+ pos=pos, axis=axis
1014
+ )
1015
+ )
1016
+ else:
1017
+ channel(_("Magnetline was already present"))
1018
+ elif action.startswith("del"):
1019
+ done = False
1020
+ if axis == "X":
1021
+ if value in self.magnet_x:
1022
+ done = True
1023
+ self.magnet_x.remove(value)
1024
+ else:
1025
+ if value in self.magnet_y:
1026
+ done = True
1027
+ self.magnet_y.remove(value)
1028
+ self.save_magnets()
1029
+ self.context.signal("refresh_scene", "Scene")
1030
+ if done:
1031
+ channel(
1032
+ _("Magnetline removed at {pos} on axis {axis}").format(
1033
+ pos=pos, axis=axis
1034
+ )
1035
+ )
1036
+ else:
1037
+ channel(_("Magnetline was not existing"))
1038
+
871
1039
  def toggle_ref_obj(self):
872
1040
  for e in self.scene.context.elements.flat(types=elem_nodes, emphasized=True):
873
1041
  if self.reference_object == e:
@@ -1100,7 +1268,7 @@ class MeerK40tScenePanel(wx.Panel):
1100
1268
 
1101
1269
  @signal_listener("create_magnets")
1102
1270
  def listen_magnet_creation(self, origin, creation_list, *args):
1103
- for (info, value) in creation_list:
1271
+ for info, value in creation_list:
1104
1272
  if info == "x":
1105
1273
  self.toggle_x_magnet(value)
1106
1274
  else:
@@ -1199,11 +1367,17 @@ class MeerK40tScenePanel(wx.Panel):
1199
1367
 
1200
1368
  def recognize_background_contours(event=None):
1201
1369
  def image_from_bitmap(myBitmap):
1370
+ img = myBitmap.ConvertToImage()
1371
+ buf = img.GetData()
1372
+ return Image.frombuffer(
1373
+ "RGB", tuple(myBitmap.GetSize()), bytes(buf), "raw", "RGB", 0, 1
1374
+ )
1202
1375
  wx_image = myBitmap.ConvertToImage()
1203
1376
  myPilImage = Image.new(
1204
1377
  "RGB", (wx_image.GetWidth(), wx_image.GetHeight())
1205
1378
  )
1206
- myPilImage.frombytes(wx_image.GetData())
1379
+ byte_data = bytes(wx_image.GetData())
1380
+ myPilImage.frombytes(byte_data)
1207
1381
  return myPilImage
1208
1382
 
1209
1383
  if not self.widget_scene.has_background:
@@ -1235,6 +1409,8 @@ class MeerK40tScenePanel(wx.Panel):
1235
1409
  dpi=500,
1236
1410
  )
1237
1411
  # print (f"Node-Dimensions: {node.bbox()}")
1412
+ # self.context.elements.elem_branch.add_node(node)
1413
+
1238
1414
  dlg = ContourDetectionDialog(self, self.context, node)
1239
1415
  dlg.ShowModal()
1240
1416
  dlg.end_dialog()
meerk40t/gui/wxmtree.py CHANGED
@@ -1379,11 +1379,13 @@ class ShadowTree:
1379
1379
  @param kwargs:
1380
1380
  @return:
1381
1381
  """
1382
- self.do_not_select = True
1383
1382
 
1384
1383
  item = node._item
1385
1384
  if item is None:
1386
- raise ValueError(f"Item was None for node {repr(node)}")
1385
+ print(f"Item was None for node {repr(node)}")
1386
+ return
1387
+
1388
+ self.do_not_select = True
1387
1389
  self.check_validity(item)
1388
1390
  # We might need to update the decorations for all parent objects
1389
1391
  informed = []
meerk40t/gui/wxutils.py CHANGED
@@ -8,8 +8,8 @@ import wx
8
8
  import wx.lib.mixins.listctrl as listmix
9
9
  from wx.lib.scrolledpanel import ScrolledPanel as SP
10
10
 
11
- from meerk40t.svgelements import Matrix
12
11
  from meerk40t.core.units import ACCEPTED_ANGLE_UNITS, ACCEPTED_UNITS, Angle, Length
12
+ from meerk40t.svgelements import Matrix
13
13
 
14
14
  _ = wx.GetTranslation
15
15
 
@@ -35,6 +35,7 @@ def get_matrix_scale(matrix):
35
35
  res = 1
36
36
  return res
37
37
 
38
+
38
39
  def get_matrix_full_scale(matrix):
39
40
  # We usually use the value_scale_x to establish a pixel size
40
41
  # by counteracting the scene matrix, linewidth = 1 / matrix.value_scale_x()
@@ -54,6 +55,7 @@ def get_matrix_full_scale(matrix):
54
55
  resy = 1
55
56
  return resx, resy
56
57
 
58
+
57
59
  def get_gc_scale(gc):
58
60
  gcmat = gc.GetTransform()
59
61
  mat_param = gcmat.Get()
@@ -67,6 +69,7 @@ def get_gc_scale(gc):
67
69
  )
68
70
  return get_matrix_scale(testmatrix)
69
71
 
72
+
70
73
  def get_gc_full_scale(gc):
71
74
  gcmat = gc.GetTransform()
72
75
  mat_param = gcmat.Get()
@@ -80,6 +83,7 @@ def get_gc_full_scale(gc):
80
83
  )
81
84
  return get_matrix_full_scale(testmatrix)
82
85
 
86
+
83
87
  def create_menu_for_choices(gui, choices: List[dict]) -> wx.Menu:
84
88
  """
85
89
  Creates a menu for a given choices table.
@@ -851,6 +855,7 @@ class TextCtrl(wx.TextCtrl):
851
855
  self._action_routine()
852
856
  finally:
853
857
  self._event_generated = None
858
+
854
859
  return handler
855
860
 
856
861
  if not self._default_values:
@@ -858,15 +863,20 @@ class TextCtrl(wx.TextCtrl):
858
863
  return
859
864
  menu = wx.Menu()
860
865
  has_info = isinstance(self._default_values[0], (list, tuple))
861
- item : wx.MenuItem = menu.Append(wx.ID_ANY, _("Default values..."), "")
866
+ item: wx.MenuItem = menu.Append(wx.ID_ANY, _("Default values..."), "")
862
867
  item.Enable(False)
863
868
  for info in self._default_values:
864
- item = menu.Append(wx.ID_ANY, info[0] if has_info else info, info[1] if has_info else "")
865
- self.Bind(wx.EVT_MENU, set_menu_value(info[0] if has_info else info), id=item.GetId())
869
+ item = menu.Append(
870
+ wx.ID_ANY, info[0] if has_info else info, info[1] if has_info else ""
871
+ )
872
+ self.Bind(
873
+ wx.EVT_MENU,
874
+ set_menu_value(info[0] if has_info else info),
875
+ id=item.GetId(),
876
+ )
866
877
  self.PopupMenu(menu)
867
878
  menu.Destroy()
868
879
 
869
-
870
880
  @property
871
881
  def warn_status(self):
872
882
  return self._warn_status
@@ -1012,6 +1022,7 @@ class wxCheckBox(wx.CheckBox):
1012
1022
  self._tool_tip = tooltip
1013
1023
  super().SetToolTip(self._tool_tip)
1014
1024
 
1025
+
1015
1026
  class wxComboBox(wx.ComboBox):
1016
1027
  """
1017
1028
  This class wraps around wx.ComboBox and creates a series of mouse over tool tips to permit Linux tooltips that
@@ -1242,11 +1253,12 @@ class StaticBoxSizer(wx.StaticBoxSizer):
1242
1253
  def Refresh(self, *args):
1243
1254
  self.sbox.Refresh(*args)
1244
1255
 
1245
- def Enable(self, enable:bool=True):
1256
+ def Enable(self, enable: bool = True):
1246
1257
  """Enable or disable the StaticBoxSizer and its children.
1247
1258
 
1248
1259
  Enables or disables all children of the sizer recursively.
1249
1260
  """
1261
+
1250
1262
  def enem(wind, flag):
1251
1263
  for c in wind.GetChildren():
1252
1264
  enem(c, flag)
@@ -1255,6 +1267,7 @@ class StaticBoxSizer(wx.StaticBoxSizer):
1255
1267
 
1256
1268
  enem(self.sbox, enable)
1257
1269
 
1270
+
1258
1271
  class ScrolledPanel(SP):
1259
1272
  """
1260
1273
  We sometimes delete things fast enough that they call _SetupAfter when dead and crash.
@@ -1268,12 +1281,21 @@ class ScrolledPanel(SP):
1268
1281
  except RuntimeError:
1269
1282
  pass
1270
1283
 
1284
+
1271
1285
  class wxListCtrl(wx.ListCtrl):
1272
1286
  """
1273
1287
  wxListCtrl will extend a regular ListCtrl by saving / restoring column widths
1274
1288
  """
1289
+
1275
1290
  def __init__(
1276
- self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, context=None, list_name=None
1291
+ self,
1292
+ parent,
1293
+ ID=wx.ID_ANY,
1294
+ pos=wx.DefaultPosition,
1295
+ size=wx.DefaultSize,
1296
+ style=0,
1297
+ context=None,
1298
+ list_name=None,
1277
1299
  ):
1278
1300
  wx.ListCtrl.__init__(self, parent, ID, pos, size, style)
1279
1301
  self.context = context
@@ -1341,7 +1363,7 @@ class wxListCtrl(wx.ListCtrl):
1341
1363
  # print(f"{self.list_name}, cols={self.GetColumnCount()}, available={list_width}, used={total}")
1342
1364
  if total < list_width:
1343
1365
  col = self.GetColumnCount() - 1
1344
- if col < 0 :
1366
+ if col < 0:
1345
1367
  return False
1346
1368
  # print(f"Will adjust last column from {last} to {last + (list_width - total)}")
1347
1369
  try:
@@ -1365,10 +1387,26 @@ class EditableListCtrl(wxListCtrl, listmix.TextEditMixin):
1365
1387
 
1366
1388
  # ----------------------------------------------------------------------
1367
1389
  def __init__(
1368
- self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, context=None, list_name=None,
1390
+ self,
1391
+ parent,
1392
+ ID=wx.ID_ANY,
1393
+ pos=wx.DefaultPosition,
1394
+ size=wx.DefaultSize,
1395
+ style=0,
1396
+ context=None,
1397
+ list_name=None,
1369
1398
  ):
1370
1399
  """Constructor"""
1371
- wxListCtrl.__init__(self, parent=parent, ID=ID, pos=pos, size=size, style=style, context=context, list_name=list_name)
1400
+ wxListCtrl.__init__(
1401
+ self,
1402
+ parent=parent,
1403
+ ID=ID,
1404
+ pos=pos,
1405
+ size=size,
1406
+ style=style,
1407
+ context=context,
1408
+ list_name=list_name,
1409
+ )
1372
1410
  listmix.TextEditMixin.__init__(self)
1373
1411
  set_color_according_to_theme(self, "list_bg", "list_fg")
1374
1412
 
@@ -1451,7 +1489,7 @@ class wxRadioBox(StaticBoxSizer):
1451
1489
  id=None,
1452
1490
  label=None,
1453
1491
  choices=None,
1454
- majorDimension = 0,
1492
+ majorDimension=0,
1455
1493
  style=0,
1456
1494
  *args,
1457
1495
  **kwargs,
@@ -1462,8 +1500,10 @@ class wxRadioBox(StaticBoxSizer):
1462
1500
  self._labels = []
1463
1501
  self._tool_tip = None
1464
1502
  self._help = None
1465
- super().__init__(parent=parent, id=wx.ID_ANY, label=label, orientation=wx.VERTICAL)
1466
- if majorDimension == 0 or style==wx.RA_SPECIFY_ROWS:
1503
+ super().__init__(
1504
+ parent=parent, id=wx.ID_ANY, label=label, orientation=wx.VERTICAL
1505
+ )
1506
+ if majorDimension == 0 or style == wx.RA_SPECIFY_ROWS:
1467
1507
  majorDimension = 1000
1468
1508
  container = None
1469
1509
  for idx, c in enumerate(self.choices):
@@ -1486,6 +1526,7 @@ class wxRadioBox(StaticBoxSizer):
1486
1526
  event.Skip()
1487
1527
 
1488
1528
  return mouse
1529
+
1489
1530
  for ctrl in self._children:
1490
1531
  ctrl.Bind(wx.EVT_MOTION, on_mouse_over_check(ctrl))
1491
1532
 
@@ -1567,16 +1608,20 @@ class wxRadioBox(StaticBoxSizer):
1567
1608
 
1568
1609
  def GetHelpText(self):
1569
1610
  return self._help
1611
+
1612
+
1570
1613
  class wxStaticText(wx.StaticText):
1571
1614
  def __init__(self, *args, **kwargs):
1572
1615
  super().__init__(*args, **kwargs)
1573
1616
  set_color_according_to_theme(self, "label_bg", "label_fg")
1574
1617
 
1618
+
1575
1619
  class wxListBox(wx.ListBox):
1576
1620
  def __init__(self, *args, **kwargs):
1577
1621
  super().__init__(*args, **kwargs)
1578
1622
  set_color_according_to_theme(self, "list_bg", "list_fg")
1579
1623
 
1624
+
1580
1625
  ##############
1581
1626
  # GUI KEYSTROKE FUNCTIONS
1582
1627
  ##############
@@ -1752,8 +1797,8 @@ def set_ctrl_value(ctrl, value):
1752
1797
  try:
1753
1798
  cursor = ctrl.GetInsertionPoint()
1754
1799
  if ctrl.GetValue() != value:
1755
- ctrl.SetValue(value)
1756
- ctrl.SetInsertionPoint(min(len(value), cursor))
1800
+ ctrl.SetValue(str(value))
1801
+ ctrl.SetInsertionPoint(min(len(str(value)), cursor))
1757
1802
  except RuntimeError:
1758
1803
  # Control might already have been destroyed
1759
1804
  pass