meerk40t 0.9.7051__py2.py3-none-any.whl → 0.9.7910__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 (69) hide show
  1. meerk40t/balormk/controller.py +3 -3
  2. meerk40t/balormk/device.py +7 -0
  3. meerk40t/balormk/driver.py +23 -14
  4. meerk40t/balormk/galvo_commands.py +18 -3
  5. meerk40t/balormk/gui/balorconfig.py +6 -0
  6. meerk40t/balormk/livelightjob.py +36 -14
  7. meerk40t/camera/camera.py +1 -0
  8. meerk40t/camera/gui/camerapanel.py +154 -58
  9. meerk40t/camera/plugin.py +46 -5
  10. meerk40t/core/elements/branches.py +90 -20
  11. meerk40t/core/elements/elements.py +59 -37
  12. meerk40t/core/elements/trace.py +10 -6
  13. meerk40t/core/node/node.py +2 -0
  14. meerk40t/core/plotplanner.py +7 -4
  15. meerk40t/device/gui/defaultactions.py +78 -14
  16. meerk40t/dxf/dxf_io.py +42 -0
  17. meerk40t/grbl/controller.py +245 -35
  18. meerk40t/grbl/device.py +102 -26
  19. meerk40t/grbl/driver.py +8 -2
  20. meerk40t/grbl/gui/grblconfiguration.py +6 -0
  21. meerk40t/grbl/gui/grblcontroller.py +1 -1
  22. meerk40t/gui/about.py +7 -0
  23. meerk40t/gui/choicepropertypanel.py +20 -30
  24. meerk40t/gui/devicepanel.py +27 -16
  25. meerk40t/gui/help_assets/help_assets.py +126 -2
  26. meerk40t/gui/icons.py +15 -0
  27. meerk40t/gui/laserpanel.py +102 -54
  28. meerk40t/gui/materialtest.py +10 -0
  29. meerk40t/gui/mkdebug.py +268 -9
  30. meerk40t/gui/navigationpanels.py +74 -8
  31. meerk40t/gui/propertypanels/operationpropertymain.py +185 -91
  32. meerk40t/gui/scenewidgets/elementswidget.py +7 -1
  33. meerk40t/gui/scenewidgets/selectionwidget.py +24 -9
  34. meerk40t/gui/simulation.py +1 -1
  35. meerk40t/gui/statusbarwidgets/shapepropwidget.py +50 -40
  36. meerk40t/gui/statusbarwidgets/statusbar.py +2 -2
  37. meerk40t/gui/toolwidgets/toolmeasure.py +1 -1
  38. meerk40t/gui/toolwidgets/toolnodeedit.py +4 -1
  39. meerk40t/gui/toolwidgets/tooltabedit.py +9 -7
  40. meerk40t/gui/wxmeerk40t.py +45 -15
  41. meerk40t/gui/wxmmain.py +23 -9
  42. meerk40t/gui/wxmribbon.py +36 -0
  43. meerk40t/gui/wxutils.py +66 -42
  44. meerk40t/kernel/inhibitor.py +120 -0
  45. meerk40t/kernel/kernel.py +38 -0
  46. meerk40t/lihuiyu/controller.py +33 -3
  47. meerk40t/lihuiyu/device.py +99 -4
  48. meerk40t/lihuiyu/driver.py +65 -5
  49. meerk40t/lihuiyu/gui/lhycontrollergui.py +69 -24
  50. meerk40t/lihuiyu/gui/lhydrivergui.py +6 -0
  51. meerk40t/lihuiyu/laserspeed.py +17 -10
  52. meerk40t/lihuiyu/parser.py +23 -0
  53. meerk40t/main.py +2 -2
  54. meerk40t/moshi/gui/moshidrivergui.py +7 -0
  55. meerk40t/newly/controller.py +3 -2
  56. meerk40t/newly/device.py +23 -2
  57. meerk40t/newly/driver.py +8 -3
  58. meerk40t/newly/gui/newlyconfig.py +7 -0
  59. meerk40t/ruida/gui/ruidaconfig.py +7 -0
  60. meerk40t/tools/geomstr.py +142 -49
  61. meerk40t/tools/rasterplotter.py +0 -5
  62. meerk40t/tools/ttfparser.py +921 -168
  63. {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/METADATA +1 -1
  64. {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/RECORD +69 -68
  65. {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/LICENSE +0 -0
  66. {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/WHEEL +0 -0
  67. {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/entry_points.txt +0 -0
  68. {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/top_level.txt +0 -0
  69. {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/zip-safe +0 -0
meerk40t/gui/mkdebug.py CHANGED
@@ -1,7 +1,7 @@
1
1
  """
2
- This module contains panels that display internal developer information.
3
- They will become visible if you type 'set debug_mode True' in the
4
- console and restart the program.
2
+ This module contains panels that display internal developer information.
3
+ They will become visible if you type 'set debug_mode True' in the
4
+ console and restart the program.
5
5
  """
6
6
 
7
7
  import time
@@ -10,6 +10,17 @@ import wx
10
10
  from wx import aui
11
11
 
12
12
  import meerk40t.gui.icons as mkicons
13
+ from meerk40t.constants import (
14
+ RASTER_B2T,
15
+ RASTER_CROSSOVER,
16
+ RASTER_GREEDY_H,
17
+ RASTER_GREEDY_V,
18
+ RASTER_HATCH,
19
+ RASTER_L2R,
20
+ RASTER_R2L,
21
+ RASTER_SPIRAL,
22
+ RASTER_T2B,
23
+ )
13
24
  from meerk40t.core.units import Angle, Length
14
25
  from meerk40t.gui.wxutils import (
15
26
  ScrolledPanel,
@@ -123,6 +134,25 @@ def register_panel_window(window, context):
123
134
  context.register("pane/debug_window", pane)
124
135
 
125
136
 
137
+ def register_panel_plotter(window, context):
138
+ pane = (
139
+ aui.AuiPaneInfo()
140
+ .Float()
141
+ .MinSize(225, 110)
142
+ .FloatingSize(400, 400)
143
+ .Caption(_("Plotter Test"))
144
+ .CaptionVisible(not context.pane_lock)
145
+ .Name("debug_plotter")
146
+ .Hide()
147
+ )
148
+ pane.dock_proportion = 225
149
+ pane.control = DebugRasterPlotterPanel(window, wx.ID_ANY, context=context)
150
+ pane.submenu = "_ZZ_" + _("Debug")
151
+ pane.helptext = _("Raster plotter test")
152
+ window.on_pane_create(pane)
153
+ context.register("pane/debug_plotter", pane)
154
+
155
+
126
156
  class ShutdownPanel(wx.Panel):
127
157
  """
128
158
  Tries to create a scenario that has led to multiple runtime errors durign shutdown
@@ -339,7 +369,7 @@ class DebugColorPanel(ScrolledPanel):
339
369
  sizer_main.Add(sizer_line, 0, wx.EXPAND, 0)
340
370
  count = 0
341
371
 
342
- col:wx.Colour = wx.SystemSettings().GetColour(getattr(wx, prop))
372
+ col: wx.Colour = wx.SystemSettings().GetColour(getattr(wx, prop))
343
373
  infosizer = wx.BoxSizer(wx.VERTICAL)
344
374
  box = wxStaticBitmap(
345
375
  self, wx.ID_ANY, size=wx.Size(32, 32), style=wx.SB_RAISED
@@ -518,8 +548,13 @@ class DebugIconPanel(wx.Panel):
518
548
  if obj is not None:
519
549
  if isinstance(obj, (mkicons.VectorIcon, mkicons.PyEmbeddedImage)):
520
550
  imgs = self.icon_show.Size
521
- ms = min(imgs[0], imgs[1]) * self.context.root.bitmap_correction_scale
522
- bmp = obj.GetBitmap(resize=ms, force_darkmode=self.context.themes.dark)
551
+ ms = (
552
+ min(imgs[0], imgs[1])
553
+ * self.context.root.bitmap_correction_scale
554
+ )
555
+ bmp = obj.GetBitmap(
556
+ resize=ms, force_darkmode=self.context.themes.dark
557
+ )
523
558
  self.icon_show.SetBitmap(bmp)
524
559
 
525
560
  def pane_show(self, *args):
@@ -578,11 +613,19 @@ class DebugWindowPanel(wx.Panel):
578
613
  toggle_left = wx.ToggleButton(self, wx.ID_ANY, "Toggle")
579
614
  radio_left = wx.RadioBox(self, wx.ID_ANY, choices=("Yes", "No", "Maybe"))
580
615
  btn_bmap_left = wx.BitmapButton(
581
- self, wx.ID_ANY, mkicons.icon_bell.GetBitmap(resize=mkicons.get_default_icon_size(self.context)/2)
616
+ self,
617
+ wx.ID_ANY,
618
+ mkicons.icon_bell.GetBitmap(
619
+ resize=mkicons.get_default_icon_size(self.context) / 2
620
+ ),
582
621
  )
583
622
  slider_left = wx.Slider(self, wx.ID_ANY, value=0, minValue=0, maxValue=100)
584
623
  static_left = wx.StaticBitmap(
585
- self, wx.ID_ANY, mkicons.icon_closed_door.GetBitmap(resize=mkicons.get_default_icon_size(self.context))
624
+ self,
625
+ wx.ID_ANY,
626
+ mkicons.icon_closed_door.GetBitmap(
627
+ resize=mkicons.get_default_icon_size(self.context)
628
+ ),
586
629
  )
587
630
  left_side.Add(cb_left, 0, 0, 0)
588
631
  left_side.Add(text_left, 0, 0, 0)
@@ -605,7 +648,11 @@ class DebugWindowPanel(wx.Panel):
605
648
  toggle_right = wxToggleButton(self, wx.ID_ANY, "Toggle")
606
649
  radio_right = wxRadioBox(self, wx.ID_ANY, choices=("Yes", "No", "Maybe"))
607
650
  static_right = wxStaticBitmap(
608
- self, wx.ID_ANY, mkicons.icon_closed_door.GetBitmap(resize=mkicons.get_default_icon_size(self.context))
651
+ self,
652
+ wx.ID_ANY,
653
+ mkicons.icon_closed_door.GetBitmap(
654
+ resize=mkicons.get_default_icon_size(self.context)
655
+ ),
609
656
  )
610
657
  # right_side.Add(cb_right, 0, 0, 0)
611
658
  right_side.Add(text_right, 0, 0, 0)
@@ -644,3 +691,215 @@ class DebugWindowPanel(wx.Panel):
644
691
 
645
692
  def pane_hide(self, *args):
646
693
  return
694
+
695
+
696
+ class DebugRasterPlotterPanel(wx.Panel):
697
+ def __init__(self, *args, context=None, **kwds):
698
+ # begin wxGlade: PositionPanel.__init__
699
+ kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL
700
+ wx.Panel.__init__(self, *args, **kwds)
701
+
702
+ self.context = context
703
+ self.context.themes.set_window_colors(self)
704
+
705
+ sizer_main = wx.BoxSizer(wx.VERTICAL)
706
+ info = StaticBoxSizer(
707
+ self, wx.ID_ANY, _("Raster Plotter Test Info"), wx.HORIZONTAL
708
+ )
709
+ info.Add(
710
+ wxStaticText(self, wx.ID_ANY, "Dimensions:"), 0, wx.ALIGN_CENTER_VERTICAL, 0
711
+ )
712
+ self.text_x = TextCtrl(self, wx.ID_ANY, "1", check="int")
713
+ self.text_y = TextCtrl(self, wx.ID_ANY, "1", check="int")
714
+ info.Add(self.text_x, 1, wx.EXPAND, 0)
715
+ info.Add(wxStaticText(self, wx.ID_ANY, "x"), 0, wx.ALIGN_CENTER_VERTICAL, 0)
716
+ info.Add(self.text_y, 1, wx.EXPAND, 0)
717
+ info.Add(wxStaticText(self, wx.ID_ANY, "pixel"), 0, wx.ALIGN_CENTER_VERTICAL, 0)
718
+ # raster properties
719
+ raster_sizer = StaticBoxSizer(
720
+ self, wx.ID_ANY, _("Raster Properties"), wx.VERTICAL
721
+ )
722
+ raster_type_sizer = wx.BoxSizer(wx.HORIZONTAL)
723
+ raster_sizer.Add(raster_type_sizer, 0, wx.EXPAND, 0)
724
+ self.raster_terms = [
725
+ (RASTER_T2B, "Top To Bottom"),
726
+ (RASTER_B2T, "Bottom To Top"),
727
+ (RASTER_R2L, "Right To Left"),
728
+ (RASTER_L2R, "Left To Right"),
729
+ (RASTER_HATCH, "Crosshatch"),
730
+ (RASTER_GREEDY_H, "Greedy horizontal"),
731
+ (RASTER_GREEDY_V, "Greedy vertical"),
732
+ (RASTER_CROSSOVER, "Crossover"),
733
+ (RASTER_SPIRAL, "Spiral"),
734
+ ]
735
+ # Look for registered raster (image) preprocessors,
736
+ # these are routines that take one image as parameter
737
+ # and deliver a set of (result image, method (aka raster_direction) )
738
+ # that will be dealt with independently
739
+ # The registered datastructure is (rasterid, description, method)
740
+ self.raster_terms.extend(
741
+ (key, description)
742
+ for key, description, method in self.context.kernel.lookup_all(
743
+ "raster_preprocessor/.*"
744
+ )
745
+ )
746
+ # Add a couple of testcases
747
+ # test_methods = (
748
+ # (-1, "Test: Horizontal Rectangle"),
749
+ # (-2, "Test: Vertical Rectangle"),
750
+ # (-3, "Test: Horizontal Snake"),
751
+ # (-4, "Test: Vertical Snake"),
752
+ # (-5, "Test: Spiral"),
753
+ # )
754
+ # self.raster_terms.extend(test_methods)
755
+
756
+ self.raster_methods = [key for key, info in self.raster_terms]
757
+
758
+ self.combo_raster_direction = wxComboBox(
759
+ self,
760
+ wx.ID_ANY,
761
+ style=wx.CB_DROPDOWN | wx.CB_READONLY,
762
+ )
763
+ raster_type_sizer.Add(
764
+ wxStaticText(self, wx.ID_ANY, "Raster Direction:"),
765
+ 0,
766
+ wx.ALIGN_CENTER_VERTICAL,
767
+ 0,
768
+ )
769
+ self.combo_raster_direction.AppendItems(
770
+ [info for key, info in self.raster_terms]
771
+ )
772
+ raster_type_sizer.Add(
773
+ self.combo_raster_direction, 1, wx.ALIGN_CENTER_VERTICAL, 0
774
+ )
775
+ self.check_raster_bidirectional = wxCheckBox(self, wx.ID_ANY, "Bidirectional")
776
+
777
+ raster_type_sizer.Add(
778
+ self.check_raster_bidirectional, 0, wx.ALIGN_CENTER_VERTICAL, 0
779
+ )
780
+ self.combo_raster_direction.SetSelection(0)
781
+
782
+ buttons = wx.BoxSizer(wx.HORIZONTAL)
783
+ self.btn_test_onepixel_black = wxButton(self, wx.ID_ANY, "Fully Black")
784
+ self.btn_test_onepixel_white = wxButton(self, wx.ID_ANY, "Fully White")
785
+ buttons.Add(self.btn_test_onepixel_black, 1, wx.EXPAND, 0)
786
+ buttons.Add(self.btn_test_onepixel_white, 1, wx.EXPAND, 0)
787
+ self.text_result = TextCtrl(
788
+ self, wx.ID_ANY, style=wx.TE_MULTILINE | wx.TE_READONLY
789
+ )
790
+
791
+ sizer_main.Add(info, 0, wx.EXPAND, 0)
792
+ sizer_main.Add(raster_sizer, 0, wx.EXPAND, 0)
793
+ sizer_main.Add(buttons, 0, wx.EXPAND, 0)
794
+ sizer_main.Add(self.text_result, 1, wx.EXPAND, 0)
795
+
796
+ self.SetSizer(sizer_main)
797
+ sizer_main.Fit(self)
798
+ self.Layout()
799
+
800
+ self.btn_test_onepixel_black.Bind(wx.EVT_BUTTON, self.test_empty_image)
801
+ self.btn_test_onepixel_white.Bind(wx.EVT_BUTTON, self.test_fully_covered_image)
802
+
803
+ def test_empty_image(self, event):
804
+ """
805
+ Tests the speed of rasterplotter for a fully black image.
806
+ """
807
+ import numpy as np
808
+ from PIL import Image, ImageDraw
809
+
810
+ from meerk40t.tools.rasterplotter import RasterPlotter
811
+
812
+ try:
813
+ x = int(self.text_x.GetValue())
814
+ y = int(self.text_y.GetValue())
815
+ except ValueError:
816
+ self.text_result.SetValue("Invalid dimensions. Please enter integers.")
817
+ return
818
+ raster_string = self.combo_raster_direction.GetStringSelection()
819
+ raster_direction = -1
820
+ for key, info in self.raster_terms:
821
+ if raster_string == info:
822
+ raster_direction = key
823
+ break
824
+ if raster_direction < 0:
825
+ self.text_result.SetValue("Invalid raster direction selected.")
826
+ return
827
+ bidir = self.check_raster_bidirectional.GetValue()
828
+
829
+ # Notabene: a black pixel is a non-burnt one, so we invert the logic here
830
+ image = Image.new("RGBA", (x, y), "white")
831
+ image = image.convert("L")
832
+ plotter = RasterPlotter(image.load(), x, y, direction=raster_direction, bidirectional=bidir)
833
+ t = time.time()
834
+ i = 0
835
+ res = []
836
+ pixels = 0
837
+ last_x, last_y = plotter.initial_position_in_scene()
838
+ for x, y, on in plotter.plot():
839
+ i += 1
840
+ if on:
841
+ pixels += (abs(x - last_x) + 1) * (abs(y - last_y) + 1)
842
+ res.append(f"{i}: ({x}, {y}) {'on' if on else 'off'}")
843
+ last_x, last_y = x, y
844
+ ipos = plotter.initial_position_in_scene()
845
+ lpos = plotter.final_position_in_scene()
846
+ res.insert(
847
+ 0,
848
+ f"Black found: {pixels} pixels: ranging from ({ipos[0]}, {ipos[1]}) to ({lpos[0]}, {lpos[1]})",
849
+ )
850
+ res.append(f"Time taken to finish process {time.time() - t:.3f}s\n")
851
+ self.text_result.SetValue("\n".join(res))
852
+
853
+ def test_fully_covered_image(self, event):
854
+ """
855
+ Tests the speed of rasterplotter for a fully black image.
856
+ """
857
+ import numpy as np
858
+ from PIL import Image, ImageDraw
859
+
860
+ from meerk40t.tools.rasterplotter import RasterPlotter
861
+
862
+ try:
863
+ x = int(self.text_x.GetValue())
864
+ y = int(self.text_y.GetValue())
865
+ except ValueError:
866
+ self.text_result.SetValue("Invalid dimensions. Please enter integers.")
867
+ return
868
+ if self.combo_raster_direction.GetSelection() < 0:
869
+ self.text_result.SetValue("Please select a raster direction.")
870
+ return
871
+ raster_string = self.combo_raster_direction.GetStringSelection()
872
+ raster_direction = -1
873
+ for key, info in self.raster_terms:
874
+ if raster_string == info:
875
+ raster_direction = key
876
+ break
877
+ if raster_direction < 0:
878
+ self.text_result.SetValue("Invalid raster direction selected.")
879
+ return
880
+ bidir = self.check_raster_bidirectional.GetValue()
881
+
882
+ # Notabene: a black pixel is a non-burnt one, so we invert the logic here
883
+ image = Image.new("RGBA", (x, y), "black")
884
+ image = image.convert("L")
885
+
886
+ plotter = RasterPlotter(image.load(), x, y, direction=raster_direction, bidirectional=bidir)
887
+ t = time.time()
888
+ i = 0
889
+ res = []
890
+ pixels = 0
891
+ ipos = plotter.initial_position_in_scene()
892
+ lpos = plotter.final_position_in_scene()
893
+ last_x, last_y = ipos
894
+ for x, y, on in plotter.plot():
895
+ i += 1
896
+ if on:
897
+ pixels += (abs(x - last_x) + 1) * (abs(y - last_y) + 1)
898
+ res.append(f"{i}: ({x}, {y}) {'on' if on else 'off'}")
899
+ last_x, last_y = x, y
900
+ res.insert(
901
+ 0,
902
+ f"White found: {pixels} pixels: ranging from ({ipos[0]}, {ipos[1]}) to ({lpos[0]}, {lpos[1]})",
903
+ )
904
+ res.append(f"Time taken to finish process {time.time() - t:.3f}s\n")
905
+ self.text_result.SetValue("\n".join(res))
@@ -1789,8 +1789,13 @@ class PulsePanel(wx.Panel):
1789
1789
  self.spin_pulse_duration = wx.SpinCtrl(
1790
1790
  self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER, value="50", min=1, max=1000
1791
1791
  )
1792
+ self.text_power = TextCtrl(
1793
+ self, wx.ID_ANY, style=wx.TE_PROCESS_ENTER, value="1000", check="float"
1794
+ )
1795
+ self.label_power = wxStaticText(self, wx.ID_ANY, "ppi")
1792
1796
  self.__set_properties()
1793
1797
  self.__do_layout()
1798
+ self.update_power_controls()
1794
1799
 
1795
1800
  self.Bind(
1796
1801
  wx.EVT_BUTTON, self.on_button_navigate_pulse, self.button_navigate_pulse
@@ -1813,13 +1818,17 @@ class PulsePanel(wx.Panel):
1813
1818
 
1814
1819
  def __do_layout(self):
1815
1820
  # begin wxGlade: PulsePanel.__do_layout
1816
- sizer_5 = StaticBoxSizer(self, wx.ID_ANY, _("Short Pulse:"), wx.HORIZONTAL)
1817
- sizer_5.Add(self.button_navigate_pulse, 0, wx.ALIGN_CENTER_VERTICAL, 0)
1818
- sizer_5.Add(self.spin_pulse_duration, 1, wx.ALIGN_CENTER_VERTICAL, 0)
1821
+ self.main_sizer = StaticBoxSizer(
1822
+ self, wx.ID_ANY, _("Short Pulse:"), wx.HORIZONTAL
1823
+ )
1824
+ self.main_sizer.Add(self.button_navigate_pulse, 0, wx.ALIGN_CENTER_VERTICAL, 0)
1825
+ self.main_sizer.Add(self.spin_pulse_duration, 1, wx.ALIGN_CENTER_VERTICAL, 0)
1819
1826
  label_4 = wxStaticText(self, wx.ID_ANY, _(" ms"))
1820
- sizer_5.Add(label_4, 0, wx.ALIGN_CENTER_VERTICAL, 0)
1821
- self.SetSizer(sizer_5)
1822
- sizer_5.Fit(self)
1827
+ self.main_sizer.Add(label_4, 0, wx.ALIGN_CENTER_VERTICAL, 0)
1828
+ self.main_sizer.Add(self.text_power, 1, wx.ALIGN_CENTER_VERTICAL, 0)
1829
+ self.main_sizer.Add(self.label_power, 0, wx.ALIGN_CENTER_VERTICAL, 0)
1830
+ self.SetSizer(self.main_sizer)
1831
+ self.main_sizer.Fit(self)
1823
1832
  self.Layout()
1824
1833
  # end wxGlade
1825
1834
 
@@ -1827,10 +1836,67 @@ class PulsePanel(wx.Panel):
1827
1836
  self, event=None
1828
1837
  ): # wxGlade: Navigation.<event_handler>
1829
1838
  value = self.spin_pulse_duration.GetValue()
1830
- self.context(f"pulse {value}\n")
1839
+ powerstr = ""
1840
+ if self.text_power.IsShown():
1841
+ power = self.text_power.GetValue()
1842
+ if power:
1843
+ try:
1844
+ power = float(power)
1845
+ except ValueError:
1846
+ power = None
1847
+ if power:
1848
+ if self.context.device.setting(
1849
+ bool, "use_percent_for_power_display", False
1850
+ ):
1851
+ # Convert percent to ppi
1852
+ power = power * 10
1853
+ power = max(0, min(1000, int(power)))
1854
+ self.context.device.setting(int, "last_pulse_duration", 50)
1855
+ self.context.device.setting(float, "last_pulse_power", 1000)
1856
+ self.context.device.last_pulse_duration = value
1857
+ self.context.device.last_pulse_power = power
1858
+ powerstr = f" -p {power}"
1859
+ self.context(f"pulse {value}{powerstr}\n")
1831
1860
 
1832
1861
  def on_spin_pulse_duration(self, event=None): # wxGlade: Navigation.<event_handler>
1833
- self.context.navigate_pulse = float(self.spin_pulse_duration.GetValue())
1862
+ dval = self.spin_pulse_duration.GetValue()
1863
+ self.context.device.setting(int, "last_pulse_duration", 50)
1864
+ self.context.device.last_pulse_duration = dval
1865
+
1866
+ def pane_show(self, *args):
1867
+ # Is the current device pwm pulse capable?
1868
+ self.context.listen("activate;device", self.on_update)
1869
+ self.update_power_controls()
1870
+
1871
+ def pane_hide(self, *args):
1872
+ self.context.unlisten("activate;device", self.on_update)
1873
+
1874
+ def on_update(self, origin, *args):
1875
+ self.update_power_controls()
1876
+
1877
+ def update_power_controls(self):
1878
+ show_power = getattr(self.context.device, "supports_pwm", False)
1879
+ self.text_power.Show(show_power)
1880
+ self.label_power.Show(show_power)
1881
+ pval = self.context.device.setting(float, "last_pulse_power", 1000)
1882
+ if pval is None:
1883
+ pval = 1000
1884
+ dval = self.context.device.setting(int, "last_pulse_duration", 50)
1885
+ if dval is None:
1886
+ dval = 50
1887
+ self.spin_pulse_duration.SetValue(dval)
1888
+ if self.context.device.setting(bool, "use_percent_for_power_display", False):
1889
+ self.text_power.SetValue(f"{pval/10.0:.1f}")
1890
+ self.text_power.set_range(0, 100)
1891
+ self.text_power.SetToolTip(_("Set the power of the laser pulse in percent"))
1892
+ self.label_power.SetLabel("%")
1893
+ else:
1894
+ self.text_power.SetValue(f"{pval}")
1895
+ self.text_power.set_range(0, 1000)
1896
+ self.text_power.SetToolTip(_("Set the power of the laser pulse in ppi"))
1897
+ self.label_power.SetLabel("ppi")
1898
+
1899
+ self.main_sizer.Layout()
1834
1900
 
1835
1901
 
1836
1902
  # class SizePanel(wx.Panel):