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
@@ -1,3 +1,4 @@
1
+ import threading
1
2
  import time
2
3
  from math import isinf, isnan
3
4
  from pathlib import Path
@@ -8,13 +9,14 @@ from wx import aui
8
9
 
9
10
  from meerk40t.gui.icons import (
10
11
  STD_ICON_SIZE,
11
- icons8_emergency_stop_button_50,
12
- icons8_pause_50,
13
- icons8_route_50,
12
+ get_default_icon_size,
13
+ icons8_emergency_stop_button,
14
+ icons8_pause,
15
+ icons8_route,
14
16
  )
15
17
  from meerk40t.gui.mwindow import MWindow
16
18
  from meerk40t.gui.wxutils import HoverButton
17
- from meerk40t.kernel import get_safe_path, signal_listener
19
+ from meerk40t.kernel import Job, get_safe_path, signal_listener
18
20
 
19
21
  _ = wx.GetTranslation
20
22
 
@@ -105,20 +107,24 @@ class SpoolerPanel(wx.Panel):
105
107
  self.combo_device.SetSelection(0) # All by default...
106
108
  self.button_pause = wx.Button(self.win_top, wx.ID_ANY, _("Pause"))
107
109
  self.button_pause.SetToolTip(_("Pause/Resume the laser"))
108
- self.button_pause.SetBitmap(icons8_pause_50.GetBitmap(resize=STD_ICON_SIZE / 2))
110
+ self.button_pause.SetBitmap(
111
+ icons8_pause.GetBitmap(resize=0.5 * get_default_icon_size())
112
+ )
109
113
  self.button_stop = HoverButton(self.win_top, wx.ID_ANY, _("Abort"))
110
114
  self.button_stop.SetToolTip(_("Stop the laser"))
111
115
  self.button_stop.SetBitmap(
112
- icons8_emergency_stop_button_50.GetBitmap(
113
- resize=STD_ICON_SIZE / 2, color=wx.WHITE, keepalpha=True
116
+ icons8_emergency_stop_button.GetBitmap(
117
+ resize=0.5 * get_default_icon_size(),
118
+ color=self.context.themes.get("stop_fg"),
119
+ keepalpha=True,
114
120
  )
115
121
  )
116
122
  self.button_stop.SetBitmapFocus(
117
- icons8_emergency_stop_button_50.GetBitmap(resize=STD_ICON_SIZE / 2)
123
+ icons8_emergency_stop_button.GetBitmap(resize=0.5 * get_default_icon_size())
118
124
  )
119
- self.button_stop.SetBackgroundColour(wx.Colour(127, 0, 0))
120
- self.button_stop.SetForegroundColour(wx.WHITE)
121
- self.button_stop.SetFocusColour(wx.BLACK)
125
+ self.button_stop.SetBackgroundColour(self.context.themes.get("stop_bg"))
126
+ self.button_stop.SetForegroundColour(self.context.themes.get("stop_fg"))
127
+ self.button_stop.SetFocusColour(self.context.themes.get("stop_fg_focus"))
122
128
 
123
129
  self.list_job_spool = wx.ListCtrl(
124
130
  self.win_top,
@@ -180,11 +186,24 @@ class SpoolerPanel(wx.Panel):
180
186
  self.set_pause_color()
181
187
  if self.context.spool_history_clear_on_start:
182
188
  self.clear_history()
189
+ # We set a timer job that will periodically check the spooler queue
190
+ # in case no signal was received
191
+ self.shown = False
192
+ self.update_lock = threading.Lock()
193
+ self.timerjob = Job(
194
+ process=self.update_queue,
195
+ job_name="spooler-update",
196
+ interval=5,
197
+ run_main=True,
198
+ )
183
199
 
184
200
  def __set_properties(self):
185
201
  # begin wxGlade: SpoolerPanel.__set_properties
186
202
  self.combo_device.SetToolTip(_("Select the device"))
187
203
  self.list_job_spool.SetToolTip(_("List and modify the queued operations"))
204
+ self.button_clear_history.SetToolTip(
205
+ _("Clear spooler history (right click for more options)")
206
+ )
188
207
  self.list_job_spool.AppendColumn(_("#"), format=wx.LIST_FORMAT_LEFT, width=58)
189
208
  self.list_job_spool.AppendColumn(
190
209
  _("Device"),
@@ -492,6 +511,13 @@ class SpoolerPanel(wx.Panel):
492
511
  return
493
512
 
494
513
  menu = wx.Menu()
514
+ item = menu.Append(
515
+ wx.ID_ANY,
516
+ f"{str(element)[:30]} [{spooler.context.label}]",
517
+ "",
518
+ wx.ITEM_NORMAL,
519
+ )
520
+ item.Enable(False)
495
521
  can_enable = False
496
522
  action = _("Remove")
497
523
  if element.status == "Running":
@@ -507,21 +533,46 @@ class SpoolerPanel(wx.Panel):
507
533
 
508
534
  item = menu.Append(
509
535
  wx.ID_ANY,
510
- f"{action} {str(element)[:30]} [{spooler.context.label}]",
536
+ f"{action}",
511
537
  "",
512
538
  wx.ITEM_NORMAL,
513
539
  )
514
540
  info_tuple = [spooler, element, remove_mode]
515
541
  self.Bind(wx.EVT_MENU, self.on_menu_popup_delete(info_tuple), item)
542
+ # Are there more loops than just one?
543
+ if hasattr(element, "loops"):
544
+ # Still something to go?
545
+ if element.loops > 1 and element.loops_executed < element.loops:
546
+ item = menu.Append(
547
+ wx.ID_ANY,
548
+ _("Finish after this loop"),
549
+ _(
550
+ "Stop the current execution after the succesful execution of this loop"
551
+ ),
552
+ wx.ITEM_NORMAL,
553
+ )
554
+ info_tuple = [spooler, element]
555
+ self.Bind(wx.EVT_MENU, self.on_menu_popup_stop_loop(info_tuple), item)
556
+ if not isinf(element.loops):
557
+ item = menu.Append(
558
+ wx.ID_ANY,
559
+ _("add another loop"),
560
+ _("add another loop to this job"),
561
+ wx.ITEM_NORMAL,
562
+ )
563
+ info_tuple = [spooler, element]
564
+ self.Bind(wx.EVT_MENU, self.on_menu_popup_add_loop(info_tuple), item)
565
+
516
566
  if can_enable:
517
567
  item = menu.Append(
518
568
  wx.ID_ANY,
519
- f"{action2} {str(element)[:30]} [{spooler.context.label}]",
569
+ f"{action2}",
520
570
  "",
521
571
  wx.ITEM_NORMAL,
522
572
  )
523
573
  info_tuple = [spooler, element]
524
574
  self.Bind(wx.EVT_MENU, self.on_menu_popup_toggle_enable(info_tuple), item)
575
+ menu.AppendSeparator()
525
576
  item = menu.Append(wx.ID_ANY, _("Clear All"), "", wx.ITEM_NORMAL)
526
577
  self.Bind(wx.EVT_MENU, self.on_menu_popup_clear(element), item)
527
578
 
@@ -564,19 +615,52 @@ class SpoolerPanel(wx.Panel):
564
615
  return delete
565
616
 
566
617
  def on_menu_popup_toggle_enable(self, element):
567
- def toggle(event=None):
618
+ def routine(event=None):
568
619
  spooler = element[0]
569
620
  job = element[1]
570
621
  job.enabled = not job.enabled
571
622
  self.refresh_spooler_list()
572
623
 
573
- return toggle
624
+ return routine
625
+
626
+ # def on_menu_popup_next_placement(self, element):
627
+ # def routine(event=None):
628
+ # spooler = element[0]
629
+ # job = element[1]
630
+ # if hasattr(job, "jump_to_next"):
631
+ # job.jump_to_next()
632
+ # self.refresh_spooler_list()
633
+
634
+ # return routine
635
+
636
+ def on_menu_popup_stop_loop(self, element):
637
+ def routine(event=None):
638
+ spooler = element[0]
639
+ job = element[1]
640
+ if hasattr(job, "stop_after_loop"):
641
+ job.stop_after_loop()
642
+ self.refresh_spooler_list()
643
+
644
+ return routine
645
+
646
+ def on_menu_popup_add_loop(self, element):
647
+ def routine(event=None):
648
+ spooler = element[0]
649
+ job = element[1]
650
+ if hasattr(job, "add_another_loop"):
651
+ job.add_another_loop()
652
+ self.refresh_spooler_list()
653
+
654
+ return routine
574
655
 
575
656
  def pane_show(self, *args):
657
+ self.shown = True
658
+ self.context.schedule(self.timerjob)
576
659
  self.refresh_spooler_list()
577
660
 
578
661
  def pane_hide(self, *args):
579
- pass
662
+ self.context.unschedule(self.timerjob)
663
+ self.shown = False
580
664
 
581
665
  @staticmethod
582
666
  def _name_str(named_obj):
@@ -908,15 +992,18 @@ class SpoolerPanel(wx.Panel):
908
992
  self.list_job_history.SetItem(list_id, col_id, new_data)
909
993
 
910
994
  def set_pause_color(self):
911
- new_color = None
995
+ new_bg_color = None
996
+ new_fg_color = None
912
997
  new_caption = _("Pause")
913
998
  try:
914
999
  if self.context.device.driver.paused:
915
- new_color = wx.YELLOW
1000
+ new_bg_color = self.context.themes.get("pause_bg")
1001
+ new_fg_color = self.context.themes.get("pause_fg")
916
1002
  new_caption = _("Resume")
917
1003
  except AttributeError:
918
1004
  pass
919
- self.button_pause.SetBackgroundColour(new_color)
1005
+ self.button_pause.SetBackgroundColour(new_bg_color)
1006
+ self.button_pause.SetForegroundColour(new_fg_color)
920
1007
  self.button_pause.SetLabelText(new_caption)
921
1008
 
922
1009
  @signal_listener("pause")
@@ -958,11 +1045,19 @@ class SpoolerPanel(wx.Panel):
958
1045
 
959
1046
  @signal_listener("driver;position")
960
1047
  @signal_listener("emulator;position")
961
- def on_device_update(self, origin, pos):
962
- # Only update every 2 seconds or so
963
- dtime = time.time()
964
- if dtime - self._last_invokation < 2:
1048
+ @signal_listener("pipe;usb_status")
1049
+ def on_device_update(self, origin, *args):
1050
+ doit = True
1051
+ with self.update_lock:
1052
+ # Only update every 2 seconds or so
1053
+ dtime = time.time()
1054
+ if dtime - self._last_invokation < 2:
1055
+ doit = False
1056
+ else:
1057
+ self._last_invokation = dtime
1058
+ if not doit:
965
1059
  return
1060
+
966
1061
  # Two things (at least) could go wrong:
967
1062
  # 1) You are in the wrong queue, ie there's a job running in the background a
968
1063
  # that provides an update but the user has changed the device so a different
@@ -975,7 +1070,6 @@ class SpoolerPanel(wx.Panel):
975
1070
  listctrl = self.list_job_spool
976
1071
  except RuntimeError:
977
1072
  return
978
- self._last_invokation = dtime
979
1073
  for list_id, entry in enumerate(self.queue_entries):
980
1074
  spooler = entry[0]
981
1075
  qindex = entry[1]
@@ -1040,6 +1134,10 @@ class SpoolerPanel(wx.Panel):
1040
1134
  self.refresh_spooler_list()
1041
1135
  self.refresh_history()
1042
1136
 
1137
+ def update_queue(self):
1138
+ if self.shown:
1139
+ self.on_device_update(None)
1140
+
1043
1141
 
1044
1142
  class JobSpooler(MWindow):
1045
1143
  def __init__(self, *args, **kwds):
@@ -1052,7 +1150,7 @@ class JobSpooler(MWindow):
1052
1150
  )
1053
1151
  self.add_module_delegate(self.panel)
1054
1152
  _icon = wx.NullIcon
1055
- _icon.CopyFromBitmap(icons8_route_50.GetBitmap())
1153
+ _icon.CopyFromBitmap(icons8_route.GetBitmap())
1056
1154
  self.SetIcon(_icon)
1057
1155
  self.SetTitle(_("Job Spooler"))
1058
1156
  self.Layout()
@@ -1064,7 +1162,7 @@ class JobSpooler(MWindow):
1064
1162
  "button/control/Spooler",
1065
1163
  {
1066
1164
  "label": _("Spooler"),
1067
- "icon": icons8_route_50,
1165
+ "icon": icons8_route,
1068
1166
  "tip": _("Opens Spooler Window"),
1069
1167
  "action": lambda v: kernel.console("window toggle JobSpooler\n"),
1070
1168
  "priority": -1,
@@ -133,13 +133,13 @@ class DefaultOperationWidget(StatusBarWidget):
133
133
  fontsize = 8
134
134
  elif len(opid) > 4:
135
135
  fontsize = 6
136
-
136
+ # use_theme=False is needed as othewise colors will get reversed
137
137
  icon = EmptyIcon(
138
138
  size=(self.iconsize, min(self.iconsize, self.height)),
139
139
  color=wx.Colour(swizzlecolor(op.color)),
140
140
  msg=opid,
141
141
  ptsize=fontsize,
142
- ).GetBitmap(noadjustment=True)
142
+ ).GetBitmap(noadjustment=True, use_theme=False)
143
143
  btn.SetBitmap(icon)
144
144
  op_label = op.label
145
145
  if op_label is None:
@@ -175,11 +175,13 @@ class DefaultOperationWidget(StatusBarWidget):
175
175
 
176
176
  def on_button_left(self, event):
177
177
  button = event.GetEventObject()
178
+ shift_pressed = event.ShiftDown()
179
+ # print (f"Shift: {event.ShiftDown()}, ctrl={event.ControlDown()}, alt={event.AltDown()}, bitmask={event.GetModifiers()}")
178
180
  idx = 0
179
181
  while idx < len(self.assign_buttons):
180
182
  if button is self.assign_buttons[idx]:
181
183
  node = self.assign_operations[idx]
182
- self.execute_on(node)
184
+ self.execute_on(node, shift_pressed)
183
185
  break
184
186
  idx += 1
185
187
 
@@ -289,9 +291,19 @@ class DefaultOperationWidget(StatusBarWidget):
289
291
  self.first_to_show = 0
290
292
  self.Show(True)
291
293
 
292
- def execute_on(self, targetop):
293
- data = None # == selected elements
294
- self.context.elements.assign_default_operation(data, targetop)
294
+ def execute_on(self, targetop, use_parent):
295
+ targetdata = []
296
+ data = list(self.context.elements.elems(emphasized=True))
297
+ for node in data:
298
+ add_node = node
299
+ if use_parent:
300
+ if node.parent is not None and node.parent.type.startswith("effect"):
301
+ add_node = node.parent
302
+ if add_node not in targetdata:
303
+ targetdata.append(add_node)
304
+
305
+ self.context.elements.assign_default_operation(targetdata, targetop)
306
+ self.context.elements.set_emphasis(data)
295
307
 
296
308
  self.reset_tooltips()
297
309
 
@@ -8,7 +8,7 @@ from meerk40t.core.elements.element_types import elem_nodes
8
8
  from meerk40t.core.laserjob import LaserJob
9
9
  from meerk40t.core.node.node import Node
10
10
  from meerk40t.core.units import UNITS_PER_INCH, Length
11
- from meerk40t.gui.icons import icons8_up_50
11
+ from meerk40t.gui.icons import icons8_up
12
12
  from meerk40t.gui.statusbarwidgets.statusbarwidget import StatusBarWidget
13
13
  from meerk40t.svgelements import Color
14
14
 
@@ -47,7 +47,7 @@ class SimpleInfoWidget(StatusBarWidget):
47
47
  self.btn_next = wx.StaticBitmap(
48
48
  self.parent,
49
49
  id=wx.ID_ANY,
50
- bitmap=icons8_up_50.GetBitmap(resize=20),
50
+ bitmap=icons8_up.GetBitmap(resize=20),
51
51
  size=wx.Size(20, 20),
52
52
  style=wx.BORDER_RAISED,
53
53
  )
@@ -2,12 +2,12 @@ import wx
2
2
 
3
3
  from meerk40t.core.elements.element_types import op_nodes
4
4
  from meerk40t.gui.icons import (
5
- icons8_diagonal_20,
6
- icons8_direction_20,
7
- icons8_image_20,
8
- icons8_laser_beam_20,
9
- icons8_scatter_plot_20,
10
- icons8_small_beam_20,
5
+ icon_effect_hatch,
6
+ icon_points,
7
+ icons8_direction,
8
+ icons8_image,
9
+ icons8_laser_beam,
10
+ icons8_laserbeam_weak,
11
11
  )
12
12
  from meerk40t.gui.laserrender import swizzlecolor
13
13
  from meerk40t.svgelements import Color
@@ -230,7 +230,7 @@ class OperationAssignWidget(StatusBarWidget):
230
230
  d = None
231
231
  if node.type == "op raster":
232
232
  c, d = get_color()
233
- result = icons8_direction_20.GetBitmap(
233
+ result = icons8_direction.GetBitmap(
234
234
  color=c,
235
235
  resize=(iconsize, iconsize),
236
236
  noadjustment=True,
@@ -238,7 +238,7 @@ class OperationAssignWidget(StatusBarWidget):
238
238
  )
239
239
  elif node.type == "op image":
240
240
  c, d = get_color()
241
- result = icons8_image_20.GetBitmap(
241
+ result = icons8_image.GetBitmap(
242
242
  color=c,
243
243
  resize=(iconsize, iconsize),
244
244
  noadjustment=True,
@@ -246,7 +246,7 @@ class OperationAssignWidget(StatusBarWidget):
246
246
  )
247
247
  elif node.type == "op engrave":
248
248
  c, d = get_color()
249
- result = icons8_small_beam_20.GetBitmap(
249
+ result = icons8_laserbeam_weak.GetBitmap(
250
250
  color=c,
251
251
  resize=(iconsize, iconsize),
252
252
  noadjustment=True,
@@ -254,7 +254,7 @@ class OperationAssignWidget(StatusBarWidget):
254
254
  )
255
255
  elif node.type == "op cut":
256
256
  c, d = get_color()
257
- result = icons8_laser_beam_20.GetBitmap(
257
+ result = icons8_laser_beam.GetBitmap(
258
258
  color=c,
259
259
  resize=(iconsize, iconsize),
260
260
  noadjustment=True,
@@ -262,7 +262,7 @@ class OperationAssignWidget(StatusBarWidget):
262
262
  )
263
263
  elif node.type == "op dots":
264
264
  c, d = get_color()
265
- result = icons8_scatter_plot_20.GetBitmap(
265
+ result = icon_points.GetBitmap(
266
266
  color=c,
267
267
  resize=(iconsize, iconsize),
268
268
  noadjustment=True,
@@ -284,7 +284,7 @@ class OperationAssignWidget(StatusBarWidget):
284
284
  self.assign_buttons[myidx].SetBitmap(wx.NullBitmap)
285
285
  else:
286
286
  self.assign_buttons[myidx].SetBitmap(image)
287
- # self.assign_buttons[myidx].SetBitmapDisabled(icons8_padlock_50.GetBitmap(color=Color("Grey"), resize=(self.iconsize, self.iconsize), noadjustment=True, keepalpha=True))
287
+ # self.assign_buttons[myidx].SetBitmapDisabled(icons8_unlock.GetBitmap(color=Color("Grey"), resize=(self.iconsize, self.iconsize), noadjustment=True, keepalpha=True))
288
288
  self.assign_buttons[myidx].SetToolTip(
289
289
  str(node)
290
290
  + "\n"
@@ -1,14 +1,14 @@
1
1
  import wx
2
2
 
3
3
  from meerk40t.gui.icons import (
4
- cap_butt_20,
5
- cap_round_20,
6
- cap_square_20,
7
- fill_evenodd,
8
- fill_nonzero,
9
- join_bevel,
10
- join_miter,
11
- join_round,
4
+ icon_cap_butt,
5
+ icon_cap_round,
6
+ icon_cap_square,
7
+ icon_fill_evenodd,
8
+ icon_fill_nonzero,
9
+ icon_join_bevel,
10
+ icon_join_miter,
11
+ icon_join_round,
12
12
  )
13
13
 
14
14
  from .statusbarwidget import StatusBarWidget
@@ -38,7 +38,12 @@ class LinecapWidget(StatusBarWidget):
38
38
  self.btn_cap_butt = wx.StaticBitmap(
39
39
  self.parent, id=wx.ID_ANY, size=wx.Size(30, -1), style=wx.BORDER_RAISED
40
40
  )
41
- self.btn_cap_butt.SetBitmap(cap_butt_20.GetBitmap(noadjustment=True))
41
+
42
+ self.btn_cap_butt.SetBitmap(
43
+ icon_cap_butt.GetBitmap(
44
+ resize=max(20, self.parent.available_height - 4), buffer=1
45
+ )
46
+ )
42
47
  self.btn_cap_butt.SetMaxSize(wx.Size(50, -1))
43
48
  self.btn_cap_butt.SetToolTip(_("Set the end of the lines to a butt-shape"))
44
49
  self.btn_cap_butt.Bind(wx.EVT_LEFT_DOWN, self.on_cap_butt)
@@ -46,7 +51,11 @@ class LinecapWidget(StatusBarWidget):
46
51
  self.btn_cap_round = wx.StaticBitmap(
47
52
  self.parent, id=wx.ID_ANY, size=wx.Size(30, -1), style=wx.BORDER_RAISED
48
53
  )
49
- self.btn_cap_round.SetBitmap(cap_round_20.GetBitmap(noadjustment=True))
54
+ self.btn_cap_round.SetBitmap(
55
+ icon_cap_round.GetBitmap(
56
+ resize=max(20, self.parent.available_height - 4), buffer=1
57
+ )
58
+ )
50
59
  self.btn_cap_round.SetMaxSize(wx.Size(50, -1))
51
60
  self.btn_cap_round.SetToolTip(_("Set the end of the lines to a round-shape"))
52
61
  self.btn_cap_round.Bind(wx.EVT_LEFT_DOWN, self.on_cap_round)
@@ -54,7 +63,12 @@ class LinecapWidget(StatusBarWidget):
54
63
  self.btn_cap_square = wx.StaticBitmap(
55
64
  self.parent, id=wx.ID_ANY, size=wx.Size(30, -1), style=wx.BORDER_RAISED
56
65
  )
57
- self.btn_cap_square.SetBitmap(cap_square_20.GetBitmap(noadjustment=True))
66
+
67
+ self.btn_cap_square.SetBitmap(
68
+ icon_cap_square.GetBitmap(
69
+ resize=max(20, self.parent.available_height - 4), buffer=1
70
+ )
71
+ )
58
72
  self.btn_cap_square.SetMaxSize(wx.Size(50, -1))
59
73
  self.btn_cap_square.SetToolTip(_("Set the end of the lines to a square-shape"))
60
74
  self.btn_cap_square.Bind(wx.EVT_LEFT_DOWN, self.on_cap_square)
@@ -101,7 +115,12 @@ class LinejoinWidget(StatusBarWidget):
101
115
  self.btn_join_bevel = wx.StaticBitmap(
102
116
  self.parent, id=wx.ID_ANY, size=wx.Size(25, -1), style=wx.BORDER_RAISED
103
117
  )
104
- self.btn_join_bevel.SetBitmap(join_bevel.GetBitmap(noadjustment=True))
118
+
119
+ self.btn_join_bevel.SetBitmap(
120
+ icon_join_bevel.GetBitmap(
121
+ resize=max(20, self.parent.available_height - 4), buffer=1
122
+ )
123
+ )
105
124
  self.btn_join_bevel.SetMaxSize(wx.Size(50, -1))
106
125
  self.btn_join_bevel.SetToolTip(_("Set the join of the lines to a bevel-shape"))
107
126
  self.btn_join_bevel.Bind(wx.EVT_LEFT_DOWN, self.on_join_bevel)
@@ -109,7 +128,11 @@ class LinejoinWidget(StatusBarWidget):
109
128
  self.btn_join_round = wx.StaticBitmap(
110
129
  self.parent, id=wx.ID_ANY, size=wx.Size(25, -1), style=wx.BORDER_RAISED
111
130
  )
112
- self.btn_join_round.SetBitmap(join_round.GetBitmap(noadjustment=True))
131
+ self.btn_join_round.SetBitmap(
132
+ icon_join_round.GetBitmap(
133
+ resize=max(20, self.parent.available_height - 4), buffer=1
134
+ )
135
+ )
113
136
  self.btn_join_round.SetMaxSize(wx.Size(50, -1))
114
137
  self.btn_join_round.SetToolTip(_("Set the join of lines to a round-shape"))
115
138
  self.btn_join_round.Bind(wx.EVT_LEFT_DOWN, self.on_join_round)
@@ -117,18 +140,22 @@ class LinejoinWidget(StatusBarWidget):
117
140
  self.btn_join_miter = wx.StaticBitmap(
118
141
  self.parent, id=wx.ID_ANY, size=wx.Size(25, -1), style=wx.BORDER_RAISED
119
142
  )
120
- self.btn_join_miter.SetBitmap(join_miter.GetBitmap(noadjustment=True))
143
+ self.btn_join_miter.SetBitmap(
144
+ icon_join_miter.GetBitmap(
145
+ resize=max(20, self.parent.available_height - 4), buffer=1
146
+ )
147
+ )
121
148
  self.btn_join_miter.SetMaxSize(wx.Size(50, -1))
122
149
  self.btn_join_miter.SetToolTip(_("Set the join of lines to a miter-shape"))
123
150
  self.btn_join_miter.Bind(wx.EVT_LEFT_DOWN, self.on_join_miter)
124
151
 
125
152
  # self.btn_join_arcs = wx.StaticBitmap(self.parent, id=wx.ID_ANY, size=wx.Size(25, -1), style=wx.BORDER_RAISED)
126
- # self.btn_join_arcs.SetBitmap(join_round.GetBitmap(noadjustment=True))
153
+ # self.btn_join_arcs.SetBitmap(icon_join_round.GetBitmap(noadjustment=True))
127
154
  # self.btn_join_arcs.SetToolTip(_("Set the join of lines to an arc-shape"))
128
155
  # self.btn_join_arcs.Bind(wx.EVT_LEFT_DOWN, self.on_join_arcs)
129
156
 
130
157
  # self.btn_join_miterclip = wx.StaticBitmap(self.parent, id=wx.ID_ANY, size=wx.Size(25, -1), style=wx.BORDER_RAISED)
131
- # self.btn_join_miterclip.SetBitmap(join_miter.GetBitmap(noadjustment=True))
158
+ # self.btn_join_miterclip.SetBitmap(icon_join_miter.GetBitmap(noadjustment=True))
132
159
  # self.btn_join_miterclip.SetToolTip(_("Set the join of lines to a miter-clip-shape"))
133
160
  # self.btn_join_miterclip.Bind(wx.EVT_LEFT_DOWN, self.on_join_miterclip)
134
161
 
@@ -182,14 +209,14 @@ class FillruleWidget(StatusBarWidget):
182
209
  self.parent, id=wx.ID_ANY, size=wx.Size(30, -1), style=wx.BORDER_RAISED
183
210
  )
184
211
  self.btn_fill_nonzero.SetMaxSize(wx.Size(50, -1))
185
- self.btn_fill_nonzero.SetBitmap(fill_nonzero.GetBitmap(noadjustment=True))
212
+ self.btn_fill_nonzero.SetBitmap(icon_fill_nonzero.GetBitmap(noadjustment=True))
186
213
  self.btn_fill_nonzero.SetToolTip(_("Set the fillstyle to non-zero (regular)"))
187
214
  self.btn_fill_nonzero.Bind(wx.EVT_LEFT_DOWN, self.on_fill_nonzero)
188
215
 
189
216
  self.btn_fill_evenodd = wx.StaticBitmap(
190
217
  self.parent, id=wx.ID_ANY, size=wx.Size(30, -1), style=wx.BORDER_RAISED
191
218
  )
192
- self.btn_fill_evenodd.SetBitmap(fill_evenodd.GetBitmap(noadjustment=True))
219
+ self.btn_fill_evenodd.SetBitmap(icon_fill_evenodd.GetBitmap(noadjustment=True))
193
220
  self.btn_fill_evenodd.SetMaxSize(wx.Size(50, -1))
194
221
  self.btn_fill_evenodd.SetToolTip(
195
222
  _("Set the fillstyle to even-odd (alternating areas)")
@@ -1,6 +1,6 @@
1
1
  import wx
2
2
 
3
- from meerk40t.gui.icons import icons8_next_page_20
3
+ from meerk40t.gui.icons import icons8_circled_right
4
4
 
5
5
 
6
6
  class CustomStatusBar(wx.StatusBar):
@@ -32,12 +32,14 @@ class CustomStatusBar(wx.StatusBar):
32
32
  btn = wx.StaticBitmap(
33
33
  self,
34
34
  id=wx.ID_ANY,
35
- bitmap=icons8_next_page_20.GetBitmap(noadjustment=True),
36
- size=wx.Size(20, self.MinHeight),
35
+ bitmap=icons8_circled_right.GetBitmap(
36
+ resize=max(20, self.available_height - 4), buffer=1
37
+ ),
38
+ size=wx.Size(self.available_height - 2, self.available_height - 2),
37
39
  # style=wx.BORDER_RAISED,
38
40
  )
39
41
  # btn.SetBackgroundColour(wx.RED)
40
- # btn.SetBitmap(icons8_next_page_20.GetBitmap(noadjustment=True, color=Color("red")))
42
+ # btn.SetBitmap(icons8_circled_right.GetBitmap(noadjustment=True, color=Color("red")))
41
43
  btn.Show(False)
42
44
  btn.Bind(wx.EVT_LEFT_DOWN, self.on_button_next)
43
45
  btn.Bind(wx.EVT_RIGHT_DOWN, self.on_button_prev)
@@ -49,6 +51,11 @@ class CustomStatusBar(wx.StatusBar):
49
51
  self.Reposition()
50
52
  self.startup = False
51
53
 
54
+ @property
55
+ def available_height(self):
56
+ sb_size = self.GetSize()
57
+ return sb_size[1]
58
+
52
59
  def Clear(self):
53
60
  """
54
61
  Resets all panels
meerk40t/gui/themes.py ADDED
@@ -0,0 +1,78 @@
1
+ """
2
+ Basic Module to provide infmoration about the GUI
3
+ """
4
+ import wx
5
+
6
+ from meerk40t.kernel import Service
7
+
8
+
9
+ class Themes(Service):
10
+ def __init__(self, kernel, index=None, *args, **kwargs):
11
+ Service.__init__(self, kernel, "themes" if index is None else f"themes{index}")
12
+ self.registered_themes = {
13
+ "system": self.load_system_default,
14
+ }
15
+ self._theme = None
16
+ self._dark = False
17
+ self._theme_properties = dict()
18
+ self.theme = "system"
19
+
20
+ @property
21
+ def dark(self):
22
+ return self._dark
23
+
24
+ @property
25
+ def theme(self):
26
+ return self._theme
27
+
28
+ @theme.setter
29
+ def theme(self, new_theme):
30
+ if new_theme in self.registered_themes:
31
+ self._theme = new_theme
32
+ self.registered_themes[new_theme]()
33
+
34
+ def get(self, property_value):
35
+ if property_value in self._theme_properties:
36
+ return self._theme_properties[property_value]
37
+ # property not found
38
+ return None
39
+
40
+ def load_system_default(self):
41
+ self._theme = "system"
42
+ self._dark = wx.SystemSettings().GetColour(wx.SYS_COLOUR_WINDOW)[0] < 127
43
+ from platform import system
44
+
45
+ buggy_darwin = bool(system() == "Darwin" and not self._dark)
46
+
47
+ self._theme_properties = dict()
48
+ tp = self._theme_properties
49
+ # Just a scaffold, will be extended later
50
+ # tp["button"] = wx.Button
51
+ tp["pause_bg"] = wx.Colour(200, 200, 0)
52
+ # wx.Colour("ORANGE") if self._dark else wx.Colour("YELLOW")
53
+ tp["pause_fg"] = wx.Colour("WHITE") if self._dark else wx.Colour("BLACK")
54
+ # Start Button
55
+ tp["start_bg"] = wx.Colour(0, 127, 0)
56
+ tp["start_fg"] = wx.Colour("WHITE")
57
+ tp["start_bg_inactive"] = (
58
+ wx.Colour("DARK SLATE GREY") if self._dark else wx.Colour(0, 127, 0)
59
+ )
60
+ tp["start_fg_focus"] = wx.BLACK
61
+ # Stop button
62
+ tp["stop_bg"] = wx.Colour(127, 0, 0) # red
63
+ tp["stop_fg"] = wx.Colour("WHITE")
64
+ tp["stop_fg_focus"] = wx.BLACK
65
+
66
+ tp["arm_bg"] = wx.Colour(0, 127, 0) # green
67
+ tp["arm_fg"] = wx.WHITE
68
+ tp["arm_bg_inactive"] = (
69
+ # wx.Colour("MAROON") if self._dark else wx.Colour("PALE_GREEN")
70
+ wx.Colour(127, 0, 0)
71
+ )
72
+ tp["arm_fg_focus"] = wx.BLACK
73
+
74
+ if buggy_darwin:
75
+ for key, item in tp.items():
76
+ if isinstance(item, wx.Colour):
77
+ # System default
78
+ tp[key] = None