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 ( + +
    + { + newLVGLActionDialogState.searchText = ""; + }} + onChange={newLVGLActionDialogState.onSearchChange} + onKeyDown={newLVGLActionDialogState.onSearchChange} + /> + + + ) => { + return ; + }} + selectNode={( + node: IListNode + ) => { + newLVGLActionDialogState.selectedActionName = + node.data.name; + }} + onDoubleClick={this.onDoubleClick} + > + +
    +
    + ); + } + } +); + +//////////////////////////////////////////////////////////////////////////////// + +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"; +*/