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.
- meerk40t/balormk/balor_params.py +1 -43
- meerk40t/balormk/controller.py +1 -41
- meerk40t/balormk/device.py +16 -22
- meerk40t/balormk/driver.py +4 -4
- meerk40t/balormk/gui/balorconfig.py +2 -2
- meerk40t/balormk/gui/balorcontroller.py +13 -5
- meerk40t/balormk/gui/baloroperationproperties.py +0 -46
- meerk40t/balormk/gui/gui.py +17 -17
- meerk40t/camera/gui/camerapanel.py +18 -11
- meerk40t/core/cutcode/rastercut.py +3 -1
- meerk40t/core/cutplan.py +145 -14
- meerk40t/core/elements/clipboard.py +18 -9
- meerk40t/core/elements/element_treeops.py +320 -180
- meerk40t/core/elements/element_types.py +7 -2
- meerk40t/core/elements/elements.py +53 -27
- meerk40t/core/elements/geometry.py +8 -0
- meerk40t/core/elements/offset_clpr.py +129 -4
- meerk40t/core/elements/offset_mk.py +3 -1
- meerk40t/core/elements/shapes.py +28 -25
- meerk40t/core/laserjob.py +7 -0
- meerk40t/core/node/bootstrap.py +4 -0
- meerk40t/core/node/effect_hatch.py +85 -96
- meerk40t/core/node/effect_wobble.py +309 -0
- meerk40t/core/node/elem_image.py +49 -19
- meerk40t/core/node/elem_line.py +60 -0
- meerk40t/core/node/elem_rect.py +5 -3
- meerk40t/core/node/image_processed.py +766 -0
- meerk40t/core/node/image_raster.py +113 -0
- meerk40t/core/node/node.py +120 -1
- meerk40t/core/node/op_cut.py +2 -8
- meerk40t/core/node/op_dots.py +0 -8
- meerk40t/core/node/op_engrave.py +2 -18
- meerk40t/core/node/op_image.py +22 -35
- meerk40t/core/node/op_raster.py +0 -9
- meerk40t/core/planner.py +32 -2
- meerk40t/core/svg_io.py +699 -461
- meerk40t/core/treeop.py +191 -0
- meerk40t/core/undos.py +15 -1
- meerk40t/core/units.py +14 -4
- meerk40t/device/dummydevice.py +3 -2
- meerk40t/device/gui/defaultactions.py +43 -55
- meerk40t/device/gui/formatterpanel.py +58 -49
- meerk40t/device/gui/warningpanel.py +12 -12
- meerk40t/device/mixins.py +13 -0
- meerk40t/dxf/dxf_io.py +9 -5
- meerk40t/extra/ezd.py +28 -26
- meerk40t/extra/imageactions.py +300 -308
- meerk40t/extra/lbrn.py +19 -2
- meerk40t/fill/fills.py +6 -6
- meerk40t/fill/patternfill.py +1061 -1061
- meerk40t/fill/patterns.py +2 -6
- meerk40t/grbl/controller.py +168 -52
- meerk40t/grbl/device.py +23 -18
- meerk40t/grbl/driver.py +39 -0
- meerk40t/grbl/emulator.py +79 -19
- meerk40t/grbl/gcodejob.py +10 -0
- meerk40t/grbl/gui/grblconfiguration.py +2 -2
- meerk40t/grbl/gui/grblcontroller.py +24 -8
- meerk40t/grbl/gui/grblhardwareconfig.py +153 -0
- meerk40t/grbl/gui/gui.py +17 -14
- meerk40t/grbl/mock_connection.py +15 -34
- meerk40t/grbl/plugin.py +0 -4
- meerk40t/grbl/serial_connection.py +2 -1
- meerk40t/gui/about.py +8 -5
- meerk40t/gui/alignment.py +10 -6
- meerk40t/gui/basicops.py +27 -17
- meerk40t/gui/bufferview.py +2 -2
- meerk40t/gui/choicepropertypanel.py +101 -13
- meerk40t/gui/consolepanel.py +12 -9
- meerk40t/gui/devicepanel.py +38 -25
- meerk40t/gui/executejob.py +6 -4
- meerk40t/gui/help_assets/help_assets.py +13 -10
- meerk40t/gui/hersheymanager.py +8 -6
- meerk40t/gui/icons.py +1951 -3065
- meerk40t/gui/imagesplitter.py +14 -7
- meerk40t/gui/keymap.py +3 -3
- meerk40t/gui/laserpanel.py +151 -84
- meerk40t/gui/laserrender.py +61 -70
- meerk40t/gui/lasertoolpanel.py +8 -7
- meerk40t/gui/materialtest.py +3 -3
- meerk40t/gui/mkdebug.py +254 -1
- meerk40t/gui/navigationpanels.py +321 -180
- meerk40t/gui/notes.py +3 -3
- meerk40t/gui/opassignment.py +12 -12
- meerk40t/gui/operation_info.py +13 -13
- meerk40t/gui/plugin.py +5 -0
- meerk40t/gui/position.py +20 -18
- meerk40t/gui/preferences.py +21 -6
- meerk40t/gui/propertypanels/attributes.py +70 -22
- meerk40t/gui/propertypanels/blobproperty.py +2 -2
- meerk40t/gui/propertypanels/consoleproperty.py +2 -2
- meerk40t/gui/propertypanels/groupproperties.py +3 -3
- meerk40t/gui/propertypanels/hatchproperty.py +11 -18
- meerk40t/gui/propertypanels/imageproperty.py +4 -3
- meerk40t/gui/propertypanels/opbranchproperties.py +1 -1
- meerk40t/gui/propertypanels/pathproperty.py +2 -2
- meerk40t/gui/propertypanels/pointproperty.py +2 -2
- meerk40t/gui/propertypanels/propertywindow.py +4 -4
- meerk40t/gui/propertypanels/textproperty.py +3 -3
- meerk40t/gui/propertypanels/wobbleproperty.py +204 -0
- meerk40t/gui/ribbon.py +367 -259
- meerk40t/gui/scene/scene.py +31 -5
- meerk40t/gui/scenewidgets/elementswidget.py +12 -4
- meerk40t/gui/scenewidgets/gridwidget.py +2 -2
- meerk40t/gui/scenewidgets/laserpathwidget.py +7 -2
- meerk40t/gui/scenewidgets/machineoriginwidget.py +6 -2
- meerk40t/gui/scenewidgets/relocatewidget.py +1 -1
- meerk40t/gui/scenewidgets/reticlewidget.py +9 -0
- meerk40t/gui/scenewidgets/selectionwidget.py +12 -7
- meerk40t/gui/simpleui.py +95 -8
- meerk40t/gui/simulation.py +44 -36
- meerk40t/gui/spoolerpanel.py +124 -26
- meerk40t/gui/statusbarwidgets/defaultoperations.py +18 -6
- meerk40t/gui/statusbarwidgets/infowidget.py +2 -2
- meerk40t/gui/statusbarwidgets/opassignwidget.py +12 -12
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +45 -18
- meerk40t/gui/statusbarwidgets/statusbar.py +11 -4
- meerk40t/gui/themes.py +78 -0
- meerk40t/gui/toolwidgets/toolcircle.py +2 -1
- meerk40t/gui/toolwidgets/toolellipse.py +2 -1
- meerk40t/gui/toolwidgets/toolimagecut.py +132 -0
- meerk40t/gui/toolwidgets/toolline.py +144 -0
- meerk40t/gui/toolwidgets/toolnodeedit.py +72 -145
- meerk40t/gui/toolwidgets/toolpoint.py +1 -1
- meerk40t/gui/toolwidgets/toolpolygon.py +8 -55
- meerk40t/gui/toolwidgets/toolrect.py +2 -1
- meerk40t/gui/usbconnect.py +2 -2
- meerk40t/gui/utilitywidgets/cyclocycloidwidget.py +2 -2
- meerk40t/gui/utilitywidgets/harmonograph.py +7 -7
- meerk40t/gui/utilitywidgets/scalewidget.py +1 -1
- meerk40t/gui/wordlisteditor.py +33 -18
- meerk40t/gui/wxmeerk40t.py +166 -66
- meerk40t/gui/wxmmain.py +236 -157
- meerk40t/gui/wxmribbon.py +49 -25
- meerk40t/gui/wxmscene.py +49 -38
- meerk40t/gui/wxmtree.py +216 -85
- meerk40t/gui/wxutils.py +62 -4
- meerk40t/image/imagetools.py +443 -15
- meerk40t/internal_plugins.py +2 -10
- meerk40t/kernel/kernel.py +12 -4
- meerk40t/lihuiyu/controller.py +7 -7
- meerk40t/lihuiyu/device.py +3 -1
- meerk40t/lihuiyu/driver.py +3 -0
- meerk40t/lihuiyu/gui/gui.py +8 -8
- meerk40t/lihuiyu/gui/lhyaccelgui.py +2 -2
- meerk40t/lihuiyu/gui/lhycontrollergui.py +73 -27
- meerk40t/lihuiyu/gui/lhydrivergui.py +2 -2
- meerk40t/lihuiyu/gui/tcpcontroller.py +22 -9
- meerk40t/main.py +6 -1
- meerk40t/moshi/controller.py +5 -5
- meerk40t/moshi/device.py +5 -2
- meerk40t/moshi/driver.py +4 -0
- meerk40t/moshi/gui/gui.py +8 -8
- meerk40t/moshi/gui/moshicontrollergui.py +24 -8
- meerk40t/moshi/gui/moshidrivergui.py +2 -2
- meerk40t/newly/controller.py +2 -0
- meerk40t/newly/device.py +9 -2
- meerk40t/newly/driver.py +4 -0
- meerk40t/newly/gui/gui.py +16 -17
- meerk40t/newly/gui/newlyconfig.py +2 -2
- meerk40t/newly/gui/newlycontroller.py +13 -5
- meerk40t/rotary/gui/gui.py +2 -2
- meerk40t/rotary/gui/rotarysettings.py +2 -2
- meerk40t/ruida/device.py +3 -0
- meerk40t/ruida/driver.py +4 -0
- meerk40t/ruida/gui/gui.py +6 -6
- meerk40t/ruida/gui/ruidaconfig.py +2 -2
- meerk40t/ruida/gui/ruidacontroller.py +13 -5
- meerk40t/svgelements.py +9 -9
- meerk40t/tools/geomstr.py +849 -153
- meerk40t/tools/kerftest.py +8 -4
- meerk40t/tools/livinghinges.py +15 -8
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/METADATA +21 -16
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/RECORD +185 -177
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/entry_points.txt +0 -1
- test/test_core_elements.py +8 -24
- test/test_file_svg.py +88 -0
- test/test_fill.py +9 -9
- test/test_geomstr.py +258 -8
- test/test_kernel.py +4 -0
- test/test_tools_rasterplotter.py +29 -0
- meerk40t/extra/embroider.py +0 -56
- meerk40t/extra/pathoptimize.py +0 -249
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/WHEEL +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.2000.dist-info → meerk40t-0.9.3001.dist-info}/zip-safe +0 -0
meerk40t/grbl/emulator.py
CHANGED
@@ -83,7 +83,9 @@ lookup = {
|
|
83
83
|
|
84
84
|
|
85
85
|
class GRBLEmulator:
|
86
|
-
def __init__(
|
86
|
+
def __init__(
|
87
|
+
self, device=None, units_to_device_matrix=None, reply=None, channel=None
|
88
|
+
):
|
87
89
|
self.device = device
|
88
90
|
self.units_to_device_matrix = units_to_device_matrix
|
89
91
|
self.settings = {
|
@@ -127,18 +129,23 @@ class GRBLEmulator:
|
|
127
129
|
self.rapid_scale = 1.0
|
128
130
|
self.power_scale = 1.0
|
129
131
|
|
130
|
-
self.reply =
|
131
|
-
self.channel =
|
132
|
+
self.reply = reply
|
133
|
+
self.channel = channel
|
132
134
|
|
133
135
|
self._grbl_specific = False
|
134
136
|
|
135
137
|
self._buffer = list()
|
138
|
+
try:
|
139
|
+
driver = device.driver
|
140
|
+
except AttributeError:
|
141
|
+
driver = None
|
136
142
|
self.job = GcodeJob(
|
137
|
-
driver=
|
143
|
+
driver=driver,
|
138
144
|
priority=0,
|
139
145
|
channel=self.channel,
|
140
146
|
units_to_device_matrix=units_to_device_matrix,
|
141
147
|
)
|
148
|
+
self.job.reply = self.reply
|
142
149
|
|
143
150
|
def __repr__(self):
|
144
151
|
return "GRBLInterpreter()"
|
@@ -154,19 +161,27 @@ class GRBLEmulator:
|
|
154
161
|
def status_update(self):
|
155
162
|
# TODO: This should reference only the driver.status.
|
156
163
|
# Idle, Run, Hold, Jog, Alarm, Door, Check, Home, Sleep
|
157
|
-
|
158
|
-
|
164
|
+
try:
|
165
|
+
pos, state, minor = self.device.driver.status()
|
166
|
+
x, y = self.units_to_device_matrix.point_in_inverse_space(pos)
|
167
|
+
z = 0.0
|
168
|
+
if state == "busy":
|
169
|
+
state = "Run"
|
170
|
+
elif state == "hold":
|
171
|
+
state = "Hold"
|
172
|
+
else:
|
173
|
+
state = "Idle"
|
174
|
+
f = self.device.driver.speed
|
175
|
+
s = self.device.driver.power
|
176
|
+
except AttributeError:
|
177
|
+
state = "Idle"
|
178
|
+
x = self.job.x
|
179
|
+
y = self.job.y
|
180
|
+
z = self.job.z
|
181
|
+
f = 0
|
182
|
+
s = 0
|
159
183
|
x /= self.job.scale
|
160
184
|
y /= self.job.scale
|
161
|
-
z = 0.0
|
162
|
-
if state == "busy":
|
163
|
-
state = "Run"
|
164
|
-
elif state == "hold":
|
165
|
-
state = "Hold"
|
166
|
-
else:
|
167
|
-
state = "Idle"
|
168
|
-
f = self.device.driver.speed
|
169
|
-
s = self.device.driver.power
|
170
185
|
return f"<{state}|MPos:{x:.3f},{y:.3f},{z:.3f}|FS:{f},{s}>\r\n"
|
171
186
|
|
172
187
|
def write(self, data):
|
@@ -194,16 +209,18 @@ class GRBLEmulator:
|
|
194
209
|
self.device.driver.pause()
|
195
210
|
except AttributeError:
|
196
211
|
pass
|
197
|
-
elif c in (
|
212
|
+
elif c in (13, 10): # "\r","\n"
|
198
213
|
# Process CRLF endlines
|
199
214
|
line = "".join(self._buffer)
|
200
215
|
if self._grbl_specific:
|
201
216
|
self._grbl_specific = False
|
202
217
|
self.reply_code(self._grbl_special(line))
|
203
218
|
else:
|
204
|
-
self.device.spooler.send(self.job, prevent_duplicate=True)
|
205
|
-
self.job.reply = self.reply
|
206
219
|
self.job.write(line)
|
220
|
+
try:
|
221
|
+
self.device.spooler.send(self.job, prevent_duplicate=True)
|
222
|
+
except AttributeError:
|
223
|
+
self.job.execute(None)
|
207
224
|
self._buffer.clear()
|
208
225
|
elif c == 0x08:
|
209
226
|
# Process Backspaces.
|
@@ -214,6 +231,11 @@ class GRBLEmulator:
|
|
214
231
|
self.device.driver.reset()
|
215
232
|
except AttributeError:
|
216
233
|
pass
|
234
|
+
self._buffer.clear()
|
235
|
+
if self.reply:
|
236
|
+
self.reply(
|
237
|
+
"Grbl 1.1f ['$' for help]\r\n" "[MSG:’$H’|’$X’ to unlock]\r\n"
|
238
|
+
)
|
217
239
|
elif c > 0x80:
|
218
240
|
if c == 0x84:
|
219
241
|
# Safety Door
|
@@ -358,9 +380,47 @@ class GRBLEmulator:
|
|
358
380
|
elif data == "$I":
|
359
381
|
# View Build Info
|
360
382
|
return 0
|
383
|
+
elif data == "$#":
|
384
|
+
if self.reply:
|
385
|
+
data = [
|
386
|
+
"[G54:0.000,0.000,0.000]",
|
387
|
+
"[G55:0.000,0.000,0.000]",
|
388
|
+
"[G56:0.000,0.000,0.000]",
|
389
|
+
"[G57:0.000,0.000,0.000]",
|
390
|
+
"[G58:0.000,0.000,0.000]",
|
391
|
+
"[G59:0.000,0.000,0.000]",
|
392
|
+
"[G28:0.000,0.000,0.000]",
|
393
|
+
"[G30:0.000,0.000,0.000]",
|
394
|
+
"[G92:0.000,0.000,0.000]",
|
395
|
+
"[TLO:0.000]",
|
396
|
+
"[PRB:0.000,0.000,0.000:0]",
|
397
|
+
"",
|
398
|
+
]
|
399
|
+
self.reply("\r\n".join(data))
|
400
|
+
return 0
|
361
401
|
elif data == "$G":
|
362
402
|
# View GCode Parser state
|
363
|
-
|
403
|
+
if self.reply:
|
404
|
+
job = self.job
|
405
|
+
modals = list()
|
406
|
+
# G0 G54 G17 G21 G90 G94 M5 M9 T0 F0 S0
|
407
|
+
modals.append(f"G{job.move_mode}")
|
408
|
+
modals.append("G54") # default coord system.
|
409
|
+
modals.append("G17") # XY plane
|
410
|
+
modals.append("G21" if job.units == "mm" else "G20") # MM data.
|
411
|
+
modals.append("G91" if job.relative else "G90")
|
412
|
+
modals.append(
|
413
|
+
"G94" if job.feed_desc in ("inch/min", "mm/min") else "G93"
|
414
|
+
)
|
415
|
+
modals.append("M5") # Not currently in a program job.
|
416
|
+
modals.append("M9") # Mist cooling.
|
417
|
+
modals.append("T0") # Tool 0
|
418
|
+
modals.append(f"F{int(job.get_feed_rate())}")
|
419
|
+
modals.append(f"S{int(job.get_power_rate())}")
|
420
|
+
|
421
|
+
modes = " ".join(modals)
|
422
|
+
self.reply(f"[GC:{modes}]\r\n")
|
423
|
+
return 0
|
364
424
|
elif data == "$N":
|
365
425
|
# View saved start up code.
|
366
426
|
return 3
|
meerk40t/grbl/gcodejob.py
CHANGED
@@ -180,6 +180,16 @@ class GcodeJob:
|
|
180
180
|
else:
|
181
181
|
return "Disabled"
|
182
182
|
|
183
|
+
def get_feed_rate(self):
|
184
|
+
if self.speed is None:
|
185
|
+
return 0
|
186
|
+
return self.feed_invert(self.speed)
|
187
|
+
|
188
|
+
def get_power_rate(self):
|
189
|
+
if self.power is None:
|
190
|
+
return 0
|
191
|
+
return self.power
|
192
|
+
|
183
193
|
def inform(self, last_command):
|
184
194
|
if not hasattr(self._driver, "signal"):
|
185
195
|
return
|
@@ -6,7 +6,7 @@ from meerk40t.device.gui.defaultactions import DefaultActionPanel
|
|
6
6
|
from meerk40t.device.gui.formatterpanel import FormatterPanel
|
7
7
|
from meerk40t.device.gui.warningpanel import WarningPanel
|
8
8
|
from meerk40t.gui.choicepropertypanel import ChoicePropertyPanel
|
9
|
-
from meerk40t.gui.icons import
|
9
|
+
from meerk40t.gui.icons import icons8_administrative_tools
|
10
10
|
from meerk40t.gui.mwindow import MWindow
|
11
11
|
from meerk40t.gui.wxutils import ScrolledPanel, StaticBoxSizer
|
12
12
|
from meerk40t.kernel import signal_listener
|
@@ -130,7 +130,7 @@ class GRBLConfiguration(MWindow):
|
|
130
130
|
super().__init__(345, 415, *args, **kwds)
|
131
131
|
self.context = self.context.device
|
132
132
|
_icon = wx.NullIcon
|
133
|
-
_icon.CopyFromBitmap(
|
133
|
+
_icon.CopyFromBitmap(icons8_administrative_tools.GetBitmap())
|
134
134
|
self.SetIcon(_icon)
|
135
135
|
self.SetTitle(_("GRBL-Configuration"))
|
136
136
|
|
@@ -6,7 +6,11 @@ import threading
|
|
6
6
|
|
7
7
|
import wx
|
8
8
|
|
9
|
-
from meerk40t.gui.icons import
|
9
|
+
from meerk40t.gui.icons import (
|
10
|
+
get_default_icon_size,
|
11
|
+
icons8_connected,
|
12
|
+
icons8_disconnected,
|
13
|
+
)
|
10
14
|
from meerk40t.gui.mwindow import MWindow
|
11
15
|
from meerk40t.gui.wxutils import dip_size
|
12
16
|
from meerk40t.kernel import signal_listener
|
@@ -46,7 +50,7 @@ class GRBLControllerPanel(wx.Panel):
|
|
46
50
|
_("Force connection/disconnection from the device.")
|
47
51
|
)
|
48
52
|
self.button_device_connect.SetBitmap(
|
49
|
-
|
53
|
+
icons8_connected.GetBitmap(use_theme=False, resize=get_default_icon_size())
|
50
54
|
)
|
51
55
|
sizer_1.Add(self.button_device_connect, 0, wx.EXPAND, 0)
|
52
56
|
|
@@ -87,7 +91,11 @@ class GRBLControllerPanel(wx.Panel):
|
|
87
91
|
btn.Bind(wx.EVT_BUTTON, self.send_gcode(entry[0]))
|
88
92
|
btn.SetToolTip(entry[2])
|
89
93
|
if entry[3] is not None:
|
90
|
-
btn.SetBitmap(
|
94
|
+
btn.SetBitmap(
|
95
|
+
entry[3].GetBitmap(
|
96
|
+
resize=0.5 * get_default_icon_size(), use_theme=False
|
97
|
+
)
|
98
|
+
)
|
91
99
|
sizer_2.Add(btn, 1, wx.EXPAND, 0)
|
92
100
|
self.btn_clear = wx.Button(self, wx.ID_ANY, _("Clear"))
|
93
101
|
self.btn_clear.SetToolTip(_("Clear log window"))
|
@@ -180,14 +188,18 @@ class GRBLControllerPanel(wx.Panel):
|
|
180
188
|
self.button_device_connect.SetBackgroundColour("#ffff00")
|
181
189
|
self.button_device_connect.SetLabel(_("Connect"))
|
182
190
|
self.button_device_connect.SetBitmap(
|
183
|
-
|
191
|
+
icons8_disconnected.GetBitmap(
|
192
|
+
use_theme=False, resize=get_default_icon_size()
|
193
|
+
)
|
184
194
|
)
|
185
195
|
self.button_device_connect.Enable()
|
186
196
|
elif state == "connected":
|
187
197
|
self.button_device_connect.SetBackgroundColour("#00ff00")
|
188
198
|
self.button_device_connect.SetLabel(_("Disconnect"))
|
189
199
|
self.button_device_connect.SetBitmap(
|
190
|
-
|
200
|
+
icons8_connected.GetBitmap(
|
201
|
+
use_theme=False, resize=get_default_icon_size()
|
202
|
+
)
|
191
203
|
)
|
192
204
|
self.button_device_connect.Enable()
|
193
205
|
|
@@ -200,14 +212,18 @@ class GRBLControllerPanel(wx.Panel):
|
|
200
212
|
self.button_device_connect.SetBackgroundColour("#ffff00")
|
201
213
|
self.button_device_connect.SetLabel(_("Connect"))
|
202
214
|
self.button_device_connect.SetBitmap(
|
203
|
-
|
215
|
+
icons8_disconnected.GetBitmap(
|
216
|
+
use_theme=False, resize=get_default_icon_size()
|
217
|
+
)
|
204
218
|
)
|
205
219
|
self.button_device_connect.Enable()
|
206
220
|
elif self.state == "connected":
|
207
221
|
self.button_device_connect.SetBackgroundColour("#00ff00")
|
208
222
|
self.button_device_connect.SetLabel(_("Disconnect"))
|
209
223
|
self.button_device_connect.SetBitmap(
|
210
|
-
|
224
|
+
icons8_connected.GetBitmap(
|
225
|
+
use_theme=False, resize=get_default_icon_size()
|
226
|
+
)
|
211
227
|
)
|
212
228
|
self.button_device_connect.Enable()
|
213
229
|
|
@@ -221,7 +237,7 @@ class GRBLController(MWindow):
|
|
221
237
|
self.service = self.context.device
|
222
238
|
self.SetTitle("GRBL Controller")
|
223
239
|
_icon = wx.NullIcon
|
224
|
-
_icon.CopyFromBitmap(
|
240
|
+
_icon.CopyFromBitmap(icons8_connected.GetBitmap())
|
225
241
|
self.SetIcon(_icon)
|
226
242
|
|
227
243
|
self.serial_panel = GRBLControllerPanel(self, wx.ID_ANY, context=self.service)
|
@@ -0,0 +1,153 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: UTF-8 -*-
|
3
|
+
#
|
4
|
+
# generated by wxGlade 1.0.5 on Mon Nov 13 07:33:41 2023
|
5
|
+
#
|
6
|
+
|
7
|
+
import threading
|
8
|
+
|
9
|
+
import wx
|
10
|
+
|
11
|
+
from meerk40t.grbl.controller import hardware_settings
|
12
|
+
from meerk40t.gui.icons import icons8_curly_brackets
|
13
|
+
from meerk40t.gui.mwindow import MWindow
|
14
|
+
from meerk40t.gui.wxutils import EditableListCtrl, ScrolledPanel, dip_size
|
15
|
+
from meerk40t.kernel import signal_listener
|
16
|
+
|
17
|
+
_ = wx.GetTranslation
|
18
|
+
|
19
|
+
|
20
|
+
class GrblIoButtons(wx.Panel):
|
21
|
+
def __init__(self, *args, context=None, **kwds):
|
22
|
+
self.service = context
|
23
|
+
kwds["style"] = kwds.get("style", 0)
|
24
|
+
wx.Panel.__init__(self, *args, **kwds)
|
25
|
+
|
26
|
+
sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
|
27
|
+
|
28
|
+
self.button_refresh = wx.Button(self, wx.ID_ANY, "Refresh")
|
29
|
+
sizer_2.Add(self.button_refresh, 1, 0, 0)
|
30
|
+
self.Bind(wx.EVT_BUTTON, self.on_button_refresh, self.button_refresh)
|
31
|
+
|
32
|
+
# self.button_write = wx.Button(self, wx.ID_ANY, "Write")
|
33
|
+
# sizer_2.Add(self.button_write, 1, 0, 0)
|
34
|
+
#
|
35
|
+
# self.button_export = wx.Button(self, wx.ID_ANY, "Export")
|
36
|
+
# sizer_2.Add(self.button_export, 1, 0, 0)
|
37
|
+
|
38
|
+
self.SetSizer(sizer_2)
|
39
|
+
|
40
|
+
def on_button_refresh(self, event):
|
41
|
+
self.service("gcode $$\n")
|
42
|
+
|
43
|
+
|
44
|
+
class GrblHardwareProperties(ScrolledPanel):
|
45
|
+
def __init__(self, *args, context=None, **kwds):
|
46
|
+
self.service = context
|
47
|
+
kwds["style"] = kwds.get("style", 0)
|
48
|
+
ScrolledPanel.__init__(self, *args, **kwds)
|
49
|
+
|
50
|
+
sizer_1 = wx.BoxSizer(wx.VERTICAL)
|
51
|
+
|
52
|
+
chart = EditableListCtrl(
|
53
|
+
self,
|
54
|
+
wx.ID_ANY,
|
55
|
+
style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES | wx.LC_SINGLE_SEL,
|
56
|
+
)
|
57
|
+
self.chart = chart
|
58
|
+
self.build_columns()
|
59
|
+
self.fill_chart()
|
60
|
+
|
61
|
+
chart.Bind(wx.EVT_LIST_BEGIN_LABEL_EDIT, self.on_label_start_edit)
|
62
|
+
chart.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.on_label_end_edit)
|
63
|
+
|
64
|
+
sizer_1.Add(self.chart, 8, wx.EXPAND, 0)
|
65
|
+
|
66
|
+
self.io_panel = GrblIoButtons(self, wx.ID_ANY, context=self.service)
|
67
|
+
sizer_1.Add(self.io_panel, 1, wx.EXPAND, 0)
|
68
|
+
self.SetSizer(sizer_1)
|
69
|
+
|
70
|
+
def build_columns(self):
|
71
|
+
chart = self.chart
|
72
|
+
for column, width in (
|
73
|
+
("$#", 60),
|
74
|
+
("Parameter", 200),
|
75
|
+
("Value", 100),
|
76
|
+
("Unit", 100),
|
77
|
+
("Description", 1000),
|
78
|
+
):
|
79
|
+
chart.AppendColumn(
|
80
|
+
column,
|
81
|
+
format=wx.LIST_FORMAT_LEFT,
|
82
|
+
width=width,
|
83
|
+
)
|
84
|
+
|
85
|
+
def fill_chart(self):
|
86
|
+
chart = self.chart
|
87
|
+
chart.DeleteAllItems()
|
88
|
+
settings = hardware_settings
|
89
|
+
for i in range(200):
|
90
|
+
d = settings(i)
|
91
|
+
if d is None:
|
92
|
+
continue
|
93
|
+
if i in self.service.hardware_config:
|
94
|
+
value = str(self.service.hardware_config[i])
|
95
|
+
else:
|
96
|
+
value = ""
|
97
|
+
ignore, parameter, units = d
|
98
|
+
|
99
|
+
row_id = chart.InsertItem(chart.GetItemCount(), f"${i}")
|
100
|
+
chart.SetItem(row_id, 1, str(parameter))
|
101
|
+
chart.SetItem(row_id, 2, str(value))
|
102
|
+
chart.SetItem(row_id, 3, str(units))
|
103
|
+
chart.SetItem(row_id, 4, str(parameter.upper()))
|
104
|
+
|
105
|
+
def on_label_start_edit(self, event):
|
106
|
+
event.Allow()
|
107
|
+
|
108
|
+
def on_label_end_edit(self, event):
|
109
|
+
row_id = event.GetIndex() # Get the current row
|
110
|
+
col_id = event.GetColumn() # Get the current column
|
111
|
+
new_data = event.GetLabel() # Get the changed data
|
112
|
+
self.chart.SetItem(row_id, col_id, new_data)
|
113
|
+
|
114
|
+
@signal_listener("grbl:hwsettings")
|
115
|
+
def hardware_settings_changed(self, origin, *args):
|
116
|
+
self.fill_chart()
|
117
|
+
|
118
|
+
def pane_show(self):
|
119
|
+
pass
|
120
|
+
|
121
|
+
def pane_hide(self):
|
122
|
+
return
|
123
|
+
|
124
|
+
|
125
|
+
# end of class GrblHardwareProperties
|
126
|
+
|
127
|
+
|
128
|
+
class GRBLHardwareConfig(MWindow):
|
129
|
+
def __init__(self, *args, **kwds):
|
130
|
+
super().__init__(1000, 500, *args, **kwds)
|
131
|
+
self.service = self.context.device
|
132
|
+
self.SetTitle(_("GRBL Hardware Config"))
|
133
|
+
_icon = wx.NullIcon
|
134
|
+
_icon.CopyFromBitmap(icons8_curly_brackets.GetBitmap())
|
135
|
+
self.SetIcon(_icon)
|
136
|
+
|
137
|
+
self.hw_panel = GrblHardwareProperties(self, wx.ID_ANY, context=self.service)
|
138
|
+
self.Layout()
|
139
|
+
self._opened_port = None
|
140
|
+
# end wxGlade
|
141
|
+
|
142
|
+
def window_open(self):
|
143
|
+
self.hw_panel.pane_show()
|
144
|
+
|
145
|
+
def window_close(self):
|
146
|
+
self.hw_panel.pane_hide()
|
147
|
+
|
148
|
+
def delegates(self):
|
149
|
+
yield self.hw_panel
|
150
|
+
|
151
|
+
@staticmethod
|
152
|
+
def submenu():
|
153
|
+
return "Device-Control", "GRBL Hardware Config"
|
meerk40t/grbl/gui/gui.py
CHANGED
@@ -14,14 +14,15 @@ def plugin(service, lifecycle):
|
|
14
14
|
if lifecycle == "added":
|
15
15
|
from meerk40t.grbl.gui.grblconfiguration import GRBLConfiguration
|
16
16
|
from meerk40t.grbl.gui.grblcontroller import GRBLController
|
17
|
+
from meerk40t.grbl.gui.grblhardwareconfig import GRBLHardwareConfig
|
17
18
|
from meerk40t.gui.icons import (
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
icons8_computer_support,
|
20
|
+
icons8_connected,
|
21
|
+
icons8_emergency_stop_button,
|
22
|
+
icons8_flash_off,
|
23
|
+
icons8_flash_on,
|
24
|
+
icons8_info,
|
25
|
+
icons8_pause,
|
25
26
|
)
|
26
27
|
|
27
28
|
service.register("window/GRBLController", GRBLController)
|
@@ -30,13 +31,15 @@ def plugin(service, lifecycle):
|
|
30
31
|
service.register("window/Configuration", GRBLConfiguration)
|
31
32
|
service.register("winpath/Configuration", service)
|
32
33
|
|
34
|
+
service.register("window/GrblHardwareConfig", GRBLHardwareConfig)
|
35
|
+
|
33
36
|
_ = service._
|
34
37
|
|
35
38
|
service.register(
|
36
39
|
"button/control/Controller",
|
37
40
|
{
|
38
41
|
"label": _("Controller"),
|
39
|
-
"icon":
|
42
|
+
"icon": icons8_connected,
|
40
43
|
"tip": _("Opens Controller Window"),
|
41
44
|
"action": lambda v: service("window toggle GRBLController\n"),
|
42
45
|
},
|
@@ -45,7 +48,7 @@ def plugin(service, lifecycle):
|
|
45
48
|
"button/device/Configuration",
|
46
49
|
{
|
47
50
|
"label": _("Config"),
|
48
|
-
"icon":
|
51
|
+
"icon": icons8_computer_support,
|
49
52
|
"tip": _("Opens device-specific configuration window"),
|
50
53
|
"action": lambda v: service("window toggle Configuration\n"),
|
51
54
|
},
|
@@ -54,7 +57,7 @@ def plugin(service, lifecycle):
|
|
54
57
|
"button/control/Pause",
|
55
58
|
{
|
56
59
|
"label": _("Pause"),
|
57
|
-
"icon":
|
60
|
+
"icon": icons8_pause,
|
58
61
|
"tip": _("Pause the laser"),
|
59
62
|
"action": lambda v: service("pause\n"),
|
60
63
|
},
|
@@ -64,7 +67,7 @@ def plugin(service, lifecycle):
|
|
64
67
|
"button/control/Stop",
|
65
68
|
{
|
66
69
|
"label": _("Stop"),
|
67
|
-
"icon":
|
70
|
+
"icon": icons8_emergency_stop_button,
|
68
71
|
"tip": _("Emergency stop the laser"),
|
69
72
|
"action": lambda v: service("estop\n"),
|
70
73
|
},
|
@@ -82,13 +85,13 @@ def plugin(service, lifecycle):
|
|
82
85
|
"button/control/Redlight",
|
83
86
|
{
|
84
87
|
"label": _("Red Dot On"),
|
85
|
-
"icon":
|
88
|
+
"icon": icons8_flash_on,
|
86
89
|
"tip": _("Turn Redlight On"),
|
87
90
|
"action": lambda v: service("red on\n"),
|
88
91
|
"toggle": {
|
89
92
|
"label": _("Red Dot Off"),
|
90
93
|
"action": lambda v: service("red off\n"),
|
91
|
-
"icon":
|
94
|
+
"icon": icons8_flash_off,
|
92
95
|
"signal": "grbl_red_dot",
|
93
96
|
},
|
94
97
|
"rule_enabled": lambda v: has_red_dot_enabled(),
|
@@ -99,7 +102,7 @@ def plugin(service, lifecycle):
|
|
99
102
|
"button/control/ClearAlarm",
|
100
103
|
{
|
101
104
|
"label": _("Clear Alarm"),
|
102
|
-
"icon":
|
105
|
+
"icon": icons8_info,
|
103
106
|
"tip": _("Send a GRBL Clear Alarm command"),
|
104
107
|
"action": lambda v: service("clear_alarm\n"),
|
105
108
|
},
|
meerk40t/grbl/mock_connection.py
CHANGED
@@ -5,6 +5,7 @@ Mock Connection for GRBL
|
|
5
5
|
The mock connection is used for debug and research purposes. And simply prints the data sent to it rather than engaging
|
6
6
|
any hardware.
|
7
7
|
"""
|
8
|
+
from meerk40t.grbl.emulator import GRBLEmulator
|
8
9
|
|
9
10
|
|
10
11
|
class MockConnection:
|
@@ -13,48 +14,29 @@ class MockConnection:
|
|
13
14
|
self.controller = controller
|
14
15
|
self.laser = None
|
15
16
|
self.read_buffer = bytearray()
|
16
|
-
self.
|
17
|
+
self.emulator = GRBLEmulator(
|
18
|
+
device=None, units_to_device_matrix=service.view.matrix, reply=self.add_read
|
19
|
+
)
|
17
20
|
|
18
21
|
@property
|
19
22
|
def connected(self):
|
20
23
|
return self.laser is not None
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
try:
|
25
|
-
r = self.read_buffer.index(b"\r")
|
26
|
-
except ValueError:
|
27
|
-
r = -1
|
28
|
-
try:
|
29
|
-
n = self.read_buffer.index(b"\n")
|
30
|
-
except ValueError:
|
31
|
-
n = -1
|
32
|
-
|
33
|
-
if n != -1:
|
34
|
-
return min(n, r) if r != -1 else n
|
35
|
-
else:
|
36
|
-
return r
|
37
|
-
|
38
|
-
def read_buffer_command(self):
|
39
|
-
q = self._index_of_read_line
|
40
|
-
if q == -1:
|
41
|
-
raise ValueError("No forward command exists.")
|
42
|
-
cmd_issued = self.read_buffer[: q + 1]
|
43
|
-
self.read_buffer = self.read_buffer[q + 1 :]
|
44
|
-
return cmd_issued
|
25
|
+
def add_read(self, code):
|
26
|
+
self.read_buffer += bytes(code, encoding="raw_unicode_escape")
|
45
27
|
|
46
28
|
def read(self):
|
47
|
-
|
48
|
-
|
49
|
-
return
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
29
|
+
f = self.read_buffer.find(b"\n")
|
30
|
+
if f == -1:
|
31
|
+
return None
|
32
|
+
response = self.read_buffer[:f]
|
33
|
+
self.read_buffer = self.read_buffer[f + 1 :]
|
34
|
+
str_response = str(response, "raw_unicode_escape")
|
35
|
+
str_response = str_response.strip()
|
36
|
+
return str_response
|
55
37
|
|
56
38
|
def write(self, line: str):
|
57
|
-
self.
|
39
|
+
self.emulator.write(line)
|
58
40
|
|
59
41
|
def connect(self):
|
60
42
|
if self.laser:
|
@@ -63,7 +45,6 @@ class MockConnection:
|
|
63
45
|
try:
|
64
46
|
self.controller.log("Attempting to Connect...", type="connection")
|
65
47
|
self.laser = True
|
66
|
-
self.just_connected = True
|
67
48
|
self.controller.log("Connected", type="connection")
|
68
49
|
self.service.signal("grbl;status", "connected")
|
69
50
|
except ConnectionError:
|
meerk40t/grbl/plugin.py
CHANGED
@@ -36,7 +36,8 @@ class SerialConnection:
|
|
36
36
|
def write(self, line):
|
37
37
|
try:
|
38
38
|
self.laser.write(bytes(line, "utf-8"))
|
39
|
-
except (SerialException, PermissionError) as e:
|
39
|
+
except (SerialException, PermissionError, TypeError) as e:
|
40
|
+
# Type error occurs when `pipe_abort_write_r` is none, inside serialpostix.read() (out of sequence close)
|
40
41
|
self.controller.log(
|
41
42
|
f"Error when writing '{line}: {str(e)}'", type="connection"
|
42
43
|
)
|
meerk40t/gui/about.py
CHANGED
@@ -3,9 +3,9 @@ import datetime
|
|
3
3
|
import wx
|
4
4
|
|
5
5
|
from ..main import APPLICATION_NAME, APPLICATION_VERSION
|
6
|
-
from .icons import
|
6
|
+
from .icons import icon_about, icon_meerk40t
|
7
7
|
from .mwindow import MWindow
|
8
|
-
from .wxutils import StaticBoxSizer
|
8
|
+
from .wxutils import ScrolledPanel, StaticBoxSizer
|
9
9
|
|
10
10
|
_ = wx.GetTranslation
|
11
11
|
|
@@ -139,11 +139,11 @@ class AboutPanel(wx.Panel):
|
|
139
139
|
# end wxGlade
|
140
140
|
|
141
141
|
|
142
|
-
class InformationPanel(
|
142
|
+
class InformationPanel(ScrolledPanel):
|
143
143
|
def __init__(self, *args, context=None, **kwds):
|
144
144
|
# begin wxGlade: MovePanel.__init__
|
145
145
|
kwds["style"] = kwds.get("style", 0) | wx.TAB_TRAVERSAL
|
146
|
-
|
146
|
+
ScrolledPanel.__init__(self, *args, **kwds)
|
147
147
|
self.context = context
|
148
148
|
self.mk_version = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY)
|
149
149
|
self.py_version = wx.TextCtrl(self, wx.ID_ANY, "", style=wx.TE_READONLY)
|
@@ -152,12 +152,14 @@ class InformationPanel(wx.Panel):
|
|
152
152
|
self.os_version = wx.TextCtrl(
|
153
153
|
self, wx.ID_ANY, "", style=wx.TE_READONLY | wx.TE_MULTILINE
|
154
154
|
)
|
155
|
+
self.os_version.SetMinSize(wx.Size(-1, 5 * 25))
|
155
156
|
self.info_btn = wx.Button(self, wx.ID_ANY, _("Copy to Clipboard"))
|
156
157
|
self.Bind(wx.EVT_BUTTON, self.copy_debug_info, self.info_btn)
|
157
158
|
self.update_btn = wx.Button(self, wx.ID_ANY, _("Check for Updates"))
|
158
159
|
self.Bind(wx.EVT_BUTTON, self.check_for_updates, self.update_btn)
|
159
160
|
self.__set_properties()
|
160
161
|
self.__do_layout()
|
162
|
+
self.SetupScrolling()
|
161
163
|
|
162
164
|
def __set_properties(self):
|
163
165
|
# Fill the content...
|
@@ -181,6 +183,7 @@ class InformationPanel(wx.Panel):
|
|
181
183
|
info += f"Version: {uname.version}" + "\n"
|
182
184
|
info += f"Machine: {uname.machine}" + "\n"
|
183
185
|
info += f"Processor: {uname.processor}" + "\n"
|
186
|
+
info += f"Theme: {self.context.themes.theme}, Darkmode: {self.context.themes.dark}\n"
|
184
187
|
try:
|
185
188
|
info += f"Ip-Address: {socket.gethostbyname(socket.gethostname())}"
|
186
189
|
except socket.gaierror:
|
@@ -284,7 +287,7 @@ class About(MWindow):
|
|
284
287
|
self.add_module_delegate(self.panel_about)
|
285
288
|
self.add_module_delegate(self.panel_info)
|
286
289
|
_icon = wx.NullIcon
|
287
|
-
_icon.CopyFromBitmap(
|
290
|
+
_icon.CopyFromBitmap(icon_about.GetBitmap())
|
288
291
|
self.SetIcon(_icon)
|
289
292
|
self.SetTitle(_("About"))
|
290
293
|
|