meerk40t 0.9.2000__py2.py3-none-any.whl → 0.9.3001__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 (187) hide show
  1. meerk40t/balormk/balor_params.py +1 -43
  2. meerk40t/balormk/controller.py +1 -41
  3. meerk40t/balormk/device.py +16 -22
  4. meerk40t/balormk/driver.py +4 -4
  5. meerk40t/balormk/gui/balorconfig.py +2 -2
  6. meerk40t/balormk/gui/balorcontroller.py +13 -5
  7. meerk40t/balormk/gui/baloroperationproperties.py +0 -46
  8. meerk40t/balormk/gui/gui.py +17 -17
  9. meerk40t/camera/gui/camerapanel.py +18 -11
  10. meerk40t/core/cutcode/rastercut.py +3 -1
  11. meerk40t/core/cutplan.py +145 -14
  12. meerk40t/core/elements/clipboard.py +18 -9
  13. meerk40t/core/elements/element_treeops.py +320 -180
  14. meerk40t/core/elements/element_types.py +7 -2
  15. meerk40t/core/elements/elements.py +53 -27
  16. meerk40t/core/elements/geometry.py +8 -0
  17. meerk40t/core/elements/offset_clpr.py +129 -4
  18. meerk40t/core/elements/offset_mk.py +3 -1
  19. meerk40t/core/elements/shapes.py +28 -25
  20. meerk40t/core/laserjob.py +7 -0
  21. meerk40t/core/node/bootstrap.py +4 -0
  22. meerk40t/core/node/effect_hatch.py +85 -96
  23. meerk40t/core/node/effect_wobble.py +309 -0
  24. meerk40t/core/node/elem_image.py +49 -19
  25. meerk40t/core/node/elem_line.py +60 -0
  26. meerk40t/core/node/elem_rect.py +5 -3
  27. meerk40t/core/node/image_processed.py +766 -0
  28. meerk40t/core/node/image_raster.py +113 -0
  29. meerk40t/core/node/node.py +120 -1
  30. meerk40t/core/node/op_cut.py +2 -8
  31. meerk40t/core/node/op_dots.py +0 -8
  32. meerk40t/core/node/op_engrave.py +2 -18
  33. meerk40t/core/node/op_image.py +22 -35
  34. meerk40t/core/node/op_raster.py +0 -9
  35. meerk40t/core/planner.py +32 -2
  36. meerk40t/core/svg_io.py +699 -461
  37. meerk40t/core/treeop.py +191 -0
  38. meerk40t/core/undos.py +15 -1
  39. meerk40t/core/units.py +14 -4
  40. meerk40t/device/dummydevice.py +3 -2
  41. meerk40t/device/gui/defaultactions.py +43 -55
  42. meerk40t/device/gui/formatterpanel.py +58 -49
  43. meerk40t/device/gui/warningpanel.py +12 -12
  44. meerk40t/device/mixins.py +13 -0
  45. meerk40t/dxf/dxf_io.py +9 -5
  46. meerk40t/extra/ezd.py +28 -26
  47. meerk40t/extra/imageactions.py +300 -308
  48. meerk40t/extra/lbrn.py +19 -2
  49. meerk40t/fill/fills.py +6 -6
  50. meerk40t/fill/patternfill.py +1061 -1061
  51. meerk40t/fill/patterns.py +2 -6
  52. meerk40t/grbl/controller.py +168 -52
  53. meerk40t/grbl/device.py +23 -18
  54. meerk40t/grbl/driver.py +39 -0
  55. meerk40t/grbl/emulator.py +79 -19
  56. meerk40t/grbl/gcodejob.py +10 -0
  57. meerk40t/grbl/gui/grblconfiguration.py +2 -2
  58. meerk40t/grbl/gui/grblcontroller.py +24 -8
  59. meerk40t/grbl/gui/grblhardwareconfig.py +153 -0
  60. meerk40t/grbl/gui/gui.py +17 -14
  61. meerk40t/grbl/mock_connection.py +15 -34
  62. meerk40t/grbl/plugin.py +0 -4
  63. meerk40t/grbl/serial_connection.py +2 -1
  64. meerk40t/gui/about.py +8 -5
  65. meerk40t/gui/alignment.py +10 -6
  66. meerk40t/gui/basicops.py +27 -17
  67. meerk40t/gui/bufferview.py +2 -2
  68. meerk40t/gui/choicepropertypanel.py +101 -13
  69. meerk40t/gui/consolepanel.py +12 -9
  70. meerk40t/gui/devicepanel.py +38 -25
  71. meerk40t/gui/executejob.py +6 -4
  72. meerk40t/gui/help_assets/help_assets.py +13 -10
  73. meerk40t/gui/hersheymanager.py +8 -6
  74. meerk40t/gui/icons.py +1951 -3065
  75. meerk40t/gui/imagesplitter.py +14 -7
  76. meerk40t/gui/keymap.py +3 -3
  77. meerk40t/gui/laserpanel.py +151 -84
  78. meerk40t/gui/laserrender.py +61 -70
  79. meerk40t/gui/lasertoolpanel.py +8 -7
  80. meerk40t/gui/materialtest.py +3 -3
  81. meerk40t/gui/mkdebug.py +254 -1
  82. meerk40t/gui/navigationpanels.py +321 -180
  83. meerk40t/gui/notes.py +3 -3
  84. meerk40t/gui/opassignment.py +12 -12
  85. meerk40t/gui/operation_info.py +13 -13
  86. meerk40t/gui/plugin.py +5 -0
  87. meerk40t/gui/position.py +20 -18
  88. meerk40t/gui/preferences.py +21 -6
  89. meerk40t/gui/propertypanels/attributes.py +70 -22
  90. meerk40t/gui/propertypanels/blobproperty.py +2 -2
  91. meerk40t/gui/propertypanels/consoleproperty.py +2 -2
  92. meerk40t/gui/propertypanels/groupproperties.py +3 -3
  93. meerk40t/gui/propertypanels/hatchproperty.py +11 -18
  94. meerk40t/gui/propertypanels/imageproperty.py +4 -3
  95. meerk40t/gui/propertypanels/opbranchproperties.py +1 -1
  96. meerk40t/gui/propertypanels/pathproperty.py +2 -2
  97. meerk40t/gui/propertypanels/pointproperty.py +2 -2
  98. meerk40t/gui/propertypanels/propertywindow.py +4 -4
  99. meerk40t/gui/propertypanels/textproperty.py +3 -3
  100. meerk40t/gui/propertypanels/wobbleproperty.py +204 -0
  101. meerk40t/gui/ribbon.py +367 -259
  102. meerk40t/gui/scene/scene.py +31 -5
  103. meerk40t/gui/scenewidgets/elementswidget.py +12 -4
  104. meerk40t/gui/scenewidgets/gridwidget.py +2 -2
  105. meerk40t/gui/scenewidgets/laserpathwidget.py +7 -2
  106. meerk40t/gui/scenewidgets/machineoriginwidget.py +6 -2
  107. meerk40t/gui/scenewidgets/relocatewidget.py +1 -1
  108. meerk40t/gui/scenewidgets/reticlewidget.py +9 -0
  109. meerk40t/gui/scenewidgets/selectionwidget.py +12 -7
  110. meerk40t/gui/simpleui.py +95 -8
  111. meerk40t/gui/simulation.py +44 -36
  112. meerk40t/gui/spoolerpanel.py +124 -26
  113. meerk40t/gui/statusbarwidgets/defaultoperations.py +18 -6
  114. meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
  115. meerk40t/gui/statusbarwidgets/opassignwidget.py +12 -12
  116. meerk40t/gui/statusbarwidgets/shapepropwidget.py +45 -18
  117. meerk40t/gui/statusbarwidgets/statusbar.py +11 -4
  118. meerk40t/gui/themes.py +78 -0
  119. meerk40t/gui/toolwidgets/toolcircle.py +2 -1
  120. meerk40t/gui/toolwidgets/toolellipse.py +2 -1
  121. meerk40t/gui/toolwidgets/toolimagecut.py +132 -0
  122. meerk40t/gui/toolwidgets/toolline.py +144 -0
  123. meerk40t/gui/toolwidgets/toolnodeedit.py +72 -145
  124. meerk40t/gui/toolwidgets/toolpoint.py +1 -1
  125. meerk40t/gui/toolwidgets/toolpolygon.py +8 -55
  126. meerk40t/gui/toolwidgets/toolrect.py +2 -1
  127. meerk40t/gui/usbconnect.py +2 -2
  128. meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +2 -2
  129. meerk40t/gui/utilitywidgets/harmonograph.py +7 -7
  130. meerk40t/gui/utilitywidgets/scalewidget.py +1 -1
  131. meerk40t/gui/wordlisteditor.py +33 -18
  132. meerk40t/gui/wxmeerk40t.py +166 -66
  133. meerk40t/gui/wxmmain.py +236 -157
  134. meerk40t/gui/wxmribbon.py +49 -25
  135. meerk40t/gui/wxmscene.py +49 -38
  136. meerk40t/gui/wxmtree.py +216 -85
  137. meerk40t/gui/wxutils.py +62 -4
  138. meerk40t/image/imagetools.py +443 -15
  139. meerk40t/internal_plugins.py +2 -10
  140. meerk40t/kernel/kernel.py +12 -4
  141. meerk40t/lihuiyu/controller.py +7 -7
  142. meerk40t/lihuiyu/device.py +3 -1
  143. meerk40t/lihuiyu/driver.py +3 -0
  144. meerk40t/lihuiyu/gui/gui.py +8 -8
  145. meerk40t/lihuiyu/gui/lhyaccelgui.py +2 -2
  146. meerk40t/lihuiyu/gui/lhycontrollergui.py +73 -27
  147. meerk40t/lihuiyu/gui/lhydrivergui.py +2 -2
  148. meerk40t/lihuiyu/gui/tcpcontroller.py +22 -9
  149. meerk40t/main.py +6 -1
  150. meerk40t/moshi/controller.py +5 -5
  151. meerk40t/moshi/device.py +5 -2
  152. meerk40t/moshi/driver.py +4 -0
  153. meerk40t/moshi/gui/gui.py +8 -8
  154. meerk40t/moshi/gui/moshicontrollergui.py +24 -8
  155. meerk40t/moshi/gui/moshidrivergui.py +2 -2
  156. meerk40t/newly/controller.py +2 -0
  157. meerk40t/newly/device.py +9 -2
  158. meerk40t/newly/driver.py +4 -0
  159. meerk40t/newly/gui/gui.py +16 -17
  160. meerk40t/newly/gui/newlyconfig.py +2 -2
  161. meerk40t/newly/gui/newlycontroller.py +13 -5
  162. meerk40t/rotary/gui/gui.py +2 -2
  163. meerk40t/rotary/gui/rotarysettings.py +2 -2
  164. meerk40t/ruida/device.py +3 -0
  165. meerk40t/ruida/driver.py +4 -0
  166. meerk40t/ruida/gui/gui.py +6 -6
  167. meerk40t/ruida/gui/ruidaconfig.py +2 -2
  168. meerk40t/ruida/gui/ruidacontroller.py +13 -5
  169. meerk40t/svgelements.py +9 -9
  170. meerk40t/tools/geomstr.py +849 -153
  171. meerk40t/tools/kerftest.py +8 -4
  172. meerk40t/tools/livinghinges.py +15 -8
  173. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/METADATA +21 -16
  174. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/RECORD +185 -177
  175. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/entry_points.txt +0 -1
  176. test/test_core_elements.py +8 -24
  177. test/test_file_svg.py +88 -0
  178. test/test_fill.py +9 -9
  179. test/test_geomstr.py +258 -8
  180. test/test_kernel.py +4 -0
  181. test/test_tools_rasterplotter.py +29 -0
  182. meerk40t/extra/embroider.py +0 -56
  183. meerk40t/extra/pathoptimize.py +0 -249
  184. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/LICENSE +0 -0
  185. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/WHEEL +0 -0
  186. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/top_level.txt +0 -0
  187. {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/zip-safe +0 -0
meerk40t/gui/alignment.py CHANGED
@@ -21,7 +21,7 @@ from meerk40t.svgelements import (
21
21
  from ..core.units import Length
22
22
  from ..gui.wxutils import StaticBoxSizer, TextCtrl, dip_size
23
23
  from ..kernel import signal_listener
24
- from .icons import STD_ICON_SIZE, icons8_arrange_50
24
+ from .icons import STD_ICON_SIZE, get_default_icon_size, icons8_arrange
25
25
  from .mwindow import MWindow
26
26
 
27
27
  _ = wx.GetTranslation
@@ -248,7 +248,9 @@ class AlignmentPanel(wx.Panel):
248
248
  )
249
249
  self.rbox_treatment.SetSelection(0)
250
250
  self.btn_align = wx.Button(self, wx.ID_ANY, "Align")
251
- self.btn_align.SetBitmap(icons8_arrange_50.GetBitmap(resize=STD_ICON_SIZE / 2))
251
+ self.btn_align.SetBitmap(
252
+ icons8_arrange.GetBitmap(resize=0.5 * get_default_icon_size())
253
+ )
252
254
 
253
255
  sizer_main.Add(self.rbox_align_x, 0, wx.EXPAND, 0)
254
256
  sizer_main.Add(self.rbox_align_y, 0, wx.EXPAND, 0)
@@ -495,7 +497,9 @@ class DistributionPanel(wx.Panel):
495
497
  )
496
498
 
497
499
  self.btn_dist = wx.Button(self, wx.ID_ANY, "Distribute")
498
- self.btn_dist.SetBitmap(icons8_arrange_50.GetBitmap(resize=STD_ICON_SIZE / 2))
500
+ self.btn_dist.SetBitmap(
501
+ icons8_arrange.GetBitmap(resize=0.5 * get_default_icon_size())
502
+ )
499
503
 
500
504
  sizer_check = StaticBoxSizer(
501
505
  self,
@@ -1166,7 +1170,7 @@ class ArrangementPanel(wx.Panel):
1166
1170
 
1167
1171
  self.btn_arrange = wx.Button(self, wx.ID_ANY, _("Arrange"))
1168
1172
  self.btn_arrange.SetBitmap(
1169
- icons8_arrange_50.GetBitmap(resize=STD_ICON_SIZE / 2)
1173
+ icons8_arrange.GetBitmap(resize=0.5 * get_default_icon_size())
1170
1174
  )
1171
1175
 
1172
1176
  sizer_dimensions = wx.BoxSizer(wx.HORIZONTAL)
@@ -1558,7 +1562,7 @@ class Alignment(MWindow):
1558
1562
  self.Layout()
1559
1563
 
1560
1564
  _icon = wx.NullIcon
1561
- _icon.CopyFromBitmap(icons8_arrange_50.GetBitmap(resize=STD_ICON_SIZE / 2))
1565
+ _icon.CopyFromBitmap(icons8_arrange.GetBitmap())
1562
1566
  self.SetIcon(_icon)
1563
1567
  self.SetTitle(_("Alignment"))
1564
1568
 
@@ -1582,7 +1586,7 @@ class Alignment(MWindow):
1582
1586
  "button/align/AlignExpert",
1583
1587
  {
1584
1588
  "label": _("Expert Mode"),
1585
- "icon": icons8_arrange_50,
1589
+ "icon": icons8_arrange,
1586
1590
  "tip": _("Open alignment dialog with advanced options"),
1587
1591
  "action": lambda v: kernel.console("window toggle Alignment\n"),
1588
1592
  "size": buttonsize,
meerk40t/gui/basicops.py CHANGED
@@ -12,11 +12,11 @@ from meerk40t.gui.laserrender import swizzlecolor
12
12
  from ..kernel import Job, lookup_listener, signal_listener
13
13
  from ..svgelements import Color
14
14
  from .icons import (
15
- icons8_direction_20,
16
- icons8_image_20,
17
- icons8_laser_beam_20,
18
- icons8_scatter_plot_20,
19
- icons8_small_beam_20,
15
+ icon_points,
16
+ icons8_direction,
17
+ icons8_image,
18
+ icons8_laser_beam,
19
+ icons8_laserbeam_weak,
20
20
  )
21
21
  from .wxutils import ScrolledPanel, StaticBoxSizer, TextCtrl, create_menu, dip_size
22
22
 
@@ -121,10 +121,13 @@ class BasicOpPanel(wx.Panel):
121
121
  self.std_color_fore = None
122
122
 
123
123
  def set_display(self):
124
- self.context.device.setting(bool, "use_percent_for_power_display", False)
125
- self.use_percent = self.context.device.use_percent_for_power_display
126
- self.context.device.setting(bool, "use_mm_min_for_speed_display", False)
127
- self.use_mm_min = self.context.device.use_mm_min_for_speed_display
124
+ dev = self.context.device
125
+ if dev is None:
126
+ dev = self.context.root
127
+ dev.setting(bool, "use_percent_for_power_display", False)
128
+ self.use_percent = dev.use_percent_for_power_display
129
+ dev.setting(bool, "use_mm_min_for_speed_display", False)
130
+ self.use_mm_min = dev.use_mm_min_for_speed_display
128
131
 
129
132
  def on_combo_color(self, event):
130
133
  value = self.combo_apply_color.GetCurrentSelection()
@@ -292,8 +295,12 @@ class BasicOpPanel(wx.Panel):
292
295
  self.context.elements.set_emphasis(None)
293
296
  for elem in mynode.children:
294
297
  elem.selected = True
295
- if elem.node is not None:
296
- elem.node.emphasized = True
298
+ try:
299
+ if elem.node is not None:
300
+ elem.node.emphasized = True
301
+ except AttributeError:
302
+ # Is a structured node like hatch-effect
303
+ pass
297
304
  mynode.highlighted = True
298
305
  self.context.elements.signal("refresh_scene", "Scene")
299
306
 
@@ -335,7 +342,7 @@ class BasicOpPanel(wx.Panel):
335
342
  d = None
336
343
  if node.type == "op raster":
337
344
  c, d = get_color()
338
- result = icons8_direction_20.GetBitmap(
345
+ result = icons8_direction.GetBitmap(
339
346
  color=c,
340
347
  resize=(iconsize, iconsize),
341
348
  noadjustment=True,
@@ -343,7 +350,7 @@ class BasicOpPanel(wx.Panel):
343
350
  )
344
351
  elif node.type == "op image":
345
352
  c, d = get_color()
346
- result = icons8_image_20.GetBitmap(
353
+ result = icons8_image.GetBitmap(
347
354
  color=c,
348
355
  resize=(iconsize, iconsize),
349
356
  noadjustment=True,
@@ -351,7 +358,7 @@ class BasicOpPanel(wx.Panel):
351
358
  )
352
359
  elif node.type == "op engrave":
353
360
  c, d = get_color()
354
- result = icons8_small_beam_20.GetBitmap(
361
+ result = icons8_laserbeam_weak.GetBitmap(
355
362
  color=c,
356
363
  resize=(iconsize, iconsize),
357
364
  noadjustment=True,
@@ -359,7 +366,7 @@ class BasicOpPanel(wx.Panel):
359
366
  )
360
367
  elif node.type == "op cut":
361
368
  c, d = get_color()
362
- result = icons8_laser_beam_20.GetBitmap(
369
+ result = icons8_laser_beam.GetBitmap(
363
370
  color=c,
364
371
  resize=(iconsize, iconsize),
365
372
  noadjustment=True,
@@ -367,7 +374,7 @@ class BasicOpPanel(wx.Panel):
367
374
  )
368
375
  elif node.type == "op dots":
369
376
  c, d = get_color()
370
- result = icons8_scatter_plot_20.GetBitmap(
377
+ result = icon_points.GetBitmap(
371
378
  color=c,
372
379
  resize=(iconsize, iconsize),
373
380
  noadjustment=True,
@@ -378,7 +385,10 @@ class BasicOpPanel(wx.Panel):
378
385
  if self.operation_sizer:
379
386
  self.operation_sizer.Clear()
380
387
  self.op_panel.DestroyChildren()
381
- self.op_panel.Freeze()
388
+ try:
389
+ self.op_panel.Freeze()
390
+ except RuntimeError:
391
+ return
382
392
  self.operation_sizer = StaticBoxSizer(
383
393
  self.op_panel, wx.ID_ANY, _("Operations"), wx.VERTICAL
384
394
  )
@@ -1,6 +1,6 @@
1
1
  import wx
2
2
 
3
- from .icons import icons8_comments_50
3
+ from .icons import icons8_comments
4
4
  from .mwindow import MWindow
5
5
  from .wxutils import dip_size
6
6
 
@@ -54,7 +54,7 @@ class BufferView(MWindow):
54
54
  self.panel = BufferViewPanel(self, wx.ID_ANY, context=self.context)
55
55
  self.add_module_delegate(self.panel)
56
56
  _icon = wx.NullIcon
57
- _icon.CopyFromBitmap(icons8_comments_50.GetBitmap())
57
+ _icon.CopyFromBitmap(icons8_comments.GetBitmap())
58
58
  self.SetIcon(_icon)
59
59
  # begin wxGlade: BufferView.__set_properties
60
60
  self.SetTitle(_("BufferView"))
@@ -937,19 +937,27 @@ class ChoicePropertyPanel(ScrolledPanel):
937
937
  style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES | wx.LC_SINGLE_SEL,
938
938
  )
939
939
  columns = c.get("columns", [])
940
- for column in columns:
941
- chart.AppendColumn(
942
- column.get("label", ""),
943
- format=wx.LIST_FORMAT_LEFT,
944
- width=column.get("width", 150),
945
- )
946
- for dataline in data:
947
- row_id = chart.InsertItem(
948
- chart.GetItemCount(), dataline.get("speed", 0)
949
- )
950
- for column_id, column in enumerate(columns):
951
- c_attr = column.get("attr")
952
- chart.SetItem(row_id, column_id, str(dataline.get(c_attr, "")))
940
+
941
+ def fill_ctrl():
942
+ chart.ClearAll()
943
+ for column in columns:
944
+ chart.AppendColumn(
945
+ column.get("label", ""),
946
+ format=wx.LIST_FORMAT_LEFT,
947
+ width=column.get("width", 150),
948
+ )
949
+ for dataline in data:
950
+ row_id = chart.InsertItem(
951
+ chart.GetItemCount(),
952
+ dataline.get("speed", 0), # TODO: Speed hardcoded
953
+ )
954
+ for column_id, column in enumerate(columns):
955
+ c_attr = column.get("attr")
956
+ chart.SetItem(
957
+ row_id, column_id, str(dataline.get(c_attr, ""))
958
+ )
959
+
960
+ fill_ctrl()
953
961
 
954
962
  def on_chart_start(columns, param, ctrl, obj):
955
963
  def chart_start(event=None):
@@ -984,6 +992,86 @@ class ChoicePropertyPanel(ScrolledPanel):
984
992
  chart.Bind(
985
993
  wx.EVT_LIST_END_LABEL_EDIT, on_chart_stop(columns, attr, chart, obj)
986
994
  )
995
+
996
+ allow_deletion = c.get("allow_deletion", False)
997
+ allow_duplication = c.get("allow_duplication", False)
998
+
999
+ def on_chart_contextmenu(columns, param, ctrl, obj):
1000
+ def chart_menu(event=None):
1001
+ row_id = event.GetIndex() # Get the current row
1002
+ if row_id < 0:
1003
+ return
1004
+ menu = wx.Menu()
1005
+ if allow_deletion:
1006
+
1007
+ def on_delete(event):
1008
+ values = getattr(obj, attr)
1009
+ # try:
1010
+ values.pop(row_id)
1011
+ self.context.signal(param, values, row_id, attr)
1012
+ fill_ctrl()
1013
+ # except IndexError:
1014
+ # pass
1015
+
1016
+ menuitem = menu.Append(
1017
+ wx.ID_ANY, _("Delete this entry"), ""
1018
+ )
1019
+ self.Bind(
1020
+ wx.EVT_MENU,
1021
+ on_delete,
1022
+ id=menuitem.GetId(),
1023
+ )
1024
+ if allow_duplication:
1025
+
1026
+ def on_duplicate(event):
1027
+ values = getattr(obj, attr)
1028
+ newentry = dict()
1029
+ for key, content in values[row_id].items():
1030
+ newentry[key] = content
1031
+ values.append(newentry)
1032
+ self.context.signal(param, values, row_id, attr)
1033
+ # except IndexError:
1034
+ # pass
1035
+ fill_ctrl()
1036
+
1037
+ menuitem = menu.Append(
1038
+ wx.ID_ANY, _("Duplicate this entry"), ""
1039
+ )
1040
+ self.Bind(
1041
+ wx.EVT_MENU,
1042
+ on_duplicate,
1043
+ id=menuitem.GetId(),
1044
+ )
1045
+
1046
+ def on_default(event):
1047
+ values = getattr(obj, attr)
1048
+ default = c.get("default", [])
1049
+ values.clear()
1050
+ for e in default:
1051
+ values.append(e)
1052
+
1053
+ self.context.signal(param, values, 0, attr)
1054
+ fill_ctrl()
1055
+ # except IndexError:
1056
+ # pass
1057
+
1058
+ menuitem = menu.Append(wx.ID_ANY, _("Restore defaults"), "")
1059
+ self.Bind(
1060
+ wx.EVT_MENU,
1061
+ on_default,
1062
+ id=menuitem.GetId(),
1063
+ )
1064
+
1065
+ if menu.MenuItemCount != 0:
1066
+ self.PopupMenu(menu)
1067
+ menu.Destroy()
1068
+
1069
+ return chart_menu
1070
+
1071
+ chart.Bind(
1072
+ wx.EVT_LIST_ITEM_RIGHT_CLICK,
1073
+ on_chart_contextmenu(columns, attr, chart, obj),
1074
+ )
987
1075
  sizer_main.Add(chart, 0, wx.EXPAND, 0)
988
1076
  elif data_type in (str, int, float):
989
1077
  # str, int, and float type objects get a TextCtrl setter.
@@ -4,15 +4,14 @@ import threading
4
4
  import wx
5
5
  from wx import aui
6
6
 
7
- from meerk40t.gui.icons import STD_ICON_SIZE, icons8_console_50
7
+ from meerk40t.gui.icons import STD_ICON_SIZE, icons8_console
8
8
  from meerk40t.gui.mwindow import MWindow
9
9
  from meerk40t.kernel import get_safe_path, signal_listener
10
10
 
11
- #
12
- # try:
13
- # from wx import richtext
14
- # except ImportError:
15
- # print("import of wx.richtext for console failed, using default console window")
11
+ try:
12
+ from wx import richtext
13
+ except ImportError:
14
+ print("import of wx.richtext for console failed, using default console window")
16
15
 
17
16
 
18
17
  _ = wx.GetTranslation
@@ -219,7 +218,11 @@ class ConsolePanel(wx.ScrolledWindow):
219
218
 
220
219
  @property
221
220
  def is_dark(self):
222
- return wx.SystemSettings().GetColour(wx.SYS_COLOUR_WINDOW)[0] < 127
221
+ # try:
222
+ # res = wx.SystemSettings().GetAppearance().IsDark()
223
+ # except AttributeError:
224
+ # res = wx.SystemSettings().GetColour(wx.SYS_COLOUR_WINDOW)[0] < 127
225
+ return self.context.themes.dark
223
226
 
224
227
  def __set_properties(self):
225
228
  # begin wxGlade: ConsolePanel.__set_properties
@@ -512,7 +515,7 @@ class Console(MWindow):
512
515
  self.panel = ConsolePanel(self, wx.ID_ANY, context=self.context)
513
516
  self.add_module_delegate(self.panel)
514
517
  _icon = wx.NullIcon
515
- _icon.CopyFromBitmap(icons8_console_50.GetBitmap())
518
+ _icon.CopyFromBitmap(icons8_console.GetBitmap())
516
519
  self.SetIcon(_icon)
517
520
  self.SetTitle(_("Console"))
518
521
  self.Layout()
@@ -524,7 +527,7 @@ class Console(MWindow):
524
527
  "button/preparation/Console",
525
528
  {
526
529
  "label": _("Console"),
527
- "icon": icons8_console_50,
530
+ "icon": icons8_console,
528
531
  "tip": _("Open Console Window"),
529
532
  "action": lambda v: kernel.console("window toggle Console\n"),
530
533
  "size": STD_ICON_SIZE,
@@ -1,7 +1,7 @@
1
1
  import wx
2
2
  from wx import aui
3
3
 
4
- from meerk40t.gui.icons import icons8_manager_50
4
+ from meerk40t.gui.icons import icons8_manager
5
5
  from meerk40t.gui.mwindow import MWindow
6
6
  from meerk40t.gui.wxutils import StaticBoxSizer, dip_size
7
7
  from meerk40t.kernel import lookup_listener, signal_listener
@@ -175,6 +175,7 @@ class DevicePanel(wx.Panel):
175
175
  self.devices_list.InsertColumn(0, _("Device"))
176
176
  self.devices_list.InsertColumn(1, _("Driver"))
177
177
  self.devices_list.InsertColumn(2, _("Type"))
178
+ self.devices_list.InsertColumn(3, _("Status"))
178
179
  sizer_1.Add(self.devices_list, 7, wx.EXPAND, 0)
179
180
 
180
181
  sizer_3 = wx.BoxSizer(wx.HORIZONTAL)
@@ -257,9 +258,10 @@ class DevicePanel(wx.Panel):
257
258
  size = self.devices_list.GetSize()
258
259
  if size[0] == 0 or size[1] == 0:
259
260
  return
260
- self.devices_list.SetColumnWidth(0, int(0.5 * size[0]))
261
+ self.devices_list.SetColumnWidth(0, int(0.4 * size[0]))
261
262
  self.devices_list.SetColumnWidth(1, int(0.25 * size[0]))
262
263
  self.devices_list.SetColumnWidth(2, int(0.25 * size[0]))
264
+ self.devices_list.SetColumnWidth(3, int(0.10 * size[0]))
263
265
 
264
266
  def on_end_edit(self, event):
265
267
  prohibited = "'" + '"' + "/"
@@ -292,6 +294,8 @@ class DevicePanel(wx.Panel):
292
294
  else:
293
295
  self.devices_list.SetItemTextColour(idx, stdcol)
294
296
 
297
+ @signal_listener("pause")
298
+ @signal_listener("pipe;running")
295
299
  @signal_listener("activate;device")
296
300
  @lookup_listener("service/device/available")
297
301
  def refresh_device_tree(self, *args):
@@ -333,13 +337,26 @@ class DevicePanel(wx.Panel):
333
337
  family_info = device.setting(str, "source", family_default)
334
338
  if family_info:
335
339
  family_info = family_info.capitalize()
340
+ active_status = ""
341
+ try:
342
+ if hasattr(device, "laser_status"):
343
+ active_status = device.laser_status
344
+ except AttributeError:
345
+ active_status = "??"
346
+
347
+ try:
348
+ if hasattr(device, "driver") and hasattr(device.driver, "paused"):
349
+ if device.driver.paused:
350
+ active_status = "paused"
351
+ except AttributeError:
352
+ pass
353
+
336
354
  self.devices_list.SetItem(index, 1, type_info)
337
355
  self.devices_list.SetItem(index, 2, family_info)
356
+ self.devices_list.SetItem(index, 3, _(active_status))
338
357
  self.devices_list.SetItemData(index, dev_index)
339
358
  if self.context.device is device:
340
359
  self.devices_list.SetItemTextColour(index, wx.RED)
341
-
342
- self.devices_list.SetFocus()
343
360
  self.on_item_selected(None)
344
361
 
345
362
  def get_new_label_for_device(self, device_type):
@@ -441,17 +458,7 @@ class DevicePanel(wx.Panel):
441
458
 
442
459
  def on_tree_popup_delete(self, service):
443
460
  def deleteit(event=None):
444
- if self.context.device is service:
445
- wx.MessageDialog(
446
- None, _("Cannot remove the currently active device."), _("Error")
447
- ).ShowModal()
448
- return
449
- try:
450
- service.destroy()
451
- self.context.signal("device;modified")
452
- except AttributeError:
453
- pass
454
- self.refresh_device_tree()
461
+ self.remove_device(service)
455
462
 
456
463
  return deleteit
457
464
 
@@ -485,20 +492,26 @@ class DevicePanel(wx.Panel):
485
492
  self.context.signal("device;modified")
486
493
  dlg.Destroy()
487
494
 
488
- def on_button_remove_device(self, event): # wxGlade: DevicePanel.<event_handler>
489
- service = self.get_selected_device()
495
+ def remove_device(self, service):
490
496
  if service is not None:
491
497
  if self.context.device is service:
492
498
  wx.MessageDialog(
493
499
  None, _("Cannot remove the currently active device."), _("Error")
494
500
  ).ShowModal()
495
501
  return
496
- try:
497
- service.destroy()
498
- self.context.signal("device;modified")
499
- except AttributeError:
500
- pass
501
- self.refresh_device_tree()
502
+ if self.context.kernel.yesno(
503
+ _("Do you really want to remove this device?\nThis can not be undone!")
504
+ ):
505
+ try:
506
+ service.destroy()
507
+ self.context.signal("device;modified")
508
+ except AttributeError:
509
+ pass
510
+ self.refresh_device_tree()
511
+
512
+ def on_button_remove_device(self, event): # wxGlade: DevicePanel.<event_handler>
513
+ service = self.get_selected_device()
514
+ self.remove_device(service)
502
515
 
503
516
  def on_button_activate_device(self, event): # wxGlade: DevicePanel.<event_handler>
504
517
  service = self.get_selected_device()
@@ -539,7 +552,7 @@ class DeviceManager(MWindow):
539
552
  self.panel = DevicePanel(self, wx.ID_ANY, context=self.context)
540
553
  self.add_module_delegate(self.panel)
541
554
  _icon = wx.NullIcon
542
- _icon.CopyFromBitmap(icons8_manager_50.GetBitmap())
555
+ _icon.CopyFromBitmap(icons8_manager.GetBitmap())
543
556
  self.SetIcon(_icon)
544
557
  self.SetTitle(_("Devices"))
545
558
 
@@ -550,7 +563,7 @@ class DeviceManager(MWindow):
550
563
  "button/device/DeviceManager",
551
564
  {
552
565
  "label": _("Devices"),
553
- "icon": icons8_manager_50,
566
+ "icon": icons8_manager,
554
567
  "tip": _("Opens Devices Window"),
555
568
  "priority": -100,
556
569
  "action": lambda v: kernel.console("window toggle DeviceManager\n"),
@@ -3,7 +3,7 @@ import wx
3
3
  from meerk40t.kernel import signal_listener
4
4
 
5
5
  from .choicepropertypanel import ChoicePropertyPanel
6
- from .icons import STD_ICON_SIZE, icons8_laser_beam_52
6
+ from .icons import get_default_icon_size, icons8_laser_beam
7
7
  from .mwindow import MWindow
8
8
  from .wxutils import disable_window
9
9
 
@@ -83,7 +83,9 @@ class PlannerPanel(wx.Panel):
83
83
  )
84
84
  )
85
85
  self.button_start.SetForegroundColour(wx.BLACK)
86
- self.button_start.SetBitmap(icons8_laser_beam_52.GetBitmap())
86
+ self.button_start.SetBitmap(
87
+ icons8_laser_beam.GetBitmap(resize=get_default_icon_size())
88
+ )
87
89
  # end wxGlade
88
90
 
89
91
  def __do_layout(self):
@@ -271,7 +273,7 @@ class ExecuteJob(MWindow):
271
273
  )
272
274
  # self.add_module_delegate(self.panel)
273
275
  _icon = wx.NullIcon
274
- _icon.CopyFromBitmap(icons8_laser_beam_52.GetBitmap())
276
+ _icon.CopyFromBitmap(icons8_laser_beam.GetBitmap())
275
277
  self.SetIcon(_icon)
276
278
  self.SetTitle(_("Execute Job"))
277
279
 
@@ -282,7 +284,7 @@ class ExecuteJob(MWindow):
282
284
  # "button/jobstart/ExecuteJob",
283
285
  # {
284
286
  # "label": _("Execute Job"),
285
- # "icon": icons8_laser_beam_52,
287
+ # "icon": icons8_laser_beam,
286
288
  # "tip": _("Execute the current laser project"),
287
289
  # "action": lambda v: kernel.console("window toggle ExecuteJob 0\n"),
288
290
  # "size": STD_ICON_SIZE,
@@ -104,43 +104,46 @@ Für eine komplette Liste der Format-Codes: https://docs.python.org/3/library/da
104
104
  """
105
105
 
106
106
  italian_wordlist_howto = """
107
- WordList(s) consente di inserire elementi di testo in un progetto sostituendoli a dei “segnaposto”. Il testo viene sostituito al momento della lavorazione. È quindi possibile produrre più elementi con testi diversi senza dover modificare ogni volta il progetto.
107
+ Variabili di testo consente di inserire elementi di testo in un progetto sostituendoli a dei “segnaposto”. Il testo viene sostituito al momento della lavorazione. È quindi possibile produrre più elementi con testi diversi senza dover modificare ogni volta il progetto.
108
108
 
109
- Un segnaposto consiste in un nome all'interno di parentesi graffe, ad esempio '{FIRSTNAME}'. Il nome viene associato al segnaposto nell'Editor di WordList e il segnaposto viene sostituito dal testo inserito nel contenuto della WordList associata.
109
+ Un segnaposto consiste in una parola all'interno di parentesi graffe, ad esempio '{FIRSTNAME}'. La parola viene associato al segnaposto presente in Gestione variabili di testo e il segnaposto viene sostituito dal testo inserito nel contenuto della variabile di testo associata.
110
110
 
111
111
  Come esempio di utilizzo di questa funzionalità, immaginiamo di voler creare una serie di etichette per la prenotazione di posti a sedere ad una cena, ognuna con il nome di una persona diversa. Dopo aver creato il percorso di taglio per il contorno dell'etichetta, ad esempio un rettangolo, si utilizza lo strumento di disegno Testo per creare un elemento testo contenente quanto segue:
112
- Questo posto è riservato a {INVITATO}".
113
112
 
114
- Quindi si utilizza l'editor WordList per creare una o più voci come segue:
113
+ Questo posto è riservato a {INVITATO}.
114
+ Quindi si utilizza Gestione variabili di testo per creare una o più voci come segue:
115
+
115
116
  |-----------|------|-------|
116
117
  | Nome | Tipo | Indice|
117
118
  |-----------|------|-------|
118
119
  | invitato | Text | 0 |
119
120
  |-----------|------|-------|
120
- Quindi selezionare la riga "firstname" e aggiungere i dati necessari nel pannello Contenuti, ad es:
121
+
122
+ Quindi selezionare la riga "invitato" e aggiungere i dati necessari nel pannello Contenuto, ad es:
123
+
121
124
  Paolo
122
125
  Davide
123
126
  Andy
124
127
 
125
-
126
-
127
128
  Eseguendo la lavorazione si otterranno segnaposto individuali con nomi diversi, ad esempio 'Questo posto è riservato a Andy'.
128
129
 
129
130
  È possibile utilizzare tutti i nomi di segnaposto che si desidera nei campi di testo del progetto.
130
131
 
131
- Il valore 'Indice' nella tabella WordList indica quale voce dell'elenco dei contenuti verrà utilizzata successivamente; zero significa la prima voce. L'indice viene automaticamente aumentato di uno alla fine di ogni singolo elemento di stampa unione.
132
+ Il valore Indice di partenza per il campo nella tabella Variabili di testo indica quale voce dell'elenco dei contenuti verrà utilizzata successivamente; zero significa la prima voce. L'indice viene automaticamente aumentato di uno alla fine di ogni singolo elemento processato.
132
133
 
133
134
  Ma supponiamo, per motivi di efficienza, di voler masterizzare contemporaneamente due tag di prenotazione di posti, ciascuno con un nome diverso dallo stesso elenco. In questo caso, se il primo tag usa '{NAME#+0}' e il secondo '{NAME#+1}' (notare il segno più). '{NAME}' o '{NAME#+0}' utilizza la voce corrente (indicata dal valore dell'indice), '{NAME#+1}' utilizza la voce successiva a quella corrente, ecc.
134
135
 
135
- Con l'uso di cui sopra, è possibile utilizzare questi valori tutte le volte che si desidera nel proprio progetto. Per far avanzare l'indice è necessario fare clic sui pulsanti Prev / Next della barra degli strumenti.
136
+ Con questo sistema, è possibile utilizzare questi valori tutte le volte che si desidera nel proprio progetto.
137
+ Per far avanzare l'indice è necessario fare clic sui pulsanti Prev / Next della barra degli strumenti.
136
138
 
137
- In alternativa all'inserimento manuale dei valori dell'elenco di parole tramite questo WordList Editor, è possibile utilizzare un file CSV standard separato da virgole. I nomi dei segnaposto sono definiti nella riga di intestazione standard del file CSV (la prima riga del file CSV) e i contenuti sono presi da tutte le righe successive. Il modo più semplice per creare un file CSV è utilizzare un foglio di calcolo, ad esempio Excel; tuttavia, ad esempio per i siti di commercio elettronico, il sito web potrebbe creare automaticamente il file CSV dagli ordini effettuati online dai clienti.
139
+ In alternativa all'inserimento manuale dei valori in Variabili di testo tramite il Gestione variabili di testo, è possibile utilizzare un file CSV standard separato da virgole. I nomi dei segnaposto sono definiti nella riga di intestazione standard del file CSV (la prima riga del file CSV) e i contenuti sono presi da tutte le righe successive. Il modo più semplice per creare un file CSV è utilizzare un foglio di calcolo, ad esempio Excel.
138
140
 
139
141
  Le voci caricate da un file CSV vengono visualizzate come Tipo CSV ed è possibile impostare i valori dell'indice per tutte le voci CSV contemporaneamente.
140
142
 
141
143
  Nota: se il CSV non ha una riga di intestazione, le colonne saranno denominate "colonna_1", "colonna_2" ecc.
142
144
 
143
145
  L'elenco di parole contiene anche alcune voci speciali (che potrebbero essere particolarmente utili per i progetti di calibrazione):
146
+
144
147
  * 'version' - Versione di Meerk40t
145
148
  * 'date' - Data di inizio dell’incisione
146
149
  * 'time' - Ora di inizio dell’incisione
@@ -12,7 +12,7 @@ from meerk40t.extra.hershey import (
12
12
  update_linetext,
13
13
  validate_node,
14
14
  )
15
- from meerk40t.gui.icons import STD_ICON_SIZE, icons8_choose_font_50
15
+ from meerk40t.gui.icons import STD_ICON_SIZE, get_default_icon_size, icons8_choose_font
16
16
  from meerk40t.gui.mwindow import MWindow
17
17
  from meerk40t.gui.wxutils import StaticBoxSizer, dip_size
18
18
  from meerk40t.kernel import get_safe_path
@@ -406,8 +406,10 @@ class HersheyFontSelector(MWindow):
406
406
  super().__init__(450, 550, submenu="", *args, **kwds)
407
407
  self.panel = PanelFontSelect(self, wx.ID_ANY, context=self.context)
408
408
  _icon = wx.NullIcon
409
- _icon.CopyFromBitmap(icons8_choose_font_50.GetBitmap(resize=STD_ICON_SIZE / 2))
410
- # _icon.CopyFromBitmap(icons8_computer_support_50.GetBitmap())
409
+ _icon.CopyFromBitmap(
410
+ icons8_choose_font.GetBitmap(resize=0.5 * get_default_icon_size())
411
+ )
412
+ # _icon.CopyFromBitmap(icons8_computer_support.GetBitmap())
411
413
  self.SetIcon(_icon)
412
414
  self.SetTitle(_("Font-Selection"))
413
415
 
@@ -809,8 +811,8 @@ class HersheyFontManager(MWindow):
809
811
  super().__init__(551, 234, submenu="", *args, **kwds)
810
812
  self.panel = PanelFontManager(self, wx.ID_ANY, context=self.context)
811
813
  _icon = wx.NullIcon
812
- _icon.CopyFromBitmap(icons8_choose_font_50.GetBitmap(resize=STD_ICON_SIZE / 2))
813
- # _icon.CopyFromBitmap(icons8_computer_support_50.GetBitmap())
814
+ _icon.CopyFromBitmap(icons8_choose_font.GetBitmap())
815
+ # _icon.CopyFromBitmap(icons8_computer_support.GetBitmap())
814
816
  self.SetIcon(_icon)
815
817
  self.SetTitle(_("Font-Manager"))
816
818
 
@@ -836,7 +838,7 @@ def register_hershey_stuff(kernel):
836
838
  "button/config/HersheyFontManager",
837
839
  {
838
840
  "label": _("Font-Manager"),
839
- "icon": icons8_choose_font_50,
841
+ "icon": icons8_choose_font,
840
842
  "tip": _("Open the vector-font management window."),
841
843
  "action": lambda v: kernel.console("window toggle HersheyFontManager\n"),
842
844
  "size": buttonsize,