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/core/treeop.py
CHANGED
@@ -2,12 +2,28 @@
|
|
2
2
|
Tree Operation decorators help define the Tree Operations found mostly in element_treeop class. We create dynamic menus
|
3
3
|
and thus need to classify the various different methods to access a node, without actually creating giant and
|
4
4
|
redundant code for each command on each code type.
|
5
|
+
|
6
|
+
These functions are overwhelmingly decorators. The `tree_operation` decorator sets the default values for the function
|
7
|
+
and all the other decorators set those values.
|
8
|
+
|
9
|
+
This data is expected to be called in a menu, but can be called via the console or through other methods.
|
5
10
|
"""
|
6
11
|
|
7
12
|
import functools
|
8
13
|
|
9
14
|
|
10
15
|
def tree_calc(value_name, calc_func):
|
16
|
+
"""
|
17
|
+
Decorate a calc function.
|
18
|
+
|
19
|
+
A calculator function will be called for each `value` in values or iterator, and will be permitted to calculate
|
20
|
+
some dynamic value from that function.
|
21
|
+
|
22
|
+
@param value_name:
|
23
|
+
@param calc_func:
|
24
|
+
@return:
|
25
|
+
"""
|
26
|
+
|
11
27
|
def decor(func):
|
12
28
|
func.calcs.append((value_name, calc_func))
|
13
29
|
return func
|
@@ -16,6 +32,13 @@ def tree_calc(value_name, calc_func):
|
|
16
32
|
|
17
33
|
|
18
34
|
def tree_values(value_name, values):
|
35
|
+
"""
|
36
|
+
Append explicit list of values and value_name to the function.
|
37
|
+
@param value_name:
|
38
|
+
@param values:
|
39
|
+
@return:
|
40
|
+
"""
|
41
|
+
|
19
42
|
def decor(func):
|
20
43
|
func.value_name = value_name
|
21
44
|
func.values = values
|
@@ -25,6 +48,16 @@ def tree_values(value_name, values):
|
|
25
48
|
|
26
49
|
|
27
50
|
def tree_iterate(value_name, start, stop, step=1):
|
51
|
+
"""
|
52
|
+
Append range list of values to function.
|
53
|
+
|
54
|
+
@param value_name:
|
55
|
+
@param start: Start value
|
56
|
+
@param stop: stop value
|
57
|
+
@param step: step amount
|
58
|
+
@return:
|
59
|
+
"""
|
60
|
+
|
28
61
|
def decor(func):
|
29
62
|
func.value_name = value_name
|
30
63
|
func.values = range(start, stop, step)
|
@@ -34,6 +67,13 @@ def tree_iterate(value_name, start, stop, step=1):
|
|
34
67
|
|
35
68
|
|
36
69
|
def tree_radio(radio_function):
|
70
|
+
"""
|
71
|
+
Append radio value to the operation for menus.
|
72
|
+
|
73
|
+
@param radio_function:
|
74
|
+
@return:
|
75
|
+
"""
|
76
|
+
|
37
77
|
def decor(func):
|
38
78
|
func.radio = radio_function
|
39
79
|
return func
|
@@ -42,6 +82,13 @@ def tree_radio(radio_function):
|
|
42
82
|
|
43
83
|
|
44
84
|
def tree_check(check_function):
|
85
|
+
"""
|
86
|
+
Append checkbox function to the operation for menus.
|
87
|
+
|
88
|
+
@param check_function:
|
89
|
+
@return:
|
90
|
+
"""
|
91
|
+
|
45
92
|
def decor(func):
|
46
93
|
func.check = check_function
|
47
94
|
return func
|
@@ -50,6 +97,13 @@ def tree_check(check_function):
|
|
50
97
|
|
51
98
|
|
52
99
|
def tree_submenu(submenu):
|
100
|
+
"""
|
101
|
+
Decorate a submenu on to the operation for menus.
|
102
|
+
|
103
|
+
@param submenu: submenu to use.
|
104
|
+
@return:
|
105
|
+
"""
|
106
|
+
|
53
107
|
def decor(func):
|
54
108
|
func.submenu = submenu
|
55
109
|
return func
|
@@ -58,6 +112,16 @@ def tree_submenu(submenu):
|
|
58
112
|
|
59
113
|
|
60
114
|
def tree_prompt(attr, prompt, data_type=str):
|
115
|
+
"""
|
116
|
+
Decorate a tree_prompt for the operations for menu, this function will request this information from the user
|
117
|
+
before calling the tree_operation function with the given attr.
|
118
|
+
|
119
|
+
@param attr:
|
120
|
+
@param prompt:
|
121
|
+
@param data_type:
|
122
|
+
@return:
|
123
|
+
"""
|
124
|
+
|
61
125
|
def decor(func):
|
62
126
|
func.user_prompt.append(
|
63
127
|
{
|
@@ -72,6 +136,15 @@ def tree_prompt(attr, prompt, data_type=str):
|
|
72
136
|
|
73
137
|
|
74
138
|
def tree_conditional(conditional):
|
139
|
+
"""
|
140
|
+
Decorate a conditional to the operation for menus.
|
141
|
+
|
142
|
+
Each conditional decorated to a function must pass for this menu item to show to the user.
|
143
|
+
|
144
|
+
@param conditional:
|
145
|
+
@return:
|
146
|
+
"""
|
147
|
+
|
75
148
|
def decor(func):
|
76
149
|
func.conditionals.append(conditional)
|
77
150
|
return func
|
@@ -80,6 +153,15 @@ def tree_conditional(conditional):
|
|
80
153
|
|
81
154
|
|
82
155
|
def tree_conditional_try(conditional):
|
156
|
+
"""
|
157
|
+
Decorate a try conditional on this operation for menu.
|
158
|
+
|
159
|
+
Try conditionals will not crash for the node, and can query states that may not exist.
|
160
|
+
|
161
|
+
@param conditional:
|
162
|
+
@return:
|
163
|
+
"""
|
164
|
+
|
83
165
|
def decor(func):
|
84
166
|
func.try_conditionals.append(conditional)
|
85
167
|
return func
|
@@ -88,6 +170,12 @@ def tree_conditional_try(conditional):
|
|
88
170
|
|
89
171
|
|
90
172
|
def tree_reference(node):
|
173
|
+
"""
|
174
|
+
Decorate a reference to on the tree.
|
175
|
+
@param node:
|
176
|
+
@return:
|
177
|
+
"""
|
178
|
+
|
91
179
|
def decor(func):
|
92
180
|
func.reference = node
|
93
181
|
return func
|
@@ -96,6 +184,12 @@ def tree_reference(node):
|
|
96
184
|
|
97
185
|
|
98
186
|
def tree_separator_after():
|
187
|
+
"""
|
188
|
+
Decorator to flag this operation as having a separator after it.
|
189
|
+
|
190
|
+
@return:
|
191
|
+
"""
|
192
|
+
|
99
193
|
def decor(func):
|
100
194
|
func.separate_after = True
|
101
195
|
return func
|
@@ -104,6 +198,12 @@ def tree_separator_after():
|
|
104
198
|
|
105
199
|
|
106
200
|
def tree_separator_before():
|
201
|
+
"""
|
202
|
+
Decorator to flag this operation as having a separator before it.
|
203
|
+
|
204
|
+
@return:
|
205
|
+
"""
|
206
|
+
|
107
207
|
def decor(func):
|
108
208
|
func.separate_before = True
|
109
209
|
return func
|
@@ -114,9 +214,28 @@ def tree_separator_before():
|
|
114
214
|
def tree_operation(
|
115
215
|
registration, name, node_type=None, help=None, enable=True, **kwargs
|
116
216
|
):
|
217
|
+
"""
|
218
|
+
Main tree registration decorator. Registers the tree operation with the given help and set the enabled state.
|
219
|
+
|
220
|
+
@param registration: This is either a service or a kernel.
|
221
|
+
@param name: Name of the tree operation being registered (required)
|
222
|
+
@param node_type: types of node this operation applies to.
|
223
|
+
@param help: Help data to be displayed in menu or other help information locations.
|
224
|
+
@param enable: Should this be enabled.
|
225
|
+
@param kwargs: Any remaining keywords.
|
226
|
+
@return:
|
227
|
+
"""
|
228
|
+
|
117
229
|
def decorator(func):
|
118
230
|
@functools.wraps(func)
|
119
231
|
def inner(node, **ik):
|
232
|
+
"""
|
233
|
+
Wrapped inner function executes the operation.
|
234
|
+
|
235
|
+
@param node:
|
236
|
+
@param ik:
|
237
|
+
@return:
|
238
|
+
"""
|
120
239
|
returned = func(node, **ik, **kwargs)
|
121
240
|
return returned
|
122
241
|
|
@@ -127,32 +246,70 @@ def tree_operation(
|
|
127
246
|
|
128
247
|
# inner.long_help = func.__doc__
|
129
248
|
inner.help = help
|
249
|
+
|
250
|
+
# Tuple of node types this applies to.
|
130
251
|
inner.node_type = ins
|
252
|
+
|
253
|
+
# Name of function.
|
131
254
|
inner.name = name
|
255
|
+
|
256
|
+
# attached radio commands.
|
132
257
|
inner.radio = None
|
258
|
+
|
259
|
+
# submenu of the operation
|
133
260
|
inner.submenu = None
|
261
|
+
|
262
|
+
# Optional information
|
134
263
|
inner.reference = None
|
264
|
+
|
265
|
+
# Should add a separator after this function.
|
135
266
|
inner.separate_after = False
|
267
|
+
|
268
|
+
# Should add a separator before this function.
|
136
269
|
inner.separate_before = False
|
270
|
+
|
271
|
+
# Conditionals required to be true to enable function.
|
137
272
|
inner.conditionals = list()
|
273
|
+
|
274
|
+
# Conditional attempted in a try-execute block (these may throw errors)
|
138
275
|
inner.try_conditionals = list()
|
276
|
+
|
277
|
+
# Prompt the user to discover this information.
|
139
278
|
inner.user_prompt = list()
|
279
|
+
|
280
|
+
# Calculations for the values.
|
140
281
|
inner.calcs = list()
|
282
|
+
|
283
|
+
# List of accepted values.
|
141
284
|
inner.values = [0]
|
285
|
+
|
286
|
+
# Function enabled/disabled
|
142
287
|
inner.enabled = enable
|
288
|
+
|
289
|
+
# Registered name is the same as the function name this is attached to.
|
143
290
|
registered_name = inner.__name__
|
144
291
|
|
145
292
|
for _in in ins:
|
293
|
+
# Register tree/node/name for each node within the registration.
|
146
294
|
p = f"tree/{_in}/{registered_name}"
|
147
295
|
if p in registration._registered:
|
296
|
+
# We used the name so we may not have duplicate tree operations with the same name.
|
148
297
|
raise NameError(f"A function of this name was already registered: {p}")
|
149
298
|
registration.register(p, inner)
|
150
299
|
return inner
|
151
300
|
|
301
|
+
# Return the entire decorator.
|
152
302
|
return decorator
|
153
303
|
|
154
304
|
|
155
305
|
def get_tree_operation(registration):
|
306
|
+
"""
|
307
|
+
Returns a tree op for all the function calls with the registration already set.
|
308
|
+
|
309
|
+
@param registration:
|
310
|
+
@return:
|
311
|
+
"""
|
312
|
+
|
156
313
|
def treeop(name, node_type=None, help=None, enable=True, **kwargs):
|
157
314
|
return tree_operation(
|
158
315
|
registration, name, node_type=node_type, help=help, enable=enable, **kwargs
|
@@ -162,17 +319,26 @@ def get_tree_operation(registration):
|
|
162
319
|
|
163
320
|
|
164
321
|
def tree_operations_for_node(registration, node):
|
322
|
+
"""
|
323
|
+
Generator to produce all tree operations for the given node.
|
324
|
+
|
325
|
+
@param registration: kernel or service on which to find these operations
|
326
|
+
@param node:
|
327
|
+
@return:
|
328
|
+
"""
|
165
329
|
if node.type is None:
|
166
330
|
return
|
167
331
|
for func, m, sname in registration.find("tree", node.type, ".*"):
|
168
332
|
reject = False
|
169
333
|
for cond in func.conditionals:
|
334
|
+
# Do not provide this if the conditionals fail.
|
170
335
|
if not cond(node):
|
171
336
|
reject = True
|
172
337
|
break
|
173
338
|
if reject:
|
174
339
|
continue
|
175
340
|
for cond in func.try_conditionals:
|
341
|
+
# Do not provide this if the try conditional fail. Crash is a pass.
|
176
342
|
try:
|
177
343
|
if not cond(node):
|
178
344
|
reject = True
|
@@ -193,6 +359,13 @@ def tree_operations_for_node(registration, node):
|
|
193
359
|
)
|
194
360
|
|
195
361
|
def unescaped(filename):
|
362
|
+
"""
|
363
|
+
Provide unescaped name/label.
|
364
|
+
OS dependency is moot.
|
365
|
+
|
366
|
+
@param filename:
|
367
|
+
@return:
|
368
|
+
"""
|
196
369
|
from platform import system
|
197
370
|
|
198
371
|
OS_NAME = system()
|
@@ -202,11 +375,13 @@ def tree_operations_for_node(registration, node):
|
|
202
375
|
newstring = filename.replace("&", "&&")
|
203
376
|
return newstring
|
204
377
|
|
378
|
+
# Create the operation calling dictionary.
|
205
379
|
func_dict = {
|
206
380
|
"name": unescaped(node_name),
|
207
381
|
"label": unescaped(node_label),
|
208
382
|
}
|
209
383
|
|
384
|
+
# @tree_values / @tree_iterate values to be appended to function dictionary.
|
210
385
|
iterator = func.values
|
211
386
|
if iterator is None:
|
212
387
|
iterator = [0]
|
@@ -215,7 +390,9 @@ def tree_operations_for_node(registration, node):
|
|
215
390
|
iterator = list(iterator())
|
216
391
|
except TypeError:
|
217
392
|
pass
|
393
|
+
|
218
394
|
for i, value in enumerate(iterator):
|
395
|
+
# Every value in the func.values gets an operation for the node.
|
219
396
|
func_dict["iterator"] = i
|
220
397
|
func_dict["value"] = value
|
221
398
|
try:
|
@@ -224,30 +401,44 @@ def tree_operations_for_node(registration, node):
|
|
224
401
|
pass
|
225
402
|
|
226
403
|
for calc in func.calcs:
|
404
|
+
# Calculators are done called for the given value, result is set in the call dictionary.
|
227
405
|
key, c = calc
|
228
406
|
value = c(value)
|
229
407
|
func_dict[key] = value
|
230
408
|
if func.radio is not None:
|
409
|
+
# Sets the radio state by the radio function.
|
231
410
|
try:
|
232
411
|
func.radio_state = func.radio(node, **func_dict)
|
233
412
|
except:
|
234
413
|
func.radio_state = False
|
235
414
|
else:
|
236
415
|
func.radio_state = None
|
416
|
+
|
237
417
|
if hasattr(func, "check") and func.check is not None:
|
418
|
+
# Sets the checkbox state by the checkbox function.
|
238
419
|
try:
|
239
420
|
func.check_state = func.check(node, **func_dict)
|
240
421
|
except:
|
241
422
|
func.check_state = False
|
242
423
|
else:
|
243
424
|
func.check_state = None
|
425
|
+
|
426
|
+
# Function name is formatted such that any {} format brackets are filled with their values.
|
244
427
|
name = func.name.format_map(func_dict)
|
428
|
+
|
429
|
+
# Set the function and real name and provide it to the caller.
|
245
430
|
func.func_dict = func_dict
|
246
431
|
func.real_name = name
|
247
432
|
yield func
|
248
433
|
|
249
434
|
|
250
435
|
def get_tree_operation_for_node(registration):
|
436
|
+
"""
|
437
|
+
Provide treeops for the given registration without needing to provide the registration each time, only the node.
|
438
|
+
@param registration:
|
439
|
+
@return:
|
440
|
+
"""
|
441
|
+
|
251
442
|
def treeop(node):
|
252
443
|
return tree_operations_for_node(registration, node)
|
253
444
|
|
meerk40t/core/undos.py
CHANGED
@@ -20,7 +20,8 @@ class UndoState:
|
|
20
20
|
|
21
21
|
|
22
22
|
class Undo:
|
23
|
-
def __init__(self, tree):
|
23
|
+
def __init__(self, service, tree):
|
24
|
+
self.service = service
|
24
25
|
self.tree = tree
|
25
26
|
self._lock = threading.Lock()
|
26
27
|
self._undo_stack = []
|
@@ -53,6 +54,7 @@ class Undo:
|
|
53
54
|
pass
|
54
55
|
del self._undo_stack[self._undo_index + 1 :]
|
55
56
|
self.message = None
|
57
|
+
self.service.signal("undoredo")
|
56
58
|
|
57
59
|
def undo(self):
|
58
60
|
"""
|
@@ -81,6 +83,7 @@ class Undo:
|
|
81
83
|
undo.state = self.tree.backup_tree() # Get unused copy
|
82
84
|
except KeyError:
|
83
85
|
pass
|
86
|
+
self.service.signal("undoredo")
|
84
87
|
return True
|
85
88
|
|
86
89
|
def redo(self):
|
@@ -102,9 +105,20 @@ class Undo:
|
|
102
105
|
redo.state = self.tree.backup_tree() # Get unused copy
|
103
106
|
except KeyError:
|
104
107
|
pass
|
108
|
+
self.service.signal("undoredo")
|
105
109
|
return True
|
106
110
|
|
107
111
|
def undolist(self):
|
108
112
|
for i, v in enumerate(self._undo_stack):
|
109
113
|
q = "*" if i == self._undo_index else " "
|
110
114
|
yield f"{q}{str(i).ljust(5)}: state {str(v)}"
|
115
|
+
|
116
|
+
def has_undo(self, *args):
|
117
|
+
if self._undo_index == 0:
|
118
|
+
# At bottom of stack.
|
119
|
+
return False
|
120
|
+
# Stack is entirely empty.
|
121
|
+
return len(self._undo_stack) != 0
|
122
|
+
|
123
|
+
def has_redo(self, *args):
|
124
|
+
return self._undo_index < len(self._undo_stack) - 1
|
meerk40t/core/units.py
CHANGED
@@ -462,7 +462,7 @@ class Angle:
|
|
462
462
|
converts to other forms of angle. Failures to parse raise ValueError.
|
463
463
|
"""
|
464
464
|
|
465
|
-
def __init__(self, angle, digits=None):
|
465
|
+
def __init__(self, angle, digits=None, preferred_units="rad"):
|
466
466
|
if isinstance(angle, Angle):
|
467
467
|
self._digits = angle._digits
|
468
468
|
self.angle = angle.angle
|
@@ -471,7 +471,7 @@ class Angle:
|
|
471
471
|
self._digits = digits
|
472
472
|
if not isinstance(angle, str):
|
473
473
|
self.angle = float(angle)
|
474
|
-
self.preferred_units =
|
474
|
+
self.preferred_units = preferred_units
|
475
475
|
return
|
476
476
|
angle = angle.lower()
|
477
477
|
if angle.endswith("deg"):
|
@@ -492,13 +492,15 @@ class Angle:
|
|
492
492
|
self.preferred_units = "%"
|
493
493
|
else:
|
494
494
|
self.angle = float(angle)
|
495
|
-
self.preferred_units =
|
495
|
+
self.preferred_units = preferred_units
|
496
496
|
|
497
497
|
def __str__(self):
|
498
498
|
return self.angle_preferred
|
499
499
|
|
500
500
|
def __copy__(self):
|
501
|
-
return Angle(
|
501
|
+
return Angle(
|
502
|
+
self.angle, preferred_units=self.preferred_units, digits=self._digits
|
503
|
+
)
|
502
504
|
|
503
505
|
def __eq__(self, other):
|
504
506
|
if hasattr(other, "angle"):
|
@@ -506,6 +508,14 @@ class Angle:
|
|
506
508
|
c1 = abs((self.angle % tau) - (other % tau)) <= 1e-11
|
507
509
|
return c1
|
508
510
|
|
511
|
+
def __float__(self):
|
512
|
+
return self.radians
|
513
|
+
|
514
|
+
def __neg__(self):
|
515
|
+
return Angle(
|
516
|
+
-self.angle, preferred_units=self.preferred_units, digits=self._digits
|
517
|
+
)
|
518
|
+
|
509
519
|
def normalize(self):
|
510
520
|
self.angle /= tau
|
511
521
|
|
meerk40t/device/dummydevice.py
CHANGED
@@ -2,7 +2,7 @@ from meerk40t.core.spoolers import Spooler
|
|
2
2
|
from meerk40t.core.view import View
|
3
3
|
from meerk40t.kernel import Service
|
4
4
|
|
5
|
-
from
|
5
|
+
from .mixins import Status
|
6
6
|
|
7
7
|
|
8
8
|
def plugin(kernel, lifecycle=None):
|
@@ -27,7 +27,7 @@ def plugin(kernel, lifecycle=None):
|
|
27
27
|
)
|
28
28
|
|
29
29
|
|
30
|
-
class DummyDevice(Service):
|
30
|
+
class DummyDevice(Service, Status):
|
31
31
|
"""
|
32
32
|
DummyDevice is a mock device service. It provides no actual device.
|
33
33
|
|
@@ -36,6 +36,7 @@ class DummyDevice(Service):
|
|
36
36
|
|
37
37
|
def __init__(self, kernel, path, *args, choices=None, **kwargs):
|
38
38
|
Service.__init__(self, kernel, path)
|
39
|
+
Status.__init__(self)
|
39
40
|
self.name = "Dummy Device"
|
40
41
|
if choices is not None:
|
41
42
|
for c in choices:
|
@@ -2,18 +2,18 @@ import wx
|
|
2
2
|
|
3
3
|
from meerk40t.gui.icons import (
|
4
4
|
STD_ICON_SIZE,
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
5
|
+
icon_bell,
|
6
|
+
icon_close_window,
|
7
|
+
icon_console,
|
8
|
+
icon_external,
|
9
|
+
icon_internal,
|
10
|
+
icon_return,
|
11
|
+
icon_round_stop,
|
12
|
+
icon_timer,
|
13
|
+
icon_trash,
|
14
|
+
icons8_down,
|
15
|
+
icons8_home_filled,
|
16
|
+
icons8_up,
|
17
17
|
)
|
18
18
|
from meerk40t.gui.wxutils import StaticBoxSizer, dip_size
|
19
19
|
|
@@ -41,17 +41,17 @@ class DefaultActionPanel(wx.Panel):
|
|
41
41
|
("Console", "util console", ""),
|
42
42
|
)
|
43
43
|
self.default_images = [
|
44
|
-
["console home -f",
|
45
|
-
["console move_abs",
|
46
|
-
["console beep",
|
47
|
-
["console interrupt",
|
48
|
-
["console quit",
|
49
|
-
["util wait",
|
50
|
-
["util home",
|
51
|
-
["util goto",
|
52
|
-
["util output",
|
53
|
-
["util input",
|
54
|
-
["util console",
|
44
|
+
["console home -f", icons8_home_filled],
|
45
|
+
["console move_abs", icon_return],
|
46
|
+
["console beep", icon_bell],
|
47
|
+
["console interrupt", icon_round_stop],
|
48
|
+
["console quit", icon_close_window],
|
49
|
+
["util wait", icon_timer],
|
50
|
+
["util home", icons8_home_filled],
|
51
|
+
["util goto", icon_return], # icon_marker
|
52
|
+
["util output", icon_external],
|
53
|
+
["util input", icon_internal],
|
54
|
+
["util console", icon_console],
|
55
55
|
]
|
56
56
|
self.prepend_ops = []
|
57
57
|
self.append_ops = []
|
@@ -61,6 +61,8 @@ class DefaultActionPanel(wx.Panel):
|
|
61
61
|
sizer_after = StaticBoxSizer(self, wx.ID_ANY, _("At job end"), wx.VERTICAL)
|
62
62
|
sizer_middle = wx.BoxSizer(wx.VERTICAL)
|
63
63
|
|
64
|
+
iconsize = dip_size(self, 30, 20)
|
65
|
+
bmpsize = min(iconsize[0], iconsize[1])
|
64
66
|
self.option_list = wx.ListCtrl(
|
65
67
|
self,
|
66
68
|
wx.ID_ANY,
|
@@ -77,42 +79,24 @@ class DefaultActionPanel(wx.Panel):
|
|
77
79
|
|
78
80
|
self.append_list = wx.ListCtrl(self, wx.ID_ANY, style=wx.LC_LIST)
|
79
81
|
self.text_param_append = wx.TextCtrl(self, wx.ID_ANY)
|
80
|
-
self.button_del_prepend = wx.StaticBitmap(
|
81
|
-
|
82
|
-
)
|
83
|
-
self.button_up_prepend = wx.StaticBitmap(
|
84
|
-
self, wx.ID_ANY, size=dip_size(self, 30, 30)
|
85
|
-
)
|
86
|
-
self.button_down_prepend = wx.StaticBitmap(
|
87
|
-
self, wx.ID_ANY, size=dip_size(self, 30, 20)
|
88
|
-
)
|
82
|
+
self.button_del_prepend = wx.StaticBitmap(self, wx.ID_ANY, size=iconsize)
|
83
|
+
self.button_up_prepend = wx.StaticBitmap(self, wx.ID_ANY, size=iconsize)
|
84
|
+
self.button_down_prepend = wx.StaticBitmap(self, wx.ID_ANY, size=iconsize)
|
89
85
|
self.button_del_prepend.SetBitmap(
|
90
|
-
|
91
|
-
)
|
92
|
-
self.button_up_prepend.SetBitmap(
|
93
|
-
icons8_up_50.GetBitmap(resize=STD_ICON_SIZE / 2)
|
86
|
+
icon_trash.GetBitmap(resize=bmpsize, buffer=1)
|
94
87
|
)
|
88
|
+
self.button_up_prepend.SetBitmap(icons8_up.GetBitmap(resize=bmpsize, buffer=1))
|
95
89
|
self.button_down_prepend.SetBitmap(
|
96
|
-
|
90
|
+
icons8_down.GetBitmap(resize=bmpsize, buffer=1)
|
97
91
|
)
|
98
92
|
|
99
|
-
self.button_del_append = wx.StaticBitmap(
|
100
|
-
|
101
|
-
)
|
102
|
-
self.
|
103
|
-
|
104
|
-
)
|
105
|
-
self.button_down_append = wx.StaticBitmap(
|
106
|
-
self, wx.ID_ANY, size=dip_size(self, 30, 30)
|
107
|
-
)
|
108
|
-
self.button_del_append.SetBitmap(
|
109
|
-
icons8_remove_25.GetBitmap(resize=STD_ICON_SIZE / 2)
|
110
|
-
)
|
111
|
-
self.button_up_append.SetBitmap(
|
112
|
-
icons8_up_50.GetBitmap(resize=STD_ICON_SIZE / 2)
|
113
|
-
)
|
93
|
+
self.button_del_append = wx.StaticBitmap(self, wx.ID_ANY, size=iconsize)
|
94
|
+
self.button_up_append = wx.StaticBitmap(self, wx.ID_ANY, size=iconsize)
|
95
|
+
self.button_down_append = wx.StaticBitmap(self, wx.ID_ANY, size=iconsize)
|
96
|
+
self.button_del_append.SetBitmap(icon_trash.GetBitmap(resize=bmpsize, buffer=1))
|
97
|
+
self.button_up_append.SetBitmap(icons8_up.GetBitmap(resize=bmpsize, buffer=1))
|
114
98
|
self.button_down_append.SetBitmap(
|
115
|
-
|
99
|
+
icons8_down.GetBitmap(resize=bmpsize, buffer=1)
|
116
100
|
)
|
117
101
|
|
118
102
|
sizer_param = StaticBoxSizer(
|
@@ -479,7 +463,9 @@ class DefaultActionPanel(wx.Panel):
|
|
479
463
|
setattr(self.context, str_count, len(self.append_ops))
|
480
464
|
|
481
465
|
def setup_state_images(self):
|
482
|
-
|
466
|
+
testsize = dip_size(self, 20, 20)
|
467
|
+
iconsize = testsize[1]
|
468
|
+
|
483
469
|
self.options_images = wx.ImageList()
|
484
470
|
self.options_images.Create(width=iconsize, height=iconsize)
|
485
471
|
self.prepend_images = wx.ImageList()
|
@@ -487,7 +473,9 @@ class DefaultActionPanel(wx.Panel):
|
|
487
473
|
self.append_images = wx.ImageList()
|
488
474
|
self.append_images.Create(width=iconsize, height=iconsize)
|
489
475
|
for entry in self.default_images:
|
490
|
-
image = entry[1].GetBitmap(
|
476
|
+
image = entry[1].GetBitmap(
|
477
|
+
resize=(iconsize, iconsize), buffer=2, noadjustment=True
|
478
|
+
)
|
491
479
|
image_id1 = self.options_images.Add(bitmap=image)
|
492
480
|
image_id2 = self.prepend_images.Add(bitmap=image)
|
493
481
|
image_id3 = self.append_images.Add(bitmap=image)
|