diff --git a/docs/components/html/en-US/LVGL.html b/docs/components/html/en-US/LVGL.html
index 50473afa3..32467639b 100644
--- a/docs/components/html/en-US/LVGL.html
+++ b/docs/components/html/en-US/LVGL.html
@@ -29,31 +29,31 @@
X: The x coordinate to set
Obj get x: Get the x coordinate of the object
Object: The object to get the x coordinate
-Result: The variable to store the x coordinate
+Store result into: The variable to store the x coordinate
Obj set y: Set the y coordinate of the object
Object: The object to set the y coordinate
Y: The y coordinate to set
Obj get y: Get the y coordinate of the object
Object: The object to get the y coordinate
-Result: The variable to store the y coordinate
+Store result into: The variable to store the y coordinate
Obj set width: Set the width of the object
Object: The object to set the width
Width: The width to set
Obj get width: Get the width of the object
Object: The object to get the width
-Result: The variable to store the width
+Store result into: The variable to store the width
Obj set height: Set the height of the object
Object: The object to set the height
Height: The height to set
Obj get height: Get the height of the object
Object: The object to get the height
-Result: The variable to store the height
+Store result into: The variable to store the height
Obj set style opa: Set the opacity of the object
Object: The object to set the opacity
Opacity: The opacity to set (0-255)
Obj get style opa: Get the opacity of the object
Object: The object to get the opacity
-Result: The variable to store the opacity
+Store result into: The variable to store the opacity
Obj add style: Add a style to the object
Object: The object to add the style
Style: The style to add
@@ -72,7 +72,7 @@
Obj has flag: Check if the object has the specified flag
Object: The object to check the flag
Flag: The flag to check
-Result: The variable to store the result
+Store result into: The variable to store the result
Obj set state checked: Set the checked state of the object
Object: The object to set the checked state
Checked: The checked state to set
@@ -88,7 +88,7 @@
Obj has state: Check if the object has the specified state
Object: The object to check the state
State: The state to check
-Result: The variable to store the result
+Store result into: The variable to store the result
Arc set value: Set the value of the arc
Object: The arc to set the value
Value: The value to set
@@ -130,7 +130,7 @@
Group: The group to focus the previous object
Group get focused: Get the focused object in the group
Group: The group to get the focused object
-Result: The variable to store the focused object
+Store result into: The variable to store the focused object
Group focus freeze: Do not let to change the focus from the current object
Group: The group to freeze/unfreeze the focus
Enabled: true: freeze, false: release freezing (normal mode)
diff --git a/docs/components/odt/en-US/actions/AddToInstrumentHistory.odt b/docs/components/odt/en-US/actions/AddToInstrumentHistory.odt
index 7005cbd96..340e8ef12 100644
Binary files a/docs/components/odt/en-US/actions/AddToInstrumentHistory.odt and b/docs/components/odt/en-US/actions/AddToInstrumentHistory.odt differ
diff --git a/docs/components/odt/en-US/actions/Animate.odt b/docs/components/odt/en-US/actions/Animate.odt
index 22ef22bcf..749a449db 100644
Binary files a/docs/components/odt/en-US/actions/Animate.odt and b/docs/components/odt/en-US/actions/Animate.odt differ
diff --git a/docs/components/odt/en-US/actions/CSVParse.odt b/docs/components/odt/en-US/actions/CSVParse.odt
index 0c5b619c2..83ffda15a 100644
Binary files a/docs/components/odt/en-US/actions/CSVParse.odt and b/docs/components/odt/en-US/actions/CSVParse.odt differ
diff --git a/docs/components/odt/en-US/actions/CSVStringify.odt b/docs/components/odt/en-US/actions/CSVStringify.odt
index 7986c6604..780be1be3 100644
Binary files a/docs/components/odt/en-US/actions/CSVStringify.odt and b/docs/components/odt/en-US/actions/CSVStringify.odt differ
diff --git a/docs/components/odt/en-US/actions/CatchError.odt b/docs/components/odt/en-US/actions/CatchError.odt
index b37c14b36..2667e1b5a 100644
Binary files a/docs/components/odt/en-US/actions/CatchError.odt and b/docs/components/odt/en-US/actions/CatchError.odt differ
diff --git a/docs/components/odt/en-US/actions/ClipboardWrite.odt b/docs/components/odt/en-US/actions/ClipboardWrite.odt
index 728a62fff..eff7190c6 100644
Binary files a/docs/components/odt/en-US/actions/ClipboardWrite.odt and b/docs/components/odt/en-US/actions/ClipboardWrite.odt differ
diff --git a/docs/components/odt/en-US/actions/CloseStream.odt b/docs/components/odt/en-US/actions/CloseStream.odt
index e2ffbc025..e5fa5097d 100644
Binary files a/docs/components/odt/en-US/actions/CloseStream.odt and b/docs/components/odt/en-US/actions/CloseStream.odt differ
diff --git a/docs/components/odt/en-US/actions/CollectStream.odt b/docs/components/odt/en-US/actions/CollectStream.odt
index 38a6de6e2..7a0f0d831 100644
Binary files a/docs/components/odt/en-US/actions/CollectStream.odt and b/docs/components/odt/en-US/actions/CollectStream.odt differ
diff --git a/docs/components/odt/en-US/actions/Comment.odt b/docs/components/odt/en-US/actions/Comment.odt
index f64ed33a9..74973db76 100644
Binary files a/docs/components/odt/en-US/actions/Comment.odt and b/docs/components/odt/en-US/actions/Comment.odt differ
diff --git a/docs/components/odt/en-US/actions/Compare.odt b/docs/components/odt/en-US/actions/Compare.odt
index 212f5cbac..acdf1a9bf 100644
Binary files a/docs/components/odt/en-US/actions/Compare.odt and b/docs/components/odt/en-US/actions/Compare.odt differ
diff --git a/docs/components/odt/en-US/actions/ConnectInstrument.odt b/docs/components/odt/en-US/actions/ConnectInstrument.odt
index c3490aa9f..848ddbb10 100644
Binary files a/docs/components/odt/en-US/actions/ConnectInstrument.odt and b/docs/components/odt/en-US/actions/ConnectInstrument.odt differ
diff --git a/docs/components/odt/en-US/actions/Constant.odt b/docs/components/odt/en-US/actions/Constant.odt
index e4ae55c0d..ed1a41792 100644
Binary files a/docs/components/odt/en-US/actions/Constant.odt and b/docs/components/odt/en-US/actions/Constant.odt differ
diff --git a/docs/components/odt/en-US/actions/Counter.odt b/docs/components/odt/en-US/actions/Counter.odt
index 9de9acaad..439a95f8b 100644
Binary files a/docs/components/odt/en-US/actions/Counter.odt and b/docs/components/odt/en-US/actions/Counter.odt differ
diff --git a/docs/components/odt/en-US/actions/DateNow.odt b/docs/components/odt/en-US/actions/DateNow.odt
index e43ea24ec..aa2bd18e3 100644
Binary files a/docs/components/odt/en-US/actions/DateNow.odt and b/docs/components/odt/en-US/actions/DateNow.odt differ
diff --git a/docs/components/odt/en-US/actions/Delay.odt b/docs/components/odt/en-US/actions/Delay.odt
index c07335f9e..491fd1470 100644
Binary files a/docs/components/odt/en-US/actions/Delay.odt and b/docs/components/odt/en-US/actions/Delay.odt differ
diff --git a/docs/components/odt/en-US/actions/DisconnectInstrument.odt b/docs/components/odt/en-US/actions/DisconnectInstrument.odt
index 402acec04..8ae8c6d85 100644
Binary files a/docs/components/odt/en-US/actions/DisconnectInstrument.odt and b/docs/components/odt/en-US/actions/DisconnectInstrument.odt differ
diff --git a/docs/components/odt/en-US/actions/DynamicCallAction.odt b/docs/components/odt/en-US/actions/DynamicCallAction.odt
index 03b421574..0198521b0 100644
Binary files a/docs/components/odt/en-US/actions/DynamicCallAction.odt and b/docs/components/odt/en-US/actions/DynamicCallAction.odt differ
diff --git a/docs/components/odt/en-US/actions/End.odt b/docs/components/odt/en-US/actions/End.odt
index afc6dcea2..83824cab2 100644
Binary files a/docs/components/odt/en-US/actions/End.odt and b/docs/components/odt/en-US/actions/End.odt differ
diff --git a/docs/components/odt/en-US/actions/Error.odt b/docs/components/odt/en-US/actions/Error.odt
index 259120303..1daf90daf 100644
Binary files a/docs/components/odt/en-US/actions/Error.odt and b/docs/components/odt/en-US/actions/Error.odt differ
diff --git a/docs/components/odt/en-US/actions/Eval JS.odt b/docs/components/odt/en-US/actions/Eval JS.odt
index 202c09161..f3cc6fea7 100644
Binary files a/docs/components/odt/en-US/actions/Eval JS.odt and b/docs/components/odt/en-US/actions/Eval JS.odt differ
diff --git a/docs/components/odt/en-US/actions/Evaluate.odt b/docs/components/odt/en-US/actions/Evaluate.odt
index 74f83c18a..070feff2b 100644
Binary files a/docs/components/odt/en-US/actions/Evaluate.odt and b/docs/components/odt/en-US/actions/Evaluate.odt differ
diff --git a/docs/components/odt/en-US/actions/ExecuteCommand.odt b/docs/components/odt/en-US/actions/ExecuteCommand.odt
index 8de5127e3..7c95d028a 100644
Binary files a/docs/components/odt/en-US/actions/ExecuteCommand.odt and b/docs/components/odt/en-US/actions/ExecuteCommand.odt differ
diff --git a/docs/components/odt/en-US/actions/FileAppend.odt b/docs/components/odt/en-US/actions/FileAppend.odt
index 2c6bf2221..faeb32746 100644
Binary files a/docs/components/odt/en-US/actions/FileAppend.odt and b/docs/components/odt/en-US/actions/FileAppend.odt differ
diff --git a/docs/components/odt/en-US/actions/FileOpenDialog.odt b/docs/components/odt/en-US/actions/FileOpenDialog.odt
index 16aadee30..85975b58e 100644
Binary files a/docs/components/odt/en-US/actions/FileOpenDialog.odt and b/docs/components/odt/en-US/actions/FileOpenDialog.odt differ
diff --git a/docs/components/odt/en-US/actions/FileRead.odt b/docs/components/odt/en-US/actions/FileRead.odt
index aba00eff0..2cba3343a 100644
Binary files a/docs/components/odt/en-US/actions/FileRead.odt and b/docs/components/odt/en-US/actions/FileRead.odt differ
diff --git a/docs/components/odt/en-US/actions/FileSaveDialog.odt b/docs/components/odt/en-US/actions/FileSaveDialog.odt
index 3b18e9ed4..3b2a90a98 100644
Binary files a/docs/components/odt/en-US/actions/FileSaveDialog.odt and b/docs/components/odt/en-US/actions/FileSaveDialog.odt differ
diff --git a/docs/components/odt/en-US/actions/FileWrite.odt b/docs/components/odt/en-US/actions/FileWrite.odt
index 634f0d333..4ec0d4ff8 100644
Binary files a/docs/components/odt/en-US/actions/FileWrite.odt and b/docs/components/odt/en-US/actions/FileWrite.odt differ
diff --git a/docs/components/odt/en-US/actions/GetInstrument.odt b/docs/components/odt/en-US/actions/GetInstrument.odt
index d5cc740dc..cc2af6d26 100644
Binary files a/docs/components/odt/en-US/actions/GetInstrument.odt and b/docs/components/odt/en-US/actions/GetInstrument.odt differ
diff --git a/docs/components/odt/en-US/actions/GetInstrumentProperties.odt b/docs/components/odt/en-US/actions/GetInstrumentProperties.odt
index c8cef8a3b..925012f05 100644
Binary files a/docs/components/odt/en-US/actions/GetInstrumentProperties.odt and b/docs/components/odt/en-US/actions/GetInstrumentProperties.odt differ
diff --git a/docs/components/odt/en-US/actions/HTTP.odt b/docs/components/odt/en-US/actions/HTTP.odt
index 156a26b92..e330c1bee 100644
Binary files a/docs/components/odt/en-US/actions/HTTP.odt and b/docs/components/odt/en-US/actions/HTTP.odt differ
diff --git a/docs/components/odt/en-US/actions/Input.odt b/docs/components/odt/en-US/actions/Input.odt
index dea689526..276746bdd 100644
Binary files a/docs/components/odt/en-US/actions/Input.odt and b/docs/components/odt/en-US/actions/Input.odt differ
diff --git a/docs/components/odt/en-US/actions/InstrumentRead.odt b/docs/components/odt/en-US/actions/InstrumentRead.odt
index 75ba02ccc..6575699fa 100644
Binary files a/docs/components/odt/en-US/actions/InstrumentRead.odt and b/docs/components/odt/en-US/actions/InstrumentRead.odt differ
diff --git a/docs/components/odt/en-US/actions/InstrumentWrite.odt b/docs/components/odt/en-US/actions/InstrumentWrite.odt
index 169e7d00e..3a31ba89e 100644
Binary files a/docs/components/odt/en-US/actions/InstrumentWrite.odt and b/docs/components/odt/en-US/actions/InstrumentWrite.odt differ
diff --git a/docs/components/odt/en-US/actions/IsTrue.odt b/docs/components/odt/en-US/actions/IsTrue.odt
index 6609afcde..932e1e828 100644
Binary files a/docs/components/odt/en-US/actions/IsTrue.odt and b/docs/components/odt/en-US/actions/IsTrue.odt differ
diff --git a/docs/components/odt/en-US/actions/JSONParse.odt b/docs/components/odt/en-US/actions/JSONParse.odt
index 3e13988cb..62bc932d1 100644
Binary files a/docs/components/odt/en-US/actions/JSONParse.odt and b/docs/components/odt/en-US/actions/JSONParse.odt differ
diff --git a/docs/components/odt/en-US/actions/JSONStringify.odt b/docs/components/odt/en-US/actions/JSONStringify.odt
index 2ae17242f..1d3b48f0b 100644
Binary files a/docs/components/odt/en-US/actions/JSONStringify.odt and b/docs/components/odt/en-US/actions/JSONStringify.odt differ
diff --git a/docs/components/odt/en-US/actions/LVGL.odt b/docs/components/odt/en-US/actions/LVGL.odt
index 799cbca80..64653eb9b 100644
Binary files a/docs/components/odt/en-US/actions/LVGL.odt and b/docs/components/odt/en-US/actions/LVGL.odt differ
diff --git a/docs/components/odt/en-US/actions/Label IN.odt b/docs/components/odt/en-US/actions/Label IN.odt
index 3deaf268e..9bb944332 100644
Binary files a/docs/components/odt/en-US/actions/Label IN.odt and b/docs/components/odt/en-US/actions/Label IN.odt differ
diff --git a/docs/components/odt/en-US/actions/Label OUT.odt b/docs/components/odt/en-US/actions/Label OUT.odt
index 2da5f5ab8..b21e6dd41 100644
Binary files a/docs/components/odt/en-US/actions/Label OUT.odt and b/docs/components/odt/en-US/actions/Label OUT.odt differ
diff --git a/docs/components/odt/en-US/actions/Log.odt b/docs/components/odt/en-US/actions/Log.odt
index 88640bb75..d7df7f615 100644
Binary files a/docs/components/odt/en-US/actions/Log.odt and b/docs/components/odt/en-US/actions/Log.odt differ
diff --git a/docs/components/odt/en-US/actions/Loop.odt b/docs/components/odt/en-US/actions/Loop.odt
index ec36e8582..c28d45d03 100644
Binary files a/docs/components/odt/en-US/actions/Loop.odt and b/docs/components/odt/en-US/actions/Loop.odt differ
diff --git a/docs/components/odt/en-US/actions/MQTTConnect.odt b/docs/components/odt/en-US/actions/MQTTConnect.odt
index 8dfee266c..03269ea50 100644
Binary files a/docs/components/odt/en-US/actions/MQTTConnect.odt and b/docs/components/odt/en-US/actions/MQTTConnect.odt differ
diff --git a/docs/components/odt/en-US/actions/MQTTDisconnect.odt b/docs/components/odt/en-US/actions/MQTTDisconnect.odt
index a7cb62847..814be23de 100644
Binary files a/docs/components/odt/en-US/actions/MQTTDisconnect.odt and b/docs/components/odt/en-US/actions/MQTTDisconnect.odt differ
diff --git a/docs/components/odt/en-US/actions/MQTTEvent.odt b/docs/components/odt/en-US/actions/MQTTEvent.odt
index d207bb8e4..2cb822e04 100644
Binary files a/docs/components/odt/en-US/actions/MQTTEvent.odt and b/docs/components/odt/en-US/actions/MQTTEvent.odt differ
diff --git a/docs/components/odt/en-US/actions/MQTTInit.odt b/docs/components/odt/en-US/actions/MQTTInit.odt
index a1b15e55b..5245d390f 100644
Binary files a/docs/components/odt/en-US/actions/MQTTInit.odt and b/docs/components/odt/en-US/actions/MQTTInit.odt differ
diff --git a/docs/components/odt/en-US/actions/MQTTPublish.odt b/docs/components/odt/en-US/actions/MQTTPublish.odt
index 3568217f6..41012b993 100644
Binary files a/docs/components/odt/en-US/actions/MQTTPublish.odt and b/docs/components/odt/en-US/actions/MQTTPublish.odt differ
diff --git a/docs/components/odt/en-US/actions/MQTTSubscribe.odt b/docs/components/odt/en-US/actions/MQTTSubscribe.odt
index a4de6b225..c1ac7f31a 100644
Binary files a/docs/components/odt/en-US/actions/MQTTSubscribe.odt and b/docs/components/odt/en-US/actions/MQTTSubscribe.odt differ
diff --git a/docs/components/odt/en-US/actions/MQTTUnsubscribe.odt b/docs/components/odt/en-US/actions/MQTTUnsubscribe.odt
index 6842a1174..7fb9ef0f2 100644
Binary files a/docs/components/odt/en-US/actions/MQTTUnsubscribe.odt and b/docs/components/odt/en-US/actions/MQTTUnsubscribe.odt differ
diff --git a/docs/components/odt/en-US/actions/Modbus.odt b/docs/components/odt/en-US/actions/Modbus.odt
index 98f28792c..ae3c8c833 100644
Binary files a/docs/components/odt/en-US/actions/Modbus.odt and b/docs/components/odt/en-US/actions/Modbus.odt differ
diff --git a/docs/components/odt/en-US/actions/NoOp.odt b/docs/components/odt/en-US/actions/NoOp.odt
index 52ef8e1f4..b166010b3 100644
Binary files a/docs/components/odt/en-US/actions/NoOp.odt and b/docs/components/odt/en-US/actions/NoOp.odt differ
diff --git a/docs/components/odt/en-US/actions/OnEvent.odt b/docs/components/odt/en-US/actions/OnEvent.odt
index 2ffab79dd..dc3aefb2e 100644
Binary files a/docs/components/odt/en-US/actions/OnEvent.odt and b/docs/components/odt/en-US/actions/OnEvent.odt differ
diff --git a/docs/components/odt/en-US/actions/Output.odt b/docs/components/odt/en-US/actions/Output.odt
index 0eed7acf9..652c68dd3 100644
Binary files a/docs/components/odt/en-US/actions/Output.odt and b/docs/components/odt/en-US/actions/Output.odt differ
diff --git a/docs/components/odt/en-US/actions/OverrideStyle.odt b/docs/components/odt/en-US/actions/OverrideStyle.odt
index 8178f2086..168bdb72d 100644
Binary files a/docs/components/odt/en-US/actions/OverrideStyle.odt and b/docs/components/odt/en-US/actions/OverrideStyle.odt differ
diff --git a/docs/components/odt/en-US/actions/PrintToPDF.odt b/docs/components/odt/en-US/actions/PrintToPDF.odt
index a66147b28..69d655e12 100644
Binary files a/docs/components/odt/en-US/actions/PrintToPDF.odt and b/docs/components/odt/en-US/actions/PrintToPDF.odt differ
diff --git a/docs/components/odt/en-US/actions/PythonEnd.odt b/docs/components/odt/en-US/actions/PythonEnd.odt
index f957e3284..9f47de3de 100644
Binary files a/docs/components/odt/en-US/actions/PythonEnd.odt and b/docs/components/odt/en-US/actions/PythonEnd.odt differ
diff --git a/docs/components/odt/en-US/actions/PythonRun.odt b/docs/components/odt/en-US/actions/PythonRun.odt
index 508912dac..a5d975aa8 100644
Binary files a/docs/components/odt/en-US/actions/PythonRun.odt and b/docs/components/odt/en-US/actions/PythonRun.odt differ
diff --git a/docs/components/odt/en-US/actions/PythonSendMessage.odt b/docs/components/odt/en-US/actions/PythonSendMessage.odt
index 063636560..c775e7602 100644
Binary files a/docs/components/odt/en-US/actions/PythonSendMessage.odt and b/docs/components/odt/en-US/actions/PythonSendMessage.odt differ
diff --git a/docs/components/odt/en-US/actions/ReadSetting.odt b/docs/components/odt/en-US/actions/ReadSetting.odt
index 8e9d49e6d..0c487e830 100644
Binary files a/docs/components/odt/en-US/actions/ReadSetting.odt and b/docs/components/odt/en-US/actions/ReadSetting.odt differ
diff --git a/docs/components/odt/en-US/actions/Regexp.odt b/docs/components/odt/en-US/actions/Regexp.odt
index c40071fce..6139504f4 100644
Binary files a/docs/components/odt/en-US/actions/Regexp.odt and b/docs/components/odt/en-US/actions/Regexp.odt differ
diff --git a/docs/components/odt/en-US/actions/SCPI.odt b/docs/components/odt/en-US/actions/SCPI.odt
index 49b40f818..45f8f66f7 100644
Binary files a/docs/components/odt/en-US/actions/SCPI.odt and b/docs/components/odt/en-US/actions/SCPI.odt differ
diff --git a/docs/components/odt/en-US/actions/SelectInstrument.odt b/docs/components/odt/en-US/actions/SelectInstrument.odt
index 95fbeb70d..607318384 100644
Binary files a/docs/components/odt/en-US/actions/SelectInstrument.odt and b/docs/components/odt/en-US/actions/SelectInstrument.odt differ
diff --git a/docs/components/odt/en-US/actions/SelectLanguage.odt b/docs/components/odt/en-US/actions/SelectLanguage.odt
index 3302d243b..e1a4d542c 100644
Binary files a/docs/components/odt/en-US/actions/SelectLanguage.odt and b/docs/components/odt/en-US/actions/SelectLanguage.odt differ
diff --git a/docs/components/odt/en-US/actions/SerialConnect.odt b/docs/components/odt/en-US/actions/SerialConnect.odt
index 090d6febd..07317e73f 100644
Binary files a/docs/components/odt/en-US/actions/SerialConnect.odt and b/docs/components/odt/en-US/actions/SerialConnect.odt differ
diff --git a/docs/components/odt/en-US/actions/SerialDisconnect.odt b/docs/components/odt/en-US/actions/SerialDisconnect.odt
index eab2daf16..708352615 100644
Binary files a/docs/components/odt/en-US/actions/SerialDisconnect.odt and b/docs/components/odt/en-US/actions/SerialDisconnect.odt differ
diff --git a/docs/components/odt/en-US/actions/SerialInit.odt b/docs/components/odt/en-US/actions/SerialInit.odt
index 703458c30..bd13d03a6 100644
Binary files a/docs/components/odt/en-US/actions/SerialInit.odt and b/docs/components/odt/en-US/actions/SerialInit.odt differ
diff --git a/docs/components/odt/en-US/actions/SerialListPorts.odt b/docs/components/odt/en-US/actions/SerialListPorts.odt
index 7512a1170..77d35419d 100644
Binary files a/docs/components/odt/en-US/actions/SerialListPorts.odt and b/docs/components/odt/en-US/actions/SerialListPorts.odt differ
diff --git a/docs/components/odt/en-US/actions/SerialRead.odt b/docs/components/odt/en-US/actions/SerialRead.odt
index ca1683832..4b8b4f090 100644
Binary files a/docs/components/odt/en-US/actions/SerialRead.odt and b/docs/components/odt/en-US/actions/SerialRead.odt differ
diff --git a/docs/components/odt/en-US/actions/SerialWrite.odt b/docs/components/odt/en-US/actions/SerialWrite.odt
index a82338410..756e4f058 100644
Binary files a/docs/components/odt/en-US/actions/SerialWrite.odt and b/docs/components/odt/en-US/actions/SerialWrite.odt differ
diff --git a/docs/components/odt/en-US/actions/SetPageDirection.odt b/docs/components/odt/en-US/actions/SetPageDirection.odt
index 8fbf4def1..08624df19 100644
Binary files a/docs/components/odt/en-US/actions/SetPageDirection.odt and b/docs/components/odt/en-US/actions/SetPageDirection.odt differ
diff --git a/docs/components/odt/en-US/actions/SetVariable.odt b/docs/components/odt/en-US/actions/SetVariable.odt
index 0b1c3bddd..6bc6f0dea 100644
Binary files a/docs/components/odt/en-US/actions/SetVariable.odt and b/docs/components/odt/en-US/actions/SetVariable.odt differ
diff --git a/docs/components/odt/en-US/actions/ShowFileInFolder.odt b/docs/components/odt/en-US/actions/ShowFileInFolder.odt
index bd0f63024..597334c48 100644
Binary files a/docs/components/odt/en-US/actions/ShowFileInFolder.odt and b/docs/components/odt/en-US/actions/ShowFileInFolder.odt differ
diff --git a/docs/components/odt/en-US/actions/ShowKeyboard.odt b/docs/components/odt/en-US/actions/ShowKeyboard.odt
index c211d8503..b8ca36c0b 100644
Binary files a/docs/components/odt/en-US/actions/ShowKeyboard.odt and b/docs/components/odt/en-US/actions/ShowKeyboard.odt differ
diff --git a/docs/components/odt/en-US/actions/ShowKeypad.odt b/docs/components/odt/en-US/actions/ShowKeypad.odt
index 0f6165380..6d5e7a5d9 100644
Binary files a/docs/components/odt/en-US/actions/ShowKeypad.odt and b/docs/components/odt/en-US/actions/ShowKeypad.odt differ
diff --git a/docs/components/odt/en-US/actions/ShowMessageBox.odt b/docs/components/odt/en-US/actions/ShowMessageBox.odt
index dde586e67..9aec52a88 100644
Binary files a/docs/components/odt/en-US/actions/ShowMessageBox.odt and b/docs/components/odt/en-US/actions/ShowMessageBox.odt differ
diff --git a/docs/components/odt/en-US/actions/ShowPage.odt b/docs/components/odt/en-US/actions/ShowPage.odt
index 747b6f964..f44f75d1d 100644
Binary files a/docs/components/odt/en-US/actions/ShowPage.odt and b/docs/components/odt/en-US/actions/ShowPage.odt differ
diff --git a/docs/components/odt/en-US/actions/SortArray.odt b/docs/components/odt/en-US/actions/SortArray.odt
index 113a19da2..716c8e7c2 100644
Binary files a/docs/components/odt/en-US/actions/SortArray.odt and b/docs/components/odt/en-US/actions/SortArray.odt differ
diff --git a/docs/components/odt/en-US/actions/Start.odt b/docs/components/odt/en-US/actions/Start.odt
index da2f35fc8..92c564d18 100644
Binary files a/docs/components/odt/en-US/actions/Start.odt and b/docs/components/odt/en-US/actions/Start.odt differ
diff --git a/docs/components/odt/en-US/actions/SwitchCase.odt b/docs/components/odt/en-US/actions/SwitchCase.odt
index c16e59b5d..7008409b3 100644
Binary files a/docs/components/odt/en-US/actions/SwitchCase.odt and b/docs/components/odt/en-US/actions/SwitchCase.odt differ
diff --git a/docs/components/odt/en-US/actions/TCPConnect.odt b/docs/components/odt/en-US/actions/TCPConnect.odt
index f9f5dbb5e..ed3f2e178 100644
Binary files a/docs/components/odt/en-US/actions/TCPConnect.odt and b/docs/components/odt/en-US/actions/TCPConnect.odt differ
diff --git a/docs/components/odt/en-US/actions/TCPDisconnect.odt b/docs/components/odt/en-US/actions/TCPDisconnect.odt
index 0f43e240f..5522686be 100644
Binary files a/docs/components/odt/en-US/actions/TCPDisconnect.odt and b/docs/components/odt/en-US/actions/TCPDisconnect.odt differ
diff --git a/docs/components/odt/en-US/actions/TCPEvent.odt b/docs/components/odt/en-US/actions/TCPEvent.odt
index ca0c12679..4152bfda0 100644
Binary files a/docs/components/odt/en-US/actions/TCPEvent.odt and b/docs/components/odt/en-US/actions/TCPEvent.odt differ
diff --git a/docs/components/odt/en-US/actions/TCPListen.odt b/docs/components/odt/en-US/actions/TCPListen.odt
index bf842ef7d..32fbf5417 100644
Binary files a/docs/components/odt/en-US/actions/TCPListen.odt and b/docs/components/odt/en-US/actions/TCPListen.odt differ
diff --git a/docs/components/odt/en-US/actions/TCPWrite.odt b/docs/components/odt/en-US/actions/TCPWrite.odt
index d97ec92f0..b3ce2c7d3 100644
Binary files a/docs/components/odt/en-US/actions/TCPWrite.odt and b/docs/components/odt/en-US/actions/TCPWrite.odt differ
diff --git a/docs/components/odt/en-US/actions/TabulatorAction.odt b/docs/components/odt/en-US/actions/TabulatorAction.odt
index 99def2bd6..1d9de2895 100644
Binary files a/docs/components/odt/en-US/actions/TabulatorAction.odt and b/docs/components/odt/en-US/actions/TabulatorAction.odt differ
diff --git a/docs/components/odt/en-US/actions/TestAndSet.odt b/docs/components/odt/en-US/actions/TestAndSet.odt
index 6823065df..243a5b41f 100644
Binary files a/docs/components/odt/en-US/actions/TestAndSet.odt and b/docs/components/odt/en-US/actions/TestAndSet.odt differ
diff --git a/docs/components/odt/en-US/actions/UDP In.odt b/docs/components/odt/en-US/actions/UDP In.odt
index 877df8944..0be33b0bf 100644
Binary files a/docs/components/odt/en-US/actions/UDP In.odt and b/docs/components/odt/en-US/actions/UDP In.odt differ
diff --git a/docs/components/odt/en-US/actions/UDP Out.odt b/docs/components/odt/en-US/actions/UDP Out.odt
index 7ed102baa..24efc8a14 100644
Binary files a/docs/components/odt/en-US/actions/UDP Out.odt and b/docs/components/odt/en-US/actions/UDP Out.odt differ
diff --git a/docs/components/odt/en-US/actions/Watch.odt b/docs/components/odt/en-US/actions/Watch.odt
index b51da71e7..0ce2fb04f 100644
Binary files a/docs/components/odt/en-US/actions/Watch.odt and b/docs/components/odt/en-US/actions/Watch.odt differ
diff --git a/docs/components/odt/en-US/actions/WriteSetting.odt b/docs/components/odt/en-US/actions/WriteSetting.odt
index de08d65d7..4faadc084 100644
Binary files a/docs/components/odt/en-US/actions/WriteSetting.odt and b/docs/components/odt/en-US/actions/WriteSetting.odt differ
diff --git a/docs/components/odt/en-US/widgets/AnimationImage.odt b/docs/components/odt/en-US/widgets/AnimationImage.odt
index 889929add..4c58ceb2c 100644
Binary files a/docs/components/odt/en-US/widgets/AnimationImage.odt and b/docs/components/odt/en-US/widgets/AnimationImage.odt differ
diff --git a/docs/components/odt/en-US/widgets/Arc.odt b/docs/components/odt/en-US/widgets/Arc.odt
index e6b7f06b0..2b1f17ddb 100644
Binary files a/docs/components/odt/en-US/widgets/Arc.odt and b/docs/components/odt/en-US/widgets/Arc.odt differ
diff --git a/docs/components/odt/en-US/widgets/Bar.odt b/docs/components/odt/en-US/widgets/Bar.odt
index b10865e3a..935f4f0c8 100644
Binary files a/docs/components/odt/en-US/widgets/Bar.odt and b/docs/components/odt/en-US/widgets/Bar.odt differ
diff --git a/docs/components/odt/en-US/widgets/BarGraph.odt b/docs/components/odt/en-US/widgets/BarGraph.odt
index 92e7f16f4..cc0c1abd3 100644
Binary files a/docs/components/odt/en-US/widgets/BarGraph.odt and b/docs/components/odt/en-US/widgets/BarGraph.odt differ
diff --git a/docs/components/odt/en-US/widgets/Bitmap (Dashboard).odt b/docs/components/odt/en-US/widgets/Bitmap (Dashboard).odt
index cb3766e7e..bc98e424e 100644
Binary files a/docs/components/odt/en-US/widgets/Bitmap (Dashboard).odt and b/docs/components/odt/en-US/widgets/Bitmap (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Bitmap (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Bitmap (EEZ-GUI).odt
index 21e96bae8..50da3e783 100644
Binary files a/docs/components/odt/en-US/widgets/Bitmap (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Bitmap (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Button (Dashboard).odt b/docs/components/odt/en-US/widgets/Button (Dashboard).odt
index 17ff21fd1..039b759c0 100644
Binary files a/docs/components/odt/en-US/widgets/Button (Dashboard).odt and b/docs/components/odt/en-US/widgets/Button (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Button (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Button (EEZ-GUI).odt
index 95d5aa0b6..4e6d8c7bd 100644
Binary files a/docs/components/odt/en-US/widgets/Button (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Button (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Button (LVGL).odt b/docs/components/odt/en-US/widgets/Button (LVGL).odt
index ee1c555ab..f26b78e5b 100644
Binary files a/docs/components/odt/en-US/widgets/Button (LVGL).odt and b/docs/components/odt/en-US/widgets/Button (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/ButtonGroup.odt b/docs/components/odt/en-US/widgets/ButtonGroup.odt
index d87839a9f..c62c0caca 100644
Binary files a/docs/components/odt/en-US/widgets/ButtonGroup.odt and b/docs/components/odt/en-US/widgets/ButtonGroup.odt differ
diff --git a/docs/components/odt/en-US/widgets/ButtonMatrix.odt b/docs/components/odt/en-US/widgets/ButtonMatrix.odt
index 9d4565884..c38b74f00 100644
Binary files a/docs/components/odt/en-US/widgets/ButtonMatrix.odt and b/docs/components/odt/en-US/widgets/ButtonMatrix.odt differ
diff --git a/docs/components/odt/en-US/widgets/Calendar.odt b/docs/components/odt/en-US/widgets/Calendar.odt
index 5808d50f6..45f2e6054 100644
Binary files a/docs/components/odt/en-US/widgets/Calendar.odt and b/docs/components/odt/en-US/widgets/Calendar.odt differ
diff --git a/docs/components/odt/en-US/widgets/Canvas.odt b/docs/components/odt/en-US/widgets/Canvas.odt
index 3b90af88a..72eae9a3b 100644
Binary files a/docs/components/odt/en-US/widgets/Canvas.odt and b/docs/components/odt/en-US/widgets/Canvas.odt differ
diff --git a/docs/components/odt/en-US/widgets/Chart.odt b/docs/components/odt/en-US/widgets/Chart.odt
index 1ec86560b..cf574cbd4 100644
Binary files a/docs/components/odt/en-US/widgets/Chart.odt and b/docs/components/odt/en-US/widgets/Chart.odt differ
diff --git a/docs/components/odt/en-US/widgets/Checkbox (Dashboard).odt b/docs/components/odt/en-US/widgets/Checkbox (Dashboard).odt
index 67a0919f9..bf77ab064 100644
Binary files a/docs/components/odt/en-US/widgets/Checkbox (Dashboard).odt and b/docs/components/odt/en-US/widgets/Checkbox (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Checkbox (LVGL).odt b/docs/components/odt/en-US/widgets/Checkbox (LVGL).odt
index 7b655ab50..7d280af03 100644
Binary files a/docs/components/odt/en-US/widgets/Checkbox (LVGL).odt and b/docs/components/odt/en-US/widgets/Checkbox (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/Colorwheel.odt b/docs/components/odt/en-US/widgets/Colorwheel.odt
index c66b5825b..2ec32f1d4 100644
Binary files a/docs/components/odt/en-US/widgets/Colorwheel.odt and b/docs/components/odt/en-US/widgets/Colorwheel.odt differ
diff --git a/docs/components/odt/en-US/widgets/Container (Dashboard).odt b/docs/components/odt/en-US/widgets/Container (Dashboard).odt
index f0bf97c4c..5109a7ff7 100644
Binary files a/docs/components/odt/en-US/widgets/Container (Dashboard).odt and b/docs/components/odt/en-US/widgets/Container (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Container (LVGL).odt b/docs/components/odt/en-US/widgets/Container (LVGL).odt
index 08c79e984..651944fc5 100644
Binary files a/docs/components/odt/en-US/widgets/Container (LVGL).odt and b/docs/components/odt/en-US/widgets/Container (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/DisplayData.odt b/docs/components/odt/en-US/widgets/DisplayData.odt
index 9785631d0..ff8bd4eba 100644
Binary files a/docs/components/odt/en-US/widgets/DisplayData.odt and b/docs/components/odt/en-US/widgets/DisplayData.odt differ
diff --git a/docs/components/odt/en-US/widgets/Dropdown (Dashboard).odt b/docs/components/odt/en-US/widgets/Dropdown (Dashboard).odt
index 900d2f68a..99eb27d5f 100644
Binary files a/docs/components/odt/en-US/widgets/Dropdown (Dashboard).odt and b/docs/components/odt/en-US/widgets/Dropdown (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Dropdown (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Dropdown (EEZ-GUI).odt
index b680333c7..f29c18f77 100644
Binary files a/docs/components/odt/en-US/widgets/Dropdown (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Dropdown (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Dropdown (LVGL).odt b/docs/components/odt/en-US/widgets/Dropdown (LVGL).odt
index e723c906d..e494de610 100644
Binary files a/docs/components/odt/en-US/widgets/Dropdown (LVGL).odt and b/docs/components/odt/en-US/widgets/Dropdown (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/EEZChart.odt b/docs/components/odt/en-US/widgets/EEZChart.odt
index fcf81fd2f..1b8b47c8a 100644
Binary files a/docs/components/odt/en-US/widgets/EEZChart.odt and b/docs/components/odt/en-US/widgets/EEZChart.odt differ
diff --git a/docs/components/odt/en-US/widgets/Embedded Dashboard.odt b/docs/components/odt/en-US/widgets/Embedded Dashboard.odt
index 97eb0ad8c..bb0bea8de 100644
Binary files a/docs/components/odt/en-US/widgets/Embedded Dashboard.odt and b/docs/components/odt/en-US/widgets/Embedded Dashboard.odt differ
diff --git a/docs/components/odt/en-US/widgets/Gauge (Dashboard).odt b/docs/components/odt/en-US/widgets/Gauge (Dashboard).odt
index a88f0a69b..3bb6a45a1 100644
Binary files a/docs/components/odt/en-US/widgets/Gauge (Dashboard).odt and b/docs/components/odt/en-US/widgets/Gauge (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Gauge (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Gauge (EEZ-GUI).odt
index de0f5cc73..a4fac727f 100644
Binary files a/docs/components/odt/en-US/widgets/Gauge (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Gauge (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Grid.odt b/docs/components/odt/en-US/widgets/Grid.odt
index e4f69f3dc..aeb069f93 100644
Binary files a/docs/components/odt/en-US/widgets/Grid.odt and b/docs/components/odt/en-US/widgets/Grid.odt differ
diff --git a/docs/components/odt/en-US/widgets/Image.odt b/docs/components/odt/en-US/widgets/Image.odt
index addfcafbe..aacc21804 100644
Binary files a/docs/components/odt/en-US/widgets/Image.odt and b/docs/components/odt/en-US/widgets/Image.odt differ
diff --git a/docs/components/odt/en-US/widgets/Imgbutton.odt b/docs/components/odt/en-US/widgets/Imgbutton.odt
index 55f584cb0..4febf37d1 100644
Binary files a/docs/components/odt/en-US/widgets/Imgbutton.odt and b/docs/components/odt/en-US/widgets/Imgbutton.odt differ
diff --git a/docs/components/odt/en-US/widgets/Input (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Input (EEZ-GUI).odt
index fd01857a7..18a9bce91 100644
Binary files a/docs/components/odt/en-US/widgets/Input (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Input (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/InstrumentTerminal.odt b/docs/components/odt/en-US/widgets/InstrumentTerminal.odt
index 1e92d472d..bc5606c2d 100644
Binary files a/docs/components/odt/en-US/widgets/InstrumentTerminal.odt and b/docs/components/odt/en-US/widgets/InstrumentTerminal.odt differ
diff --git a/docs/components/odt/en-US/widgets/Keyboard.odt b/docs/components/odt/en-US/widgets/Keyboard.odt
index f86cae942..47df9eb8f 100644
Binary files a/docs/components/odt/en-US/widgets/Keyboard.odt and b/docs/components/odt/en-US/widgets/Keyboard.odt differ
diff --git a/docs/components/odt/en-US/widgets/Label.odt b/docs/components/odt/en-US/widgets/Label.odt
index 3f9545a12..6085539f9 100644
Binary files a/docs/components/odt/en-US/widgets/Label.odt and b/docs/components/odt/en-US/widgets/Label.odt differ
diff --git a/docs/components/odt/en-US/widgets/Led.odt b/docs/components/odt/en-US/widgets/Led.odt
index 78af652ea..2b3d68c07 100644
Binary files a/docs/components/odt/en-US/widgets/Led.odt and b/docs/components/odt/en-US/widgets/Led.odt differ
diff --git a/docs/components/odt/en-US/widgets/Line.odt b/docs/components/odt/en-US/widgets/Line.odt
index 0356bbaf2..5a99c4420 100644
Binary files a/docs/components/odt/en-US/widgets/Line.odt and b/docs/components/odt/en-US/widgets/Line.odt differ
diff --git a/docs/components/odt/en-US/widgets/LineChart (Dashboard).odt b/docs/components/odt/en-US/widgets/LineChart (Dashboard).odt
index 56cfaced1..346d5a5e4 100644
Binary files a/docs/components/odt/en-US/widgets/LineChart (Dashboard).odt and b/docs/components/odt/en-US/widgets/LineChart (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/LineChart (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/LineChart (EEZ-GUI).odt
index 910a3041c..edf11c2fe 100644
Binary files a/docs/components/odt/en-US/widgets/LineChart (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/LineChart (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/List (Dashboard).odt b/docs/components/odt/en-US/widgets/List (Dashboard).odt
index 99531692b..19c0c2d6f 100644
Binary files a/docs/components/odt/en-US/widgets/List (Dashboard).odt and b/docs/components/odt/en-US/widgets/List (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/List (LVGL).odt b/docs/components/odt/en-US/widgets/List (LVGL).odt
index ec9bf0751..0acd18833 100644
Binary files a/docs/components/odt/en-US/widgets/List (LVGL).odt and b/docs/components/odt/en-US/widgets/List (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/Lottie.odt b/docs/components/odt/en-US/widgets/Lottie.odt
index 2a8c94cd0..4a25991df 100644
Binary files a/docs/components/odt/en-US/widgets/Lottie.odt and b/docs/components/odt/en-US/widgets/Lottie.odt differ
diff --git a/docs/components/odt/en-US/widgets/Markdown.odt b/docs/components/odt/en-US/widgets/Markdown.odt
index 5894a0504..2b4438aea 100644
Binary files a/docs/components/odt/en-US/widgets/Markdown.odt and b/docs/components/odt/en-US/widgets/Markdown.odt differ
diff --git a/docs/components/odt/en-US/widgets/Menu.odt b/docs/components/odt/en-US/widgets/Menu.odt
index cd2ed44ae..9d380a756 100644
Binary files a/docs/components/odt/en-US/widgets/Menu.odt and b/docs/components/odt/en-US/widgets/Menu.odt differ
diff --git a/docs/components/odt/en-US/widgets/MessageBox.odt b/docs/components/odt/en-US/widgets/MessageBox.odt
index 634af4014..814d0036b 100644
Binary files a/docs/components/odt/en-US/widgets/MessageBox.odt and b/docs/components/odt/en-US/widgets/MessageBox.odt differ
diff --git a/docs/components/odt/en-US/widgets/Meter.odt b/docs/components/odt/en-US/widgets/Meter.odt
index cff14120b..6900bc984 100644
Binary files a/docs/components/odt/en-US/widgets/Meter.odt and b/docs/components/odt/en-US/widgets/Meter.odt differ
diff --git a/docs/components/odt/en-US/widgets/MultilineText.odt b/docs/components/odt/en-US/widgets/MultilineText.odt
index 5cbf7ab4a..758bc2d9d 100644
Binary files a/docs/components/odt/en-US/widgets/MultilineText.odt and b/docs/components/odt/en-US/widgets/MultilineText.odt differ
diff --git a/docs/components/odt/en-US/widgets/NumberInput.odt b/docs/components/odt/en-US/widgets/NumberInput.odt
index 509b5d2c0..46bf57f3b 100644
Binary files a/docs/components/odt/en-US/widgets/NumberInput.odt and b/docs/components/odt/en-US/widgets/NumberInput.odt differ
diff --git a/docs/components/odt/en-US/widgets/Panel.odt b/docs/components/odt/en-US/widgets/Panel.odt
index d21040fa9..add9dfe1b 100644
Binary files a/docs/components/odt/en-US/widgets/Panel.odt and b/docs/components/odt/en-US/widgets/Panel.odt differ
diff --git a/docs/components/odt/en-US/widgets/Plotly.odt b/docs/components/odt/en-US/widgets/Plotly.odt
index af5e64f7b..d71e0bb65 100644
Binary files a/docs/components/odt/en-US/widgets/Plotly.odt and b/docs/components/odt/en-US/widgets/Plotly.odt differ
diff --git a/docs/components/odt/en-US/widgets/Progress (Dashboard).odt b/docs/components/odt/en-US/widgets/Progress (Dashboard).odt
index a994b0418..3e9001d75 100644
Binary files a/docs/components/odt/en-US/widgets/Progress (Dashboard).odt and b/docs/components/odt/en-US/widgets/Progress (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Progress (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Progress (EEZ-GUI).odt
index b735714c1..539615973 100644
Binary files a/docs/components/odt/en-US/widgets/Progress (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Progress (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/QRCode (Dashboard).odt b/docs/components/odt/en-US/widgets/QRCode (Dashboard).odt
index e0a672bf0..81b60893a 100644
Binary files a/docs/components/odt/en-US/widgets/QRCode (Dashboard).odt and b/docs/components/odt/en-US/widgets/QRCode (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/QRCode (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/QRCode (EEZ-GUI).odt
index 476aa9a97..b8089ed69 100644
Binary files a/docs/components/odt/en-US/widgets/QRCode (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/QRCode (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Radio.odt b/docs/components/odt/en-US/widgets/Radio.odt
index c548abbe0..2a9e7491f 100644
Binary files a/docs/components/odt/en-US/widgets/Radio.odt and b/docs/components/odt/en-US/widgets/Radio.odt differ
diff --git a/docs/components/odt/en-US/widgets/Rectangle (Dashboard).odt b/docs/components/odt/en-US/widgets/Rectangle (Dashboard).odt
index a06947c46..9e8b621e2 100644
Binary files a/docs/components/odt/en-US/widgets/Rectangle (Dashboard).odt and b/docs/components/odt/en-US/widgets/Rectangle (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Rectangle (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Rectangle (EEZ-GUI).odt
index dfe28fc4f..325475e35 100644
Binary files a/docs/components/odt/en-US/widgets/Rectangle (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Rectangle (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Roller (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Roller (EEZ-GUI).odt
index 419db01c4..d112d7a98 100644
Binary files a/docs/components/odt/en-US/widgets/Roller (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Roller (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Roller (LVGL).odt b/docs/components/odt/en-US/widgets/Roller (LVGL).odt
index 988afe774..4563204ea 100644
Binary files a/docs/components/odt/en-US/widgets/Roller (LVGL).odt and b/docs/components/odt/en-US/widgets/Roller (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/Scale.odt b/docs/components/odt/en-US/widgets/Scale.odt
index 9a837b269..8206f571d 100644
Binary files a/docs/components/odt/en-US/widgets/Scale.odt and b/docs/components/odt/en-US/widgets/Scale.odt differ
diff --git a/docs/components/odt/en-US/widgets/ScrollBar.odt b/docs/components/odt/en-US/widgets/ScrollBar.odt
index 63173241a..a6e7ecbc8 100644
Binary files a/docs/components/odt/en-US/widgets/ScrollBar.odt and b/docs/components/odt/en-US/widgets/ScrollBar.odt differ
diff --git a/docs/components/odt/en-US/widgets/Select.odt b/docs/components/odt/en-US/widgets/Select.odt
index 5b0eddcee..9faa6bddc 100644
Binary files a/docs/components/odt/en-US/widgets/Select.odt and b/docs/components/odt/en-US/widgets/Select.odt differ
diff --git a/docs/components/odt/en-US/widgets/Slider (Dashboard).odt b/docs/components/odt/en-US/widgets/Slider (Dashboard).odt
index 0d769e5a2..67cc5e6f2 100644
Binary files a/docs/components/odt/en-US/widgets/Slider (Dashboard).odt and b/docs/components/odt/en-US/widgets/Slider (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Slider (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Slider (EEZ-GUI).odt
index d2a54e6ae..5b7eb6706 100644
Binary files a/docs/components/odt/en-US/widgets/Slider (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Slider (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Slider (LVGL).odt b/docs/components/odt/en-US/widgets/Slider (LVGL).odt
index d7a7c74d8..4e834f415 100644
Binary files a/docs/components/odt/en-US/widgets/Slider (LVGL).odt and b/docs/components/odt/en-US/widgets/Slider (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/Span.odt b/docs/components/odt/en-US/widgets/Span.odt
index 5587ddf4d..85130abb7 100644
Binary files a/docs/components/odt/en-US/widgets/Span.odt and b/docs/components/odt/en-US/widgets/Span.odt differ
diff --git a/docs/components/odt/en-US/widgets/Spinbox.odt b/docs/components/odt/en-US/widgets/Spinbox.odt
index 43ad0b76d..fb4edd765 100644
Binary files a/docs/components/odt/en-US/widgets/Spinbox.odt and b/docs/components/odt/en-US/widgets/Spinbox.odt differ
diff --git a/docs/components/odt/en-US/widgets/Spinner (Dashboard).odt b/docs/components/odt/en-US/widgets/Spinner (Dashboard).odt
index 36d026f38..22e085221 100644
Binary files a/docs/components/odt/en-US/widgets/Spinner (Dashboard).odt and b/docs/components/odt/en-US/widgets/Spinner (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Spinner (LVGL).odt b/docs/components/odt/en-US/widgets/Spinner (LVGL).odt
index d0f7c131f..85abcc12a 100644
Binary files a/docs/components/odt/en-US/widgets/Spinner (LVGL).odt and b/docs/components/odt/en-US/widgets/Spinner (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/Switch (Dashboard).odt b/docs/components/odt/en-US/widgets/Switch (Dashboard).odt
index ede26b65f..ac51aa833 100644
Binary files a/docs/components/odt/en-US/widgets/Switch (Dashboard).odt and b/docs/components/odt/en-US/widgets/Switch (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Switch (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Switch (EEZ-GUI).odt
index c35a4da91..271fac9e8 100644
Binary files a/docs/components/odt/en-US/widgets/Switch (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Switch (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/Switch (LVGL).odt b/docs/components/odt/en-US/widgets/Switch (LVGL).odt
index 3fd7c95d4..74013bb4d 100644
Binary files a/docs/components/odt/en-US/widgets/Switch (LVGL).odt and b/docs/components/odt/en-US/widgets/Switch (LVGL).odt differ
diff --git a/docs/components/odt/en-US/widgets/Tab.odt b/docs/components/odt/en-US/widgets/Tab.odt
index 0e682f953..521cf8561 100644
Binary files a/docs/components/odt/en-US/widgets/Tab.odt and b/docs/components/odt/en-US/widgets/Tab.odt differ
diff --git a/docs/components/odt/en-US/widgets/Table.odt b/docs/components/odt/en-US/widgets/Table.odt
index 0b8212153..f623fc6ad 100644
Binary files a/docs/components/odt/en-US/widgets/Table.odt and b/docs/components/odt/en-US/widgets/Table.odt differ
diff --git a/docs/components/odt/en-US/widgets/Tabulator.odt b/docs/components/odt/en-US/widgets/Tabulator.odt
index 61b4a58ec..3234bb406 100644
Binary files a/docs/components/odt/en-US/widgets/Tabulator.odt and b/docs/components/odt/en-US/widgets/Tabulator.odt differ
diff --git a/docs/components/odt/en-US/widgets/Tabview.odt b/docs/components/odt/en-US/widgets/Tabview.odt
index f2997b5d2..506599c20 100644
Binary files a/docs/components/odt/en-US/widgets/Tabview.odt and b/docs/components/odt/en-US/widgets/Tabview.odt differ
diff --git a/docs/components/odt/en-US/widgets/Terminal.odt b/docs/components/odt/en-US/widgets/Terminal.odt
index aff2c857f..b84b1d7e5 100644
Binary files a/docs/components/odt/en-US/widgets/Terminal.odt and b/docs/components/odt/en-US/widgets/Terminal.odt differ
diff --git a/docs/components/odt/en-US/widgets/Text (Dashboard).odt b/docs/components/odt/en-US/widgets/Text (Dashboard).odt
index 5f5e6b8d0..cd794faa0 100644
Binary files a/docs/components/odt/en-US/widgets/Text (Dashboard).odt and b/docs/components/odt/en-US/widgets/Text (Dashboard).odt differ
diff --git a/docs/components/odt/en-US/widgets/Text (EEZ-GUI).odt b/docs/components/odt/en-US/widgets/Text (EEZ-GUI).odt
index 82ddb2b8c..8c6c5ada7 100644
Binary files a/docs/components/odt/en-US/widgets/Text (EEZ-GUI).odt and b/docs/components/odt/en-US/widgets/Text (EEZ-GUI).odt differ
diff --git a/docs/components/odt/en-US/widgets/TextInput.odt b/docs/components/odt/en-US/widgets/TextInput.odt
index d116fee30..d8257f4c4 100644
Binary files a/docs/components/odt/en-US/widgets/TextInput.odt and b/docs/components/odt/en-US/widgets/TextInput.odt differ
diff --git a/docs/components/odt/en-US/widgets/Textarea.odt b/docs/components/odt/en-US/widgets/Textarea.odt
index 22272631f..3beea8106 100644
Binary files a/docs/components/odt/en-US/widgets/Textarea.odt and b/docs/components/odt/en-US/widgets/Textarea.odt differ
diff --git a/docs/components/odt/en-US/widgets/TileView.odt b/docs/components/odt/en-US/widgets/TileView.odt
index e58ef7f17..f849f5932 100644
Binary files a/docs/components/odt/en-US/widgets/TileView.odt and b/docs/components/odt/en-US/widgets/TileView.odt differ
diff --git a/docs/components/odt/en-US/widgets/ToggleButton.odt b/docs/components/odt/en-US/widgets/ToggleButton.odt
index 65935c736..e252b17cd 100644
Binary files a/docs/components/odt/en-US/widgets/ToggleButton.odt and b/docs/components/odt/en-US/widgets/ToggleButton.odt differ
diff --git a/docs/components/odt/en-US/widgets/UpDown.odt b/docs/components/odt/en-US/widgets/UpDown.odt
index 3ffc0c8b6..95f734473 100644
Binary files a/docs/components/odt/en-US/widgets/UpDown.odt and b/docs/components/odt/en-US/widgets/UpDown.odt differ
diff --git a/docs/components/odt/en-US/widgets/Window.odt b/docs/components/odt/en-US/widgets/Window.odt
index 7acc4681a..aa9dbd0d6 100644
Binary files a/docs/components/odt/en-US/widgets/Window.odt and b/docs/components/odt/en-US/widgets/Window.odt differ
diff --git a/help/en-US/components/actions/LVGL.md b/help/en-US/components/actions/LVGL.md
index c2bba721c..7c6688ee0 100644
--- a/help/en-US/components/actions/LVGL.md
+++ b/help/en-US/components/actions/LVGL.md
@@ -8,172 +8,172 @@ Performs one or more LVGL specific actions.
List of actions to be executed. The following actions are available:
-- **Change screen**: Change the screen to the specified screen
+- **Change Screen**: Change the screen to the specified screen
- *Screen*: The screen to change to
- *Fade mode*: Selection of animation when moving from the previous page to a new page
- *Speed*: Animation duration in milliseconds
- *Delay*: Delay in milliseconds before the animation starts.
-- **Change to previous screen**: Change to the previous screen
+- **Change to Previous Screen**: Change to the previous screen
- *Fade mode*: Selection of animation when moving from the previous page to a new page
- *Speed*: Animation duration in milliseconds
- *Delay*: Delay in milliseconds before the animation starts.
-- **Obj set x**: Set the x coordinate of the object
+- **Obj Set X**: Set the x coordinate of the object
- *Object*: The object to set the x coordinate
- *X*: The x coordinate to set
-- **Obj get x**: Get the x coordinate of the object
+- **Obj Get X**: Get the x coordinate of the object
- *Object*: The object to get the x coordinate
- *Store result into*: The variable to store the x coordinate
-- **Obj set y**: Set the y coordinate of the object
+- **Obj Set Y**: Set the y coordinate of the object
- *Object*: The object to set the y coordinate
- *Y*: The y coordinate to set
-- **Obj get y**: Get the y coordinate of the object
+- **Obj Get Y**: Get the y coordinate of the object
- *Object*: The object to get the y coordinate
- *Store result into*: The variable to store the y coordinate
-- **Obj set width**: Set the width of the object
+- **Obj Set Width**: Set the width of the object
- *Object*: The object to set the width
- *Width*: The width to set
-- **Obj get width**: Get the width of the object
+- **Obj Get Width**: Get the width of the object
- *Object*: The object to get the width
- *Store result into*: The variable to store the width
-- **Obj set height**: Set the height of the object
+- **Obj Set Height**: Set the height of the object
- *Object*: The object to set the height
- *Height*: The height to set
-- **Obj get height**: Get the height of the object
+- **Obj Get Height**: Get the height of the object
- *Object*: The object to get the height
- *Store result into*: The variable to store the height
-- **Obj set style opa**: Set the opacity of the object
+- **Obj Set Style Opa**: Set the opacity of the object
- *Object*: The object to set the opacity
- *Opacity*: The opacity to set (0-255)
-- **Obj get style opa**: Get the opacity of the object
+- **Obj Get Style Opa**: Get the opacity of the object
- *Object*: The object to get the opacity
- *Store result into*: The variable to store the opacity
-- **Obj add style**: Add a style to the object
+- **Obj Add Style**: Add a style to the object
- *Object*: The object to add the style
- *Style*: The style to add
-- **Obj remove style**: Remove a style from the object
+- **Obj Remove Style**: Remove a style from the object
- *Object*: The object to remove the style
- *Style*: The style to remove
-- **Obj set flag hidden**: Set the hidden flag of the object
+- **Obj Set Flag Hidden**: Set the hidden flag of the object
- *Object*: The object to set the hidden flag
- *Hidden*: The hidden flag value
-- **Obj add flag**: Add a flag to the object
+- **Obj Add Flag**: Add a flag to the object
- *Object*: The object to add the flag
- *Flag*: The flag to add
-- **Obj clear flag**: Clear a flag from the object
+- **Obj Clear Flag**: Clear a flag from the object
- *Object*: The object to clear the flag
- *Flag*: The flag to clear
-- **Obj has flag**: Check if the object has the specified flag
+- **Obj Has Flag**: Check if the object has the specified flag
- *Object*: The object to check the flag
- *Flag*: The flag to check
- *Store result into*: The variable to store the result
-- **Obj set state checked**: Set the checked state of the object
+- **Obj Set State Checked**: Set the checked state of the object
- *Object*: The object to set the checked state
- *Checked*: The checked state to set
-- **Obj set state disabled**: Set the disabled state of the object
+- **Obj Set State Disabled**: Set the disabled state of the object
- *Object*: The object to set the disabled state
- *Disabled*: The disabled state to set
-- **Obj add state**: Add a state to the object
+- **Obj Add State**: Add a state to the object
- *Object*: The object to add the state
- *State*: The state to add
-- **Obj clear state**: Clear a state from the object
+- **Obj Clear State**: Clear a state from the object
- *Object*: The object to clear the state
- *State*: The state to clear
-- **Obj has state**: Check if the object has the specified state
+- **Obj Has State**: Check if the object has the specified state
- *Object*: The object to check the state
- *State*: The state to check
- *Store result into*: The variable to store the result
-- **Arc set value**: Set the value of the arc
+- **Arc Set Value**: Set the value of the arc
- *Object*: The arc to set the value
- *Value*: The value to set
-- **Bar set value**: Set the value of the bar
+- **Bar Set Value**: Set the value of the bar
- *Object*: The bar to set the value
- *Value*: The value to set (0-100)
- *Animated*: Use animation when setting the value
-- **Dropdown set selected**: Set the selected item of the dropdown
+- **Dropdown Set Selected**: Set the selected item of the dropdown
- *Object*: The dropdown to set the selected item
- *Selected*: The index of the selected item
-- **Image set src**: Set the source image of the image
+- **Image Set Src**: Set the source image of the image
- *Object*: The image to set the source
- *Src*: The source image to set given as a string
-- **Image set angle**: Set the angle of the image
+- **Image Set Angle**: Set the angle of the image
- *Object*: The image to set the angle
- *Angle*: The angle to set. Angle has 0.1 degree precision, so for 45.8° set 458.
-- **Image set zoom**: Set the zoom of the image
+- **Image Set Zoom**: Set the zoom of the image
- *Object*: The image to set the zoom
- *Zoom*: The zoom to set. Set factor to 256 to disable zooming. A larger value enlarges the images (e.g. 512 double size), a smaller value shrinks it (e.g. 128 half size).
-- **Label set text**: Set the text of the label
+- **Label Set Text**: Set the text of the label
- *Object*: The label to set the text
- *Text*: The text to set
-- **Roller set selected**: Set the selected item of the roller
+- **Roller Set Selected**: Set the selected item of the roller
- *Object*: The roller to set the selected item
- *Selected*: The index of the selected item
- *Animated*: Use animation when setting the selected item
-- **Slider set value**: Set the value of the slider
+- **Slider Set Value**: Set the value of the slider
- *Object*: The slider to set the value
- *Value*: The value to set
- *Animated*: Use animation when setting the value
-- **Keyboard set textarea**: Set the textarea for the keyboard
+- **Keyboard Set Textarea**: Set the textarea for the keyboard
- *Object*: The keyboard to set the textarea
- *Textarea*: The textarea to set
-- **Group focus obj**: Focus the object
+- **Group Focus Obj**: Focus the object
- *Object*: The object to focus
-- **Group focus next**: Focus the next object in the group
+- **Group Focus Next**: Focus the next object in the group
- *Group*: The group to focus the next object
-- **Group focus prev**: Focus the previous object in the group
+- **Group Focus Prev**: Focus the previous object in the group
- *Group*: The group to focus the previous object
-- **Group get focused**: Get the focused object in the group
+- **Group Get Focused**: Get the focused object in the group
- *Group*: The group to get the focused object
- *Store result into*: The variable to store the focused object
-- **Group focus freeze**: Do not let to change the focus from the current object
+- **Group Focus Freeze**: Do not let to change the focus from the current object
- *Group*: The group to freeze/unfreeze the focus
- *Enabled*: true: freeze, false: release freezing (normal mode)
-- **Group set wrap**: Set whether focus next/prev will allow wrapping from first->last or last->first object.
+- **Group Set Wrap**: Set whether focus next/prev will allow wrapping from first->last or last->first object.
- *Group*: The group to set the wrap
- *Enabled*: true: wrap, false: no wrap
-- **Group set editing**: Manually set the current mode (edit or navigate).
+- **Group Set Editing**: Manually set the current mode (edit or navigate).
- *Group*: The group to set the editing mode
- *Enabled*: true: edit mode, false: navigate mode
-- **Anim x**: Animate the x coordinate of the object
+- **Anim X**: Animate the x coordinate of the object
- *Object*: The object to animate
- *Start*: The start value of the animation
- *End*: The end value of the animation
@@ -183,7 +183,7 @@ List of actions to be executed. The following actions are available:
- *Instant*: If checked apply the start value immediately, otherwise apply the start value after a delay when the animation really starts
- *Path*: The animation path
-- **Anim y**: Animate the y coordinate of the object
+- **Anim Y**: Animate the y coordinate of the object
- *Object*: The object to animate
- *Start*: The start value of the animation
- *End*: The end value of the animation
@@ -193,7 +193,7 @@ List of actions to be executed. The following actions are available:
- *Instant*: If checked apply the start value immediately, otherwise apply the start value after a delay when the animation really starts
- *Path*: The animation path
-- **Anim width**: Animate the width of the object
+- **Anim Width**: Animate the width of the object
- *Object*: The object to animate
- *Start*: The start value of the animation
- *End*: The end value of the animation
@@ -203,7 +203,7 @@ List of actions to be executed. The following actions are available:
- *Instant*: If checked apply the start value immediately, otherwise apply the start value after a delay when the animation really starts
- *Path*: The animation path
-- **Anim height**: Animate the height of the object
+- **Anim Height**: Animate the height of the object
- *Object*: The object to animate
- *Start*: The start value of the animation
- *End*: The end value of the animation
@@ -213,7 +213,7 @@ List of actions to be executed. The following actions are available:
- *Instant*: If checked apply the start value immediately, otherwise apply the start value after a delay when the animation really starts
- *Path*: The animation path
-- **Anim opacity**: Animate the opacity of the object
+- **Anim Opacity**: Animate the opacity of the object
- *Object*: The object to animate
- *Start*: The start value of the animation
- *End*: The end value of the animation
@@ -223,7 +223,7 @@ List of actions to be executed. The following actions are available:
- *Instant*: If checked apply the start value immediately, otherwise apply the start value after a delay when the animation really starts
- *Path*: The animation path
-- **Anim image zoom**: Animate the zoom of the image
+- **Anim Image Zoom**: Animate the zoom of the image
- *Object*: The object to animate
- *Start*: The start value of the animation
- *End*: The end value of the animation
@@ -233,7 +233,7 @@ List of actions to be executed. The following actions are available:
- *Instant*: If checked apply the start value immediately, otherwise apply the start value after a delay when the animation really starts
- *Path*: The animation path
-- **Anim image angle**: Animate the angle of the image
+- **Anim Image Angle**: Animate the angle of the image
- *Object*: The object to animate
- *Start*: The start value of the animation
- *End*: The end value of the animation
diff --git a/packages/eez-studio-ui/_stylesheets/project-editor.less b/packages/eez-studio-ui/_stylesheets/project-editor.less
index ac8f20171..c8a92202b 100644
--- a/packages/eez-studio-ui/_stylesheets/project-editor.less
+++ b/packages/eez-studio-ui/_stylesheets/project-editor.less
@@ -3623,3 +3623,23 @@
}
}
}
+
+.EezStudio_NewLVGLActionDialog {
+ .EezStudio_SearchInput_Container {
+ border: 1px solid @borderColor;
+ border-bottom: none;
+ }
+ .EezStudio_ListContainer {
+ min-height: 50px;
+ max-height: 480px;
+
+ .EezStudio_List {
+ padding: 5px;
+
+ > div.EezStudio_Selected {
+ background-color: @selectionBackgroundColor;
+ color: @selectionColor;
+ }
+ }
+ }
+}
diff --git a/packages/project-editor/lvgl/actions.tsx b/packages/project-editor/lvgl/actions.tsx
index 682d91d0a..3a36943cd 100644
--- a/packages/project-editor/lvgl/actions.tsx
+++ b/packages/project-editor/lvgl/actions.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { makeObservable, observable } from "mobx";
+import { computed, makeObservable, observable, runInAction } from "mobx";
import {
registerClass,
@@ -50,7 +50,6 @@ import {
} from "project-editor/project/project";
import { Assets, DataBuffer } from "project-editor/build/assets";
import { ProjectEditor } from "project-editor/project-editor-interface";
-import { showGenericDialog } from "eez-studio-ui/generic-dialog";
import { makeLvglExpressionProperty } from "project-editor/lvgl/expression-property";
import {
buildAssignableExpression,
@@ -58,3246 +57,3491 @@ import {
} from "project-editor/flow/expression";
import { escapeCString } from "./widget-common";
import { makeEndInstruction } from "project-editor/flow/expression/instructions";
-
-/*
+import { RightArrow } from "project-editor/ui-components/icons";
+import { Dialog, showDialog } from "eez-studio-ui/dialog";
+import { observer } from "mobx-react";
+import { SearchInput } from "eez-studio-ui/search-input";
+import { IListNode, List, ListContainer, ListItem } from "eez-studio-ui/list";
////////////////////////////////////////////////////////////////////////////////
-const LVGL_ACTIONS = {
- CHANGE_SCREEN: 0,
- PLAY_ANIMATION: 1,
- SET_PROPERTY: 2,
- ADD_STYLE: 3,
- REMOVE_STYLE: 4,
- ADD_FLAG: 5,
- CLEAR_FLAG: 6,
- ADD_STATE: 8,
- CLEAR_STATE: 9,
- GROUP: 7
-};
-
-////////////////////////////////////////////////////////////////////////////////
+type LvglActionPropertyType =
+ | "boolean"
+ | "integer"
+ | "string"
+ | `enum:${string}`
+ | "screen"
+ | "widget"
+ | `widget:${string}`
+ | "group"
+ | "style"
+ | "image";
-export class LVGLActionType extends EezObject {
- action: keyof typeof LVGL_ACTIONS;
+export interface IActionPropertyDefinition {
+ name: string;
+ type: LvglActionPropertyType;
+ isAssignable?: boolean;
+ helpText: string;
+}
- static classInfo: ClassInfo = {
- getClass: function (projectStore: ProjectStore, jsObject: any) {
- if (jsObject.action == "CHANGE_SCREEN")
- return LVGLChangeScreenActionType;
- else if (jsObject.action == "PLAY_ANIMATION")
- return LVGLPlayAnimationActionType;
- else if (jsObject.action == "SET_PROPERTY")
- return LVGLSetPropertyActionType;
- else if (jsObject.action == "ADD_STYLE")
- return LVGLAddStyleActionType;
- else if (jsObject.action == "REMOVE_STYLE")
- return LVGLRemoveStyleActionType;
- else if (jsObject.action == "ADD_FLAG")
- return LVGLAddFlagActionType;
- else if (jsObject.action == "CLEAR_FLAG")
- return LVGLClearFlagActionType;
- else if (jsObject.action == "ADD_STATE")
- return LVGLAddStateActionType;
- else if (jsObject.action == "CLEAR_STATE")
- return LVGLClearStateActionType;
- else return LVGLGroupActionType;
- },
+function getValueTypeFromActionPropertyType(
+ actionPropertyType: LvglActionPropertyType
+): ValueType {
+ if (actionPropertyType == "screen") {
+ return "integer";
+ }
- properties: [
- {
- name: "action",
- displayName: (object: LVGLActionType) => {
- const actions = getParent(object) as LVGLActionType[];
- if (actions.length < 2) {
- return "Action";
- }
- return `Action #${actions.indexOf(object) + 1}`;
- },
- type: PropertyType.Enum,
- enumItems: Object.keys(LVGL_ACTIONS).map(id => ({
- id
- })),
- enumDisallowUndefined: true,
- hideInPropertyGrid: true
- }
- ],
+ if (actionPropertyType.startsWith("widget:")) {
+ return "widget";
+ }
- newItem: async (object: LVGLActionType[]) => {
- const project = ProjectEditor.getProject(object);
+ if (actionPropertyType == "group") {
+ return "integer";
+ }
- const result = await showGenericDialog({
- dialogDefinition: {
- title: "New LVGL Action",
- fields: [
- {
- name: "action",
- displayName: "Action type",
- type: "enum",
- enumItems: Object.keys(LVGL_ACTIONS).map(id => ({
- id,
- label: humanize(id)
- }))
- }
- ]
- },
- values: {
- action: "CHANGE_SCREEN"
- },
- dialogContext: project
- });
+ if (actionPropertyType == "style") {
+ return "integer";
+ }
- const actionTypeProperties = {
- action: result.values.action
- };
+ if (actionPropertyType == "image") {
+ return "string";
+ }
- let actionTypeObject;
+ return actionPropertyType as ValueType;
+}
- if (result.values.action == "CHANGE_SCREEN") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLChangeScreenActionType.classInfo.defaultValue
- ),
- LVGLChangeScreenActionType
- );
- } else if (result.values.action == "PLAY_ANIMATION") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLPlayAnimationActionType.classInfo.defaultValue
- ),
- LVGLPlayAnimationActionType
- );
- } else if (result.values.action == "SET_PROPERTY") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLSetPropertyActionType.classInfo.defaultValue
- ),
- LVGLSetPropertyActionType
- );
- } else if (result.values.action == "ADD_STYLE") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLAddStyleActionType.classInfo.defaultValue
- ),
- LVGLAddStyleActionType
- );
- } else if (result.values.action == "REMOVE_STYLE") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLRemoveStyleActionType.classInfo.defaultValue
- ),
- LVGLRemoveStyleActionType
- );
- } else if (result.values.action == "ADD_FLAG") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLAddFlagActionType.classInfo.defaultValue
- ),
- LVGLAddFlagActionType
- );
- } else if (result.values.action == "CLEAR_FLAG") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLClearFlagActionType.classInfo.defaultValue
- ),
- LVGLClearFlagActionType
- );
- } else if (result.values.action == "ADD_STATE") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLAddStateActionType.classInfo.defaultValue
- ),
- LVGLAddStateActionType
- );
- } else if (result.values.action == "CLEAR_STATE") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLClearStateActionType.classInfo.defaultValue
- ),
- LVGLClearStateActionType
- );
- } else if (result.values.action == "GROUP") {
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
- LVGLGroupActionType.classInfo.defaultValue
- ),
- LVGLGroupActionType
- );
- }
+////////////////////////////////////////////////////////////////////////////////
- return actionTypeObject;
- }
- };
+export interface IActionDefinition {
+ name: string;
+ properties: IActionPropertyDefinition[];
+ defaults: any;
+ label?: (
+ propertyValues: string[],
+ propertyNames: string[]
+ ) => React.ReactNode;
+ helpText: string;
+}
- override makeEditable() {
- super.makeEditable();
+export const actionDefinitions: IActionDefinition[] = [];
+const actionClasses = new Map();
+const actionNameToActionId = new Map();
- makeObservable(this, {
- action: observable
- });
- }
+let nextActionId = 0;
- build(assets: Assets, dataBuffer: DataBuffer) {}
+function getActionDisplayName(actionDefinition: IActionDefinition) {
+ return humanize(actionDefinition.name)
+ .split(" ")
+ .map(word =>
+ word == "to" ? word : word[0].toUpperCase() + word.substring(1)
+ )
+ .join(" ");
}
-////////////////////////////////////////////////////////////////////////////////
+export function registerAction(actionDefinition: IActionDefinition) {
+ actionDefinitions.push(actionDefinition);
-const FADE_MODES = {
- NONE: 0,
- OVER_LEFT: 1,
- OVER_RIGHT: 2,
- OVER_TOP: 3,
- OVER_BOTTOM: 4,
- MOVE_LEFT: 5,
- MOVE_RIGHT: 6,
- MOVE_TOP: 7,
- MOVE_BOTTOM: 8,
- FADE_IN: 9,
- FADE_OUT: 10,
- OUT_LEFT: 11,
- OUT_RIGHT: 12,
- OUT_TOP: 13,
- OUT_BOTTOM: 14
-};
-
-export class LVGLChangeScreenActionType extends LVGLActionType {
- showPreviousScreen: boolean;
- screen: string;
- fadeMode: keyof typeof FADE_MODES;
- speed: number;
- delay: number;
-
- override makeEditable() {
- super.makeEditable();
+ actionNameToActionId.set(actionDefinition.name, nextActionId++);
- makeObservable(this, {
- showPreviousScreen: observable,
- screen: observable,
- fadeMode: observable,
- speed: observable,
- delay: observable
- });
- }
+ const properties: PropertyInfo[] = [];
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "showPreviousScreen",
- displayName: "Previous screen",
- type: PropertyType.Boolean,
- checkboxStyleSwitch: true
- },
- {
- name: "screen",
- type: PropertyType.ObjectReference,
- referencedObjectCollectionPath: "userPages",
- disabled: (action: LVGLChangeScreenActionType) =>
- action.showPreviousScreen
- },
- {
- name: "fadeMode",
- type: PropertyType.Enum,
- enumItems: Object.keys(FADE_MODES).map(id => ({
- id
- })),
- enumDisallowUndefined: true
- },
- {
- name: "speed",
- displayName: "Speed (ms)",
- type: PropertyType.Number
- },
- {
- name: "delay",
- displayName: "Delay (ms)",
- type: PropertyType.Number
- }
- ],
- defaultValue: {
- fadeMode: "FADE_IN",
- showPreviousScreen: false,
- speed: 200,
- delay: 0
- },
- listLabel: (action: LVGLChangeScreenActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Change screen";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- return `${singleItem ? "" : "Change screen: "}${
- action.showPreviousScreen
- ? "Previous Screen"
- : `Screen=${action.screen}`
- }, Speed=${action.speed} ms, Delay=${action.delay} ms`;
- },
- check: (object: LVGLChangeScreenActionType, messages: IMessage[]) => {
- if (!object.showPreviousScreen) {
- if (!object.screen) {
- messages.push(propertyNotSetMessage(object, "screen"));
- } else {
- let page = findPage(getProject(object), object.screen);
- if (!page) {
- messages.push(
- propertyNotFoundMessage(object, "screen")
- );
- }
- }
- }
- }
- });
+ for (const actionProperty of actionDefinition.properties) {
+ const expressionType = getValueTypeFromActionPropertyType(
+ actionProperty.type
+ );
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // screen
- let screen: number;
- if (this.showPreviousScreen) {
- screen = -1;
+ if (actionProperty.isAssignable) {
+ properties.push(
+ makeAssignableExpressionProperty(
+ {
+ name: actionProperty.name,
+ displayName: `Store ${actionProperty.name} into`,
+ type: PropertyType.MultilineText
+ },
+ expressionType
+ )
+ );
} else {
- if (this.screen) {
- screen = assets.getPageIndex(this, "screen");
- } else {
- screen = 0;
- }
- }
- dataBuffer.writeInt32(screen);
-
- // fadeMode
- dataBuffer.writeUint32(FADE_MODES[this.fadeMode]);
-
- // speed
- dataBuffer.writeUint32(this.speed);
+ let enumItems:
+ | ((actionType: LVGLActionType) => EnumItem[])
+ | undefined;
+ let enumDisallowUndefined = true;
- // delay
- dataBuffer.writeUint32(this.delay);
- }
-}
+ let referencedObjectCollectionPath: string | undefined;
-registerClass("LVGLChangeScreenActionType", LVGLChangeScreenActionType);
+ if (actionProperty.type.startsWith("enum:")) {
+ enumItems = (actionType: LVGLActionType) => {
+ let enumItems = [];
-////////////////////////////////////////////////////////////////////////////////
+ const enumType = getEnumFromType(
+ ProjectEditor.getProject(actionType),
+ actionProperty.type
+ );
+ if (enumType) {
+ for (const member of enumType.members) {
+ enumItems.push({
+ id: member.name,
+ label: member.name
+ });
+ }
+ }
-const ANIM_PROPERTIES = {
- POSITION_X: 0,
- POSITION_Y: 1,
- WIDTH: 2,
- HEIGHT: 3,
- OPACITY: 4,
- IMAGE_ZOOM: 5,
- IMAGE_ANGLE: 6
-};
+ return enumItems;
+ };
+ } else if (actionProperty.type == "screen") {
+ referencedObjectCollectionPath = "userPages";
+ } else if (actionProperty.type.startsWith("widget")) {
+ enumItems = (actionType: LVGLActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
-const ANIM_PATHS = {
- LINEAR: 0,
- EASE_IN: 1,
- EASE_OUT: 2,
- EASE_IN_OUT: 3,
- OVERSHOOT: 4,
- BOUNCE: 5
-};
+ const widgetType = actionProperty.type.slice(
+ "widget:".length
+ );
-export class LVGLPlayAnimationActionType extends LVGLActionType {
- target: string;
- property: keyof typeof ANIM_PROPERTIES;
- start: number;
- end: number;
- delay: number;
- time: number;
- relative: boolean;
- instant: boolean;
- path: keyof typeof ANIM_PATHS;
+ return lvglIdentifiers
+ .filter(lvglIdentifier => {
+ if (!widgetType) {
+ return (
+ lvglIdentifier.object instanceof
+ ProjectEditor.LVGLWidgetClass
+ );
+ } else {
+ const lvglWidgetClassName = `LVGL${widgetType}Widget`;
- override makeEditable() {
- super.makeEditable();
+ const projectStore =
+ ProjectEditor.getProjectStore(actionType);
- makeObservable(this, {
- target: observable,
- property: observable,
- start: observable,
- end: observable,
- delay: observable,
- time: observable,
- relative: observable,
- instant: observable,
- path: observable
- });
- }
+ const lvglWidgetClass = getClassByName(
+ projectStore,
+ lvglWidgetClassName
+ )!;
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "target",
- type: PropertyType.Enum,
- enumItems: (component: LVGLActionComponent) => {
- return ProjectEditor.getProjectStore(component)
- .lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(component)
- )
+ return (
+ lvglIdentifier.object instanceof
+ lvglWidgetClass
+ );
+ }
+ })
.map(lvglIdentifier => ({
id: lvglIdentifier.identifier,
- label: lvglIdentifier.displayName
+ label: lvglIdentifier.identifier
}));
- }
- },
- {
- name: "property",
- type: PropertyType.Enum,
- enumItems: Object.keys(ANIM_PROPERTIES).map(id => ({ id })),
- enumDisallowUndefined: true
- },
- {
- name: "start",
- type: PropertyType.Number
- },
- {
- name: "end",
- type: PropertyType.Number
- },
- {
- name: "delay",
- displayName: "Delay (ms)",
- type: PropertyType.Number
- },
- {
- name: "time",
- displayName: "Time (ms)",
- type: PropertyType.Number
- },
- {
- name: "relative",
- type: PropertyType.Boolean,
- checkboxStyleSwitch: true
- },
- {
- name: "instant",
- type: PropertyType.Boolean,
- checkboxStyleSwitch: true
- },
- {
- name: "path",
- type: PropertyType.Enum,
- enumItems: Object.keys(ANIM_PATHS).map(id => ({ id })),
- enumDisallowUndefined: true
- }
- ],
- defaultValue: {
- property: "POSITION_X",
- start: 0,
- end: 100,
- delay: 0,
- time: 1000,
- relative: true,
- instant: false,
- path: ""
- },
- listLabel: (
- action: LVGLPlayAnimationActionType,
- collapsed: boolean
- ) => {
- if (!collapsed) {
- return "Play animation";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- return `${singleItem ? "" : "Play animation: "}Target=${
- action.target
- }, Property=${action.property}, Start=${action.start}, End=${
- action.end
- }, Delay=${action.delay} ms, Time=${action.time} ms, Relative=${
- action.relative ? "On" : "Off"
- }, Instant=${action.instant ? "On" : "Off"} ${action.path}`;
- },
- check: (object: LVGLPlayAnimationActionType, messages: IMessage[]) => {
- if (!object.target) {
- messages.push(propertyNotSetMessage(object, "target"));
- } else {
- if (
- ProjectEditor.getProjectStore(
- object
- ).lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- ) == undefined
- ) {
- messages.push(propertyNotFoundMessage(object, "target"));
- }
+ };
+ referencedObjectCollectionPath = "";
+ } else if (actionProperty.type == "style") {
+ referencedObjectCollectionPath = "allLvglStyles";
+ } else if (actionProperty.type == "image") {
+ referencedObjectCollectionPath = "bitmaps";
+ } else if (actionProperty.type == "group") {
+ referencedObjectCollectionPath = "lvglGroups/groups";
}
- }
- });
-
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
-
- // property
- dataBuffer.writeUint32(ANIM_PROPERTIES[this.property]);
-
- // start
- dataBuffer.writeInt32(this.start);
-
- // end
- dataBuffer.writeInt32(this.end);
- // delay
- dataBuffer.writeUint32(this.delay);
+ const lvglExpressionProperty = makeLvglExpressionProperty(
+ actionProperty.name,
+ expressionType,
+ "input",
+ ["literal", "expression"],
+ {
+ dynamicType: () => {
+ if (referencedObjectCollectionPath != undefined) {
+ return PropertyType.ObjectReference;
+ }
- // time
- dataBuffer.writeUint32(this.time);
+ if (enumItems != undefined) {
+ return PropertyType.Enum;
+ }
- // flags
- const ANIMATION_ITEM_FLAG_RELATIVE = 1 << 0;
- const ANIMATION_ITEM_FLAG_INSTANT = 1 << 1;
- dataBuffer.writeUint32(
- (this.relative ? ANIMATION_ITEM_FLAG_RELATIVE : 0) |
- (this.instant ? ANIMATION_ITEM_FLAG_INSTANT : 0)
- );
+ return expressionType == "integer" ||
+ expressionType == "float" ||
+ expressionType == "double"
+ ? PropertyType.Number
+ : expressionType == "boolean"
+ ? PropertyType.Boolean
+ : PropertyType.MultilineText;
+ },
+ enumItems,
+ enumDisallowUndefined,
+ checkboxStyleSwitch: true,
+ referencedObjectCollectionPath,
+ lvglActionPropertyType: actionProperty.type
+ }
+ );
- // path
- dataBuffer.writeUint32(ANIM_PATHS[this.path]);
+ properties.push(...lvglExpressionProperty);
+ }
}
-}
-
-registerClass("LVGLPlayAnimationActionType", LVGLPlayAnimationActionType);
-
-////////////////////////////////////////////////////////////////////////////////
-const enum PropertyCode {
- NONE,
+ const defaultValue = Object.assign({}, actionDefinition.defaults);
- ARC_VALUE,
+ actionDefinition.properties.forEach(propertyDefinition => {
+ if (!propertyDefinition.isAssignable) {
+ defaultValue[propertyDefinition.name + "Type"] = "literal";
+ }
+ });
- BAR_VALUE,
+ const actionDisplayName = getActionDisplayName(actionDefinition);
- BASIC_X,
- BASIC_Y,
- BASIC_WIDTH,
- BASIC_HEIGHT,
- BASIC_OPACITY,
- BASIC_HIDDEN,
- BASIC_CHECKED,
- BASIC_DISABLED,
+ const actionClass = class extends LVGLActionType {
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties,
+ label: () => actionDisplayName,
+ defaultValue,
+ listLabel: (action: LVGLActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return actionDisplayName;
+ }
- DROPDOWN_SELECTED,
+ const propertyNames = actionDefinition.properties.map(
+ actionProperty => humanize(actionProperty.name)
+ );
+ const propertyValues = actionDefinition.properties.map(
+ actionProperty => {
+ let value = (action as any)[actionProperty.name];
- IMAGE_IMAGE,
- IMAGE_ANGLE,
- IMAGE_ZOOM,
+ if (typeof value == "boolean") {
+ value = value ? "ON" : "OFF";
+ } else if (
+ actionProperty.isAssignable ||
+ (action as any)[actionProperty.name + "Type"] ==
+ "expression"
+ ) {
+ value = `{${value}}`;
+ }
- LABEL_TEXT,
+ return value;
+ }
+ );
- ROLLER_SELECTED,
+ let propertiesDescription: React.ReactNode;
+ if (actionDefinition.label) {
+ propertiesDescription = actionDefinition.label(
+ propertyValues,
+ propertyNames
+ );
+ } else {
+ propertiesDescription = actionDefinition.properties.map(
+ (actionProperty, i) => {
+ return (
+ <>
+ {propertyNames[i]}
+ {actionProperty.isAssignable ? (
+
+ ) : (
+ "="
+ )}
+ {propertyValues[i]}
+ {i <
+ actionDefinition.properties.length -
+ 1 && ", "}
+ >
+ );
+ }
+ );
+ }
- SLIDER_VALUE,
+ return (
+ <>
+ {actionDisplayName}
+ {propertiesDescription}
+ >
+ );
+ },
- KEYBOARD_TEXTAREA
-}
+ updateObjectValueHook(object, values) {
+ const projectStore = ProjectEditor.getProjectStore(object);
-type PropertiesType = {
- [targetType: string]: {
- [propName: string]: {
- code: PropertyCode;
- type: "number" | "string" | "boolean" | "image" | "textarea";
- animated: boolean;
- };
- };
-};
+ for (const key of Object.keys(values)) {
+ if (key.endsWith("Type")) {
+ const propertyName = key.slice(0, -"Type".length);
+ const propertyDefinition =
+ actionDefinition.properties.find(
+ propertyDefinition =>
+ propertyDefinition.name == propertyName
+ );
+ if (propertyDefinition) {
+ if (propertyDefinition.type.startsWith("enum:")) {
+ const enumName = propertyDefinition.type.slice(
+ "enum:".length
+ );
-const PROPERTIES = {
- arc: {
- value: {
- code: PropertyCode.ARC_VALUE,
- type: "number" as const,
- animated: false
- }
- },
- bar: {
- value: {
- code: PropertyCode.BAR_VALUE,
- type: "number" as const,
- animated: true
- }
- },
- basic: {
- x: {
- code: PropertyCode.BASIC_X,
- type: "number" as const,
- animated: false
- },
- y: {
- code: PropertyCode.BASIC_Y,
- type: "number" as const,
- animated: false
- },
- width: {
- code: PropertyCode.BASIC_WIDTH,
- type: "number" as const,
- animated: false
- },
- height: {
- code: PropertyCode.BASIC_HEIGHT,
- type: "number" as const,
- animated: false
- },
- opacity: {
- code: PropertyCode.BASIC_OPACITY,
- type: "number" as const,
- animated: false
- },
- hidden: {
- code: PropertyCode.BASIC_HIDDEN,
- type: "boolean" as const,
- animated: false
- },
- checked: {
- code: PropertyCode.BASIC_CHECKED,
- type: "boolean" as const,
- animated: false
- },
- disabled: {
- code: PropertyCode.BASIC_DISABLED,
- type: "boolean" as const,
- animated: false
- }
- },
- dropdown: {
- selected: {
- code: PropertyCode.DROPDOWN_SELECTED,
- type: "number" as const,
- animated: false
- }
- },
- image: {
- image: {
- code: PropertyCode.IMAGE_IMAGE,
- type: "image" as const,
- animated: false
- },
- angle: {
- code: PropertyCode.IMAGE_ANGLE,
- type: "number" as const,
- animated: false
- },
- zoom: {
- code: PropertyCode.IMAGE_ZOOM,
- type: "number" as const,
- animated: false
- }
- },
- label: {
- text: {
- code: PropertyCode.LABEL_TEXT,
- type: "string" as const,
- animated: false
- }
- },
- roller: {
- selected: {
- code: PropertyCode.ROLLER_SELECTED,
- type: "number" as const,
- animated: true
- }
- },
- slider: {
- value: {
- code: PropertyCode.SLIDER_VALUE,
- type: "number" as const,
- animated: true
- }
- },
- keyboard: {
- textarea: {
- code: PropertyCode.KEYBOARD_TEXTAREA,
- type: "textarea" as const,
- animated: false
- }
- }
-};
+ if (
+ values[key] == "expression" &&
+ (object as any)[key] == "literal"
+ ) {
+ projectStore.updateObject(object, {
+ [propertyName]: `${enumName}.${
+ (object as any)[propertyName]
+ }`
+ });
+ } else if (
+ values[key] == "literal" &&
+ (object as any)[key] == "expression"
+ ) {
+ if (
+ (object as any)[
+ propertyName
+ ].startsWith(enumName + ".")
+ ) {
+ let value = (object as any)[
+ propertyName
+ ].slice((enumName + ".").length);
-function filterSetPropertyTarget(
- actionType: LVGLSetPropertyActionType,
- object: Page | LVGLWidget
-) {
- if (actionType.targetType == "arc") {
- return object instanceof LVGLArcWidget;
- } else if (actionType.targetType == "bar") {
- return object instanceof LVGLBarWidget;
- } else if (actionType.targetType == "basic") {
- return true;
- } else if (actionType.targetType == "dropdown") {
- return object instanceof LVGLDropdownWidget;
- } else if (actionType.targetType == "image") {
- return object instanceof LVGLImageWidget;
- } else if (actionType.targetType == "label") {
- return object instanceof LVGLLabelWidget;
- } else if (actionType.targetType == "roller") {
- return object instanceof LVGLRollerWidget;
- } else if (actionType.targetType == "slider") {
- return object instanceof LVGLSliderWidget;
- } else if (actionType.targetType == "keyboard") {
- return object instanceof LVGLKeyboardWidget;
- } else {
- return false;
- }
-}
+ const enumType = getEnumFromType(
+ projectStore.project,
+ `enum:${enumName}`
+ );
+ if (enumType) {
+ if (
+ !enumType.members.find(
+ member =>
+ member.name == value
+ )
+ ) {
+ value =
+ enumType.members[0].name;
+ }
+ } else {
+ value = "";
+ }
-export class LVGLSetPropertyActionType extends LVGLActionType {
- targetType: keyof typeof PROPERTIES;
- target: string;
- property: string;
- animated: boolean;
- value: number | string | boolean;
- valueType: LVGLPropertyType;
- textarea: string;
+ projectStore.updateObject(object, {
+ [propertyName]: value
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+ },
- override makeEditable() {
- super.makeEditable();
+ check: (object: LVGLActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
+ const component = getAncestorOfType(
+ object,
+ LVGLActionComponent.classInfo
+ );
+ if (component) {
+ for (const propertyInfo of properties) {
+ if (propertyInfo.expressionType == undefined) {
+ continue;
+ }
- makeObservable(this, {
- targetType: observable,
- target: observable,
- property: observable,
- animated: observable,
- value: observable,
- valueType: observable,
- textarea: observable
- });
- }
+ if (
+ (object as any)[propertyInfo.name + "Type"] ==
+ "expression" ||
+ isFlowProperty(object, propertyInfo, ["assignable"])
+ ) {
+ ProjectEditor.checkProperty(
+ projectStore,
+ component,
+ messages,
+ object,
+ propertyInfo
+ );
+ } else {
+ const project = ProjectEditor.getProject(object);
+ const value = (object as any)[propertyInfo.name];
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "targetType",
- type: PropertyType.Enum,
- enumItems: Object.keys(PROPERTIES).map(id => ({
- id
- })),
- enumDisallowUndefined: true
- },
- {
- name: "target",
- displayName: "Target",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLSetPropertyActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
+ if (
+ propertyInfo.lvglActionPropertyType == "screen"
+ ) {
+ if (!value) {
+ messages.push(
+ propertyNotSetMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ } else {
+ let page = findPage(project, value);
+ if (!page) {
+ messages.push(
+ propertyNotFoundMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ }
+ } else if (
+ propertyInfo.lvglActionPropertyType?.startsWith(
+ "widget"
+ )
+ ) {
+ if (!value) {
+ messages.push(
+ propertyNotSetMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ } else {
+ const lvglIdentifier =
+ ProjectEditor.getProjectStore(
+ object
+ ).lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ value
+ );
- return lvglIdentifiers
- .filter(lvglIdentifier =>
- filterSetPropertyTarget(
- actionType,
- lvglIdentifier.object
- )
- )
- .map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- }
- },
- {
- name: "property",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLSetPropertyActionType) => {
- return Object.keys(PROPERTIES[actionType.targetType]).map(
- id => ({
- id
- })
- );
- },
- enumDisallowUndefined: true
- },
- ...makeLvglExpressionProperty(
- "value",
- "any",
- "input",
- ["literal", "expression"],
- {
- dynamicType: (actionType: LVGLSetPropertyActionType) => {
- const type = actionType.propertyInfo.type;
- return type == "image"
- ? PropertyType.ObjectReference
- : type == "number"
- ? PropertyType.Number
- : type == "boolean"
- ? PropertyType.Boolean
- : PropertyType.MultilineText;
- },
- checkboxStyleSwitch: true,
- dynamicTypeReferencedObjectCollectionPath: (
- actionType: LVGLSetPropertyActionType
- ) => {
- const type = actionType.propertyInfo.type;
- return type == "image" ? "bitmaps" : undefined;
- },
- displayName: (actionType: LVGLSetPropertyActionType) => {
- if (actionType.propertyInfo.type == "image") {
- return "Image";
- }
- return "Value";
- },
- disabled: (actionType: LVGLSetPropertyActionType) =>
- actionType.propertyInfo.type == "textarea"
- }
- ),
- {
- name: "textarea",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLSetPropertyActionType) => {
- const page = getAncestorOfType(
- actionType,
- ProjectEditor.PageClass.classInfo
- ) as Page;
- return page._lvglWidgets
- .filter(
- lvglWidget =>
- lvglWidget instanceof LVGLTextareaWidget &&
- lvglWidget.identifier
- )
- .map(lvglWidget => ({
- id: lvglWidget.identifier,
- label: lvglWidget.identifier
- }));
- },
- disabled: (actionType: LVGLSetPropertyActionType) =>
- actionType.propertyInfo.type != "textarea"
- },
- {
- name: "animated",
- type: PropertyType.Boolean,
- checkboxStyleSwitch: true,
- disabled: (actionType: LVGLSetPropertyActionType) =>
- !actionType.propertyInfo.animated
- }
- ],
- defaultValue: {
- targetType: "bar",
- property: "value",
- animated: false,
- valueType: "literal"
- },
- listLabel: (action: LVGLSetPropertyActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Set property";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- return (
- <>
- {`${singleItem ? "" : "Set property: "}${action.target}.${
- action.propertyInfo.code != PropertyCode.NONE
- ? humanize(action.property)
- : ""
- }`}
-
- {action.propertyInfo.type != "textarea"
- ? action.valueExpr
- : action.textarea
- ? action.textarea
- : ""}
- {action.propertyInfo.animated
- ? `, Animated=${action.animated ? "On" : "Off"}`
- : ""}
- >
- );
- },
- updateObjectValueHook: (
- actionType: LVGLSetPropertyActionType,
- values: Partial
- ) => {
- if (values.targetType != undefined) {
- if (
- (PROPERTIES as PropertiesType)[values.targetType][
- actionType.property
- ] == undefined
- ) {
- ProjectEditor.getProjectStore(actionType).updateObject(
- actionType,
- {
- property: Object.keys(
- (PROPERTIES as PropertiesType)[
- values.targetType
- ]
- )[0]
+ if (lvglIdentifier == undefined) {
+ messages.push(
+ propertyNotFoundMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ } else {
+ const widgetType =
+ propertyInfo.lvglActionPropertyType.slice(
+ "widget:".length
+ );
+ if (widgetType) {
+ const classInfo = getClassInfo(
+ lvglIdentifier.object
+ );
+ const expectedClassInfo =
+ getClassByName(
+ project._store,
+ `LVGL${widgetType}Widget`
+ )?.classInfo;
+
+ if (
+ classInfo != expectedClassInfo
+ ) {
+ messages.push(
+ new Message(
+ MessageType.ERROR,
+ `Invalid object type`,
+ getChildOfObject(
+ object,
+ propertyInfo.name
+ )
+ )
+ );
+ }
+ }
+ }
+ }
+ } else if (
+ propertyInfo.lvglActionPropertyType == "group"
+ ) {
+ if (value) {
+ if (
+ !projectStore.project.lvglGroups.groups.some(
+ group => group.name == value
+ )
+ ) {
+ messages.push(
+ propertyNotFoundMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else {
+ messages.push(
+ propertyNotSetMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else if (
+ propertyInfo.lvglActionPropertyType == "style"
+ ) {
+ if (value) {
+ const lvglStyle = findLvglStyle(
+ projectStore.project,
+ value
+ );
+
+ if (!lvglStyle) {
+ messages.push(
+ propertyNotFoundMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else {
+ messages.push(
+ propertyNotSetMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else if (
+ propertyInfo.lvglActionPropertyType == "image"
+ ) {
+ if (value) {
+ const bitmap = findBitmap(
+ ProjectEditor.getProject(object),
+ value
+ );
+
+ if (!bitmap) {
+ messages.push(
+ propertyNotFoundMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else {
+ messages.push(
+ propertyNotSetMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else if (
+ propertyInfo.lvglActionPropertyType?.startsWith(
+ "enum:"
+ )
+ ) {
+ if (value) {
+ const enumType = getEnumFromType(
+ project,
+ propertyInfo.lvglActionPropertyType
+ );
+ if (
+ !enumType ||
+ !enumType.members.find(
+ member => member.name == value
+ )
+ ) {
+ messages.push(
+ propertyNotFoundMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else {
+ messages.push(
+ propertyNotSetMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
+ } else if (value == undefined) {
+ messages.push(
+ propertyNotSetMessage(
+ object,
+ propertyInfo.name
+ )
+ );
+ }
}
- );
+ }
}
}
- },
- check: (object: LVGLSetPropertyActionType, messages: IMessage[]) => {
- if (!object.target) {
- messages.push(propertyNotSetMessage(object, "target"));
- } else {
- const lvglIdentifier = ProjectEditor.getProjectStore(
- object
- ).lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
+ });
- if (lvglIdentifier == undefined) {
- messages.push(propertyNotFoundMessage(object, "target"));
- } else {
- if (
- !filterSetPropertyTarget(object, lvglIdentifier.object)
- ) {
- messages.push(
- new Message(
- MessageType.ERROR,
- `Invalid target type`,
- getChildOfObject(object, "target")
- )
- );
- }
+ override makeEditable() {
+ super.makeEditable();
+
+ const observables: any = {};
+
+ actionDefinition.properties.forEach(propertyInfo => {
+ (this as any)[propertyInfo.name] = undefined;
+ observables[propertyInfo.name] = observable;
+
+ if (!propertyInfo.isAssignable) {
+ (this as any)[propertyInfo.name + "Type"] = undefined;
+ observables[propertyInfo.name + "Type"] = observable;
}
- }
+ });
- if (object.propertyInfo.code == PropertyCode.NONE) {
- messages.push(propertyNotSetMessage(object, "property"));
- }
+ makeObservable(this, observables);
+ }
+ };
- if (object.valueType == "literal") {
- if (object.propertyInfo.type == "image") {
- if (object.value) {
- const bitmap = findBitmap(
- ProjectEditor.getProject(object),
- object.value
- );
+ actionClasses.set(actionDefinition.name, actionClass);
+}
- if (!bitmap) {
- messages.push(
- propertyNotFoundMessage(object, "value")
- );
- }
- } else {
- messages.push(propertyNotSetMessage(object, "value"));
- }
+////////////////////////////////////////////////////////////////////////////////
+
+async function showNewLVGLActionDialog() {
+ return new Promise(resolve => {
+ const onOk = (value: string) => {
+ resolve(value);
+ };
+
+ const onCancel = () => {
+ resolve(null);
+ };
+
+ showDialog();
+ });
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+class NewLVGLActionDialogState {
+ searchText: string = "";
+ _selectedActionName: string | undefined;
+
+ constructor() {
+ makeObservable(this, {
+ searchText: observable,
+ _selectedActionName: observable,
+ filteredActionDefinitions: computed
+ });
+ }
+
+ onSearchChange = (event: any) => {
+ runInAction(() => {
+ this.searchText = ($(event.target).val() as string).trim();
+ this._selectedActionName = this.filteredActionDefinitions[0]?.name;
+ });
+ };
+
+ get selectedActionName() {
+ return (
+ this._selectedActionName || this.filteredActionDefinitions[0]?.name
+ );
+ }
+
+ set selectedActionName(name: string) {
+ runInAction(() => {
+ this._selectedActionName = name;
+ });
+ }
+
+ get filteredActionDefinitions() {
+ return actionDefinitions.filter(actionDefinition =>
+ getActionDisplayName(actionDefinition)
+ .toLowerCase()
+ .includes(this.searchText.toLowerCase())
+ );
+ }
+}
+
+const newLVGLActionDialogState = new NewLVGLActionDialogState();
+
+const NewLVGLActionDialog = observer(
+ class NewLVGLActionDialog extends React.Component<{
+ onOk: (value: string) => void;
+ onCancel: () => void;
+ }> {
+ ref = React.createRef();
+
+ open: boolean = true;
+
+ constructor(props: any) {
+ super(props);
+
+ makeObservable(this, {
+ open: observable,
+ nodes: computed
+ });
+ }
+
+ get nodes() {
+ const nodes: IListNode[] = [];
+
+ for (const actionDefinition of actionDefinitions) {
+ const actionDisplayName =
+ getActionDisplayName(actionDefinition);
+
+ if (
+ actionDisplayName
+ .toLowerCase()
+ .indexOf(
+ newLVGLActionDialogState.searchText.toLowerCase()
+ ) == -1
+ ) {
+ continue;
}
+
+ nodes.push({
+ id: actionDefinition.name,
+ label: actionDisplayName,
+ data: actionDefinition,
+ selected:
+ actionDefinition.name ==
+ newLVGLActionDialogState.selectedActionName
+ });
}
- if (object.propertyInfo.type == "textarea") {
- if (object.textarea) {
- const lvglIdentifier = ProjectEditor.getProjectStore(
- object
- ).lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.textarea
- );
+ return nodes;
+ }
- if (lvglIdentifier == undefined) {
- messages.push(
- propertyNotFoundMessage(object, "textarea")
- );
- } else {
- if (
- !(
- lvglIdentifier.object instanceof
- LVGLTextareaWidget
- )
- ) {
- messages.push(
- new Message(
- MessageType.ERROR,
- `Not a textarea widget`,
- getChildOfObject(object, "textarea")
- )
- );
- }
- }
- }
+ onOkEnabled = () => {
+ return !!newLVGLActionDialogState.selectedActionName;
+ };
+
+ onOk = () => {
+ this.props.onOk(newLVGLActionDialogState.selectedActionName);
+ return true;
+ };
+
+ onDoubleClick = () => {
+ if (newLVGLActionDialogState.selectedActionName) {
+ this.onOk();
+ runInAction(() => {
+ this.open = false;
+ });
+ }
+ };
+
+ componentDidMount(): void {
+ const element = this.ref.current?.querySelector(
+ ".EezStudio_ListItem.EezStudio_Selected"
+ );
+ if (element) {
+ element.scrollIntoView({
+ block: "nearest",
+ behavior: "auto"
+ });
}
}
- });
- get propertyInfo() {
- return (
- (PROPERTIES as PropertiesType)[this.targetType][this.property] ?? {
- code: PropertyCode.NONE,
- type: "integer",
- animated: false
+ render() {
+ return (
+
+ );
+ }
+ }
+);
+
+////////////////////////////////////////////////////////////////////////////////
+
+interface IBuildProperties {
+ name: string;
+ expression: string;
+ isAssignable: boolean;
+ isHidden: boolean;
+ isBuildable: boolean;
+}
+
+export class LVGLActionType extends EezObject {
+ action: string;
+
+ static classInfo: ClassInfo = {
+ getClass: function (projectStore: ProjectStore, jsObject: any) {
+ if (jsObject.action == "ObjectSetX") jsObject.action = "objSetX";
+
+ const actionClass = actionClasses.get(jsObject.action);
+ if (actionClass) {
+ return actionClass;
+ }
+
+ return LVGLActionType;
+ },
+
+ properties: [
+ {
+ name: "action",
+ displayName: (object: LVGLActionType) => {
+ const actions = getParent(object) as LVGLActionType[];
+ if (actions.length < 2) {
+ return "Action";
+ }
+ return `Action #${actions.indexOf(object) + 1}`;
+ },
+ type: PropertyType.Enum,
+ enumItems: [...actionClasses.keys()].map(id => ({
+ id
+ })),
+ enumDisallowUndefined: true,
+ hideInPropertyGrid: true
}
- );
- }
+ ],
- get valueExpr() {
- if (typeof this.value == "number") {
- return this.value.toString();
- }
+ newItem: async (object: LVGLActionType[]) => {
+ const project = ProjectEditor.getProject(object);
- if (typeof this.value == "boolean") {
- return this.value ? "true" : "false";
- }
+ const action = await showNewLVGLActionDialog();
- if (this.valueType == "literal") {
- if (this.propertyInfo.type == "boolean") {
- return this.value ? "true" : "false";
+ if (!action) {
+ return undefined;
}
- }
-
- if (this.valueType == "expression") {
- return this.value as string;
- }
- return escapeCString(this.value ?? "");
- }
+ const actionTypeProperties = {
+ action
+ };
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- ProjectEditor.getProjectStore(
- this
- ).lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
+ let actionTypeObject;
- // property
- dataBuffer.writeUint32(this.propertyInfo.code);
+ const ActionClass = actionClasses.get(action)!;
- // value
- dataBuffer.writeObjectOffset(() =>
- buildExpression(
- assets,
- dataBuffer,
- getAncestorOfType(
- this,
- LVGLActionComponent.classInfo
- ) as LVGLActionComponent,
- this.valueExpr
- )
- );
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
- // textarea
- if (this.textarea) {
- dataBuffer.writeInt32(
- ProjectEditor.getProjectStore(
- this
- ).lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.textarea
- )?.index ?? -1
+ ActionClass.classInfo.defaultValue
+ ),
+ ActionClass
);
- } else {
- dataBuffer.writeInt32(-1);
- }
-
- // animated
- dataBuffer.writeUint32(this.animated ? 1 : 0);
- }
-}
-
-registerClass("LVGLSetPropertyActionType", LVGLSetPropertyActionType);
-
-////////////////////////////////////////////////////////////////////////////////
-export class LVGLAddStyleActionType extends LVGLActionType {
- target: string;
- style: string;
+ return actionTypeObject;
+ }
+ };
override makeEditable() {
super.makeEditable();
makeObservable(this, {
- target: observable,
- style: observable
+ action: observable
});
}
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "target",
- displayName: "Target",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLAddStyleActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
+ getExpression(assets: Assets, propertyInfo: PropertyInfo) {
+ let value = (this as any)[propertyInfo.name];
- return lvglIdentifiers.map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
+ if (isFlowProperty(this, propertyInfo, ["assignable"])) {
+ return value;
+ }
+
+ let valueType = (this as any)[propertyInfo.name + "Type"] ?? "literal";
+
+ if (typeof value == "number") {
+ return value.toString();
+ }
+
+ if (typeof value == "boolean") {
+ return value ? "true" : "false";
+ }
+
+ if (valueType == "literal") {
+ if (propertyInfo.lvglActionPropertyType == "boolean") {
+ return value ? "true" : "false";
+ } else if (propertyInfo.lvglActionPropertyType == "integer") {
+ return value;
+ } else if (propertyInfo.lvglActionPropertyType == "string") {
+ return escapeCString(value ?? "");
+ } else if (
+ propertyInfo.lvglActionPropertyType?.startsWith("enum:")
+ ) {
+ const enumType = getEnumFromType(
+ assets.projectStore.project,
+ propertyInfo.expressionType!
+ );
+ if (enumType) {
+ const enumMember = enumType.members.find(
+ member => member.name == value
+ );
+ if (enumMember) {
+ return enumMember.value.toString();
+ }
}
- },
- {
- name: "style",
- type: PropertyType.ObjectReference,
- referencedObjectCollectionPath: "allLvglStyles"
- }
- ],
- defaultValue: {},
- listLabel: (action: LVGLAddStyleActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Add style";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- if (singleItem) {
+ return 0;
+ } else if (propertyInfo.lvglActionPropertyType == "screen") {
+ return assets.getPageIndex(this, propertyInfo.name);
+ } else if (
+ propertyInfo.lvglActionPropertyType?.startsWith("widget")
+ ) {
return (
- <>
- {action.style} to {action.target}
- >
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ value
+ )?.index ?? -1
);
- } else {
- return (
- <>
- Add style {action.style} to {action.target}
- >
+ } else if (propertyInfo.lvglActionPropertyType == "group") {
+ return assets.projectStore.project.lvglGroups.groups.findIndex(
+ group => group.name == value
+ );
+ } else if (propertyInfo.lvglActionPropertyType == "style") {
+ const lvglStyle = findLvglStyle(
+ assets.projectStore.project,
+ value
);
+
+ if (lvglStyle) {
+ return assets.projectStore.lvglIdentifiers.styles.indexOf(
+ lvglStyle
+ );
+ } else {
+ return -1;
+ }
+ } else if (propertyInfo.lvglActionPropertyType == "image") {
+ return escapeCString(value ?? "");
}
- },
- check: (object: LVGLAddStyleActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
+ }
+ return value;
+ }
+
+ getBuildProperties(assets: Assets): IBuildProperties[] {
+ const classInfo = getClassInfo(this);
+ return classInfo.properties
+ .filter(propertyInfo => propertyInfo.expressionType != undefined)
+ .map(propertyInfo => ({
+ name: propertyInfo.name,
+ expression: this.getExpression(assets, propertyInfo),
+ isAssignable: isFlowProperty(this, propertyInfo, [
+ "assignable"
+ ]),
+ isHidden: false,
+ isBuildable: true
+ }));
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+export class LVGLActionComponent extends ActionComponent {
+ actions: LVGLActionType[];
+
+ static classInfo = makeDerivedClassInfo(ActionComponent.classInfo, {
+ flowComponentId: COMPONENT_TYPE_LVGL_ACTION_API,
+ componentPaletteGroupName: "!2LVGL",
+ componentPaletteLabel: "LVGL",
+ enabledInComponentPalette: (projectType: ProjectType) =>
+ projectType === ProjectType.LVGL,
+ properties: [
+ {
+ name: "actions",
+ type: PropertyType.Array,
+ typeClass: LVGLActionType,
+ propertyGridGroup: specificGroup,
+ partOfNavigation: false,
+ enumerable: false,
+ defaultValue: []
+ }
+ ],
+ beforeLoadHook: (object: LVGLActionComponent, objectJs: any) => {
+ if (objectJs.action != undefined) {
+ if (objectJs.action == "CHANGE_SCREEN") {
+ let action: any = {
+ action: objectJs.action
+ };
+
+ action.screen =
+ objectJs.changeScreenTarget ?? objectJs.screen;
+ action.fadeMode =
+ objectJs.changeScreenFadeMode ?? objectJs.fadeMode;
+ action.speed = objectJs.changeScreenSpeed ?? objectJs.speed;
+ action.delay = objectJs.changeScreenDelay ?? objectJs.delay;
- if (object.target) {
- const lvglIdentifier =
- projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
+ objectJs.actions = [action];
+ } else if (objectJs.action == "PLAY_ANIMATION") {
+ objectJs.actions = objectJs.animItems.map((item: any) => {
+ let action: any = {
+ action: objectJs.action
+ };
- if (lvglIdentifier == undefined) {
- messages.push(propertyNotFoundMessage(object, "target"));
- }
- } else {
- messages.push(propertyNotSetMessage(object, "target"));
- }
+ action.target = objectJs.animTarget;
+ action.property = item.property;
+ action.start = item.start;
+ action.end = item.end;
+ action.delay = objectJs.animDelay + item.delay;
+ action.time = item.time;
+ action.relative = item.relative;
+ action.instant = item.instant;
+ action.path = item.path;
- if (object.style) {
- const lvglStyle = findLvglStyle(
- projectStore.project,
- object.style
- );
+ return action;
+ });
+ } else if (objectJs.action == "SET_PROPERTY") {
+ let action: any = {
+ action: objectJs.action
+ };
- if (!lvglStyle) {
- messages.push(propertyNotFoundMessage(object, "style"));
+ action.targetType = objectJs.setPropTargetType;
+ action.target = objectJs.setPropTarget;
+ action.property = objectJs.setPropProperty;
+ action.value = objectJs.setPropValue;
+ action.valueType = objectJs.setPropValueType;
+ action.animated = objectJs.setPropAnim;
+
+ objectJs.actions = [action];
}
- } else {
- messages.push(propertyNotSetMessage(object, "style"));
- }
- }
- });
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- ProjectEditor.getProjectStore(
- this
- ).lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
+ delete objectJs.screen;
+ delete objectJs.changeScreenTarget;
+ delete objectJs.fadeMode;
+ delete objectJs.changeScreenFadeMode;
+ delete objectJs.speed;
+ delete objectJs.changeScreenSpeed;
+ delete objectJs.delay;
+ delete objectJs.changeScreenDelay;
- // style
- if (this.style) {
- const lvglStyle = findLvglStyle(
- assets.projectStore.project,
- this.style
- );
+ delete objectJs.animTarget;
+ delete objectJs.animDelay;
+ delete objectJs.animItems;
- if (lvglStyle) {
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.styles.indexOf(
- lvglStyle
- )
- );
- } else {
- dataBuffer.writeInt32(-1);
+ delete objectJs.setPropTargetType;
+ delete objectJs.setPropTarget;
+ delete objectJs.setPropProperty;
+ delete objectJs.setPropAnim;
+ delete objectJs.setPropValue;
+ delete objectJs.setPropValueType;
}
- } else {
- dataBuffer.writeInt32(-1);
- }
- }
-}
-registerClass("LVGLAddStyleActionType", LVGLAddStyleActionType);
+ for (const actionJs of objectJs.actions) {
+ switch (actionJs.action) {
+ case "CHANGE_SCREEN":
+ if (actionJs.showPreviousScreen == true) {
+ actionJs.action = "changeToPreviousScreen";
+ } else {
+ actionJs.action = "changeScreen";
+ actionJs.screenType = "literal";
+ }
+ actionJs.fadeModeType = "literal";
+ actionJs.speedType = "literal";
+ actionJs.delayType = "literal";
+ break;
+ case "PLAY_ANIMATION":
+ switch (actionJs.property) {
+ case "POSITION_X":
+ actionJs.action = "animX";
+ break;
+ case "POSITION_Y":
+ actionJs.action = "animY";
+ break;
+ case "WIDTH":
+ actionJs.action = "animWidth";
+ break;
+ case "HEIGHT":
+ actionJs.action = "animHeight";
+ break;
+ case "OPACITY":
+ actionJs.action = "animOpacity";
+ break;
+ case "IMAGE_ZOOM":
+ actionJs.action = "animImageZoom";
+ break;
+ case "IMAGE_ANGLE":
+ actionJs.action = "animImageAngle";
+ break;
+ }
+ delete actionJs.property;
+
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+
+ actionJs.startType = "literal";
+ actionJs.endType = "literal";
+ actionJs.delayType = "literal";
+ actionJs.timeType = "literal";
+ actionJs.relative = actionJs.relative ?? false;
+ actionJs.relativeType = "literal";
+ actionJs.instant = actionJs.instant ?? false;
+ actionJs.instantType = "literal";
+ if (!actionJs.path) {
+ actionJs.path = "LINEAR";
+ }
+ actionJs.pathType = "literal";
+ break;
+ case "SET_PROPERTY":
+ switch (actionJs.targetType) {
+ case "arc":
+ actionJs.action = "arcSetValue";
+ break;
+ case "bar":
+ actionJs.action = "barSetValue";
+ actionJs.animatedType = "literal";
+ break;
+ case "basic":
+ switch (actionJs.property) {
+ case "x":
+ actionJs.action = "objSetX";
+ actionJs.x = actionJs.value;
+ delete actionJs.value;
+ actionJs.xType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "y":
+ actionJs.action = "objSetY";
+ actionJs.y = actionJs.value;
+ delete actionJs.value;
+ actionJs.yType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "width":
+ actionJs.action = "objSetWidth";
+ actionJs.width = actionJs.value;
+ delete actionJs.value;
+ actionJs.widthType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "height":
+ actionJs.action = "objSetHeight";
+ actionJs.height = actionJs.value;
+ delete actionJs.value;
+ actionJs.heightType =
+ actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "opacity":
+ actionJs.action = "objSetStyleOpa";
+ actionJs.opacity = actionJs.value;
+ delete actionJs.value;
+ actionJs.opacityType =
+ actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "hidden":
+ actionJs.action = "objSetFlagHidden";
+ actionJs.hidden =
+ actionJs.value ?? false;
+ delete actionJs.value;
+ actionJs.hiddenType =
+ actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "checked":
+ actionJs.action = "objSetStateChecked";
+ actionJs.checked =
+ actionJs.value ?? false;
+ delete actionJs.value;
+ actionJs.checkedType =
+ actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "disabled":
+ actionJs.action = "objSetStateDisabled";
+ actionJs.disabled =
+ actionJs.value ?? false;
+ delete actionJs.value;
+ actionJs.disabledType =
+ actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ }
+ break;
+ case "dropdown":
+ actionJs.action = "dropdownSetSelected";
+ actionJs.selected = actionJs.value;
+ delete actionJs.value;
+ actionJs.selectedType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "image":
+ switch (actionJs.property) {
+ case "image":
+ actionJs.action = "imageSetSrc";
+ actionJs.src = actionJs.value;
+ delete actionJs.value;
+ actionJs.srcType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "angle":
+ actionJs.action = "imageSetAngle";
+ actionJs.angle = actionJs.value;
+ delete actionJs.value;
+ actionJs.angleType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "zoom":
+ actionJs.action = "imageSetZoom";
+ actionJs.zoom = actionJs.value;
+ delete actionJs.value;
+ actionJs.zoomType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ }
+ break;
+ case "label":
+ actionJs.action = "labelSetText";
+ actionJs.text = actionJs.value;
+ delete actionJs.value;
+ actionJs.textType = actionJs.valueType;
+ delete actionJs.valueType;
+ break;
+ case "roller":
+ actionJs.action = "rollerSetSelected";
+
+ actionJs.selected = actionJs.value;
+ delete actionJs.value;
+ actionJs.selectedType = actionJs.valueType;
+ delete actionJs.valueType;
-////////////////////////////////////////////////////////////////////////////////
+ actionJs.animatedType = "literal";
+ break;
+ case "slider":
+ actionJs.action = "sliderSetValue";
-export class LVGLRemoveStyleActionType extends LVGLActionType {
- target: string;
- style: string;
+ actionJs.animatedType = "literal";
+ break;
+ case "keyboard":
+ actionJs.action = "keyboardSetTextarea";
- override makeEditable() {
- super.makeEditable();
+ actionJs.textarea = actionJs.textarea;
+ actionJs.textareaType = "literal";
+ break;
+ }
+ delete actionJs.targetType;
+ delete actionJs.property;
- makeObservable(this, {
- target: observable,
- style: observable
- });
- }
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ break;
+ case "ADD_STYLE":
+ actionJs.action = "objAddStyle";
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ actionJs.styleType = "literal";
+ break;
+ case "REMOVE_STYLE":
+ actionJs.action = "objRemoveStyle";
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ actionJs.styleType = "literal";
+ break;
+ case "ADD_FLAG":
+ actionJs.action = "objAddFlag";
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ actionJs.flagType = "literal";
+ break;
+ case "CLEAR_FLAG":
+ actionJs.action = "objClearFlag";
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ actionJs.flagType = "literal";
+ break;
+ case "ADD_STATE":
+ actionJs.action = "objAddState";
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ actionJs.stateType = "literal";
+ break;
+ case "CLEAR_STATE":
+ actionJs.action = "objClearState";
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ actionJs.stateType = "literal";
+ break;
+ case "GROUP":
+ switch (actionJs.groupAction) {
+ case "SET_WRAP":
+ actionJs.action = "groupSetWrap";
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "target",
- displayName: "Target",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLRemoveStyleActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
+ actionJs.group = actionJs.target;
+ delete actionJs.target;
+ actionJs.groupType = "literal";
- return lvglIdentifiers.map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- }
- },
- {
- name: "style",
- type: PropertyType.ObjectReference,
- referencedObjectCollectionPath: "allLvglStyles"
- }
- ],
- defaultValue: {},
- listLabel: (action: LVGLRemoveStyleActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Remove style";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- if (singleItem) {
- return (
- <>
- {action.style} from {action.target}
- >
- );
- } else {
- return (
- <>
- Remove style {action.style} from {action.target}
- >
- );
- }
- },
- check: (object: LVGLRemoveStyleActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
+ actionJs.enabled = actionJs.enable ?? false;
+ delete actionJs.enable;
+ actionJs.enabledType = "literal";
+ break;
+ case "FOCUS_OBJ":
+ actionJs.action = "groupFocusObj";
+ actionJs.object = actionJs.target;
+ delete actionJs.target;
+ actionJs.objectType = "literal";
+ break;
+ case "FOCUS_NEXT":
+ actionJs.action = "groupFocusNext";
+ actionJs.group = actionJs.target;
+ delete actionJs.target;
+ actionJs.groupType = "literal";
+ break;
+ case "FOCUS_PREVIOUS":
+ actionJs.action = "groupFocusPrev";
+ actionJs.group = actionJs.target;
+ delete actionJs.target;
+ actionJs.groupType = "literal";
+ break;
+ case "FOCUS_FREEZE":
+ actionJs.action = "groupFocusFreeze";
- if (object.target) {
- const lvglIdentifier =
- projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
+ actionJs.group = actionJs.target;
+ delete actionJs.target;
+ actionJs.groupType = "literal";
- if (lvglIdentifier == undefined) {
- messages.push(propertyNotFoundMessage(object, "target"));
- }
- } else {
- messages.push(propertyNotSetMessage(object, "target"));
- }
+ actionJs.enabled = actionJs.enable ?? false;
+ delete actionJs.enable;
+ actionJs.enabledType = "literal";
+ break;
+ case "SET_EDITING":
+ actionJs.action = "groupSetEditing";
- if (object.style) {
- const lvglStyle = findLvglStyle(
- projectStore.project,
- object.style
- );
+ actionJs.group = actionJs.target;
+ delete actionJs.target;
+ actionJs.groupType = "literal";
- if (!lvglStyle) {
- messages.push(propertyNotFoundMessage(object, "style"));
+ actionJs.enabled = actionJs.enable ?? false;
+ delete actionJs.enable;
+ actionJs.enabledType = "literal";
+ break;
+ }
+ delete actionJs.groupAction;
+ break;
}
- } else {
- messages.push(propertyNotSetMessage(object, "style"));
- }
- }
- });
-
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
-
- // style
- if (this.style) {
- const lvglStyle = findLvglStyle(
- assets.projectStore.project,
- this.style
- );
-
- if (lvglStyle) {
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.styles.indexOf(
- lvglStyle
- )
- );
- } else {
- dataBuffer.writeInt32(-1);
}
- } else {
- dataBuffer.writeInt32(-1);
- }
- }
-}
-
-registerClass("LVGLRemoveStyleActionType", LVGLRemoveStyleActionType);
-
-////////////////////////////////////////////////////////////////////////////////
-
-export class LVGLAddFlagActionType extends LVGLActionType {
- target: string;
- flag: keyof typeof LVGL_FLAG_CODES;
+ },
+ icon: (
+
+ ),
+ componentHeaderColor: "#FBDEDE",
+ defaultValue: {
+ actions: []
+ }
+ });
override makeEditable() {
super.makeEditable();
makeObservable(this, {
- target: observable,
- flag: observable
+ actions: observable
});
}
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
+ getInputs() {
+ return [
{
- name: "target",
- displayName: "Target",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLAddFlagActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
-
- return lvglIdentifiers.map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- }
+ name: "@seqin",
+ type: "any" as ValueType,
+ isSequenceInput: true,
+ isOptionalInput: true
},
- {
- name: "flag",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLAddFlagActionType) => {
- return Object.keys(getLvglFlagCodes(actionType)).map(
- flag => ({
- id: flag,
- label: flag
- })
- );
- }
- }
- ],
- defaultValue: {},
- listLabel: (action: LVGLAddFlagActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Add flag";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- if (singleItem) {
- return (
- <>
- {action.flag} in {action.target}
- >
- );
- } else {
- return (
- <>
- Add flag {action.flag} in {action.target}
- >
- );
- }
- },
- check: (object: LVGLAddFlagActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
-
- if (object.target) {
- const lvglIdentifier =
- projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
+ ...super.getInputs()
+ ];
+ }
- if (lvglIdentifier == undefined) {
- messages.push(propertyNotFoundMessage(object, "target"));
- }
- } else {
- messages.push(propertyNotSetMessage(object, "target"));
- }
- }
- });
+ getOutputs() {
+ return [
+ {
+ name: "@seqout",
+ type: "null" as ValueType,
+ isSequenceOutput: true,
+ isOptionalOutput: true
+ },
+ ...super.getOutputs()
+ ];
+ }
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
+ getBody(flowContext: IFlowContext): React.ReactNode {
+ return (
+
+ {this.actions.map((action, i) => (
+
+ {this.actions.length > 1 ? `#${i + 1} ` : ""}
+ {getListLabel(action, true)}
+
+ ))}
+
);
-
- // flag
- dataBuffer.writeUint32(getLvglFlagCodes(this)[this.flag] ?? 0);
}
-}
-
-registerClass("LVGLAddFlagActionType", LVGLAddFlagActionType);
-////////////////////////////////////////////////////////////////////////////////
+ buildFlowComponentSpecific(assets: Assets, dataBuffer: DataBuffer) {
+ dataBuffer.writeArray(this.actions, action => {
+ // action
+ dataBuffer.writeUint32(actionNameToActionId.get(action.action)!);
-export class LVGLClearFlagActionType extends LVGLActionType {
- target: string;
- flag: keyof typeof LVGL_FLAG_CODES;
+ // properties
+ const buildProperties = action.getBuildProperties(assets);
+ //console.log(buildProperties);
+ dataBuffer.writeArray(buildProperties, buildProperty => {
+ if (!buildProperty.isHidden) {
+ try {
+ if (buildProperty.isBuildable) {
+ let expression = buildProperty.expression;
- override makeEditable() {
- super.makeEditable();
+ if (buildProperty.isAssignable) {
+ buildAssignableExpression(
+ assets,
+ dataBuffer,
+ this,
+ expression
+ );
+ } else {
+ buildExpression(
+ assets,
+ dataBuffer,
+ this,
+ expression
+ );
+ }
+ } else {
+ dataBuffer.writeUint16NonAligned(
+ makeEndInstruction()
+ );
+ }
+ } catch (err) {
+ assets.projectStore.outputSectionsStore.write(
+ Section.OUTPUT,
+ MessageType.ERROR,
+ err.toString(),
+ getChildOfObject(action, buildProperty.name)
+ );
- makeObservable(this, {
- target: observable,
- flag: observable
+ dataBuffer.writeUint16NonAligned(makeEndInstruction());
+ }
+ } else {
+ dataBuffer.writeUint16NonAligned(makeEndInstruction());
+ }
+ });
});
}
+}
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "target",
- displayName: "Target",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLClearFlagActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
+registerClass("LVGLActionComponent", LVGLActionComponent);
- return lvglIdentifiers.map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- }
- },
- {
- name: "flag",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLClearFlagActionType) => {
- return Object.keys(getLvglFlagCodes(actionType)).map(
- flag => ({
- id: flag,
- label: flag
- })
- );
- }
- }
- ],
- defaultValue: {},
- listLabel: (action: LVGLClearFlagActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Clear flag";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- if (singleItem) {
- return (
- <>
- {action.flag} in {action.target}
- >
- );
- } else {
- return (
- <>
- Clear flag {action.flag} in {action.target}
- >
- );
- }
- },
- check: (object: LVGLClearFlagActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
+////////////////////////////////////////////////////////////////////////////////
- if (object.target) {
- const lvglIdentifier =
- projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
+export function generateLVGLActionsMarkdown() {
+ let result =
+ "List of actions to be executed. The following actions are available:\n\n";
- if (lvglIdentifier == undefined) {
- messages.push(propertyNotFoundMessage(object, "target"));
- }
- } else {
- messages.push(propertyNotSetMessage(object, "target"));
- }
+ for (const actionDefinition of actionDefinitions) {
+ result += `- **${getActionDisplayName(actionDefinition)}**: ${
+ actionDefinition.helpText
+ }\n`;
+
+ for (const actionProperty of actionDefinition.properties) {
+ result += ` - *${
+ actionProperty.isAssignable
+ ? `Store ${actionProperty.name} into`
+ : humanize(actionProperty.name)
+ }*: ${actionProperty.helpText}\n`;
}
- });
-
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
- // flag
- dataBuffer.writeUint32(getLvglFlagCodes(this)[this.flag] ?? 0);
+ result += "\n";
}
+
+ result += "\n";
+
+ return result;
}
-registerClass("LVGLClearFlagActionType", LVGLClearFlagActionType);
+////////////////////////////////////////////////////////////////////////////////
+
+import "./actions-catalog";
+
+/*
////////////////////////////////////////////////////////////////////////////////
-export class LVGLAddStateActionType extends LVGLActionType {
- target: string;
- state: keyof typeof LVGL_STATE_CODES;
+const LVGL_ACTIONS = {
+ CHANGE_SCREEN: 0,
+ PLAY_ANIMATION: 1,
+ SET_PROPERTY: 2,
+ ADD_STYLE: 3,
+ REMOVE_STYLE: 4,
+ ADD_FLAG: 5,
+ CLEAR_FLAG: 6,
+ ADD_STATE: 8,
+ CLEAR_STATE: 9,
+ GROUP: 7
+};
- override makeEditable() {
- super.makeEditable();
+////////////////////////////////////////////////////////////////////////////////
- makeObservable(this, {
- target: observable,
- state: observable
- });
- }
+export class LVGLActionType extends EezObject {
+ action: keyof typeof LVGL_ACTIONS;
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "target",
- displayName: "Target",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLAddStateActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
+ static classInfo: ClassInfo = {
+ getClass: function (projectStore: ProjectStore, jsObject: any) {
+ if (jsObject.action == "CHANGE_SCREEN")
+ return LVGLChangeScreenActionType;
+ else if (jsObject.action == "PLAY_ANIMATION")
+ return LVGLPlayAnimationActionType;
+ else if (jsObject.action == "SET_PROPERTY")
+ return LVGLSetPropertyActionType;
+ else if (jsObject.action == "ADD_STYLE")
+ return LVGLAddStyleActionType;
+ else if (jsObject.action == "REMOVE_STYLE")
+ return LVGLRemoveStyleActionType;
+ else if (jsObject.action == "ADD_FLAG")
+ return LVGLAddFlagActionType;
+ else if (jsObject.action == "CLEAR_FLAG")
+ return LVGLClearFlagActionType;
+ else if (jsObject.action == "ADD_STATE")
+ return LVGLAddStateActionType;
+ else if (jsObject.action == "CLEAR_STATE")
+ return LVGLClearStateActionType;
+ else return LVGLGroupActionType;
+ },
- return lvglIdentifiers.map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- }
- },
+ properties: [
{
- name: "state",
+ name: "action",
+ displayName: (object: LVGLActionType) => {
+ const actions = getParent(object) as LVGLActionType[];
+ if (actions.length < 2) {
+ return "Action";
+ }
+ return `Action #${actions.indexOf(object) + 1}`;
+ },
type: PropertyType.Enum,
- enumItems: (actionType: LVGLAddStateActionType) => {
- return Object.keys(LVGL_STATE_CODES).map(state => ({
- id: state,
- label: state
- }));
- }
+ enumItems: Object.keys(LVGL_ACTIONS).map(id => ({
+ id
+ })),
+ enumDisallowUndefined: true,
+ hideInPropertyGrid: true
}
],
- defaultValue: {},
- listLabel: (action: LVGLAddStateActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Add state";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- if (singleItem) {
- return (
- <>
- {action.state} in {action.target}
- >
- );
- } else {
- return (
- <>
- Add state {action.state} in {action.target}
- >
- );
- }
- },
- check: (object: LVGLAddStateActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
- if (object.target) {
- const lvglIdentifier =
- projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
+ newItem: async (object: LVGLActionType[]) => {
+ const project = ProjectEditor.getProject(object);
- if (lvglIdentifier == undefined) {
- messages.push(propertyNotFoundMessage(object, "target"));
- }
- } else {
- messages.push(propertyNotSetMessage(object, "target"));
+ const result = await showGenericDialog({
+ dialogDefinition: {
+ title: "New LVGL Action",
+ fields: [
+ {
+ name: "action",
+ displayName: "Action type",
+ type: "enum",
+ enumItems: Object.keys(LVGL_ACTIONS).map(id => ({
+ id,
+ label: humanize(id)
+ }))
+ }
+ ]
+ },
+ values: {
+ action: "CHANGE_SCREEN"
+ },
+ dialogContext: project
+ });
+
+ const actionTypeProperties = {
+ action: result.values.action
+ };
+
+ let actionTypeObject;
+
+ if (result.values.action == "CHANGE_SCREEN") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLChangeScreenActionType.classInfo.defaultValue
+ ),
+ LVGLChangeScreenActionType
+ );
+ } else if (result.values.action == "PLAY_ANIMATION") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLPlayAnimationActionType.classInfo.defaultValue
+ ),
+ LVGLPlayAnimationActionType
+ );
+ } else if (result.values.action == "SET_PROPERTY") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLSetPropertyActionType.classInfo.defaultValue
+ ),
+ LVGLSetPropertyActionType
+ );
+ } else if (result.values.action == "ADD_STYLE") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLAddStyleActionType.classInfo.defaultValue
+ ),
+ LVGLAddStyleActionType
+ );
+ } else if (result.values.action == "REMOVE_STYLE") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLRemoveStyleActionType.classInfo.defaultValue
+ ),
+ LVGLRemoveStyleActionType
+ );
+ } else if (result.values.action == "ADD_FLAG") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLAddFlagActionType.classInfo.defaultValue
+ ),
+ LVGLAddFlagActionType
+ );
+ } else if (result.values.action == "CLEAR_FLAG") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLClearFlagActionType.classInfo.defaultValue
+ ),
+ LVGLClearFlagActionType
+ );
+ } else if (result.values.action == "ADD_STATE") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLAddStateActionType.classInfo.defaultValue
+ ),
+ LVGLAddStateActionType
+ );
+ } else if (result.values.action == "CLEAR_STATE") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLClearStateActionType.classInfo.defaultValue
+ ),
+ LVGLClearStateActionType
+ );
+ } else if (result.values.action == "GROUP") {
+ actionTypeObject = createObject(
+ project._store,
+ Object.assign(
+ actionTypeProperties,
+ LVGLGroupActionType.classInfo.defaultValue
+ ),
+ LVGLGroupActionType
+ );
}
- }
- });
-
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
-
- // state
- dataBuffer.writeUint32(LVGL_STATE_CODES[this.state] ?? 0);
- }
-}
-
-registerClass("LVGLAddStateActionType", LVGLAddStateActionType);
-
-////////////////////////////////////////////////////////////////////////////////
-export class LVGLClearStateActionType extends LVGLActionType {
- target: string;
- state: keyof typeof LVGL_STATE_CODES;
+ return actionTypeObject;
+ }
+ };
override makeEditable() {
super.makeEditable();
makeObservable(this, {
- target: observable,
- state: observable
+ action: observable
});
}
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties: [
- {
- name: "target",
- displayName: "Target",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLClearStateActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
-
- return lvglIdentifiers.map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- }
- },
- {
- name: "state",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLClearStateActionType) => {
- return Object.keys(LVGL_STATE_CODES).map(state => ({
- id: state,
- label: state
- }));
- }
- }
- ],
- defaultValue: {},
- listLabel: (action: LVGLClearStateActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Clear state";
- }
- let singleItem =
- (getParent(action) as LVGLActionType[]).length == 1;
- if (singleItem) {
- return (
- <>
- {action.state} in {action.target}
- >
- );
- } else {
- return (
- <>
- Clear state {action.state} in {action.target}
- >
- );
- }
- },
- check: (object: LVGLClearStateActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
-
- if (object.target) {
- const lvglIdentifier =
- projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
-
- if (lvglIdentifier == undefined) {
- messages.push(propertyNotFoundMessage(object, "target"));
- }
- } else {
- messages.push(propertyNotSetMessage(object, "target"));
- }
- }
- });
-
- override build(assets: Assets, dataBuffer: DataBuffer) {
- // target
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
-
- // state
- dataBuffer.writeUint32(LVGL_STATE_CODES[this.state] ?? 0);
- }
+ build(assets: Assets, dataBuffer: DataBuffer) {}
}
-registerClass("LVGLClearStateActionType", LVGLClearStateActionType);
-
////////////////////////////////////////////////////////////////////////////////
-const GROUP_ACTIONS = {
- SET_WRAP: 0,
- FOCUS_OBJ: 1,
- FOCUS_NEXT: 2,
- FOCUS_PREVIOUS: 3,
- FOCUS_FREEZE: 4,
- SET_EDITING: 5
+const FADE_MODES = {
+ NONE: 0,
+ OVER_LEFT: 1,
+ OVER_RIGHT: 2,
+ OVER_TOP: 3,
+ OVER_BOTTOM: 4,
+ MOVE_LEFT: 5,
+ MOVE_RIGHT: 6,
+ MOVE_TOP: 7,
+ MOVE_BOTTOM: 8,
+ FADE_IN: 9,
+ FADE_OUT: 10,
+ OUT_LEFT: 11,
+ OUT_RIGHT: 12,
+ OUT_TOP: 13,
+ OUT_BOTTOM: 14
};
-export class LVGLGroupActionType extends LVGLActionType {
- groupAction: keyof typeof GROUP_ACTIONS;
- target: string;
- enable: boolean;
+export class LVGLChangeScreenActionType extends LVGLActionType {
+ showPreviousScreen: boolean;
+ screen: string;
+ fadeMode: keyof typeof FADE_MODES;
+ speed: number;
+ delay: number;
override makeEditable() {
super.makeEditable();
makeObservable(this, {
- groupAction: observable,
- target: observable,
- enable: observable
+ showPreviousScreen: observable,
+ screen: observable,
+ fadeMode: observable,
+ speed: observable,
+ delay: observable
});
}
static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
properties: [
{
- name: "groupAction",
+ name: "showPreviousScreen",
+ displayName: "Previous screen",
+ type: PropertyType.Boolean,
+ checkboxStyleSwitch: true
+ },
+ {
+ name: "screen",
+ type: PropertyType.ObjectReference,
+ referencedObjectCollectionPath: "userPages",
+ disabled: (action: LVGLChangeScreenActionType) =>
+ action.showPreviousScreen
+ },
+ {
+ name: "fadeMode",
type: PropertyType.Enum,
- enumItems: Object.keys(GROUP_ACTIONS).map(id => ({
+ enumItems: Object.keys(FADE_MODES).map(id => ({
id
})),
enumDisallowUndefined: true
},
{
- name: "target",
- displayName: (actionType: LVGLGroupActionType) =>
- actionType.groupAction == "FOCUS_OBJ"
- ? "Target widget"
- : "Target group",
- type: PropertyType.Enum,
- enumItems: (actionType: LVGLGroupActionType) => {
- const projectStore =
- ProjectEditor.getProjectStore(actionType);
- if (actionType.groupAction == "FOCUS_OBJ") {
- const lvglIdentifiers =
- projectStore.lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
- );
-
- return lvglIdentifiers.map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- } else {
- return projectStore.project.lvglGroups.groups.map(
- group => ({
- id: group.name,
- label: group.name
- })
- );
- }
- }
+ name: "speed",
+ displayName: "Speed (ms)",
+ type: PropertyType.Number
},
{
- name: "enable",
- type: PropertyType.Boolean,
- checkboxStyleSwitch: true,
- disabled: (actionType: LVGLGroupActionType) =>
- !(
- actionType.groupAction == "SET_WRAP" ||
- actionType.groupAction == "FOCUS_FREEZE" ||
- actionType.groupAction == "SET_EDITING"
- )
+ name: "delay",
+ displayName: "Delay (ms)",
+ type: PropertyType.Number
}
],
defaultValue: {
- groupAction: "SET_WRAP"
+ fadeMode: "FADE_IN",
+ showPreviousScreen: false,
+ speed: 200,
+ delay: 0
},
- listLabel: (action: LVGLGroupActionType, collapsed: boolean) => {
- if (!collapsed) {
- return "Group";
- }
- if (action.groupAction == "SET_WRAP") {
- return (
- <>
- Set wrap to {action.enable ? "ON" : "OFF"} for group "
- {action.target}"
- >
- );
- } else if (action.groupAction == "FOCUS_OBJ") {
- return <>Set focus to widget "{action.target}">;
- } else if (action.groupAction == "FOCUS_NEXT") {
- return <>Focus next for group "{action.target}">;
- } else if (action.groupAction == "FOCUS_PREVIOUS") {
- return <>Focus previous for group "{action.target}">;
- } else if (action.groupAction == "FOCUS_FREEZE") {
- return <>Freeze focus for group "{action.target}">;
- } else {
- return (
- <>
- Set editing to {action.enable ? "ON" : "OFF"} for group
- "{action.target}"
- >
- );
+ listLabel: (action: LVGLChangeScreenActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Change screen";
}
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ return `${singleItem ? "" : "Change screen: "}${
+ action.showPreviousScreen
+ ? "Previous Screen"
+ : `Screen=${action.screen}`
+ }, Speed=${action.speed} ms, Delay=${action.delay} ms`;
},
- check: (object: LVGLGroupActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
-
- if (object.target) {
- if (object.groupAction == "FOCUS_OBJ") {
- const lvglIdentifier =
- projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- object.target
- );
-
- if (lvglIdentifier == undefined) {
- messages.push(
- propertyNotFoundMessage(object, "target")
- );
- }
+ check: (object: LVGLChangeScreenActionType, messages: IMessage[]) => {
+ if (!object.showPreviousScreen) {
+ if (!object.screen) {
+ messages.push(propertyNotSetMessage(object, "screen"));
} else {
- if (
- !projectStore.project.lvglGroups.groups.some(
- group => group.name == object.target
- )
- ) {
+ let page = findPage(getProject(object), object.screen);
+ if (!page) {
messages.push(
- propertyNotFoundMessage(object, "target")
+ propertyNotFoundMessage(object, "screen")
);
}
}
- } else {
- messages.push(propertyNotSetMessage(object, "target"));
}
}
});
override build(assets: Assets, dataBuffer: DataBuffer) {
- // groupAction
- dataBuffer.writeUint32(GROUP_ACTIONS[this.groupAction]);
-
- // target
- if (this.groupAction == "FOCUS_OBJ") {
- dataBuffer.writeInt32(
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- this.target
- )?.index ?? -1
- );
+ // screen
+ let screen: number;
+ if (this.showPreviousScreen) {
+ screen = -1;
} else {
- const index =
- assets.projectStore.project.lvglGroups.groups.findIndex(
- group => group.name == this.target
- );
-
- dataBuffer.writeInt32(index);
+ if (this.screen) {
+ screen = assets.getPageIndex(this, "screen");
+ } else {
+ screen = 0;
+ }
}
+ dataBuffer.writeInt32(screen);
- // style
- dataBuffer.writeUint32(this.enable ? 1 : 0);
+ // fadeMode
+ dataBuffer.writeUint32(FADE_MODES[this.fadeMode]);
+
+ // speed
+ dataBuffer.writeUint32(this.speed);
+
+ // delay
+ dataBuffer.writeUint32(this.delay);
}
}
-registerClass("LVGLGroupActionType", LVGLGroupActionType);
+registerClass("LVGLChangeScreenActionType", LVGLChangeScreenActionType);
////////////////////////////////////////////////////////////////////////////////
-export class LVGLActionComponent extends ActionComponent {
- actions: LVGLActionType[];
-
- static classInfo = makeDerivedClassInfo(ActionComponent.classInfo, {
- flowComponentId: COMPONENT_TYPE_LVGL_ACTION,
- componentPaletteGroupName: "!2LVGL",
- componentPaletteLabel: "LVGL",
- enabledInComponentPalette: (projectType: ProjectType) =>
- projectType === ProjectType.LVGL,
- label: (component: LVGLActionComponent) => {
- if (component.actions.length == 1) {
- return `LVGL ${humanize(component.actions[0].action)}`;
- }
- return "LVGL";
- },
- properties: [
- {
- name: "actions",
- type: PropertyType.Array,
- typeClass: LVGLActionType,
- propertyGridGroup: specificGroup,
- partOfNavigation: false,
- enumerable: false,
- defaultValue: []
- }
- ],
- beforeLoadHook: (object: LVGLActionComponent, objectJs: any) => {
- if (objectJs.action != undefined) {
- if (objectJs.action == "CHANGE_SCREEN") {
- let action: Partial = {
- action: objectJs.action
- };
-
- action.screen =
- objectJs.changeScreenTarget ?? objectJs.screen;
- action.fadeMode =
- objectJs.changeScreenFadeMode ?? objectJs.fadeMode;
- action.speed = objectJs.changeScreenSpeed ?? objectJs.speed;
- action.delay = objectJs.changeScreenDelay ?? objectJs.delay;
+const ANIM_PROPERTIES = {
+ POSITION_X: 0,
+ POSITION_Y: 1,
+ WIDTH: 2,
+ HEIGHT: 3,
+ OPACITY: 4,
+ IMAGE_ZOOM: 5,
+ IMAGE_ANGLE: 6
+};
- objectJs.actions = [action];
- } else if (objectJs.action == "PLAY_ANIMATION") {
- objectJs.actions = objectJs.animItems.map((item: any) => {
- let action: Partial = {
- action: objectJs.action
- };
+const ANIM_PATHS = {
+ LINEAR: 0,
+ EASE_IN: 1,
+ EASE_OUT: 2,
+ EASE_IN_OUT: 3,
+ OVERSHOOT: 4,
+ BOUNCE: 5
+};
- action.target = objectJs.animTarget;
- action.property = item.property;
- action.start = item.start;
- action.end = item.end;
- action.delay = objectJs.animDelay + item.delay;
- action.time = item.time;
- action.relative = item.relative;
- action.instant = item.instant;
- action.path = item.path;
+export class LVGLPlayAnimationActionType extends LVGLActionType {
+ target: string;
+ property: keyof typeof ANIM_PROPERTIES;
+ start: number;
+ end: number;
+ delay: number;
+ time: number;
+ relative: boolean;
+ instant: boolean;
+ path: keyof typeof ANIM_PATHS;
- return action;
- });
- } else if (objectJs.action == "SET_PROPERTY") {
- let action: Partial = {
- action: objectJs.action
- };
+ override makeEditable() {
+ super.makeEditable();
- action.targetType = objectJs.setPropTargetType;
- action.target = objectJs.setPropTarget;
- action.property = objectJs.setPropProperty;
- action.value = objectJs.setPropValue;
- action.valueType = objectJs.setPropValueType;
- action.animated = objectJs.setPropAnim;
+ makeObservable(this, {
+ target: observable,
+ property: observable,
+ start: observable,
+ end: observable,
+ delay: observable,
+ time: observable,
+ relative: observable,
+ instant: observable,
+ path: observable
+ });
+ }
- objectJs.actions = [action];
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "target",
+ type: PropertyType.Enum,
+ enumItems: (component: LVGLActionComponent) => {
+ return ProjectEditor.getProjectStore(component)
+ .lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(component)
+ )
+ .map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.displayName
+ }));
}
-
- delete objectJs.screen;
- delete objectJs.changeScreenTarget;
- delete objectJs.fadeMode;
- delete objectJs.changeScreenFadeMode;
- delete objectJs.speed;
- delete objectJs.changeScreenSpeed;
- delete objectJs.delay;
- delete objectJs.changeScreenDelay;
-
- delete objectJs.animTarget;
- delete objectJs.animDelay;
- delete objectJs.animItems;
-
- delete objectJs.setPropTargetType;
- delete objectJs.setPropTarget;
- delete objectJs.setPropProperty;
- delete objectJs.setPropAnim;
- delete objectJs.setPropValue;
- delete objectJs.setPropValueType;
+ },
+ {
+ name: "property",
+ type: PropertyType.Enum,
+ enumItems: Object.keys(ANIM_PROPERTIES).map(id => ({ id })),
+ enumDisallowUndefined: true
+ },
+ {
+ name: "start",
+ type: PropertyType.Number
+ },
+ {
+ name: "end",
+ type: PropertyType.Number
+ },
+ {
+ name: "delay",
+ displayName: "Delay (ms)",
+ type: PropertyType.Number
+ },
+ {
+ name: "time",
+ displayName: "Time (ms)",
+ type: PropertyType.Number
+ },
+ {
+ name: "relative",
+ type: PropertyType.Boolean,
+ checkboxStyleSwitch: true
+ },
+ {
+ name: "instant",
+ type: PropertyType.Boolean,
+ checkboxStyleSwitch: true
+ },
+ {
+ name: "path",
+ type: PropertyType.Enum,
+ enumItems: Object.keys(ANIM_PATHS).map(id => ({ id })),
+ enumDisallowUndefined: true
}
- },
- icon: (
-
- ),
- componentHeaderColor: "#FBDEDE",
+ ],
defaultValue: {
- actions: []
+ property: "POSITION_X",
+ start: 0,
+ end: 100,
+ delay: 0,
+ time: 1000,
+ relative: true,
+ instant: false,
+ path: ""
+ },
+ listLabel: (
+ action: LVGLPlayAnimationActionType,
+ collapsed: boolean
+ ) => {
+ if (!collapsed) {
+ return "Play animation";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ return `${singleItem ? "" : "Play animation: "}Target=${
+ action.target
+ }, Property=${action.property}, Start=${action.start}, End=${
+ action.end
+ }, Delay=${action.delay} ms, Time=${action.time} ms, Relative=${
+ action.relative ? "On" : "Off"
+ }, Instant=${action.instant ? "On" : "Off"} ${action.path}`;
+ },
+ check: (object: LVGLPlayAnimationActionType, messages: IMessage[]) => {
+ if (!object.target) {
+ messages.push(propertyNotSetMessage(object, "target"));
+ } else {
+ if (
+ ProjectEditor.getProjectStore(
+ object
+ ).lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
+ ) == undefined
+ ) {
+ messages.push(propertyNotFoundMessage(object, "target"));
+ }
+ }
}
});
- override makeEditable() {
- super.makeEditable();
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
- makeObservable(this, {
- actions: observable
- });
- }
+ // property
+ dataBuffer.writeUint32(ANIM_PROPERTIES[this.property]);
- getInputs() {
- return [
- {
- name: "@seqin",
- type: "any" as ValueType,
- isSequenceInput: true,
- isOptionalInput: true
- },
- ...super.getInputs()
- ];
- }
+ // start
+ dataBuffer.writeInt32(this.start);
- getOutputs() {
- return [
- {
- name: "@seqout",
- type: "null" as ValueType,
- isSequenceOutput: true,
- isOptionalOutput: true
- },
- ...super.getOutputs()
- ];
- }
+ // end
+ dataBuffer.writeInt32(this.end);
- getBody(flowContext: IFlowContext): React.ReactNode {
- return (
-
- {this.actions.map((action, i) => (
-
- {this.actions.length > 1 ? `#${i + 1} ` : ""}
- {getListLabel(action, true)}
-
- ))}
-
- );
- }
+ // delay
+ dataBuffer.writeUint32(this.delay);
- buildFlowComponentSpecific(assets: Assets, dataBuffer: DataBuffer) {
- dataBuffer.writeArray(this.actions, action => {
- // action
- dataBuffer.writeUint32(LVGL_ACTIONS[action.action]);
+ // time
+ dataBuffer.writeUint32(this.time);
- // ...specific
- action.build(assets, dataBuffer);
- });
+ // flags
+ const ANIMATION_ITEM_FLAG_RELATIVE = 1 << 0;
+ const ANIMATION_ITEM_FLAG_INSTANT = 1 << 1;
+ dataBuffer.writeUint32(
+ (this.relative ? ANIMATION_ITEM_FLAG_RELATIVE : 0) |
+ (this.instant ? ANIMATION_ITEM_FLAG_INSTANT : 0)
+ );
+
+ // path
+ dataBuffer.writeUint32(ANIM_PATHS[this.path]);
}
}
-registerClass("LVGLActionComponent", LVGLActionComponent);
-*/
+registerClass("LVGLPlayAnimationActionType", LVGLPlayAnimationActionType);
////////////////////////////////////////////////////////////////////////////////
-type LvglActionPropertyType =
- | "boolean"
- | "integer"
- | "string"
- | `enum:${string}`
- | "screen"
- | "widget"
- | `widget:${string}`
- | "group"
- | "style"
- | "image";
+const enum PropertyCode {
+ NONE,
-export interface IActionPropertyDefinition {
- name: string;
- type: LvglActionPropertyType;
- isAssignable?: boolean;
- helpText: string;
-}
+ ARC_VALUE,
-function getValueTypeFromActionPropertyType(
- actionPropertyType: LvglActionPropertyType
-): ValueType {
- if (actionPropertyType == "screen") {
- return "integer";
- }
+ BAR_VALUE,
- if (actionPropertyType.startsWith("widget:")) {
- return "widget";
- }
+ BASIC_X,
+ BASIC_Y,
+ BASIC_WIDTH,
+ BASIC_HEIGHT,
+ BASIC_OPACITY,
+ BASIC_HIDDEN,
+ BASIC_CHECKED,
+ BASIC_DISABLED,
- if (actionPropertyType == "group") {
- return "integer";
- }
+ DROPDOWN_SELECTED,
- if (actionPropertyType == "style") {
- return "integer";
+ IMAGE_IMAGE,
+ IMAGE_ANGLE,
+ IMAGE_ZOOM,
+
+ LABEL_TEXT,
+
+ ROLLER_SELECTED,
+
+ SLIDER_VALUE,
+
+ KEYBOARD_TEXTAREA
+}
+
+type PropertiesType = {
+ [targetType: string]: {
+ [propName: string]: {
+ code: PropertyCode;
+ type: "number" | "string" | "boolean" | "image" | "textarea";
+ animated: boolean;
+ };
+ };
+};
+
+const PROPERTIES = {
+ arc: {
+ value: {
+ code: PropertyCode.ARC_VALUE,
+ type: "number" as const,
+ animated: false
+ }
+ },
+ bar: {
+ value: {
+ code: PropertyCode.BAR_VALUE,
+ type: "number" as const,
+ animated: true
+ }
+ },
+ basic: {
+ x: {
+ code: PropertyCode.BASIC_X,
+ type: "number" as const,
+ animated: false
+ },
+ y: {
+ code: PropertyCode.BASIC_Y,
+ type: "number" as const,
+ animated: false
+ },
+ width: {
+ code: PropertyCode.BASIC_WIDTH,
+ type: "number" as const,
+ animated: false
+ },
+ height: {
+ code: PropertyCode.BASIC_HEIGHT,
+ type: "number" as const,
+ animated: false
+ },
+ opacity: {
+ code: PropertyCode.BASIC_OPACITY,
+ type: "number" as const,
+ animated: false
+ },
+ hidden: {
+ code: PropertyCode.BASIC_HIDDEN,
+ type: "boolean" as const,
+ animated: false
+ },
+ checked: {
+ code: PropertyCode.BASIC_CHECKED,
+ type: "boolean" as const,
+ animated: false
+ },
+ disabled: {
+ code: PropertyCode.BASIC_DISABLED,
+ type: "boolean" as const,
+ animated: false
+ }
+ },
+ dropdown: {
+ selected: {
+ code: PropertyCode.DROPDOWN_SELECTED,
+ type: "number" as const,
+ animated: false
+ }
+ },
+ image: {
+ image: {
+ code: PropertyCode.IMAGE_IMAGE,
+ type: "image" as const,
+ animated: false
+ },
+ angle: {
+ code: PropertyCode.IMAGE_ANGLE,
+ type: "number" as const,
+ animated: false
+ },
+ zoom: {
+ code: PropertyCode.IMAGE_ZOOM,
+ type: "number" as const,
+ animated: false
+ }
+ },
+ label: {
+ text: {
+ code: PropertyCode.LABEL_TEXT,
+ type: "string" as const,
+ animated: false
+ }
+ },
+ roller: {
+ selected: {
+ code: PropertyCode.ROLLER_SELECTED,
+ type: "number" as const,
+ animated: true
+ }
+ },
+ slider: {
+ value: {
+ code: PropertyCode.SLIDER_VALUE,
+ type: "number" as const,
+ animated: true
+ }
+ },
+ keyboard: {
+ textarea: {
+ code: PropertyCode.KEYBOARD_TEXTAREA,
+ type: "textarea" as const,
+ animated: false
+ }
}
+};
- if (actionPropertyType == "image") {
- return "string";
+function filterSetPropertyTarget(
+ actionType: LVGLSetPropertyActionType,
+ object: Page | LVGLWidget
+) {
+ if (actionType.targetType == "arc") {
+ return object instanceof LVGLArcWidget;
+ } else if (actionType.targetType == "bar") {
+ return object instanceof LVGLBarWidget;
+ } else if (actionType.targetType == "basic") {
+ return true;
+ } else if (actionType.targetType == "dropdown") {
+ return object instanceof LVGLDropdownWidget;
+ } else if (actionType.targetType == "image") {
+ return object instanceof LVGLImageWidget;
+ } else if (actionType.targetType == "label") {
+ return object instanceof LVGLLabelWidget;
+ } else if (actionType.targetType == "roller") {
+ return object instanceof LVGLRollerWidget;
+ } else if (actionType.targetType == "slider") {
+ return object instanceof LVGLSliderWidget;
+ } else if (actionType.targetType == "keyboard") {
+ return object instanceof LVGLKeyboardWidget;
+ } else {
+ return false;
}
-
- return actionPropertyType as ValueType;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-export interface IActionDefinition {
- name: string;
- properties: IActionPropertyDefinition[];
- defaults: any;
- label?: (
- propertyValues: string[],
- propertyNames: string[]
- ) => React.ReactNode;
- helpText: string;
}
-export const actionDefinitions: IActionDefinition[] = [];
-const actionClasses = new Map();
-const actionNameToActionId = new Map();
-
-let nextActionId = 0;
-
-export function registerAction(actionDefinition: IActionDefinition) {
- actionDefinitions.push(actionDefinition);
+export class LVGLSetPropertyActionType extends LVGLActionType {
+ targetType: keyof typeof PROPERTIES;
+ target: string;
+ property: string;
+ animated: boolean;
+ value: number | string | boolean;
+ valueType: LVGLPropertyType;
+ textarea: string;
- actionNameToActionId.set(actionDefinition.name, nextActionId++);
+ override makeEditable() {
+ super.makeEditable();
- const properties: PropertyInfo[] = [];
+ makeObservable(this, {
+ targetType: observable,
+ target: observable,
+ property: observable,
+ animated: observable,
+ value: observable,
+ valueType: observable,
+ textarea: observable
+ });
+ }
- for (const actionProperty of actionDefinition.properties) {
- const expressionType = getValueTypeFromActionPropertyType(
- actionProperty.type
- );
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "targetType",
+ type: PropertyType.Enum,
+ enumItems: Object.keys(PROPERTIES).map(id => ({
+ id
+ })),
+ enumDisallowUndefined: true
+ },
+ {
+ name: "target",
+ displayName: "Target",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLSetPropertyActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
- if (actionProperty.isAssignable) {
- properties.push(
- makeAssignableExpressionProperty(
- {
- name: actionProperty.name,
- displayName: `Store ${actionProperty.name} into`,
- type: PropertyType.MultilineText
+ return lvglIdentifiers
+ .filter(lvglIdentifier =>
+ filterSetPropertyTarget(
+ actionType,
+ lvglIdentifier.object
+ )
+ )
+ .map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
+ }
+ },
+ {
+ name: "property",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLSetPropertyActionType) => {
+ return Object.keys(PROPERTIES[actionType.targetType]).map(
+ id => ({
+ id
+ })
+ );
+ },
+ enumDisallowUndefined: true
+ },
+ ...makeLvglExpressionProperty(
+ "value",
+ "any",
+ "input",
+ ["literal", "expression"],
+ {
+ dynamicType: (actionType: LVGLSetPropertyActionType) => {
+ const type = actionType.propertyInfo.type;
+ return type == "image"
+ ? PropertyType.ObjectReference
+ : type == "number"
+ ? PropertyType.Number
+ : type == "boolean"
+ ? PropertyType.Boolean
+ : PropertyType.MultilineText;
},
- expressionType
- )
+ checkboxStyleSwitch: true,
+ dynamicTypeReferencedObjectCollectionPath: (
+ actionType: LVGLSetPropertyActionType
+ ) => {
+ const type = actionType.propertyInfo.type;
+ return type == "image" ? "bitmaps" : undefined;
+ },
+ displayName: (actionType: LVGLSetPropertyActionType) => {
+ if (actionType.propertyInfo.type == "image") {
+ return "Image";
+ }
+ return "Value";
+ },
+ disabled: (actionType: LVGLSetPropertyActionType) =>
+ actionType.propertyInfo.type == "textarea"
+ }
+ ),
+ {
+ name: "textarea",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLSetPropertyActionType) => {
+ const page = getAncestorOfType(
+ actionType,
+ ProjectEditor.PageClass.classInfo
+ ) as Page;
+ return page._lvglWidgets
+ .filter(
+ lvglWidget =>
+ lvglWidget instanceof LVGLTextareaWidget &&
+ lvglWidget.identifier
+ )
+ .map(lvglWidget => ({
+ id: lvglWidget.identifier,
+ label: lvglWidget.identifier
+ }));
+ },
+ disabled: (actionType: LVGLSetPropertyActionType) =>
+ actionType.propertyInfo.type != "textarea"
+ },
+ {
+ name: "animated",
+ type: PropertyType.Boolean,
+ checkboxStyleSwitch: true,
+ disabled: (actionType: LVGLSetPropertyActionType) =>
+ !actionType.propertyInfo.animated
+ }
+ ],
+ defaultValue: {
+ targetType: "bar",
+ property: "value",
+ animated: false,
+ valueType: "literal"
+ },
+ listLabel: (action: LVGLSetPropertyActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Set property";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ return (
+ <>
+ {`${singleItem ? "" : "Set property: "}${action.target}.${
+ action.propertyInfo.code != PropertyCode.NONE
+ ? humanize(action.property)
+ : ""
+ }`}
+
+ {action.propertyInfo.type != "textarea"
+ ? action.valueExpr
+ : action.textarea
+ ? action.textarea
+ : ""}
+ {action.propertyInfo.animated
+ ? `, Animated=${action.animated ? "On" : "Off"}`
+ : ""}
+ >
);
- } else {
- let enumItems:
- | ((actionType: LVGLActionType) => EnumItem[])
- | undefined;
- let enumDisallowUndefined = true;
+ },
+ updateObjectValueHook: (
+ actionType: LVGLSetPropertyActionType,
+ values: Partial
+ ) => {
+ if (values.targetType != undefined) {
+ if (
+ (PROPERTIES as PropertiesType)[values.targetType][
+ actionType.property
+ ] == undefined
+ ) {
+ ProjectEditor.getProjectStore(actionType).updateObject(
+ actionType,
+ {
+ property: Object.keys(
+ (PROPERTIES as PropertiesType)[
+ values.targetType
+ ]
+ )[0]
+ }
+ );
+ }
+ }
+ },
+ check: (object: LVGLSetPropertyActionType, messages: IMessage[]) => {
+ if (!object.target) {
+ messages.push(propertyNotSetMessage(object, "target"));
+ } else {
+ const lvglIdentifier = ProjectEditor.getProjectStore(
+ object
+ ).lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
+ );
- let referencedObjectCollectionPath: string | undefined;
+ if (lvglIdentifier == undefined) {
+ messages.push(propertyNotFoundMessage(object, "target"));
+ } else {
+ if (
+ !filterSetPropertyTarget(object, lvglIdentifier.object)
+ ) {
+ messages.push(
+ new Message(
+ MessageType.ERROR,
+ `Invalid target type`,
+ getChildOfObject(object, "target")
+ )
+ );
+ }
+ }
+ }
- if (actionProperty.type.startsWith("enum:")) {
- enumItems = (actionType: LVGLActionType) => {
- let enumItems = [];
+ if (object.propertyInfo.code == PropertyCode.NONE) {
+ messages.push(propertyNotSetMessage(object, "property"));
+ }
- const enumType = getEnumFromType(
- ProjectEditor.getProject(actionType),
- actionProperty.type
- );
- if (enumType) {
- for (const member of enumType.members) {
- enumItems.push({
- id: member.name,
- label: member.name
- });
+ if (object.valueType == "literal") {
+ if (object.propertyInfo.type == "image") {
+ if (object.value) {
+ const bitmap = findBitmap(
+ ProjectEditor.getProject(object),
+ object.value
+ );
+
+ if (!bitmap) {
+ messages.push(
+ propertyNotFoundMessage(object, "value")
+ );
}
+ } else {
+ messages.push(propertyNotSetMessage(object, "value"));
}
+ }
+ }
- return enumItems;
- };
- } else if (actionProperty.type == "screen") {
- referencedObjectCollectionPath = "userPages";
- } else if (actionProperty.type.startsWith("widget")) {
- enumItems = (actionType: LVGLActionType) => {
- const lvglIdentifiers = ProjectEditor.getProjectStore(
- actionType
- ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
- ProjectEditor.getFlow(actionType)
+ if (object.propertyInfo.type == "textarea") {
+ if (object.textarea) {
+ const lvglIdentifier = ProjectEditor.getProjectStore(
+ object
+ ).lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.textarea
);
- const widgetType = actionProperty.type.slice(
- "widget:".length
- );
+ if (lvglIdentifier == undefined) {
+ messages.push(
+ propertyNotFoundMessage(object, "textarea")
+ );
+ } else {
+ if (
+ !(
+ lvglIdentifier.object instanceof
+ LVGLTextareaWidget
+ )
+ ) {
+ messages.push(
+ new Message(
+ MessageType.ERROR,
+ `Not a textarea widget`,
+ getChildOfObject(object, "textarea")
+ )
+ );
+ }
+ }
+ }
+ }
+ }
+ });
- return lvglIdentifiers
- .filter(lvglIdentifier => {
- if (!widgetType) {
- return (
- lvglIdentifier.object instanceof
- ProjectEditor.LVGLWidgetClass
- );
- } else {
- const lvglWidgetClassName = `LVGL${widgetType}Widget`;
+ get propertyInfo() {
+ return (
+ (PROPERTIES as PropertiesType)[this.targetType][this.property] ?? {
+ code: PropertyCode.NONE,
+ type: "integer",
+ animated: false
+ }
+ );
+ }
- const projectStore =
- ProjectEditor.getProjectStore(actionType);
+ get valueExpr() {
+ if (typeof this.value == "number") {
+ return this.value.toString();
+ }
- const lvglWidgetClass = getClassByName(
- projectStore,
- lvglWidgetClassName
- )!;
+ if (typeof this.value == "boolean") {
+ return this.value ? "true" : "false";
+ }
- return (
- lvglIdentifier.object instanceof
- lvglWidgetClass
- );
- }
- })
- .map(lvglIdentifier => ({
- id: lvglIdentifier.identifier,
- label: lvglIdentifier.identifier
- }));
- };
- referencedObjectCollectionPath = "";
- } else if (actionProperty.type == "style") {
- referencedObjectCollectionPath = "allLvglStyles";
- } else if (actionProperty.type == "image") {
- referencedObjectCollectionPath = "bitmaps";
- } else if (actionProperty.type == "group") {
- referencedObjectCollectionPath = "lvglGroups/groups";
+ if (this.valueType == "literal") {
+ if (this.propertyInfo.type == "boolean") {
+ return this.value ? "true" : "false";
}
+ }
- const lvglExpressionProperty = makeLvglExpressionProperty(
- actionProperty.name,
- expressionType,
- "input",
- ["literal", "expression"],
- {
- dynamicType: () => {
- if (referencedObjectCollectionPath != undefined) {
- return PropertyType.ObjectReference;
- }
+ if (this.valueType == "expression") {
+ return this.value as string;
+ }
- if (enumItems != undefined) {
- return PropertyType.Enum;
- }
+ return escapeCString(this.value ?? "");
+ }
- return expressionType == "integer" ||
- expressionType == "float" ||
- expressionType == "double"
- ? PropertyType.Number
- : expressionType == "boolean"
- ? PropertyType.Boolean
- : PropertyType.MultilineText;
- },
- enumItems,
- enumDisallowUndefined,
- checkboxStyleSwitch: true,
- referencedObjectCollectionPath,
- lvglActionPropertyType: actionProperty.type
- }
- );
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ ProjectEditor.getProjectStore(
+ this
+ ).lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
+
+ // property
+ dataBuffer.writeUint32(this.propertyInfo.code);
+
+ // value
+ dataBuffer.writeObjectOffset(() =>
+ buildExpression(
+ assets,
+ dataBuffer,
+ getAncestorOfType(
+ this,
+ LVGLActionComponent.classInfo
+ ) as LVGLActionComponent,
+ this.valueExpr
+ )
+ );
- properties.push(...lvglExpressionProperty);
+ // textarea
+ if (this.textarea) {
+ dataBuffer.writeInt32(
+ ProjectEditor.getProjectStore(
+ this
+ ).lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.textarea
+ )?.index ?? -1
+ );
+ } else {
+ dataBuffer.writeInt32(-1);
}
+
+ // animated
+ dataBuffer.writeUint32(this.animated ? 1 : 0);
}
+}
- const defaultValue = Object.assign({}, actionDefinition.defaults);
+registerClass("LVGLSetPropertyActionType", LVGLSetPropertyActionType);
- actionDefinition.properties.forEach(propertyDefinition => {
- if (!propertyDefinition.isAssignable) {
- defaultValue[propertyDefinition.name + "Type"] = "literal";
- }
- });
+////////////////////////////////////////////////////////////////////////////////
- const actionDisplayName = humanize(actionDefinition.name)
- .split(" ")
- .map(word =>
- word == "to" ? word : word[0].toUpperCase() + word.substring(1)
- )
- .join(" ");
+export class LVGLAddStyleActionType extends LVGLActionType {
+ target: string;
+ style: string;
- const actionClass = class extends LVGLActionType {
- static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
- properties,
- label: () => actionDisplayName,
- defaultValue,
- listLabel: (action: LVGLActionType, collapsed: boolean) => {
- if (!collapsed) {
- return actionDisplayName;
- }
+ override makeEditable() {
+ super.makeEditable();
- const propertyNames = actionDefinition.properties.map(
- actionProperty => humanize(actionProperty.name)
- );
- const propertyValues = actionDefinition.properties.map(
- actionProperty => {
- let value = (action as any)[actionProperty.name];
+ makeObservable(this, {
+ target: observable,
+ style: observable
+ });
+ }
- if (typeof value == "boolean") {
- value = value ? "ON" : "OFF";
- } else if (
- actionProperty.isAssignable ||
- (action as any)[actionProperty.name + "Type"] ==
- "expression"
- ) {
- value = `{${value}}`;
- }
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "target",
+ displayName: "Target",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLAddStyleActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
- return value;
- }
+ return lvglIdentifiers.map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
+ }
+ },
+ {
+ name: "style",
+ type: PropertyType.ObjectReference,
+ referencedObjectCollectionPath: "allLvglStyles"
+ }
+ ],
+ defaultValue: {},
+ listLabel: (action: LVGLAddStyleActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Add style";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ if (singleItem) {
+ return (
+ <>
+ {action.style} to {action.target}
+ >
+ );
+ } else {
+ return (
+ <>
+ Add style {action.style} to {action.target}
+ >
);
+ }
+ },
+ check: (object: LVGLAddStyleActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
- let propertiesDescription: React.ReactNode;
- if (actionDefinition.label) {
- propertiesDescription = actionDefinition.label(
- propertyValues,
- propertyNames
- );
- } else {
- propertiesDescription = actionDefinition.properties.map(
- (actionProperty, i) => {
- return (
- <>
- {propertyNames[i]}
- {actionProperty.isAssignable ? (
-
- ) : (
- "="
- )}
- {propertyValues[i]}
- {i <
- actionDefinition.properties.length -
- 1 && ", "}
- >
- );
- }
+ if (object.target) {
+ const lvglIdentifier =
+ projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
);
+
+ if (lvglIdentifier == undefined) {
+ messages.push(propertyNotFoundMessage(object, "target"));
}
+ } else {
+ messages.push(propertyNotSetMessage(object, "target"));
+ }
- return (
- <>
- {actionDisplayName}
- {propertiesDescription}
- >
+ if (object.style) {
+ const lvglStyle = findLvglStyle(
+ projectStore.project,
+ object.style
);
- },
- updateObjectValueHook(object, values) {
- const projectStore = ProjectEditor.getProjectStore(object);
+ if (!lvglStyle) {
+ messages.push(propertyNotFoundMessage(object, "style"));
+ }
+ } else {
+ messages.push(propertyNotSetMessage(object, "style"));
+ }
+ }
+ });
- for (const key of Object.keys(values)) {
- if (key.endsWith("Type")) {
- const propertyName = key.slice(0, -"Type".length);
- const propertyDefinition =
- actionDefinition.properties.find(
- propertyDefinition =>
- propertyDefinition.name == propertyName
- );
- if (propertyDefinition) {
- if (propertyDefinition.type.startsWith("enum:")) {
- const enumName = propertyDefinition.type.slice(
- "enum:".length
- );
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ ProjectEditor.getProjectStore(
+ this
+ ).lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
- if (
- values[key] == "expression" &&
- (object as any)[key] == "literal"
- ) {
- projectStore.updateObject(object, {
- [propertyName]: `${enumName}.${
- (object as any)[propertyName]
- }`
- });
- } else if (
- values[key] == "literal" &&
- (object as any)[key] == "expression"
- ) {
- if (
- (object as any)[
- propertyName
- ].startsWith(enumName + ".")
- ) {
- let value = (object as any)[
- propertyName
- ].slice((enumName + ".").length);
+ // style
+ if (this.style) {
+ const lvglStyle = findLvglStyle(
+ assets.projectStore.project,
+ this.style
+ );
- const enumType = getEnumFromType(
- projectStore.project,
- `enum:${enumName}`
- );
- if (enumType) {
- if (
- !enumType.members.find(
- member =>
- member.name == value
- )
- ) {
- value =
- enumType.members[0].name;
- }
- } else {
- value = "";
- }
+ if (lvglStyle) {
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.styles.indexOf(
+ lvglStyle
+ )
+ );
+ } else {
+ dataBuffer.writeInt32(-1);
+ }
+ } else {
+ dataBuffer.writeInt32(-1);
+ }
+ }
+}
+
+registerClass("LVGLAddStyleActionType", LVGLAddStyleActionType);
+
+////////////////////////////////////////////////////////////////////////////////
+
+export class LVGLRemoveStyleActionType extends LVGLActionType {
+ target: string;
+ style: string;
- projectStore.updateObject(object, {
- [propertyName]: value
- });
- }
- }
- }
- }
- }
+ override makeEditable() {
+ super.makeEditable();
+
+ makeObservable(this, {
+ target: observable,
+ style: observable
+ });
+ }
+
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "target",
+ displayName: "Target",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLRemoveStyleActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
+
+ return lvglIdentifiers.map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
}
},
+ {
+ name: "style",
+ type: PropertyType.ObjectReference,
+ referencedObjectCollectionPath: "allLvglStyles"
+ }
+ ],
+ defaultValue: {},
+ listLabel: (action: LVGLRemoveStyleActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Remove style";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ if (singleItem) {
+ return (
+ <>
+ {action.style} from {action.target}
+ >
+ );
+ } else {
+ return (
+ <>
+ Remove style {action.style} from {action.target}
+ >
+ );
+ }
+ },
+ check: (object: LVGLRemoveStyleActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
- check: (object: LVGLActionType, messages: IMessage[]) => {
- const projectStore = ProjectEditor.getProjectStore(object);
- const component = getAncestorOfType(
- object,
- LVGLActionComponent.classInfo
+ if (object.target) {
+ const lvglIdentifier =
+ projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
+ );
+
+ if (lvglIdentifier == undefined) {
+ messages.push(propertyNotFoundMessage(object, "target"));
+ }
+ } else {
+ messages.push(propertyNotSetMessage(object, "target"));
+ }
+
+ if (object.style) {
+ const lvglStyle = findLvglStyle(
+ projectStore.project,
+ object.style
);
- if (component) {
- for (const propertyInfo of properties) {
- if (propertyInfo.expressionType == undefined) {
- continue;
- }
- if (
- (object as any)[propertyInfo.name + "Type"] ==
- "expression" ||
- isFlowProperty(object, propertyInfo, ["assignable"])
- ) {
- ProjectEditor.checkProperty(
- projectStore,
- component,
- messages,
- object,
- propertyInfo
- );
- } else {
- const project = ProjectEditor.getProject(object);
- const value = (object as any)[propertyInfo.name];
+ if (!lvglStyle) {
+ messages.push(propertyNotFoundMessage(object, "style"));
+ }
+ } else {
+ messages.push(propertyNotSetMessage(object, "style"));
+ }
+ }
+ });
- if (
- propertyInfo.lvglActionPropertyType == "screen"
- ) {
- if (!value) {
- messages.push(
- propertyNotSetMessage(
- object,
- propertyInfo.name
- )
- );
- } else {
- let page = findPage(project, value);
- if (!page) {
- messages.push(
- propertyNotFoundMessage(
- object,
- propertyInfo.name
- )
- );
- }
- }
- } else if (
- propertyInfo.lvglActionPropertyType?.startsWith(
- "widget"
- )
- ) {
- if (!value) {
- messages.push(
- propertyNotSetMessage(
- object,
- propertyInfo.name
- )
- );
- } else {
- const lvglIdentifier =
- ProjectEditor.getProjectStore(
- object
- ).lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(object),
- value
- );
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
- if (lvglIdentifier == undefined) {
- messages.push(
- propertyNotFoundMessage(
- object,
- propertyInfo.name
- )
- );
- } else {
- const widgetType =
- propertyInfo.lvglActionPropertyType.slice(
- "widget:".length
- );
- if (widgetType) {
- const classInfo = getClassInfo(
- lvglIdentifier.object
- );
- const expectedClassInfo =
- getClassByName(
- project._store,
- `LVGL${widgetType}Widget`
- )?.classInfo;
+ // style
+ if (this.style) {
+ const lvglStyle = findLvglStyle(
+ assets.projectStore.project,
+ this.style
+ );
- if (
- classInfo != expectedClassInfo
- ) {
- messages.push(
- new Message(
- MessageType.ERROR,
- `Invalid object type`,
- getChildOfObject(
- object,
- propertyInfo.name
- )
- )
- );
- }
- }
- }
- }
- } else if (
- propertyInfo.lvglActionPropertyType == "group"
- ) {
- if (value) {
- if (
- !projectStore.project.lvglGroups.groups.some(
- group => group.name == value
- )
- ) {
- messages.push(
- propertyNotFoundMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else {
- messages.push(
- propertyNotSetMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else if (
- propertyInfo.lvglActionPropertyType == "style"
- ) {
- if (value) {
- const lvglStyle = findLvglStyle(
- projectStore.project,
- value
- );
+ if (lvglStyle) {
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.styles.indexOf(
+ lvglStyle
+ )
+ );
+ } else {
+ dataBuffer.writeInt32(-1);
+ }
+ } else {
+ dataBuffer.writeInt32(-1);
+ }
+ }
+}
- if (!lvglStyle) {
- messages.push(
- propertyNotFoundMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else {
- messages.push(
- propertyNotSetMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else if (
- propertyInfo.lvglActionPropertyType == "image"
- ) {
- if (value) {
- const bitmap = findBitmap(
- ProjectEditor.getProject(object),
- value
- );
+registerClass("LVGLRemoveStyleActionType", LVGLRemoveStyleActionType);
- if (!bitmap) {
- messages.push(
- propertyNotFoundMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else {
- messages.push(
- propertyNotSetMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else if (
- propertyInfo.lvglActionPropertyType?.startsWith(
- "enum:"
- )
- ) {
- if (value) {
- const enumType = getEnumFromType(
- project,
- propertyInfo.lvglActionPropertyType
- );
- if (
- !enumType ||
- !enumType.members.find(
- member => member.name == value
- )
- ) {
- messages.push(
- propertyNotFoundMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else {
- messages.push(
- propertyNotSetMessage(
- object,
- propertyInfo.name
- )
- );
- }
- } else if (value == undefined) {
- messages.push(
- propertyNotSetMessage(
- object,
- propertyInfo.name
- )
- );
- }
- }
- }
+////////////////////////////////////////////////////////////////////////////////
+
+export class LVGLAddFlagActionType extends LVGLActionType {
+ target: string;
+ flag: keyof typeof LVGL_FLAG_CODES;
+
+ override makeEditable() {
+ super.makeEditable();
+
+ makeObservable(this, {
+ target: observable,
+ flag: observable
+ });
+ }
+
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "target",
+ displayName: "Target",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLAddFlagActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
+
+ return lvglIdentifiers.map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
+ }
+ },
+ {
+ name: "flag",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLAddFlagActionType) => {
+ return Object.keys(getLvglFlagCodes(actionType)).map(
+ flag => ({
+ id: flag,
+ label: flag
+ })
+ );
+ }
+ }
+ ],
+ defaultValue: {},
+ listLabel: (action: LVGLAddFlagActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Add flag";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ if (singleItem) {
+ return (
+ <>
+ {action.flag} in {action.target}
+ >
+ );
+ } else {
+ return (
+ <>
+ Add flag {action.flag} in {action.target}
+ >
+ );
+ }
+ },
+ check: (object: LVGLAddFlagActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
+
+ if (object.target) {
+ const lvglIdentifier =
+ projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
+ );
+
+ if (lvglIdentifier == undefined) {
+ messages.push(propertyNotFoundMessage(object, "target"));
}
+ } else {
+ messages.push(propertyNotSetMessage(object, "target"));
}
+ }
+ });
+
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
+
+ // flag
+ dataBuffer.writeUint32(getLvglFlagCodes(this)[this.flag] ?? 0);
+ }
+}
+
+registerClass("LVGLAddFlagActionType", LVGLAddFlagActionType);
+
+////////////////////////////////////////////////////////////////////////////////
+
+export class LVGLClearFlagActionType extends LVGLActionType {
+ target: string;
+ flag: keyof typeof LVGL_FLAG_CODES;
+
+ override makeEditable() {
+ super.makeEditable();
+
+ makeObservable(this, {
+ target: observable,
+ flag: observable
});
+ }
- override makeEditable() {
- super.makeEditable();
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "target",
+ displayName: "Target",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLClearFlagActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
- const observables: any = {};
+ return lvglIdentifiers.map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
+ }
+ },
+ {
+ name: "flag",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLClearFlagActionType) => {
+ return Object.keys(getLvglFlagCodes(actionType)).map(
+ flag => ({
+ id: flag,
+ label: flag
+ })
+ );
+ }
+ }
+ ],
+ defaultValue: {},
+ listLabel: (action: LVGLClearFlagActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Clear flag";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ if (singleItem) {
+ return (
+ <>
+ {action.flag} in {action.target}
+ >
+ );
+ } else {
+ return (
+ <>
+ Clear flag {action.flag} in {action.target}
+ >
+ );
+ }
+ },
+ check: (object: LVGLClearFlagActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
- actionDefinition.properties.forEach(propertyInfo => {
- (this as any)[propertyInfo.name] = undefined;
- observables[propertyInfo.name] = observable;
+ if (object.target) {
+ const lvglIdentifier =
+ projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
+ );
- if (!propertyInfo.isAssignable) {
- (this as any)[propertyInfo.name + "Type"] = undefined;
- observables[propertyInfo.name + "Type"] = observable;
+ if (lvglIdentifier == undefined) {
+ messages.push(propertyNotFoundMessage(object, "target"));
}
- });
-
- makeObservable(this, observables);
+ } else {
+ messages.push(propertyNotSetMessage(object, "target"));
+ }
}
- };
-
- actionClasses.set(actionDefinition.name, actionClass);
-}
+ });
-////////////////////////////////////////////////////////////////////////////////
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
-interface IBuildProperties {
- name: string;
- expression: string;
- isAssignable: boolean;
- isHidden: boolean;
- isBuildable: boolean;
+ // flag
+ dataBuffer.writeUint32(getLvglFlagCodes(this)[this.flag] ?? 0);
+ }
}
-export class LVGLActionType extends EezObject {
- action: string;
+registerClass("LVGLClearFlagActionType", LVGLClearFlagActionType);
- static classInfo: ClassInfo = {
- getClass: function (projectStore: ProjectStore, jsObject: any) {
- if (jsObject.action == "ObjectSetX") jsObject.action = "objSetX";
+////////////////////////////////////////////////////////////////////////////////
- const actionClass = actionClasses.get(jsObject.action);
- if (actionClass) {
- return actionClass;
- }
+export class LVGLAddStateActionType extends LVGLActionType {
+ target: string;
+ state: keyof typeof LVGL_STATE_CODES;
- return LVGLActionType;
- },
+ override makeEditable() {
+ super.makeEditable();
+
+ makeObservable(this, {
+ target: observable,
+ state: observable
+ });
+ }
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
properties: [
{
- name: "action",
- displayName: (object: LVGLActionType) => {
- const actions = getParent(object) as LVGLActionType[];
- if (actions.length < 2) {
- return "Action";
- }
- return `Action #${actions.indexOf(object) + 1}`;
- },
+ name: "target",
+ displayName: "Target",
type: PropertyType.Enum,
- enumItems: [...actionClasses.keys()].map(id => ({
- id
- })),
- enumDisallowUndefined: true,
- hideInPropertyGrid: true
+ enumItems: (actionType: LVGLAddStateActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
+
+ return lvglIdentifiers.map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
+ }
+ },
+ {
+ name: "state",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLAddStateActionType) => {
+ return Object.keys(LVGL_STATE_CODES).map(state => ({
+ id: state,
+ label: state
+ }));
+ }
}
],
+ defaultValue: {},
+ listLabel: (action: LVGLAddStateActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Add state";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ if (singleItem) {
+ return (
+ <>
+ {action.state} in {action.target}
+ >
+ );
+ } else {
+ return (
+ <>
+ Add state {action.state} in {action.target}
+ >
+ );
+ }
+ },
+ check: (object: LVGLAddStateActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
- newItem: async (object: LVGLActionType[]) => {
- const project = ProjectEditor.getProject(object);
-
- const result = await showGenericDialog({
- dialogDefinition: {
- title: "New LVGL Action",
- fields: [
- {
- name: "action",
- displayName: "Action type",
- type: "enum",
- enumItems: [...actionClasses.keys()].map(id => ({
- id,
- label:
- actionClasses
- .get(id)
- ?.classInfo.label?.(undefined as any) ??
- id
- }))
- }
- ]
- },
- values: {
- action: [...actionClasses.keys()][0]
- },
- dialogContext: project
- });
+ if (object.target) {
+ const lvglIdentifier =
+ projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
+ );
- const actionTypeProperties = {
- action: result.values.action
- };
+ if (lvglIdentifier == undefined) {
+ messages.push(propertyNotFoundMessage(object, "target"));
+ }
+ } else {
+ messages.push(propertyNotSetMessage(object, "target"));
+ }
+ }
+ });
- let actionTypeObject;
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
- const ActionClass = actionClasses.get(result.values.action)!;
+ // state
+ dataBuffer.writeUint32(LVGL_STATE_CODES[this.state] ?? 0);
+ }
+}
- actionTypeObject = createObject(
- project._store,
- Object.assign(
- actionTypeProperties,
+registerClass("LVGLAddStateActionType", LVGLAddStateActionType);
- ActionClass.classInfo.defaultValue
- ),
- ActionClass
- );
+////////////////////////////////////////////////////////////////////////////////
- return actionTypeObject;
- }
- };
+export class LVGLClearStateActionType extends LVGLActionType {
+ target: string;
+ state: keyof typeof LVGL_STATE_CODES;
override makeEditable() {
super.makeEditable();
makeObservable(this, {
- action: observable
+ target: observable,
+ state: observable
});
}
- getExpression(assets: Assets, propertyInfo: PropertyInfo) {
- let value = (this as any)[propertyInfo.name];
-
- if (isFlowProperty(this, propertyInfo, ["assignable"])) {
- return value;
- }
-
- let valueType = (this as any)[propertyInfo.name + "Type"] ?? "literal";
-
- if (typeof value == "number") {
- return value.toString();
- }
-
- if (typeof value == "boolean") {
- return value ? "true" : "false";
- }
-
- if (valueType == "literal") {
- if (propertyInfo.lvglActionPropertyType == "boolean") {
- return value ? "true" : "false";
- } else if (propertyInfo.lvglActionPropertyType == "integer") {
- return value;
- } else if (propertyInfo.lvglActionPropertyType == "string") {
- return escapeCString(value ?? "");
- } else if (
- propertyInfo.lvglActionPropertyType?.startsWith("enum:")
- ) {
- const enumType = getEnumFromType(
- assets.projectStore.project,
- propertyInfo.expressionType!
- );
- if (enumType) {
- const enumMember = enumType.members.find(
- member => member.name == value
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "target",
+ displayName: "Target",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLClearStateActionType) => {
+ const lvglIdentifiers = ProjectEditor.getProjectStore(
+ actionType
+ ).lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
);
- if (enumMember) {
- return enumMember.value.toString();
- }
+
+ return lvglIdentifiers.map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
+ }
+ },
+ {
+ name: "state",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLClearStateActionType) => {
+ return Object.keys(LVGL_STATE_CODES).map(state => ({
+ id: state,
+ label: state
+ }));
}
- return 0;
- } else if (propertyInfo.lvglActionPropertyType == "screen") {
- return assets.getPageIndex(this, propertyInfo.name);
- } else if (
- propertyInfo.lvglActionPropertyType?.startsWith("widget")
- ) {
+ }
+ ],
+ defaultValue: {},
+ listLabel: (action: LVGLClearStateActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Clear state";
+ }
+ let singleItem =
+ (getParent(action) as LVGLActionType[]).length == 1;
+ if (singleItem) {
return (
- assets.projectStore.lvglIdentifiers.getIdentifierByName(
- ProjectEditor.getFlow(this),
- value
- )?.index ?? -1
- );
- } else if (propertyInfo.lvglActionPropertyType == "group") {
- return assets.projectStore.project.lvglGroups.groups.findIndex(
- group => group.name == value
+ <>
+ {action.state} in {action.target}
+ >
);
- } else if (propertyInfo.lvglActionPropertyType == "style") {
- const lvglStyle = findLvglStyle(
- assets.projectStore.project,
- value
+ } else {
+ return (
+ <>
+ Clear state {action.state} in {action.target}
+ >
);
+ }
+ },
+ check: (object: LVGLClearStateActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
- if (lvglStyle) {
- return assets.projectStore.lvglIdentifiers.styles.indexOf(
- lvglStyle
+ if (object.target) {
+ const lvglIdentifier =
+ projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
);
- } else {
- return -1;
+
+ if (lvglIdentifier == undefined) {
+ messages.push(propertyNotFoundMessage(object, "target"));
}
- } else if (propertyInfo.lvglActionPropertyType == "image") {
- return escapeCString(value ?? "");
+ } else {
+ messages.push(propertyNotSetMessage(object, "target"));
}
}
- return value;
- }
+ });
- getBuildProperties(assets: Assets): IBuildProperties[] {
- const classInfo = getClassInfo(this);
- return classInfo.properties
- .filter(propertyInfo => propertyInfo.expressionType != undefined)
- .map(propertyInfo => ({
- name: propertyInfo.name,
- expression: this.getExpression(assets, propertyInfo),
- isAssignable: isFlowProperty(this, propertyInfo, [
- "assignable"
- ]),
- isHidden: false,
- isBuildable: true
- }));
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // target
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
+
+ // state
+ dataBuffer.writeUint32(LVGL_STATE_CODES[this.state] ?? 0);
}
}
+registerClass("LVGLClearStateActionType", LVGLClearStateActionType);
+
////////////////////////////////////////////////////////////////////////////////
-export class LVGLActionComponent extends ActionComponent {
- actions: LVGLActionType[];
+const GROUP_ACTIONS = {
+ SET_WRAP: 0,
+ FOCUS_OBJ: 1,
+ FOCUS_NEXT: 2,
+ FOCUS_PREVIOUS: 3,
+ FOCUS_FREEZE: 4,
+ SET_EDITING: 5
+};
- static classInfo = makeDerivedClassInfo(ActionComponent.classInfo, {
- flowComponentId: COMPONENT_TYPE_LVGL_ACTION_API,
- componentPaletteGroupName: "!2LVGL",
- componentPaletteLabel: "LVGL",
- enabledInComponentPalette: (projectType: ProjectType) =>
- projectType === ProjectType.LVGL,
- properties: [
- {
- name: "actions",
- type: PropertyType.Array,
- typeClass: LVGLActionType,
- propertyGridGroup: specificGroup,
- partOfNavigation: false,
- enumerable: false,
- defaultValue: []
- }
- ],
- beforeLoadHook: (object: LVGLActionComponent, objectJs: any) => {
- if (objectJs.action != undefined) {
- if (objectJs.action == "CHANGE_SCREEN") {
- let action: any = {
- action: objectJs.action
- };
+export class LVGLGroupActionType extends LVGLActionType {
+ groupAction: keyof typeof GROUP_ACTIONS;
+ target: string;
+ enable: boolean;
- action.screen =
- objectJs.changeScreenTarget ?? objectJs.screen;
- action.fadeMode =
- objectJs.changeScreenFadeMode ?? objectJs.fadeMode;
- action.speed = objectJs.changeScreenSpeed ?? objectJs.speed;
- action.delay = objectJs.changeScreenDelay ?? objectJs.delay;
+ override makeEditable() {
+ super.makeEditable();
- objectJs.actions = [action];
- } else if (objectJs.action == "PLAY_ANIMATION") {
- objectJs.actions = objectJs.animItems.map((item: any) => {
- let action: any = {
- action: objectJs.action
- };
+ makeObservable(this, {
+ groupAction: observable,
+ target: observable,
+ enable: observable
+ });
+ }
- action.target = objectJs.animTarget;
- action.property = item.property;
- action.start = item.start;
- action.end = item.end;
- action.delay = objectJs.animDelay + item.delay;
- action.time = item.time;
- action.relative = item.relative;
- action.instant = item.instant;
- action.path = item.path;
+ static classInfo = makeDerivedClassInfo(LVGLActionType.classInfo, {
+ properties: [
+ {
+ name: "groupAction",
+ type: PropertyType.Enum,
+ enumItems: Object.keys(GROUP_ACTIONS).map(id => ({
+ id
+ })),
+ enumDisallowUndefined: true
+ },
+ {
+ name: "target",
+ displayName: (actionType: LVGLGroupActionType) =>
+ actionType.groupAction == "FOCUS_OBJ"
+ ? "Target widget"
+ : "Target group",
+ type: PropertyType.Enum,
+ enumItems: (actionType: LVGLGroupActionType) => {
+ const projectStore =
+ ProjectEditor.getProjectStore(actionType);
+ if (actionType.groupAction == "FOCUS_OBJ") {
+ const lvglIdentifiers =
+ projectStore.lvglIdentifiers.getIdentifiersVisibleFromFlow(
+ ProjectEditor.getFlow(actionType)
+ );
- return action;
- });
- } else if (objectJs.action == "SET_PROPERTY") {
- let action: any = {
- action: objectJs.action
- };
+ return lvglIdentifiers.map(lvglIdentifier => ({
+ id: lvglIdentifier.identifier,
+ label: lvglIdentifier.identifier
+ }));
+ } else {
+ return projectStore.project.lvglGroups.groups.map(
+ group => ({
+ id: group.name,
+ label: group.name
+ })
+ );
+ }
+ }
+ },
+ {
+ name: "enable",
+ type: PropertyType.Boolean,
+ checkboxStyleSwitch: true,
+ disabled: (actionType: LVGLGroupActionType) =>
+ !(
+ actionType.groupAction == "SET_WRAP" ||
+ actionType.groupAction == "FOCUS_FREEZE" ||
+ actionType.groupAction == "SET_EDITING"
+ )
+ }
+ ],
+ defaultValue: {
+ groupAction: "SET_WRAP"
+ },
+ listLabel: (action: LVGLGroupActionType, collapsed: boolean) => {
+ if (!collapsed) {
+ return "Group";
+ }
+ if (action.groupAction == "SET_WRAP") {
+ return (
+ <>
+ Set wrap to {action.enable ? "ON" : "OFF"} for group "
+ {action.target}"
+ >
+ );
+ } else if (action.groupAction == "FOCUS_OBJ") {
+ return <>Set focus to widget "{action.target}">;
+ } else if (action.groupAction == "FOCUS_NEXT") {
+ return <>Focus next for group "{action.target}">;
+ } else if (action.groupAction == "FOCUS_PREVIOUS") {
+ return <>Focus previous for group "{action.target}">;
+ } else if (action.groupAction == "FOCUS_FREEZE") {
+ return <>Freeze focus for group "{action.target}">;
+ } else {
+ return (
+ <>
+ Set editing to {action.enable ? "ON" : "OFF"} for group
+ "{action.target}"
+ >
+ );
+ }
+ },
+ check: (object: LVGLGroupActionType, messages: IMessage[]) => {
+ const projectStore = ProjectEditor.getProjectStore(object);
- action.targetType = objectJs.setPropTargetType;
- action.target = objectJs.setPropTarget;
- action.property = objectJs.setPropProperty;
- action.value = objectJs.setPropValue;
- action.valueType = objectJs.setPropValueType;
- action.animated = objectJs.setPropAnim;
+ if (object.target) {
+ if (object.groupAction == "FOCUS_OBJ") {
+ const lvglIdentifier =
+ projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(object),
+ object.target
+ );
- objectJs.actions = [action];
+ if (lvglIdentifier == undefined) {
+ messages.push(
+ propertyNotFoundMessage(object, "target")
+ );
+ }
+ } else {
+ if (
+ !projectStore.project.lvglGroups.groups.some(
+ group => group.name == object.target
+ )
+ ) {
+ messages.push(
+ propertyNotFoundMessage(object, "target")
+ );
+ }
}
+ } else {
+ messages.push(propertyNotSetMessage(object, "target"));
+ }
+ }
+ });
- delete objectJs.screen;
- delete objectJs.changeScreenTarget;
- delete objectJs.fadeMode;
- delete objectJs.changeScreenFadeMode;
- delete objectJs.speed;
- delete objectJs.changeScreenSpeed;
- delete objectJs.delay;
- delete objectJs.changeScreenDelay;
+ override build(assets: Assets, dataBuffer: DataBuffer) {
+ // groupAction
+ dataBuffer.writeUint32(GROUP_ACTIONS[this.groupAction]);
- delete objectJs.animTarget;
- delete objectJs.animDelay;
- delete objectJs.animItems;
+ // target
+ if (this.groupAction == "FOCUS_OBJ") {
+ dataBuffer.writeInt32(
+ assets.projectStore.lvglIdentifiers.getIdentifierByName(
+ ProjectEditor.getFlow(this),
+ this.target
+ )?.index ?? -1
+ );
+ } else {
+ const index =
+ assets.projectStore.project.lvglGroups.groups.findIndex(
+ group => group.name == this.target
+ );
- delete objectJs.setPropTargetType;
- delete objectJs.setPropTarget;
- delete objectJs.setPropProperty;
- delete objectJs.setPropAnim;
- delete objectJs.setPropValue;
- delete objectJs.setPropValueType;
- }
+ dataBuffer.writeInt32(index);
+ }
- for (const actionJs of objectJs.actions) {
- switch (actionJs.action) {
- case "CHANGE_SCREEN":
- if (actionJs.showPreviousScreen == true) {
- actionJs.action = "changeToPreviousScreen";
- } else {
- actionJs.action = "changeScreen";
- actionJs.screenType = "literal";
- }
- actionJs.fadeModeType = "literal";
- actionJs.speedType = "literal";
- actionJs.delayType = "literal";
- break;
- case "PLAY_ANIMATION":
- switch (actionJs.property) {
- case "POSITION_X":
- actionJs.action = "animX";
- break;
- case "POSITION_Y":
- actionJs.action = "animY";
- break;
- case "WIDTH":
- actionJs.action = "animWidth";
- break;
- case "HEIGHT":
- actionJs.action = "animHeight";
- break;
- case "OPACITY":
- actionJs.action = "animOpacity";
- break;
- case "IMAGE_ZOOM":
- actionJs.action = "animImageZoom";
- break;
- case "IMAGE_ANGLE":
- actionJs.action = "animImageAngle";
- break;
- }
- delete actionJs.property;
+ // style
+ dataBuffer.writeUint32(this.enable ? 1 : 0);
+ }
+}
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
+registerClass("LVGLGroupActionType", LVGLGroupActionType);
- actionJs.startType = "literal";
- actionJs.endType = "literal";
- actionJs.delayType = "literal";
- actionJs.timeType = "literal";
- actionJs.relative = actionJs.relative ?? false;
- actionJs.relativeType = "literal";
- actionJs.instant = actionJs.instant ?? false;
- actionJs.instantType = "literal";
- if (!actionJs.path) {
- actionJs.path = "LINEAR";
- }
- actionJs.pathType = "literal";
- break;
- case "SET_PROPERTY":
- switch (actionJs.targetType) {
- case "arc":
- actionJs.action = "arcSetValue";
- break;
- case "bar":
- actionJs.action = "barSetValue";
- actionJs.animatedType = "literal";
- break;
- case "basic":
- switch (actionJs.property) {
- case "x":
- actionJs.action = "objSetX";
- actionJs.x = actionJs.value;
- delete actionJs.value;
- actionJs.xType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "y":
- actionJs.action = "objSetY";
- actionJs.y = actionJs.value;
- delete actionJs.value;
- actionJs.yType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "width":
- actionJs.action = "objSetWidth";
- actionJs.width = actionJs.value;
- delete actionJs.value;
- actionJs.widthType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "height":
- actionJs.action = "objSetHeight";
- actionJs.height = actionJs.value;
- delete actionJs.value;
- actionJs.heightType =
- actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "opacity":
- actionJs.action = "objSetStyleOpa";
- actionJs.opacity = actionJs.value;
- delete actionJs.value;
- actionJs.opacityType =
- actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "hidden":
- actionJs.action = "objSetFlagHidden";
- actionJs.hidden =
- actionJs.value ?? false;
- delete actionJs.value;
- actionJs.hiddenType =
- actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "checked":
- actionJs.action = "objSetStateChecked";
- actionJs.checked =
- actionJs.value ?? false;
- delete actionJs.value;
- actionJs.checkedType =
- actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "disabled":
- actionJs.action = "objSetStateDisabled";
- actionJs.disabled =
- actionJs.value ?? false;
- delete actionJs.value;
- actionJs.disabledType =
- actionJs.valueType;
- delete actionJs.valueType;
- break;
- }
- break;
- case "dropdown":
- actionJs.action = "dropdownSetSelected";
- actionJs.selected = actionJs.value;
- delete actionJs.value;
- actionJs.selectedType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "image":
- switch (actionJs.property) {
- case "image":
- actionJs.action = "imageSetSrc";
- actionJs.src = actionJs.value;
- delete actionJs.value;
- actionJs.srcType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "angle":
- actionJs.action = "imageSetAngle";
- actionJs.angle = actionJs.value;
- delete actionJs.value;
- actionJs.angleType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "zoom":
- actionJs.action = "imageSetZoom";
- actionJs.zoom = actionJs.value;
- delete actionJs.value;
- actionJs.zoomType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- }
- break;
- case "label":
- actionJs.action = "labelSetText";
- actionJs.text = actionJs.value;
- delete actionJs.value;
- actionJs.textType = actionJs.valueType;
- delete actionJs.valueType;
- break;
- case "roller":
- actionJs.action = "rollerSetSelected";
+////////////////////////////////////////////////////////////////////////////////
- actionJs.selected = actionJs.value;
- delete actionJs.value;
- actionJs.selectedType = actionJs.valueType;
- delete actionJs.valueType;
+export class LVGLActionComponent extends ActionComponent {
+ actions: LVGLActionType[];
- actionJs.animatedType = "literal";
- break;
- case "slider":
- actionJs.action = "sliderSetValue";
+ static classInfo = makeDerivedClassInfo(ActionComponent.classInfo, {
+ flowComponentId: COMPONENT_TYPE_LVGL_ACTION,
+ componentPaletteGroupName: "!2LVGL",
+ componentPaletteLabel: "LVGL",
+ enabledInComponentPalette: (projectType: ProjectType) =>
+ projectType === ProjectType.LVGL,
+ label: (component: LVGLActionComponent) => {
+ if (component.actions.length == 1) {
+ return `LVGL ${humanize(component.actions[0].action)}`;
+ }
+ return "LVGL";
+ },
+ properties: [
+ {
+ name: "actions",
+ type: PropertyType.Array,
+ typeClass: LVGLActionType,
+ propertyGridGroup: specificGroup,
+ partOfNavigation: false,
+ enumerable: false,
+ defaultValue: []
+ }
+ ],
+ beforeLoadHook: (object: LVGLActionComponent, objectJs: any) => {
+ if (objectJs.action != undefined) {
+ if (objectJs.action == "CHANGE_SCREEN") {
+ let action: Partial = {
+ action: objectJs.action
+ };
- actionJs.animatedType = "literal";
- break;
- case "keyboard":
- actionJs.action = "keyboardSetTextarea";
+ action.screen =
+ objectJs.changeScreenTarget ?? objectJs.screen;
+ action.fadeMode =
+ objectJs.changeScreenFadeMode ?? objectJs.fadeMode;
+ action.speed = objectJs.changeScreenSpeed ?? objectJs.speed;
+ action.delay = objectJs.changeScreenDelay ?? objectJs.delay;
- actionJs.textarea = actionJs.textarea;
- actionJs.textareaType = "literal";
- break;
- }
- delete actionJs.targetType;
- delete actionJs.property;
+ objectJs.actions = [action];
+ } else if (objectJs.action == "PLAY_ANIMATION") {
+ objectJs.actions = objectJs.animItems.map((item: any) => {
+ let action: Partial = {
+ action: objectJs.action
+ };
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- break;
- case "ADD_STYLE":
- actionJs.action = "objAddStyle";
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- actionJs.styleType = "literal";
- break;
- case "REMOVE_STYLE":
- actionJs.action = "objRemoveStyle";
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- actionJs.styleType = "literal";
- break;
- case "ADD_FLAG":
- actionJs.action = "objAddFlag";
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- actionJs.flagType = "literal";
- break;
- case "CLEAR_FLAG":
- actionJs.action = "objClearFlag";
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- actionJs.flagType = "literal";
- break;
- case "ADD_STATE":
- actionJs.action = "objAddState";
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- actionJs.stateType = "literal";
- break;
- case "CLEAR_STATE":
- actionJs.action = "objClearState";
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- actionJs.stateType = "literal";
- break;
- case "GROUP":
- switch (actionJs.groupAction) {
- case "SET_WRAP":
- actionJs.action = "groupSetWrap";
+ action.target = objectJs.animTarget;
+ action.property = item.property;
+ action.start = item.start;
+ action.end = item.end;
+ action.delay = objectJs.animDelay + item.delay;
+ action.time = item.time;
+ action.relative = item.relative;
+ action.instant = item.instant;
+ action.path = item.path;
- actionJs.group = actionJs.target;
- delete actionJs.target;
- actionJs.groupType = "literal";
+ return action;
+ });
+ } else if (objectJs.action == "SET_PROPERTY") {
+ let action: Partial = {
+ action: objectJs.action
+ };
- actionJs.enabled = actionJs.enable ?? false;
- delete actionJs.enable;
- actionJs.enabledType = "literal";
- break;
- case "FOCUS_OBJ":
- actionJs.action = "groupFocusObj";
- actionJs.object = actionJs.target;
- delete actionJs.target;
- actionJs.objectType = "literal";
- break;
- case "FOCUS_NEXT":
- actionJs.action = "groupFocusNext";
- actionJs.group = actionJs.target;
- delete actionJs.target;
- actionJs.groupType = "literal";
- break;
- case "FOCUS_PREVIOUS":
- actionJs.action = "groupFocusPrev";
- actionJs.group = actionJs.target;
- delete actionJs.target;
- actionJs.groupType = "literal";
- break;
- case "FOCUS_FREEZE":
- actionJs.action = "groupFocusFreeze";
+ action.targetType = objectJs.setPropTargetType;
+ action.target = objectJs.setPropTarget;
+ action.property = objectJs.setPropProperty;
+ action.value = objectJs.setPropValue;
+ action.valueType = objectJs.setPropValueType;
+ action.animated = objectJs.setPropAnim;
- actionJs.group = actionJs.target;
- delete actionJs.target;
- actionJs.groupType = "literal";
+ objectJs.actions = [action];
+ }
- actionJs.enabled = actionJs.enable ?? false;
- delete actionJs.enable;
- actionJs.enabledType = "literal";
- break;
- case "SET_EDITING":
- actionJs.action = "groupSetEditing";
+ delete objectJs.screen;
+ delete objectJs.changeScreenTarget;
+ delete objectJs.fadeMode;
+ delete objectJs.changeScreenFadeMode;
+ delete objectJs.speed;
+ delete objectJs.changeScreenSpeed;
+ delete objectJs.delay;
+ delete objectJs.changeScreenDelay;
- actionJs.group = actionJs.target;
- delete actionJs.target;
- actionJs.groupType = "literal";
+ delete objectJs.animTarget;
+ delete objectJs.animDelay;
+ delete objectJs.animItems;
- actionJs.enabled = actionJs.enable ?? false;
- delete actionJs.enable;
- actionJs.enabledType = "literal";
- break;
- }
- delete actionJs.groupAction;
- break;
- }
+ delete objectJs.setPropTargetType;
+ delete objectJs.setPropTarget;
+ delete objectJs.setPropProperty;
+ delete objectJs.setPropAnim;
+ delete objectJs.setPropValue;
+ delete objectJs.setPropValueType;
}
},
icon: (
@@ -3357,85 +3601,13 @@ export class LVGLActionComponent extends ActionComponent {
buildFlowComponentSpecific(assets: Assets, dataBuffer: DataBuffer) {
dataBuffer.writeArray(this.actions, action => {
// action
- dataBuffer.writeUint32(actionNameToActionId.get(action.action)!);
-
- // properties
- const buildProperties = action.getBuildProperties(assets);
- //console.log(buildProperties);
- dataBuffer.writeArray(buildProperties, buildProperty => {
- if (!buildProperty.isHidden) {
- try {
- if (buildProperty.isBuildable) {
- let expression = buildProperty.expression;
-
- if (buildProperty.isAssignable) {
- buildAssignableExpression(
- assets,
- dataBuffer,
- this,
- expression
- );
- } else {
- buildExpression(
- assets,
- dataBuffer,
- this,
- expression
- );
- }
- } else {
- dataBuffer.writeUint16NonAligned(
- makeEndInstruction()
- );
- }
- } catch (err) {
- assets.projectStore.outputSectionsStore.write(
- Section.OUTPUT,
- MessageType.ERROR,
- err.toString(),
- getChildOfObject(action, buildProperty.name)
- );
+ dataBuffer.writeUint32(LVGL_ACTIONS[action.action]);
- dataBuffer.writeUint16NonAligned(makeEndInstruction());
- }
- } else {
- dataBuffer.writeUint16NonAligned(makeEndInstruction());
- }
- });
+ // ...specific
+ action.build(assets, dataBuffer);
});
}
}
registerClass("LVGLActionComponent", LVGLActionComponent);
-
-////////////////////////////////////////////////////////////////////////////////
-
-export function generateLVGLActionsMarkdown() {
- let result =
- "List of actions to be executed. The following actions are available:\n\n";
-
- for (const actionDefinition of actionDefinitions) {
- result += `- **${humanize(actionDefinition.name)}**: ${
- actionDefinition.helpText
- }\n`;
-
- for (const actionProperty of actionDefinition.properties) {
- result += ` - *${
- actionProperty.isAssignable
- ? `Store ${actionProperty.name} into`
- : humanize(actionProperty.name)
- }*: ${actionProperty.helpText}\n`;
- }
-
- result += "\n";
- }
-
- result += "\n";
-
- return result;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
-import "./actions-catalog";
-import { RightArrow } from "project-editor/ui-components/icons";
+*/