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.
- meerk40t/balormk/controller.py +3 -3
- meerk40t/balormk/device.py +7 -0
- meerk40t/balormk/driver.py +23 -14
- meerk40t/balormk/galvo_commands.py +18 -3
- meerk40t/balormk/gui/balorconfig.py +6 -0
- meerk40t/balormk/livelightjob.py +36 -14
- meerk40t/camera/camera.py +1 -0
- meerk40t/camera/gui/camerapanel.py +154 -58
- meerk40t/camera/plugin.py +46 -5
- meerk40t/core/elements/branches.py +90 -20
- meerk40t/core/elements/elements.py +59 -37
- meerk40t/core/elements/trace.py +10 -6
- meerk40t/core/node/node.py +2 -0
- meerk40t/core/plotplanner.py +7 -4
- meerk40t/device/gui/defaultactions.py +78 -14
- meerk40t/dxf/dxf_io.py +42 -0
- meerk40t/grbl/controller.py +245 -35
- meerk40t/grbl/device.py +102 -26
- meerk40t/grbl/driver.py +8 -2
- meerk40t/grbl/gui/grblconfiguration.py +6 -0
- meerk40t/grbl/gui/grblcontroller.py +1 -1
- meerk40t/gui/about.py +7 -0
- meerk40t/gui/choicepropertypanel.py +20 -30
- meerk40t/gui/devicepanel.py +27 -16
- meerk40t/gui/help_assets/help_assets.py +126 -2
- meerk40t/gui/icons.py +15 -0
- meerk40t/gui/laserpanel.py +102 -54
- meerk40t/gui/materialtest.py +10 -0
- meerk40t/gui/mkdebug.py +268 -9
- meerk40t/gui/navigationpanels.py +74 -8
- meerk40t/gui/propertypanels/operationpropertymain.py +185 -91
- meerk40t/gui/scenewidgets/elementswidget.py +7 -1
- meerk40t/gui/scenewidgets/selectionwidget.py +24 -9
- meerk40t/gui/simulation.py +1 -1
- meerk40t/gui/statusbarwidgets/shapepropwidget.py +50 -40
- meerk40t/gui/statusbarwidgets/statusbar.py +2 -2
- meerk40t/gui/toolwidgets/toolmeasure.py +1 -1
- meerk40t/gui/toolwidgets/toolnodeedit.py +4 -1
- meerk40t/gui/toolwidgets/tooltabedit.py +9 -7
- meerk40t/gui/wxmeerk40t.py +45 -15
- meerk40t/gui/wxmmain.py +23 -9
- meerk40t/gui/wxmribbon.py +36 -0
- meerk40t/gui/wxutils.py +66 -42
- meerk40t/kernel/inhibitor.py +120 -0
- meerk40t/kernel/kernel.py +38 -0
- meerk40t/lihuiyu/controller.py +33 -3
- meerk40t/lihuiyu/device.py +99 -4
- meerk40t/lihuiyu/driver.py +65 -5
- meerk40t/lihuiyu/gui/lhycontrollergui.py +69 -24
- meerk40t/lihuiyu/gui/lhydrivergui.py +6 -0
- meerk40t/lihuiyu/laserspeed.py +17 -10
- meerk40t/lihuiyu/parser.py +23 -0
- meerk40t/main.py +2 -2
- meerk40t/moshi/gui/moshidrivergui.py +7 -0
- meerk40t/newly/controller.py +3 -2
- meerk40t/newly/device.py +23 -2
- meerk40t/newly/driver.py +8 -3
- meerk40t/newly/gui/newlyconfig.py +7 -0
- meerk40t/ruida/gui/ruidaconfig.py +7 -0
- meerk40t/tools/geomstr.py +142 -49
- meerk40t/tools/rasterplotter.py +0 -5
- meerk40t/tools/ttfparser.py +921 -168
- {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/METADATA +1 -1
- {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/RECORD +69 -68
- {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/LICENSE +0 -0
- {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/WHEEL +0 -0
- {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/entry_points.txt +0 -0
- {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/top_level.txt +0 -0
- {meerk40t-0.9.7051.dist-info → meerk40t-0.9.7910.dist-info}/zip-safe +0 -0
meerk40t/grbl/device.py
CHANGED
@@ -467,6 +467,18 @@ class GRBLDevice(Service, Status):
|
|
467
467
|
"conditional": (self, "use_red_dot"),
|
468
468
|
"section": "_10_Red Dot",
|
469
469
|
},
|
470
|
+
{
|
471
|
+
"attr": "use_red_dot_for_outline",
|
472
|
+
"object": self,
|
473
|
+
"default": True,
|
474
|
+
"type": bool,
|
475
|
+
"label": _("Active during Outline"),
|
476
|
+
"tip": _(
|
477
|
+
"If active then the red dot will automatically be used if you outline the burn area"
|
478
|
+
),
|
479
|
+
"conditional": (self, "use_red_dot"),
|
480
|
+
"section": "_10_Red Dot",
|
481
|
+
},
|
470
482
|
{
|
471
483
|
"attr": "max_vector_speed",
|
472
484
|
"object": self,
|
@@ -879,7 +891,14 @@ class GRBLDevice(Service, Status):
|
|
879
891
|
self("bind w +yforward")
|
880
892
|
|
881
893
|
@self.console_option(
|
882
|
-
"strength", "s", type=int, help="Set the dot laser strength."
|
894
|
+
"strength", "s", type=int, help=_("Set the dot laser strength (0..1000).")
|
895
|
+
)
|
896
|
+
@self.console_option(
|
897
|
+
"force",
|
898
|
+
"f",
|
899
|
+
type=bool,
|
900
|
+
action="store_true",
|
901
|
+
help=_("Force the red dot command even if a job is running."),
|
883
902
|
)
|
884
903
|
@self.console_argument("off", type=str)
|
885
904
|
@self.console_command(
|
@@ -887,40 +906,46 @@ class GRBLDevice(Service, Status):
|
|
887
906
|
help=_("Turns redlight on/off"),
|
888
907
|
)
|
889
908
|
def red_dot_on(
|
890
|
-
command,
|
909
|
+
command,
|
910
|
+
channel,
|
911
|
+
_,
|
912
|
+
off=None,
|
913
|
+
strength=None,
|
914
|
+
force=None,
|
915
|
+
remainder=None,
|
916
|
+
**kwgs,
|
891
917
|
):
|
918
|
+
if force is None:
|
919
|
+
force = False
|
892
920
|
if not self.use_red_dot:
|
893
|
-
channel("Red Dot feature is not enabled, see config")
|
921
|
+
channel(_("Red Dot feature is not enabled, see config"))
|
894
922
|
# self.redlight_preferred = False
|
895
923
|
return
|
896
|
-
if not self.spooler.is_idle:
|
897
|
-
channel("Won't interfere with a running job, abort...")
|
924
|
+
if not force and not self.spooler.is_idle:
|
925
|
+
channel(_("Won't interfere with a running job, abort..."))
|
898
926
|
return
|
899
927
|
if strength is not None:
|
900
928
|
if 0 <= strength <= 1000:
|
901
929
|
self.red_dot_level = strength
|
902
930
|
channel(
|
903
|
-
|
931
|
+
_("Laser strength for red dot is now: {power}").format(
|
932
|
+
power=f"{self.red_dot_level / 10.0:.1f}%"
|
933
|
+
)
|
934
|
+
)
|
935
|
+
else:
|
936
|
+
channel(
|
937
|
+
_(
|
938
|
+
"Laser strength for red dot must be between 0 and 1000, not {power}"
|
939
|
+
).format(power=strength)
|
904
940
|
)
|
941
|
+
return
|
905
942
|
if off == "off":
|
906
|
-
self.
|
907
|
-
|
908
|
-
self.driver.move_mode = 0
|
909
|
-
# self.redlight_preferred = False
|
910
|
-
channel("Turning off redlight.")
|
943
|
+
self.red_dot(False)
|
944
|
+
channel(_("Red light is now off."))
|
911
945
|
self.signal("grbl_red_dot", False)
|
912
946
|
else:
|
913
|
-
|
914
|
-
|
915
|
-
self.driver._clean()
|
916
|
-
rapid_speed = self.setting(float, "rapid_speed", 600.0)
|
917
|
-
self.driver.laser_on(power=int(self.red_dot_level), speed=rapid_speed)
|
918
|
-
# By default, any move is a G0 move which will not activate the laser,
|
919
|
-
# so we need to switch to G1 mode:
|
920
|
-
self.driver.move_mode = 1
|
921
|
-
# An arbitrary move to turn the laser really on!
|
922
|
-
# self.driver.grbl("G1")
|
923
|
-
channel("Turning on redlight.")
|
947
|
+
self.red_dot(True)
|
948
|
+
channel(_("Red light is now on."))
|
924
949
|
self.signal("grbl_red_dot", True)
|
925
950
|
|
926
951
|
@self.console_option(
|
@@ -929,12 +954,15 @@ class GRBLDevice(Service, Status):
|
|
929
954
|
action="store_true",
|
930
955
|
help=_("override one second laser fire pulse duration"),
|
931
956
|
)
|
957
|
+
@self.console_option("power", "p", type=str, help=_("laser fire power"))
|
932
958
|
@self.console_argument("time", type=float, help=_("laser fire pulse duration"))
|
933
959
|
@self.console_command(
|
934
960
|
"pulse",
|
935
961
|
help=_("pulse <time>: Pulse the laser in place."),
|
936
962
|
)
|
937
|
-
def pulse(
|
963
|
+
def pulse(
|
964
|
+
command, channel, _, time=None, power=None, idonotlovemyhouse=False, **kwgs
|
965
|
+
):
|
938
966
|
if time is None:
|
939
967
|
channel(_("Must specify a pulse time in milliseconds."))
|
940
968
|
return
|
@@ -949,12 +977,25 @@ class GRBLDevice(Service, Status):
|
|
949
977
|
return
|
950
978
|
except IndexError:
|
951
979
|
return
|
952
|
-
|
980
|
+
if power is not None:
|
981
|
+
try:
|
982
|
+
if power.endswith("%"):
|
983
|
+
power = power[:-1]
|
984
|
+
power = float(power) * 10
|
985
|
+
else:
|
986
|
+
power = float(power)
|
987
|
+
except ValueError:
|
988
|
+
channel(_("Power must be valid value."))
|
989
|
+
return
|
990
|
+
if not (0 <= power <= 1000):
|
991
|
+
channel(_("Power must be between 0 and 1000."))
|
992
|
+
return
|
993
|
+
power = 1000 if power is None else int(power)
|
953
994
|
if self.spooler.is_idle:
|
954
|
-
self.driver.laser_on(power=
|
995
|
+
self.driver.laser_on(power=power, speed=1000)
|
955
996
|
sleep(time / 1000)
|
956
997
|
self.driver.laser_off()
|
957
|
-
label = _("Pulse laser for {time}ms").format(time=time)
|
998
|
+
label = _("Pulse laser for {time}ms").format(time=time) + f" [{power}]"
|
958
999
|
channel(label)
|
959
1000
|
else:
|
960
1001
|
channel(_("Pulse laser failed: Busy"))
|
@@ -1044,6 +1085,13 @@ class GRBLDevice(Service, Status):
|
|
1044
1085
|
name = self.label.replace(" ", "-")
|
1045
1086
|
return name.replace("/", "-")
|
1046
1087
|
|
1088
|
+
@property
|
1089
|
+
def supports_pwm(self):
|
1090
|
+
"""
|
1091
|
+
Returns whether this device supports PWM.
|
1092
|
+
"""
|
1093
|
+
return True
|
1094
|
+
|
1047
1095
|
def _register_console_serial(self):
|
1048
1096
|
_ = self.kernel.translation
|
1049
1097
|
|
@@ -1169,3 +1217,31 @@ class GRBLDevice(Service, Status):
|
|
1169
1217
|
return {
|
1170
1218
|
"gantry": True,
|
1171
1219
|
}
|
1220
|
+
|
1221
|
+
def red_dot(self, turn_on):
|
1222
|
+
if turn_on:
|
1223
|
+
# self.redlight_preferred = True
|
1224
|
+
# self.driver.set("power", int(self.red_dot_level / 100 * 1000))
|
1225
|
+
self.driver._clean()
|
1226
|
+
rapid_speed = self.setting(float, "rapid_speed", 600.0)
|
1227
|
+
self.driver.laser_on(power=int(self.red_dot_level), speed=rapid_speed)
|
1228
|
+
# By default, any move is a G0 move which will not activate the laser,
|
1229
|
+
# so we need to switch to G1 mode:
|
1230
|
+
self.driver.move_mode = 1
|
1231
|
+
# An arbitrary move to turn the laser really on!
|
1232
|
+
# self.driver.grbl("G1")
|
1233
|
+
else:
|
1234
|
+
self.driver.laser_off()
|
1235
|
+
# self.driver.grbl("G0")
|
1236
|
+
self.driver.move_mode = 0
|
1237
|
+
# self.redlight_preferred = False
|
1238
|
+
|
1239
|
+
def pre_outline(self):
|
1240
|
+
if not (self.use_red_dot and self.use_red_dot_for_outline):
|
1241
|
+
return
|
1242
|
+
yield ("console", "red on -f")
|
1243
|
+
|
1244
|
+
def post_outline(self):
|
1245
|
+
if not (self.use_red_dot and self.use_red_dot_for_outline):
|
1246
|
+
return
|
1247
|
+
yield ("console", "red off -f")
|
meerk40t/grbl/driver.py
CHANGED
@@ -217,7 +217,7 @@ class GRBLDriver(Parameters):
|
|
217
217
|
(old_current[0], old_current[1], new_current[0], new_current[1]),
|
218
218
|
)
|
219
219
|
|
220
|
-
def dwell(self, time_in_ms):
|
220
|
+
def dwell(self, time_in_ms, settings=None):
|
221
221
|
"""
|
222
222
|
Requests that the laser fire in place for the given time period. This could be done in a series of commands,
|
223
223
|
move to a location, turn laser on, wait, turn laser off. However, some drivers have specific laser-in-place
|
@@ -226,7 +226,13 @@ class GRBLDriver(Parameters):
|
|
226
226
|
@param time_in_ms:
|
227
227
|
@return:
|
228
228
|
"""
|
229
|
-
|
229
|
+
if settings is not None and "power" in settings:
|
230
|
+
power = settings["power"]
|
231
|
+
else:
|
232
|
+
power = self.power
|
233
|
+
self.laser_on(
|
234
|
+
power=power
|
235
|
+
) # This can't be sent early since these are timed operations.
|
230
236
|
self.wait(time_in_ms)
|
231
237
|
self.laser_off()
|
232
238
|
|
@@ -371,3 +371,9 @@ class GRBLConfiguration(MWindow):
|
|
371
371
|
else:
|
372
372
|
# Different command
|
373
373
|
pass
|
374
|
+
|
375
|
+
@signal_listener("activate;device")
|
376
|
+
def on_device_changes(self, *args):
|
377
|
+
# Device activated, make sure we are still fine...
|
378
|
+
if self.context.device.name != 'GRBLDevice':
|
379
|
+
wx.CallAfter(self.Close)
|
@@ -260,7 +260,7 @@ class GRBLControllerPanel(wx.Panel):
|
|
260
260
|
|
261
261
|
def edit_macro(self, idx):
|
262
262
|
def handler(event):
|
263
|
-
macro = self.macros[idx]
|
263
|
+
macro = str(self.macros[idx])
|
264
264
|
dlg = wx.TextEntryDialog(
|
265
265
|
self, _("Content for macro {index}").format(index = idx + 1),
|
266
266
|
value=macro,
|
meerk40t/gui/about.py
CHANGED
@@ -1595,6 +1595,13 @@ class InformationPanel(ScrolledPanel):
|
|
1595
1595
|
info += f"Version: {uname.version}" + "\n"
|
1596
1596
|
info += f"Machine: {uname.machine}" + "\n"
|
1597
1597
|
info += f"Processor: {uname.processor}" + "\n"
|
1598
|
+
try:
|
1599
|
+
import psutil
|
1600
|
+
mem = psutil.virtual_memory()
|
1601
|
+
available_mb = f"{mem.available / (1024 * 1024):.2f} MB"
|
1602
|
+
info += f"Available memory: {available_mb}\n"
|
1603
|
+
except ImportError:
|
1604
|
+
pass
|
1598
1605
|
info += f"Theme: {self.context.themes.theme}, Darkmode: {self.context.themes.dark}\n"
|
1599
1606
|
try:
|
1600
1607
|
info += f"Ip-Address: {socket.gethostbyname(socket.gethostname())}"
|
@@ -139,7 +139,7 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
139
139
|
# we need to create an independent copy of the lookup, otherwise
|
140
140
|
# any amendments to choices like injector will affect the original
|
141
141
|
standardhelp = ""
|
142
|
-
|
142
|
+
|
143
143
|
def on_combo_text(param, ctrl, obj, dtype, addsig):
|
144
144
|
def select(event=None):
|
145
145
|
v = dtype(ctrl.GetValue())
|
@@ -314,9 +314,7 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
314
314
|
dlg = wx.ColourDialog(self, color_data)
|
315
315
|
if dlg.ShowModal() == wx.ID_OK:
|
316
316
|
color_data = dlg.GetColourData()
|
317
|
-
data = Color(
|
318
|
-
swizzlecolor(color_data.GetColour().GetRGB()), 1.0
|
319
|
-
)
|
317
|
+
data = Color(swizzlecolor(color_data.GetColour().GetRGB()), 1.0)
|
320
318
|
set_color(ctrl, data)
|
321
319
|
try:
|
322
320
|
data_v = data.hexa
|
@@ -331,7 +329,7 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
331
329
|
pass
|
332
330
|
|
333
331
|
return click
|
334
|
-
|
332
|
+
|
335
333
|
def on_angle_text(param, ctrl, obj, dtype, addsig):
|
336
334
|
def text():
|
337
335
|
try:
|
@@ -407,9 +405,7 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
407
405
|
# except IndexError:
|
408
406
|
# pass
|
409
407
|
|
410
|
-
menuitem = menu.Append(
|
411
|
-
wx.ID_ANY, _("Delete this entry"), ""
|
412
|
-
)
|
408
|
+
menuitem = menu.Append(wx.ID_ANY, _("Delete this entry"), "")
|
413
409
|
self.Bind(
|
414
410
|
wx.EVT_MENU,
|
415
411
|
on_delete,
|
@@ -431,9 +427,7 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
431
427
|
# pass
|
432
428
|
fill_ctrl(ctrl, local_obj, param, columns)
|
433
429
|
|
434
|
-
menuitem = menu.Append(
|
435
|
-
wx.ID_ANY, _("Duplicate this entry"), ""
|
436
|
-
)
|
430
|
+
menuitem = menu.Append(wx.ID_ANY, _("Duplicate this entry"), "")
|
437
431
|
self.Bind(
|
438
432
|
wx.EVT_MENU,
|
439
433
|
on_duplicate,
|
@@ -498,7 +492,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
498
492
|
|
499
493
|
return text
|
500
494
|
|
501
|
-
|
502
495
|
for choice in choices:
|
503
496
|
if isinstance(choice, dict):
|
504
497
|
if "help" not in choice:
|
@@ -785,7 +778,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
785
778
|
wants_listener = False
|
786
779
|
control = wxButton(self, label=label)
|
787
780
|
|
788
|
-
|
789
781
|
control.Bind(
|
790
782
|
wx.EVT_BUTTON,
|
791
783
|
on_button(attr, obj, additional_signal),
|
@@ -799,7 +791,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
799
791
|
control.SetValue(data)
|
800
792
|
control.SetMinSize(dip_size(self, -1, 23))
|
801
793
|
|
802
|
-
|
803
794
|
control.Bind(
|
804
795
|
wx.EVT_CHECKBOX,
|
805
796
|
on_checkbox_check(attr, control, obj, additional_signal),
|
@@ -824,7 +815,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
824
815
|
control_sizer.Add(control, 1, wx.EXPAND, 0)
|
825
816
|
current_sizer.Add(control_sizer, expansion_flag * weight, wx.EXPAND, 0)
|
826
817
|
|
827
|
-
|
828
818
|
control.SetActionRoutine(
|
829
819
|
on_generic_multi(attr, control, obj, data_type, additional_signal)
|
830
820
|
)
|
@@ -843,7 +833,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
843
833
|
# filename = _("No File")
|
844
834
|
control.SetValue(filename)
|
845
835
|
|
846
|
-
|
847
836
|
control.SetActionRoutine(
|
848
837
|
on_file_text(attr, control, obj, data_type, additional_signal)
|
849
838
|
)
|
@@ -880,6 +869,10 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
880
869
|
value = int(data)
|
881
870
|
else:
|
882
871
|
value = int(data)
|
872
|
+
if callable(minvalue):
|
873
|
+
minvalue = minvalue()
|
874
|
+
if callable(maxvalue):
|
875
|
+
maxvalue = maxvalue()
|
883
876
|
control = wx.Slider(
|
884
877
|
self,
|
885
878
|
wx.ID_ANY,
|
@@ -889,7 +882,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
889
882
|
style=wx.SL_HORIZONTAL | wx.SL_VALUE_LABEL,
|
890
883
|
)
|
891
884
|
|
892
|
-
|
893
885
|
if ctrl_width > 0:
|
894
886
|
control.SetMaxSize(dip_size(self, ctrl_width, -1))
|
895
887
|
control_sizer.Add(control, 1, wx.EXPAND, 0)
|
@@ -928,7 +920,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
928
920
|
if least is not None:
|
929
921
|
control.SetValue(least)
|
930
922
|
|
931
|
-
|
932
923
|
if ctrl_width > 0:
|
933
924
|
control.SetMaxSize(dip_size(self, ctrl_width, -1))
|
934
925
|
control_sizer.Add(control, 1, wx.ALIGN_CENTER_VERTICAL, 0)
|
@@ -957,7 +948,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
957
948
|
else:
|
958
949
|
control.SetSelection(int(data))
|
959
950
|
|
960
|
-
|
961
951
|
if ctrl_width > 0:
|
962
952
|
control.SetMaxSize(dip_size(self, ctrl_width, -1))
|
963
953
|
control_sizer.Add(control, 1, wx.ALIGN_CENTER_VERTICAL, 0)
|
@@ -979,7 +969,7 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
979
969
|
data = c.get("default")
|
980
970
|
display_list.insert(0, str(data))
|
981
971
|
choice_list.insert(0, str(data))
|
982
|
-
cb_style = wx.CB_DROPDOWN | wx.CB_READONLY
|
972
|
+
cb_style = wx.CB_DROPDOWN | wx.CB_READONLY
|
983
973
|
control = wxComboBox(
|
984
974
|
self,
|
985
975
|
wx.ID_ANY,
|
@@ -995,7 +985,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
995
985
|
# print ("Choices: %s" % choice_list)
|
996
986
|
# print ("To set: %s" % str(data))
|
997
987
|
|
998
|
-
|
999
988
|
if label != "":
|
1000
989
|
# Try to center it vertically to the controls extent
|
1001
990
|
wd, ht = control.GetSize()
|
@@ -1013,14 +1002,16 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
1013
1002
|
elif data_type in (str, int, float) and data_style == "combosmall":
|
1014
1003
|
control_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
1015
1004
|
exclusive = c.get("exclusive", True)
|
1016
|
-
cb_style =
|
1005
|
+
cb_style = (
|
1006
|
+
wx.CB_DROPDOWN | wx.CB_READONLY if exclusive else wx.CB_DROPDOWN
|
1007
|
+
)
|
1017
1008
|
|
1018
1009
|
choice_list = list(map(str, c.get("choices", [c.get("default")])))
|
1019
1010
|
control = wxComboBox(
|
1020
1011
|
self,
|
1021
1012
|
wx.ID_ANY,
|
1022
1013
|
choices=choice_list,
|
1023
|
-
style
|
1014
|
+
style=cb_style,
|
1024
1015
|
)
|
1025
1016
|
# Constrain the width
|
1026
1017
|
testsize = control.GetBestSize()
|
@@ -1043,7 +1034,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
1043
1034
|
if least is not None:
|
1044
1035
|
control.SetValue(least)
|
1045
1036
|
|
1046
|
-
|
1047
1037
|
if label != "":
|
1048
1038
|
# Try to center it vertically to the controls extent
|
1049
1039
|
wd, ht = control.GetSize()
|
@@ -1083,7 +1073,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
1083
1073
|
else:
|
1084
1074
|
control_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
1085
1075
|
|
1086
|
-
|
1087
1076
|
bit_sizer = wx.BoxSizer(wx.VERTICAL)
|
1088
1077
|
label_text = wxStaticText(
|
1089
1078
|
self, wx.ID_ANY, "", style=wx.ALIGN_CENTRE_HORIZONTAL
|
@@ -1117,7 +1106,10 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
1117
1106
|
control.SetValue(bool((data >> b) & 1))
|
1118
1107
|
if mask:
|
1119
1108
|
control.Enable(bool((mask_bits >> b) & 1))
|
1120
|
-
control.Bind(
|
1109
|
+
control.Bind(
|
1110
|
+
wx.EVT_CHECKBOX,
|
1111
|
+
on_checkbox_bitcheck(attr, control, obj, b, additional_signal),
|
1112
|
+
)
|
1121
1113
|
|
1122
1114
|
# mask bit
|
1123
1115
|
if mask:
|
@@ -1177,7 +1169,8 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
1177
1169
|
self,
|
1178
1170
|
wx.ID_ANY,
|
1179
1171
|
style=wx.LC_HRULES | wx.LC_REPORT | wx.LC_VRULES | wx.LC_SINGLE_SEL,
|
1180
|
-
context=self.context,
|
1172
|
+
context=self.context,
|
1173
|
+
list_name=f"list_chart_{attr}",
|
1181
1174
|
)
|
1182
1175
|
l_columns = c.get("columns", [])
|
1183
1176
|
|
@@ -1224,13 +1217,11 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
1224
1217
|
|
1225
1218
|
fill_ctrl(chart, obj, attr, l_columns)
|
1226
1219
|
|
1227
|
-
|
1228
1220
|
chart.Bind(
|
1229
1221
|
wx.EVT_LIST_BEGIN_LABEL_EDIT,
|
1230
1222
|
on_chart_start(l_columns, attr, chart, obj),
|
1231
1223
|
)
|
1232
1224
|
|
1233
|
-
|
1234
1225
|
chart.Bind(
|
1235
1226
|
wx.EVT_LIST_END_LABEL_EDIT,
|
1236
1227
|
on_chart_stop(l_columns, attr, chart, obj),
|
@@ -1326,7 +1317,6 @@ class ChoicePropertyPanel(ScrolledPanel):
|
|
1326
1317
|
control.SetMaxSize(dip_size(self, ctrl_width, -1))
|
1327
1318
|
control_sizer.Add(control, 1, wx.EXPAND, 0)
|
1328
1319
|
|
1329
|
-
|
1330
1320
|
control.SetActionRoutine(
|
1331
1321
|
on_generic_text(attr, control, obj, data_type, additional_signal)
|
1332
1322
|
)
|
meerk40t/gui/devicepanel.py
CHANGED
@@ -243,9 +243,7 @@ class DevicePanel(wx.Panel):
|
|
243
243
|
sizer_1.Add(sizer_3, 1, wx.EXPAND, 0)
|
244
244
|
# All devices
|
245
245
|
self.devices = []
|
246
|
-
|
247
|
-
self.current_item = 0
|
248
|
-
|
246
|
+
|
249
247
|
self.button_create_device = wxButton(self, wx.ID_ANY, _("Create New Device"))
|
250
248
|
sizer_3.Add(self.button_create_device, 0, 0, 0)
|
251
249
|
|
@@ -305,12 +303,16 @@ class DevicePanel(wx.Panel):
|
|
305
303
|
self.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.on_end_edit, self.devices_list)
|
306
304
|
# end wxGlade
|
307
305
|
|
306
|
+
@property
|
307
|
+
def current_item(self):
|
308
|
+
if self.devices_list.GetSelectedItemCount() > 0:
|
309
|
+
return self.devices_list.GetFirstSelected()
|
310
|
+
return -1
|
311
|
+
|
308
312
|
def pane_show(self, *args):
|
309
313
|
self.refresh_device_tree()
|
310
314
|
if len(self.devices) > 0:
|
311
315
|
self.devices_list.Select(0, 1)
|
312
|
-
else:
|
313
|
-
self.current_item = -1
|
314
316
|
self.enable_controls()
|
315
317
|
|
316
318
|
def pane_hide(self, *args):
|
@@ -453,17 +455,14 @@ class DevicePanel(wx.Panel):
|
|
453
455
|
return label
|
454
456
|
|
455
457
|
def on_item_selected(self, event):
|
456
|
-
if event
|
457
|
-
self.current_item = self.devices_list.GetFirstSelected()
|
458
|
-
else:
|
459
|
-
self.current_item = event.Index
|
458
|
+
if event:
|
460
459
|
event.Skip()
|
461
460
|
self.enable_controls()
|
462
461
|
|
463
462
|
def on_item_deselected(self, event):
|
464
|
-
|
463
|
+
if event:
|
464
|
+
event.Skip()
|
465
465
|
self.enable_controls()
|
466
|
-
event.Skip()
|
467
466
|
|
468
467
|
def enable_controls(self):
|
469
468
|
if self.current_item < 0:
|
@@ -522,8 +521,9 @@ class DevicePanel(wx.Panel):
|
|
522
521
|
|
523
522
|
def on_tree_popup_rename(self, service):
|
524
523
|
def renameit(event=None):
|
524
|
+
lbl = str(service.label or "")
|
525
525
|
with wx.TextEntryDialog(
|
526
|
-
None, _("What do you call this device?"), _("Device Label"),
|
526
|
+
None, _("What do you call this device?"), _("Device Label"), lbl
|
527
527
|
) as dlg:
|
528
528
|
dlg.SetValue(service.label)
|
529
529
|
if dlg.ShowModal() == wx.ID_OK:
|
@@ -608,21 +608,32 @@ class DevicePanel(wx.Panel):
|
|
608
608
|
self.duplicate_device(service)
|
609
609
|
|
610
610
|
def on_button_activate_device(self, event): # wxGlade: DevicePanel.<event_handler>
|
611
|
+
def reselect(idx):
|
612
|
+
def handler():
|
613
|
+
if idx >= 0:
|
614
|
+
self.devices_list.Select(idx, 1)
|
615
|
+
self.devices_list.Focus(idx)
|
616
|
+
|
617
|
+
return handler
|
618
|
+
|
619
|
+
idx = self.current_item
|
620
|
+
if idx < 0:
|
621
|
+
return
|
611
622
|
service = self.get_selected_device()
|
612
623
|
if service is not None:
|
613
624
|
service.kernel.activate_service_path("device", service.path)
|
614
625
|
self.recolor_device_items()
|
626
|
+
wx.CallLater(750, reselect(idx))
|
615
627
|
|
616
628
|
def on_button_config_device(self, event): # wxGlade: DevicePanel.<event_handler>
|
617
|
-
|
618
|
-
if service is not None:
|
619
|
-
service("window toggle Configuration\n")
|
629
|
+
self.context("window toggle Configuration\n")
|
620
630
|
|
621
631
|
def on_button_rename_device(self, event): # wxGlade: DevicePanel.<event_handler>
|
622
632
|
service = self.get_selected_device()
|
623
633
|
if service is not None:
|
634
|
+
label = str(service.label or "")
|
624
635
|
with wx.TextEntryDialog(
|
625
|
-
None, _("What do you call this device?"), _("Device Label"),
|
636
|
+
None, _("What do you call this device?"), _("Device Label"), label
|
626
637
|
) as dlg:
|
627
638
|
dlg.SetValue(service.label)
|
628
639
|
if dlg.ShowModal() == wx.ID_OK:
|