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
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(
@@ -872,14 +879,12 @@ class MeerK40tScenePanel(wx.Panel):
872
879
  @context.console_argument(
873
880
  "action", type=str, help=_("Action: clear or set / delete with coordinate")
874
881
  )
875
- @context.console_argument(
876
- "axis", type=str, help=_("Axis (X or Y)")
877
- )
882
+ @context.console_argument("axis", type=str, help=_("Axis (X or Y)"))
878
883
  @context.console_argument("pos", type=str, help=_("Position for magnetline"))
879
884
  @context.console_command(
880
885
  "magnet",
881
886
  help=_("magnet <action> <axis> <position>"),
882
- input_type="scene",
887
+ input_type=("scene", None),
883
888
  )
884
889
  def magnet_set(
885
890
  command,
@@ -892,10 +897,20 @@ class MeerK40tScenePanel(wx.Panel):
892
897
  ):
893
898
  def info(opt_msg):
894
899
  channel(
895
- _("You need to provide the intended action:") + "\n" +
896
- _("clear x - clear y : will clear all magnets on the given axis") + "\n" +
897
- _("set x <pos> - set y <pos>: will set a magnet line on the given axis") + "\n" +
898
- _("delete x <pos> - delete y <pos>: will delete the magnet line on the given axis")
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
+ )
899
914
  )
900
915
  if opt_msg:
901
916
  channel(opt_msg)
@@ -906,17 +921,33 @@ class MeerK40tScenePanel(wx.Panel):
906
921
  action = action.lower()
907
922
  axis = axis.upper()
908
923
  value = None
909
- if pos:
910
- try:
911
- rel_len = self.context.device.view.width if axis == "X" else self.context.device.view.height
912
- value = float(Length(pos, relative_length=rel_len))
913
- except ValueError:
914
- info (f"Invalid length: {pos}")
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"))
915
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
916
947
 
917
- if action != "clear" and value is None:
918
- info(_("You need to provide a position"))
919
- return
948
+ if action != "clear" and value is None:
949
+ info(_("You need to provide a position"))
950
+ return
920
951
 
921
952
  if action == "clear":
922
953
  if axis == "X":
@@ -927,7 +958,43 @@ class MeerK40tScenePanel(wx.Panel):
927
958
  self.magnet_y.clear()
928
959
  self.save_magnets()
929
960
  self.context.signal("refresh_scene", "Scene")
930
- channel (_("Deleted {count} magnet lines on axis {axis}").format(axis=axis, count=count))
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
+
931
998
  elif action == "set":
932
999
  done = False
933
1000
  if axis == "X":
@@ -941,7 +1008,11 @@ class MeerK40tScenePanel(wx.Panel):
941
1008
  self.save_magnets()
942
1009
  self.context.signal("refresh_scene", "Scene")
943
1010
  if done:
944
- channel(_("Magnetline appended at {pos} on axis {axis}").format(pos=pos, axis=axis))
1011
+ channel(
1012
+ _("Magnetline appended at {pos} on axis {axis}").format(
1013
+ pos=pos, axis=axis
1014
+ )
1015
+ )
945
1016
  else:
946
1017
  channel(_("Magnetline was already present"))
947
1018
  elif action.startswith("del"):
@@ -957,7 +1028,11 @@ class MeerK40tScenePanel(wx.Panel):
957
1028
  self.save_magnets()
958
1029
  self.context.signal("refresh_scene", "Scene")
959
1030
  if done:
960
- channel(_("Magnetline removed at {pos} on axis {axis}").format(pos=pos, axis=axis))
1031
+ channel(
1032
+ _("Magnetline removed at {pos} on axis {axis}").format(
1033
+ pos=pos, axis=axis
1034
+ )
1035
+ )
961
1036
  else:
962
1037
  channel(_("Magnetline was not existing"))
963
1038
 
@@ -1193,7 +1268,7 @@ class MeerK40tScenePanel(wx.Panel):
1193
1268
 
1194
1269
  @signal_listener("create_magnets")
1195
1270
  def listen_magnet_creation(self, origin, creation_list, *args):
1196
- for (info, value) in creation_list:
1271
+ for info, value in creation_list:
1197
1272
  if info == "x":
1198
1273
  self.toggle_x_magnet(value)
1199
1274
  else:
@@ -1292,11 +1367,17 @@ class MeerK40tScenePanel(wx.Panel):
1292
1367
 
1293
1368
  def recognize_background_contours(event=None):
1294
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
+ )
1295
1375
  wx_image = myBitmap.ConvertToImage()
1296
1376
  myPilImage = Image.new(
1297
1377
  "RGB", (wx_image.GetWidth(), wx_image.GetHeight())
1298
1378
  )
1299
- myPilImage.frombytes(wx_image.GetData())
1379
+ byte_data = bytes(wx_image.GetData())
1380
+ myPilImage.frombytes(byte_data)
1300
1381
  return myPilImage
1301
1382
 
1302
1383
  if not self.widget_scene.has_background:
@@ -1328,6 +1409,8 @@ class MeerK40tScenePanel(wx.Panel):
1328
1409
  dpi=500,
1329
1410
  )
1330
1411
  # print (f"Node-Dimensions: {node.bbox()}")
1412
+ # self.context.elements.elem_branch.add_node(node)
1413
+
1331
1414
  dlg = ContourDetectionDialog(self, self.context, node)
1332
1415
  dlg.ShowModal()
1333
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